Compare commits

...

608 Commits

Author SHA1 Message Date
Matthias Mailänder
70a5333b40 fixes #2363
typo leading to a crash when clicking a disabled tab
2012-08-22 12:40:38 +12:00
Igor Popov
e8359b08c6 change IsAdmin indicator to d2k like 2012-08-22 12:38:10 +12:00
Scott_NZ
cebc0b66a5 Make the Viewport code easier to follow 2012-08-20 20:45:56 +12:00
Scott_NZ
6ac86cbc1a Fix UnitsNearActor basing itself off the Soviet WP, instead of the actual actor. Move the power code to the unit building method so the Soviets don't build units completely, even if they have enough money. 2012-08-20 20:45:54 +12:00
Curtis Shmyr
60ceb800e1 Remove contrails from pbox vulcan - was not working as intended 2012-08-20 15:06:36 +12:00
Igor Popov
5f47b7b7fc add 3v3 d2k map by Combine; add 2 ra maps by Holloweye (conquest + minigame) 2012-08-20 13:54:11 +12:00
Scott_NZ
7e2866714c Overhaul Soviet base 2012-08-20 03:32:09 +12:00
Scott_NZ
7e8313b808 Add music to Allies 02 2012-08-19 17:19:45 +12:00
Scott_NZ
bfd28abb70 FMV videos for Allies 01, also adjust music to play a random track 2012-08-19 17:00:03 +12:00
Scott_NZ
1afc0cbfce Remove fast unit production for Soviets, this is too overwhelming 2012-08-19 13:05:05 +12:00
Scott_NZ
82bcd19d2e Fix crash when Media.PlayFMVFullscreen is called 2012-08-19 12:56:12 +12:00
Scott_NZ
49049a715b Give allies base more reinforcements after 12 mins 2012-08-19 12:55:38 +12:00
Scott_NZ
3114a5b85e Add Soviet apc/flamer rush after 7 minutes 2012-08-18 17:26:18 +12:00
Scott_NZ
222f17a586 Minor refactor 2012-08-18 01:45:05 +12:00
Scott_NZ
91027e9961 Use FirstOrDefault when getting closest building 2012-08-18 00:01:35 +12:00
Scott_NZ
a06a7a8ccb Replace arty with fix/2tnk 2012-08-18 00:00:44 +12:00
Scott_NZ
a8bae22dd3 Give arty back so the allies stand a chance 2012-08-17 23:27:19 +12:00
Scott_NZ
daa89f52b6 Add lethal Soviet attacks and increase heavy tank production 2012-08-17 23:13:35 +12:00
Scott_NZ
22c1059904 Rework water area near the town 2012-08-17 20:28:05 +12:00
Scott_NZ
c0138966e7 Rework Allied base a bit 2012-08-17 20:02:39 +12:00
Scott_NZ
0f14263b82 Make walls not contribute to allied building check 2012-08-17 17:48:47 +12:00
Scott_NZ
dfc6304efa Increase the difficulty 2012-08-17 17:31:18 +12:00
Scott_NZ
632d717af8 Fix HeliLand constructor 2012-08-16 22:04:10 +12:00
Scott_NZ
a74a3aa3b5 Disable bots 2012-08-16 21:47:22 +12:00
Scott_NZ
c90c351692 Spaces in csproj 2012-08-16 21:47:21 +12:00
Scott_NZ
5612a57842 and some more 2012-08-16 21:47:20 +12:00
Scott_NZ
6e3c8c9745 Fix some old VS-induced nastiess 2012-08-16 21:47:19 +12:00
Scott_NZ
0920c67017 Require ra mod, pack allies 02 2012-08-16 21:47:18 +12:00
Scott_NZ
1ed0d80348 Fix static readonly field capitalisation conventions 2012-08-16 21:47:17 +12:00
Scott_NZ
c41fcb15b0 Fail Allies01/Allies02 if the extraction helicopter is destroyed 2012-08-16 21:47:16 +12:00
Scott_NZ
6c79b454bf Improve Allies base 2012-08-16 21:47:16 +12:00
Scott_NZ
610e40b8d6 Give Allies2 player some cash when they receive reinforcements 2012-08-16 21:47:15 +12:00
Scott_NZ
5038018aa5 Give the Soviets money as they need it. 2012-08-16 21:47:14 +12:00
Scott_NZ
cce12e781f Kill the allied players if they fail the mission. Also fail the mission if the Allies2 player loses all of their buildings. 2012-08-16 21:47:13 +12:00
Scott_NZ
245de3abcb Making HBOX unbuildable was crashing the game 2012-08-16 21:47:12 +12:00
Scott_NZ
11f9fa1942 Some code polish 2012-08-16 21:47:11 +12:00
Scott_NZ
85fa7eb8c4 Modify tech tree, disable bots 2012-08-16 21:47:10 +12:00
Scott_NZ
62d7168d41 Make the mission not unwinnable if Einstein can't cross the bridge because it is destroyed 2012-08-16 21:47:09 +12:00
Scott_NZ
2a053daa2e Add Soviet attacks, scrap chinook timer since we might have pathing issues if Tanya is on the island and we have off-map attacks. Counter this by bringing back reinforcements timer 2012-08-16 21:47:09 +12:00
Scott_NZ
21a903fe2d Remove an ai activation check, we want it to always activate even if the host is a spectator 2012-08-16 21:47:08 +12:00
Scott_NZ
83fc546fbe Reposition Soviet barracks/kennel 2012-08-16 21:47:07 +12:00
Scott_NZ
f648223c39 Improve the deploy routine so that baseCenter is still set even if the mcv is a fact 2012-08-16 21:47:06 +12:00
Scott_NZ
583c3f9a64 Produce dogs, adjust allied building positions 2012-08-16 21:47:05 +12:00
Scott_NZ
0d9c78670e Basic Soviet AI. This is flawed right now as it will just charge all of its starting units towards Tanya 2012-08-16 21:47:04 +12:00
Scott_NZ
32a37d8c0f Stop the hacky AI unpacking the fact into a mcv if it starts with a fact instead of a mcv 2012-08-16 21:47:03 +12:00
Scott_NZ
168ff6dc82 Remove "timer started" conflict 2012-08-16 21:47:03 +12:00
Scott_NZ
03f904155e Reinforcements voice with chopper extraction 2012-08-16 21:47:02 +12:00
Scott_NZ
f479f9a32d Have reinforcements come immediately.. 2012-08-16 21:47:01 +12:00
Scott_NZ
bdbb9d2a9f Add oil facility outside allies2 2012-08-16 21:47:00 +12:00
Scott_NZ
e3ae0ceae3 Add some more map detail 2012-08-16 21:46:59 +12:00
Scott_NZ
34ea82e267 Improved Soviet base layout further 2012-08-16 21:46:58 +12:00
Scott_NZ
fe7e016e33 Improved layout of Soviet base 2012-08-16 21:46:57 +12:00
Scott_NZ
f901355bef Make tran unselectable 2012-08-16 21:46:56 +12:00
Scott_NZ
60fb45c909 Move the sam site around to make a new outpost on the top left, add engineer rescue 2012-08-16 21:46:56 +12:00
Scott_NZ
9ccfb2c322 Make the mission actually winnable 2012-08-16 21:46:55 +12:00
Scott_NZ
0c9f39df78 Clean up allies01/allies02 code by storing world object 2012-08-16 21:46:54 +12:00
Scott_NZ
7fffb71ac4 Clean up timer code, add chinook extraction of Einstein 2012-08-16 21:46:53 +12:00
Scott_NZ
bf0cee9057 Redo outpost: move it into the town and put a miss in the old position. The player can rescue engineers from miss to capture the outpost. 2012-08-16 21:46:52 +12:00
Scott_NZ
55b17f70a8 Adjust to 6 mins 2012-08-16 21:46:51 +12:00
Scott_NZ
c9318cd2dd Chinook timer 2012-08-16 21:46:50 +12:00
Scott_NZ
ffd2588f50 Improved the soviet base 2012-08-16 21:46:49 +12:00
Scott_NZ
c3b9b37122 Bit of cleanup, add position parameter 2012-08-16 21:46:48 +12:00
Scott_NZ
a30d82b333 Convert timer actions to be properties 2012-08-16 21:46:47 +12:00
Scott_NZ
81e2c1d2d7 Implement basic reinforcements for allies2 2012-08-16 21:46:46 +12:00
Scott_NZ
5f2ffc0508 Clean up the timer widget code 2012-08-16 21:46:45 +12:00
Scott_NZ
00297b607b Add drawing widget for reinforcements 2012-08-16 21:46:45 +12:00
Scott_NZ
1c702048a1 Make allies 01 less loud 2012-08-16 21:46:44 +12:00
Scott_NZ
fdd356c2e7 Improve allied base, stop tanya autotargeting 2012-08-16 21:46:43 +12:00
Scott_NZ
1e64a63fa4 Have the starting camera viewport position be determined by the local player 2012-08-16 21:46:42 +12:00
Scott_NZ
05f079758a Begin building basic Allies 02 framework 2012-08-16 21:46:41 +12:00
Scott_NZ
b220bbeda2 Wire up SAM 4 2012-08-16 21:46:40 +12:00
Scott_NZ
0a358a8846 Soviet base: construction yard, sam site, silos 2012-08-16 21:46:39 +12:00
Scott_NZ
ed43c1b482 Modified the bridge to stop crossing with sea units, and opened up the mountain for an alternative route to the Soviet outpost 2012-08-16 21:46:39 +12:00
Scott_NZ
c505954b07 bleh, tabify 2012-08-16 21:46:38 +12:00
Scott_NZ
d5279d123f Start work on Allies 02 script, reveal sam site locations 2012-08-16 21:46:37 +12:00
Scott_NZ
9be501fc3d Improve the objective text in Allies 01 - Einstein/Tanya can't be killed 2012-08-16 21:46:36 +12:00
Scott_NZ
1721d7e025 Add Kennel to allies 02 2012-08-16 21:46:35 +12:00
Scott_NZ
881484d06a Some allies 02 map work - add sub pen and rework the Soviet base a bit 2012-08-16 21:46:34 +12:00
Scott_NZ
537cfb8fd3 Add Kennel to Allies 01 2012-08-16 21:46:33 +12:00
Scott_NZ
41f1ea36fe Add Kennel structure 2012-08-16 21:46:32 +12:00
Scott_NZ
486d340028 Bridges 2012-08-16 21:46:32 +12:00
Scott_NZ
e2bbd22144 Add allies-02 map yaml/bin 2012-08-16 21:46:31 +12:00
Scott_NZ
43d0363a55 Formatting improvements from Husk/Allies01 2012-08-16 21:46:30 +12:00
NukemBro
b253de508b Added new RA map: Chaos Canyon 2012-08-16 09:34:24 +12:00
Chris Forbes
1da82aeba9 slow sniper rof to 70 2012-08-16 09:30:03 +12:00
Chris Forbes
db4d6aaf22 sniper requires dome 2012-08-15 21:55:18 +12:00
Matthias Mailänder
5ea86873c6 fixes #2360, fixes #2227
use notifications.yaml for biolab production queue (crash fix)
remove bio prerequisite for visceroid (won't work after capture)
2012-08-15 08:52:03 +12:00
Chris Forbes
0f126fd630 tidy in defaults.yaml 2012-08-15 08:51:15 +12:00
Chris Forbes
ecc2a7241f fix case on WastedAfterwards 2012-08-15 08:51:14 +12:00
Matthias Mailänder
fbf68db0c0 change some d2k weapon sounds 2012-08-15 08:51:12 +12:00
Matthias Mailänder
9ce8c90d25 added Harissons high-quality temperate terrain expansion
new brigdes, fjords, debris, cliffs
2012-08-15 08:51:01 +12:00
Matthias Mailänder
affa9ca336 revert CaptureActor.Range, PascalCase conventions, compatibilty
the hardcoded Range=3 was crap for smaller/bigger buildings
try not to break TransformOnCapture as it is used for cnc husks
2012-08-15 08:49:49 +12:00
Chris Forbes
3a1c4d1e6f sniper is soviet-only; use initial stance correctly 2012-08-15 08:49:20 +12:00
Matthias Mailänder
45fbecbcd0 sniper can go into pillbox and garrision church 2012-08-15 08:49:16 +12:00
Matthias Mailänder
02f28f54c7 add sniper to ra 2012-08-15 08:49:12 +12:00
Matthias Mailänder
81f035904e remove TODO list, use bug-tracker 2012-08-15 08:48:48 +12:00
Matthias Mailänder
8e2d712688 fix cnc snow theatre crash 2012-08-14 11:01:36 +12:00
Matthias Mailänder
29b63bc3c0 add hospital and biolab sequences 2012-08-14 11:01:34 +12:00
Matthias Mailänder
d98cdd5331 new d2k map: Venac ditch by Combine
http://content.open-ra.org/?p=detail&table=maps&id=635
2012-08-14 11:01:18 +12:00
Matthias Mailänder
94905afa3c better cropped volkov icon, thanks to BaronOfStuff 2012-08-14 10:45:09 +12:00
Matthias Mailänder
a659892227 added emperor palace icon, thanks to D2k Sardaukar and Grand Leo 2012-08-14 10:44:51 +12:00
Chris Forbes
82eddfdf98 #2354 fixed - multiple collection of crates 2012-08-09 10:25:45 +12:00
Chris Forbes
063191b09e fix #2353 - missing dep between d2k and cnc mods broke parallel make 2012-08-08 07:36:49 +12:00
Curtis Shmyr
3fc6f62aea Conflicts:
OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs
2012-07-31 09:20:22 +12:00
Scott_NZ
48f934f188 Set up tran husks, and stop husk placement causing crashes 2012-07-31 09:12:22 +12:00
psydev
192af5d60f Tank shells do 100% vs. armor again. Buff turret. MRLS fixed.
Conflicts:

	mods/cnc/weapons.yaml
2012-07-31 09:10:32 +12:00
psydev
53a7b0987b Fixed structure build menus
Made the building menu more logical. Rows according to tech tree. 

power / refinery / silos       0/10/15
barracks / outpost / starport    20/30/40
light factory / heavy factory / repair bay   50/60/70
high-tech factory / ix tech center / palace    80/90/100

If you want to move silos to the Defense queue, then I would re-arrange it slightly.
2012-07-31 08:24:54 +12:00
psydev
a3897dbc15 Sonic tank moved to end of build menu (100)
Sonic tank moved to bottom of vehicle build menu (set palette order to 100)
2012-07-31 08:23:08 +12:00
Chris Forbes
55651738a7 add heli crash shps 2012-07-30 09:22:36 +12:00
psydev
22bddf9645 Removed the "tip" jutting out of 3 buildings, so they are rectangular instead of awkwardly shaped.
- heavy factory
- high tech factory
- ix research center
2012-07-25 08:58:18 +12:00
psydev
2a37e6233e Added "AutoTargetIgnore:" to ^Building: 2012-07-25 08:57:50 +12:00
Matthias Mailänder
c1722e1270 remove broken sandworm and thumper, fixes #2332 2012-07-25 08:57:05 +12:00
Matthias Mailänder
95c27ef943 deviatortank should require tech building 2012-07-25 08:57:01 +12:00
Matthias Mailänder
3aafde7e18 slower infantry feet animation 2012-07-25 08:56:54 +12:00
Matthias Mailänder
85678de9f0 made silos more flexible for d2k mod 2012-07-24 08:29:18 +12:00
Matthias Mailänder
bda4bfa4f3 d2k: tooltip for $ icon is now starport instead of ship 2012-07-23 09:34:16 +12:00
Matthias Mailänder
481624e3f0 fixed d2k crash: Unit pips does not have a sequence pip-red 2012-07-23 09:34:06 +12:00
ew07002
d1f12ff801 Add some usability features to the TilesetBuilder
- title bar shows tile position (x, y and tile nr (from left top))
 - make 'overlays' button a toggle button and properly sync state with
   tileset surface
 - add export option for 'Template CellID <-> tile number' mapping
 - overlay pen color is now white (todo: make configurable)
2012-07-23 09:33:57 +12:00
Matthias Mailänder
eae482d413 tweak d2k aircrafts a little 2012-07-23 09:33:53 +12:00
Matthias Mailänder
abd774d017 d2k: faster aircrafts, slower trikes, concrete buildings
avoid capturing light buildings by deviator weapon
2012-07-23 09:33:51 +12:00
Matthias Mailänder
f2c630731e added some files from content.open-ra.org, fixes #2182
adds Volkov with some minor changes (no C4, range fixes)
adds soviet forward command center build animation
adds icon for mines (not visible in-game yet)
2012-07-23 09:33:46 +12:00
Matthias Mailänder
3e3977776d fixes #2322 (stuck units when leaving repair pad)
by adding bibs and defining a sane default rallypoint exit cell
2012-07-21 00:01:26 +02:00
Matthias Mailänder
36fbddbb5c fix d2k production queues
ClassicProductionQueue gets support for new notification system
d2k now uses the ClassicProductionQueue system to avoid spamming
Starport has cheaper threshold prices
adds a new production queue but has long delivery times
also no starport price fluctuation to improve balancing
2012-07-20 23:05:28 +02:00
Matthias Mailänder
e33d988301 d2k UI reskinning complete, thanks to @JOoGraphics 2012-07-20 20:00:09 +02:00
Matthias Mailänder
a55167c9ac another d2k loadscreen made by @katzsmile 2012-07-19 23:16:05 +02:00
Matthias Mailänder
d0a4555a1f new admin icon that does fit and some more icons for the future 2012-07-19 21:37:24 +02:00
Matthias Mailänder
4724ac6b00 experimenting with concrete plates
pretty useless at the moment, removed by default
2012-07-19 20:08:59 +02:00
Matthias Mailänder
d998367d35 d2k UI improvements by @JOoGraphics 2012-07-19 17:56:41 +02:00
Matthias Mailänder
0e9e7d0a9d added http://dunefont.co.nr/ to artsrc
maybe used for logos, splashscreens or menus later
2012-07-18 22:08:46 +02:00
Matthias Mailänder
5e1e5903d6 reworked d2k dialog UI, thanks to @JOoGraphics 2012-07-18 19:11:06 +02:00
Matthias Mailänder
25fae5d109 fixed d2k harvester dock animation 2012-07-17 22:03:30 +02:00
Matthias Mailänder
44b8630c71 support reversed remapping for d2k 2012-07-17 17:01:37 +02:00
Matthias Mailänder
6204bfcabf added hospital/bio lab to RA 2012-07-17 14:18:10 +02:00
Matthias Mailänder
1355a9f837 added extra d2k buildings for creeps/neutral
new SHPs, needs update for d2k-packages.zip
2012-07-17 14:02:22 +02:00
Matthias Mailänder
db8f22cdbf d2k harvester unload a little less ugly, RALint fixes
frames were swapped, offset and turnaround still wrong
remember: this changes unload.shp (copy to dl-mirrors)
2012-07-16 22:23:56 +02:00
Matthias Mailänder
860ec9d85f added passenger seat to trike/raider 2012-07-16 21:11:27 +02:00
Matthias Mailänder
5f2f25b758 added d2k superweapons, fixed c4/nuke cursor 2012-07-16 21:02:55 +02:00
Matthias Mailänder
3728685c67 fixed UPnP more crashes
proper timeout: does not crash/lag if no UPnP devices are found
close all ports, sockets, responses after they have been used
so it does not crash when port forwarding for the 2nd time
put all exceptions logs into OpenRA sourcecode
2012-07-15 22:31:02 +02:00
Matthias Mailänder
5e6b8deec1 remove ugly test map again 2012-07-15 18:39:48 +02:00
Matthias Mailänder
21f2b0df43 fixed a crash when siege tanks are built 2012-07-15 18:39:17 +02:00
Chris Forbes
2100484598 fix name of the-duell map for d2k; space breaks rpm build 2012-07-15 12:40:58 +12:00
James Dunne
ba1a36f26e Units heading in generally opposite directions are now considered blockers; this fixes pathing deadlocks. 2012-07-05 23:53:31 -05:00
James Dunne
9c9a16d80e Path planning no longer considers moving friendly units as blockers. 2012-07-05 23:52:34 -05:00
Chris Forbes
3d8e215598 Merge pull request #2296 from ScottNZ/bleed
Allies 01 fixes
2012-07-05 20:06:44 -07:00
James Dunne
ce806fdbe6 Prevent too many instances of a single sound starting at once in an absolute location and attenuate volume of new sounds based on number active sounds already playing. 2012-07-06 14:41:24 +12:00
Matthias Mailänder
208a3a47fe don't crash when sound rules are not loaded
e.g. when trying to get the gamefiles
2012-07-06 14:37:24 +12:00
Matthias Mailänder
f0708ecfb2 cut out the black tile 2012-07-06 14:37:17 +12:00
Matthias Mailänder
653d72086c A10 crash site to terrain
it is not transparent and will look wrong in desert/winter
2012-07-06 14:37:14 +12:00
Matthias Mailänder
9258ba3ec7 new spice shp with 20 densities
hopefully nicer looking spices tiles
and less insane growth rate
avoided edge tiles because of #2247
2012-07-06 14:36:56 +12:00
Matthias Mailänder
d851c5646e a10cr dimensions fixed 2012-07-06 14:36:52 +12:00
Matthias Mailänder
ac0d3779f1 added @Nyerguds awesome cnc A10 crash site
ripped from a Westwood beta screenshot
2012-07-06 14:36:49 +12:00
Matthias Mailänder
9a0d62dc85 removed pyle again (no changes) 2012-07-06 14:36:44 +12:00
James Dunne
59e1703b41 Added mouse-wheel support for flipping tabs in build palette. 2012-07-06 14:32:26 +12:00
James Dunne
e49a439c79 You win chrisf =P 2012-07-03 19:05:46 -05:00
James Dunne
b2e9085371 More detailed exception reporting on crash. 2012-07-03 15:37:37 -05:00
Matthias Mailänder
8cea309ec6 more SHP fixes by Nyerguds
- The SSM Launcher (mlrs.shp) was updated because the very last
  turret frame without missiles had messed up house colours
- buildings that showed remap color instead of real yellow:
* Civilian Oil Derrick (Made correct remap for v19.shp)
* Advanced Communications Center (shadow under the big dish
  turned to remap, in both eye.shp and eyemake.shp)
* Tiberium Silo (random remap pixels in the collapse frame
  of silo.shp, and the entire lower right edge on silomake.shp)
* Barracks (remap pixels showing up in the
  normally gray buildup on pylemake.shp)
2012-07-03 09:21:54 +12:00
Matthias Mailänder
a59dfa555c map clear radar color for interior to black 2012-07-03 09:21:54 +12:00
Matthias Mailänder
e22126ca02 added ice floes to ra 2012-07-03 09:21:54 +12:00
Matthias Mailänder
867f112dfe base cnc snow on temperat to remove snowy greenland tiles 2012-07-03 09:21:54 +12:00
Matthias Mailänder
24e6e23000 fixed building dimensions as d2k now has bibs 2012-07-03 09:21:54 +12:00
Matthias Mailänder
498adc86a9 add bibs for d2k
copy & paste with gimp and OpenRA.Utility
2012-07-03 09:21:54 +12:00
Matthias Mailänder
a20d1c95c8 noticable SHP fixes from C&C 1.06c rev3
including a snow theatre now fixed with few backfalls to winter
hand of nod with logo (like in the beta)
fence fixes (one frame did not fit to the rest)
factory retains the shadow of the make animation
nicer ion cannon icon from a westwood render
2012-07-03 09:21:54 +12:00
ScottNZ
4a101cf1b1 Convert line endings 2012-07-02 16:19:57 +12:00
ScottNZ
583b11a2b2 Remove bad/duplicate UnloadCargo line 2012-07-02 14:03:26 +12:00
ScottNZ
b3c5137add Merge 2012-07-02 13:46:28 +12:00
Chris Forbes
3dc39b2c9d fixed #2167 -- silly inconsistency between InfDeath and dieN sequence numbering 2012-07-02 09:42:20 +12:00
ScottNZ
5897a44fc5 Remove unneeded barrel YAML overrides 2012-07-02 04:22:23 +12:00
ScottNZ
8b0f15f80b Bring Soviet patrol back a bit 2012-07-02 04:21:10 +12:00
ScottNZ
1262cf0f29 Bit of cleanup 2012-07-02 03:54:55 +12:00
ScottNZ
b74e63f42d Drain Soviet resources so the ore truck doesn't stay at the refinery 2012-07-01 20:30:25 +12:00
Matthias Mailänder
e89ee2c131 new AttackLoyalty, range and stay alive option for Capture
AttackLoyalty for d2k Deviator which captures units
also shooting a fake missile (see issue #2251)

CaptureActor now supports Generals styles gameplay
but is disabled by default (see issue #2274)
fixes the annoyance that engineers will not take
the shortest root to the building by the way

removing ProvidesCustomPrerequisite because it's
tooltip messages relies on hardcoded hacks
2012-07-01 20:26:25 +12:00
Chris Forbes
c2321e3eea fixed #2284 - crash in upnp when device found but it doesnt want to talk upnp 2012-07-01 20:14:14 +12:00
Matthias Mailänder
22a49ba7c6 added HarvesterAttackNotifier.cs to .csproj
Conflicts:
	mods/d2k/rules/system.yaml
2012-07-01 20:00:57 +12:00
Chris Forbes
4d614e9122 include d2k mod in official packages 2012-07-01 20:00:12 +12:00
Chris Forbes
e0069fd62a make UnloadCargo.unloadAll configurable; go back to all by default 2012-07-01 19:45:31 +12:00
Matthias Mailänder
c75c72b525 made palette shadowindex configurable 2012-07-01 19:37:57 +12:00
Chris Forbes
007b2c5434 make click-without-drag feel better in editor 2012-07-01 18:37:46 +12:00
Chris Forbes
b8a932a084 try to make selection feel better 2012-07-01 18:31:46 +12:00
Curtis Shmyr
61c3932340 Selection tool / copy paste for editor 2012-07-01 18:23:46 +12:00
Chris Forbes
c2029e9d5c fixed #2166 - filtering of passengers to show with RenderCargo 2012-07-01 18:22:19 +12:00
Chris Forbes
d0548d6766 Drop EvaAlerts from OpenRA.Game.csproj 2012-07-01 18:10:17 +12:00
Chris Forbes
5a40c5df03 tidy health transfer 2012-07-01 18:08:10 +12:00
Matthias Mailänder
f5ba36a735 Unload only 1 cargo per mouseclick, for more control 2012-07-01 18:07:33 +12:00
Matthias Mailänder
efe2f2e043 UnloadCargo rallypoint fixes #2016 2012-07-01 18:07:05 +12:00
Matthias Mailänder
6681382819 unclock factory exits 2012-07-01 14:53:45 +12:00
Matthias Mailänder
7a578a0679 notifications (formerly EVAalerts) centralized and race specific
outsourced into notifications.yaml
triggered with PlayNotification(...)

(v2: less redundant code for PlayVoice/Notifications)

added harvester under attack and battlecontrol terminated
2012-07-01 14:39:30 +12:00
Chris Forbes
5fee165692 fixed #2289 - missing chrono effects on return 2012-07-01 14:24:49 +12:00
Chris Forbes
0a4669b925 Add SimpleTeleport for non-chrono jumps (used in scripts etc) 2012-07-01 14:05:21 +12:00
Chris Forbes
109546d20f fixed #2286 - chrono kills passengers on return too 2012-07-01 13:31:04 +12:00
James Dunne
f5c606266d Fixed shift-tab keyboard shortcut in build palette. 2012-07-01 13:08:00 +12:00
ScottNZ
facf958bae Move towards extraction LZ if einstein isn't in the world. 2012-07-01 13:02:23 +12:00
Matthias Mailänder
480db8be42 non-capturable hospital with heal-zone
will heal engineer, capturing it is useless;
heal-zone makes less sense, but it looks nicer
(otherwise infantry drawn on top of the building)
2012-07-01 13:02:23 +12:00
James Dunne
7c4e32bd94 Applied ToDictionaryWithConflictLog to MixFile reader. 2012-07-01 13:01:54 +12:00
James Dunne
854a9c4eb7 Added new ToDictionaryWithConflictLog to help diagnose ToDictionary bombs. 2012-07-01 13:01:24 +12:00
ScottNZ
cbb0b17c31 Add AutoTargetIgnore for stek 2012-07-01 12:52:36 +12:00
Chris Forbes
f2ab8a8541 generalize rough cursor to be customizable for any terrain type 2012-07-01 12:49:14 +12:00
Matthias Mailänder
63d21eac8c arrakis tileset categorized for editor
thanks to CombineCnR
2012-07-01 12:41:29 +12:00
Matthias Mailänder
579ff04f68 fixes #2253
rough mouse-cursor for infantry-only areas
blue move cursor for d2k rally points
2012-07-01 12:41:23 +12:00
ScottNZ
18d75feb15 Adjust the patrol starting position 2012-07-01 12:14:12 +12:00
James Dunne
11da96fe22 Fix for #2277: Failing to load sounds/music should never crash. 2012-07-01 09:11:27 +12:00
Chris Forbes
9201b1cced fixed #2198 - crates are collected when landing on top of a unit 2012-07-01 09:04:49 +12:00
ScottNZ
e02397da3e Use Sound.PlayMusic for Hell March 2012-07-01 03:47:08 +12:00
ScottNZ
6014f648f4 Add e1, dog, e1 soviet patrol 2012-07-01 03:29:05 +12:00
ScottNZ
2c55a008f1 Reduced cruiser range from 32 to 25 to reduce risk of friendly fire. Increased barrel hitpoints. Removed jeep cargo ability as a workaround for Einstein being removed from the game world and Soviet forces not attacking. 2012-06-30 23:33:09 +12:00
ScottNZ
b9be918b6c Remove some code noise and improved the chinook cargo check 2012-06-30 23:27:14 +12:00
ScottNZ
781cbc00d3 Make Einstein run out of the building when he appears. 2012-06-30 20:27:39 +12:00
Chris Forbes
b9365a149f remove old crates list 2012-06-30 17:06:15 +12:00
James Dunne
1d4f1c657f Fix for crash after selling all refineries. 2012-06-30 16:37:50 +12:00
James Dunne
9a66d7b530 Harvesters will return to ordered-to location if told to harvest a specific cell while full after delivery instead of the last successfully harvested cell which may be far away. 2012-06-30 16:37:50 +12:00
Chris Forbes
3a87b934a6 fixed #2257 - reenable PrimaryBuilding support for afld/hpad 2012-06-30 16:10:13 +12:00
Chris Forbes
9845d0e035 fixed #2260 - spec chat should use contrast 2012-06-30 16:05:33 +12:00
James Dunne
3754e791e5 Fix for null ref exception after refinery is sold. 2012-06-29 22:55:45 -05:00
James Dunne
643154de15 Harvesters obey player when told to stop or move somewhere else. 2012-06-29 22:38:24 -05:00
ScottNZ
af8b29aee5 Map polishing: removed mpspawn. Removed unneeded YAML. 3tnk now starts facing north. Changed soldier next to barrels from e1 to e2. Adjusted the player colour to a lighter blue. Adjusted the chinook despawn location. e2 now always explode when they die to make the barrel chain reaction reliable. Reduced HP of barrels also. 2012-06-29 09:09:39 +12:00
ScottNZ
36c0ec753d Move viewport to where the player starts 2012-06-29 09:09:39 +12:00
Matthias Mailänder
9115fc4397 fixes #2157
Tooltip descriptions now showup in CnC.
2012-06-29 09:06:15 +12:00
Matthias Mailänder
0d59a4dcd7 fixes #2005
Don't save floats in settings.yaml using country-specific
decimal separators which can be misunderstood as
group seperators which will put values out-of-range.
2012-06-29 09:00:28 +12:00
Chris Forbes
e0c3c53c00 fix up music error 2012-06-29 09:00:28 +12:00
Generalcamo
11654cc893 More Strings Corrected.
Some tracks are missing, however I don't know the file name of those.
2012-06-29 08:45:45 +12:00
Generalcamo
bb85ea75e4 More Strings Corrected. I notice a few Counterstrike tracks are missing, they might be in the aftermath file though. Will check. 2012-06-29 08:45:44 +12:00
Generalcamo
2450576dbe Once Again, corrected strings. Also added a track 2012-06-29 08:45:44 +12:00
Generalcamo
dd81b6d872 Corrected Music Strings, added a voiced track
The music strings have been taken from Frank Klepacki's Website and the CD. In some cases, I have added parenthesis to show the names that many people give them
2012-06-29 08:45:44 +12:00
James Dunne
3160034d66 Now checking AcceptsSmudgeType for all cells to smudge and picking appropriate SmudgeLayer to render with. 2012-06-27 23:54:49 -05:00
James Dunne
d0d3813173 Water will not be smudged/scorched any more from nukes. All resources in range of nuke are destroyed now, not just the ones on the edge of the circle. 2012-06-27 22:56:48 -05:00
James Dunne
2ff4a76955 Fixed zombie aircraft flying around after being told to fall to earth. 2012-06-27 22:02:29 -05:00
Matthias Mailänder
9626ed356c fixed crash when mod not found, don't save broken settings
default mod is Red Alert
2012-06-28 13:10:41 +12:00
Matthias Mailänder
5ecf8d3b7f added real allyrepair, fixed flagfly shadow 2012-06-28 13:10:41 +12:00
Matthias Mailänder
8041b17032 fixed turret facing order, added rocket turret 2012-06-28 13:10:41 +12:00
Matthias Mailänder
b9cda8fcca relative altitude for carryall cargo 2012-06-28 13:10:41 +12:00
Matthias Mailänder
ed6a625c69 nonstandard build time value for a cnc classic mod fixes #2164
remove the testcase in structures.yaml if unwanted for cnc mod
2012-06-28 13:10:41 +12:00
Matthias Mailänder
d498ff1085 +RenderBuildingSeparateTurret 2012-06-28 13:10:40 +12:00
James Dunne
f8a0dd59b7 Fixed null reference bug. 2012-06-27 18:38:12 -05:00
James Dunne
8e602104af Harvesters - made search radius configurable for both initial search from proc and search from harvest location. 2012-06-27 18:00:42 -05:00
James Dunne
aac78773f4 Upgraded to VS2010 2012-06-26 20:39:56 -05:00
Matthias Mailänder
d3915ad291 string AcceptsSmudgeType replaces boolean AcceptSmudge
because Dune 2000 has different craters for rock and sand
2012-06-27 13:19:52 +12:00
Matthias Mailänder
b61e4a6083 don't mount unneeded RA game files
voices and tilesets already completely replaced
2012-06-27 13:19:52 +12:00
Matthias Mailänder
5318380bfa auto-restart the game after getting the game-files 2012-06-27 13:19:52 +12:00
Matthias Mailänder
a64629f1c5 remove ready/hold/group pip from BuildPaletteWidget
and render as text instead
2012-06-27 13:19:52 +12:00
Matthias Mailänder
5231da1ea3 READY/ON HOLD as DrawText instead of SHP 2012-06-27 13:13:55 +12:00
Chris Forbes
aa06751de5 categorize the rest of the temperat tileset 2012-06-26 20:12:01 +12:00
Chris Forbes
f10eb9e082 add category headers in editor 2012-06-26 19:58:04 +12:00
Chris Forbes
9966b4efd1 group tiles by category 2012-06-26 19:33:11 +12:00
Chris Forbes
0ec3e8b227 add Category to tileset entries 2012-06-26 19:33:02 +12:00
Chris Forbes
984a498ed2 Finish fixing #2136 2012-06-26 19:24:59 +12:00
Igor Popov
c122e6f54d indicate-admin: implementation (ra) 2012-06-26 18:58:31 +12:00
Chris Forbes
1924cc71f1 fix canceling of WaitFor 2012-06-26 11:48:15 +12:00
Chris Forbes
220473bf74 remove duplication in UOG 2012-06-26 11:31:13 +12:00
James Dunne
4373f577d8 Added ResourceClaimLayer trait to World for cnc and d2k. 2012-06-24 21:41:16 -05:00
James Dunne
2f773e49ef Fixed null ref exception while playing cnc. 2012-06-24 21:41:16 -05:00
James Dunne
03ec1f08cf Made ResourceClaimLayer trait optional on World actor to fix cnc and d2k. 2012-06-24 21:41:16 -05:00
James Dunne
a0f9f98b1c Removed unnecessary mobile local. 2012-06-24 21:00:25 -05:00
James Dunne
b59a0e8c0d Fixed harvesters for AI to search the entire map when no more resources nearby. 2012-06-24 20:26:01 -05:00
James Dunne
1fa70d259f Removed INudge in favor of INotifyBlockingMove. 2012-06-24 20:26:01 -05:00
James Dunne
1f0da42a15 Refineries now show which harvesters are linked by holding down ALT key. 2012-06-24 20:26:01 -05:00
James Dunne
845379e577 Harvesters no longer block each other during low-ore contention and wait for a random amount of time while idle to search for more resources. 2012-06-24 20:26:00 -05:00
James Dunne
80123b6aa4 Many harvester behavior improvements; summary below.
Implemented Harvester territory marking with a simple resource claim system in ResourceClaimLayer trait added to World.
Added customCost for PathSearch to support new Harvester search preferences.
Explicit delivery order forces harvester to always deliver to that refinery.
Explicit harvest order frees harvester from forced delivery refinery and allows for auto-balancing.
Harvesters auto-balance refinery choice such that no more than 3 harvesters are linked to any one refinery at a time.
Harvesters try very hard to not block the refinery dock location.
Harvesters try to avoid enemy territory when searching for resources.
Group-select harvest order intelligently disperses harvesters around the order location.
Fixed PathFinder caching to not be a sliding window. This is a correctness issue. Sliding window causes no-route paths to be cached permanently in tight move loops and doesn't allow eventual progress to be made. This may have negative performance implications.
2012-06-24 20:26:00 -05:00
Matthias Mailänder
1aafc9f726 fix utilty remap, remapped flag/poweroff to d2k.pal 2012-06-25 10:21:39 +12:00
Chris Forbes
8607575e2b Merge remote-tracking branch 'matt/patch-2' 2012-06-25 09:52:24 +12:00
Chris Forbes
162c386bdd Merge remote-tracking branch 'matt/bleed' 2012-06-25 09:40:22 +12:00
Chris Forbes
445e5ec84b fix #2215 - add shadow.shp based on RA but with proper size for d2k 2012-06-25 09:27:39 +12:00
Matthias Mailänder
54c35e3721 fixed some selection boxes 2012-06-25 09:07:44 +12:00
Chris Forbes
a2b92d0fe4 Merge commit 'matt/dune^'
Conflicts:
	.gitignore
	mods/d2k/rules/system.yaml
2012-06-25 09:05:49 +12:00
Chris Forbes
2ed12f1d95 Merge remote-tracking branch 'scott/bleed'
Conflicts:
	OpenRA.Mods.RA/Missions/Allies01Script.cs
2012-06-25 08:45:16 +12:00
James Dunne
fe5bcdeab9 Fix for PaletteFormat break in Editor. 2012-06-24 13:58:49 -05:00
ScottNZ
9c6bc45f8f Fix whitespace 2012-06-25 05:34:06 +12:00
ScottNZ
2cc749118f Make it more overwhelming at the fifth wave and each wave after that 2012-06-25 05:19:25 +12:00
ScottNZ
331388bfe8 Merge pull request #1 from Mailaender/patch-5
Added Prof. Einstein sequences and rules
2012-06-24 09:31:38 -07:00
Matthias Mailänder
079a52ee65 added Einstein 2012-06-24 19:27:05 +03:00
Matthias Mailänder
5b470650b7 added Einstein 2012-06-24 19:26:03 +03:00
Matthias Mailänder
380875ad3e added Einstein 2012-06-24 19:24:26 +03:00
Matthias Mailänder
79976a4bfe transpose infantry/ornithocopter 2012-06-24 15:48:11 +02:00
Matthias Mailänder
769b5d7dc6 fixed OpenRA.Utility --remap
now uses the mod parameter again
2012-06-24 12:32:52 +02:00
Matthias Mailänder
2a95c5f668 fix PlayerColorPalette in Editor 2012-06-24 11:56:52 +02:00
Chris Forbes
1bf649d27d Merge remote-tracking branch 'matt/bleed' 2012-06-24 21:34:37 +12:00
ScottNZ
bda92f3898 Only send the heavy tank on the last wave, this is the first mission after all 2012-06-24 21:28:46 +12:00
Matthias Mailänder
7220025a62 make orni flap slower 2012-06-24 11:21:50 +02:00
Matthias Mailänder
0b6eda0815 replaced RA sounds by Dune 2000 ones 2012-06-23 16:00:20 +02:00
Matthias Mailänder
e70e778775 make ornithocopter flap (broken)
needs frame resorting similiar to the infantry
2012-06-23 14:20:34 +02:00
ScottNZ
7fb659bd3a Make the mission a bit harder - add a heavy tank to each wave 2012-06-23 20:41:43 +12:00
Matthias Mailänder
b109436cc3 race specific BaseAttackNotifier 2012-06-22 18:21:29 +02:00
ScottNZ
6ba0c448c8 Remove killing of player when they fail the mission, this is more fun and it's also really loud when all the units die at once 2012-06-22 15:27:07 +12:00
ScottNZ
ed5ff9cd31 Bleep when objective shown 2012-06-22 13:39:36 +12:00
ScottNZ
1146790dc1 Reworked the left side of the map to make it useful, and moved one of the spawnpoints there. 2012-06-22 13:07:24 +12:00
James Dunne
cf1d4d0efb Fixed radar click position - was not respecting zoom setting for emulating the mouse coordinate. 2012-06-21 19:41:23 -05:00
James Dunne
b127ae8027 Added sub-pixel position/vector types.
Updated Sync code to handle new sub-pixel types.
2012-06-21 19:41:12 -05:00
James Dunne
9c49143534 New types for cell and pixel coordinate position/vectors. 2012-06-21 15:36:59 -05:00
Matthias Mailänder
6bc3249685 voices now support prefixes
required for d2k
2012-06-21 15:31:12 +02:00
ScottNZ
3ab197f400 Buff the Allies a bit - give them some riflemen. 2012-06-21 23:34:34 +12:00
ScottNZ
9ff69b7946 Add EVA voices
Use new WaitFor when waiting for Einstein
Have a small delay before the Soviets counterattack
Have the Soviets Attack-Move towards Einstein during the counterattack, this makes them much more damaging
Spawn the signal flare only after Einstein has been spawned, also add EVA voice for this
2012-06-21 22:53:20 +12:00
Chris Forbes
0b98a8ce5e Merge remote-tracking branch 'scott/bleed' 2012-06-21 11:54:54 +12:00
James Dunne
2e26047b23 Added myself to AUTHORS. 2012-06-20 18:20:26 -05:00
Chris Forbes
2cdd1f7376 fix #2126 - crash on spawning a corpse for an actor which has already been destroyed 2012-06-21 09:50:02 +12:00
Matthias Mailänder
033dd10192 git ignore some KDE crap 2012-06-20 23:46:53 +02:00
Matthias Mailänder
9f5a8512d2 race specific ProductionQueue audio 2012-06-20 23:40:08 +02:00
Chris Forbes
5c4e49cc3f fix #2196 - crash when cycling stances while a unit dies 2012-06-21 09:33:47 +12:00
James Dunne
8eb4782a49 Fixed socket code constantly throwing exceptions about non-blocking. 2012-06-21 09:29:02 +12:00
Chris Forbes
99eb3b046d fix #2239 - add WaitFor(predicate) 2012-06-21 09:26:05 +12:00
Matthias Mailänder
ac0389d04f race specific notifications/mcv-crate 2012-06-20 21:35:23 +02:00
Matthias Mailänder
6929ed024a added harvester unload, thumper which spawns sandworms
worm won't attack, dogjaw is stupid and moving mine did not work
2012-06-20 16:57:09 +02:00
Matthias Mailänder
f4cb798c8b small code optimisations as suggested 2012-06-20 09:51:00 +02:00
ScottNZ
8f6b8b75bc Remove redundant call to InternalName when mission failed 2012-06-20 18:17:13 +12:00
ScottNZ
cb3daab5fa Tabify lines 2012-06-20 17:48:03 +12:00
James Dunne
4d16ca238c Fixed broken Install from CD code in RA. 2012-06-20 09:47:19 +12:00
Matthias Mailänder
84d623397b made PaletteFormat configurable
as suggested in issue #2219
2012-06-19 21:36:10 +02:00
Matthias Mailänder
26b75f406f new settings Transparent for cursors.yaml 2012-06-19 07:43:06 +02:00
ScottNZ
b30e4ab432 Use SharedRandom to stop desync 2012-06-19 14:43:11 +12:00
ScottNZ
b0e10c9ada Don't need lzRange 2012-06-19 12:57:45 +12:00
Matthias Mailänder
c6a1031ab7 fix cnc palette issues
cursor not supporting transparency which is only needed for d2k
2012-06-18 17:44:03 +02:00
Matthias Mailänder
7cbed30dc6 fix cnc palette issues
cursor not supporting transparency; wrong icon, fx palette
2012-06-18 17:40:22 +02:00
Matthias Mailänder
ce0099f5d2 fix settings for d2k and cnc
no UPnP for CnC singleplayer skirmishes, use RA chromes at D2k
2012-06-18 17:07:56 +02:00
Matthias Mailänder
45a5e317c0 Merge remote-tracking branch 'openra/bleed' into bleed 2012-06-18 16:38:17 +02:00
ScottNZ
11ddd88d60 Remove more unneeded code, use CallFunc activity to make Tanya laugh when she disembarks. 2012-06-19 01:45:46 +12:00
ScottNZ
ce05b8dfec Use IsInMap & IsInWorld to detect whether Einstein has been saved 2012-06-19 01:27:42 +12:00
ScottNZ
f5d397030c Remove unneeded UnitsNearExtractionLZ code 2012-06-19 01:19:09 +12:00
ScottNZ
874799c2c3 Made Soviet attack waves a bit saner 2012-06-19 01:04:18 +12:00
ScottNZ
20af089fcd Added Allies 01 SP map and Allies01Script.cs 2012-06-18 22:13:24 +12:00
unknown
21ab0b461c Added straightforward hover behavior for all units. Give a unit a nonzero Altitude: in its Mobile: block and the WithShadow: trait to make it hover. 2012-06-18 20:53:38 +12:00
Chris Forbes
7af0e64708 allow --transpose to do multiple operations in one pass 2012-06-18 20:38:37 +12:00
Matthias Mailänder
527c6dc36b "repair" infantry at hospital 2012-06-18 03:30:53 +03:00
Matthias Mailänder
8831a93375 make the hospital become a repairunit (for infantry) 2012-06-18 03:29:17 +03:00
Matthias Mailänder
677efcbced add notifications 2012-06-18 02:18:01 +02:00
Chris Forbes
4f1a7ff5fb add --transpose option to utility 2012-06-18 11:22:24 +12:00
Matthias Mailänder
c9edf7d0dc added Renderer Dropdown in RA Settings 2012-06-18 09:30:52 +12:00
Chris Forbes
d64ecac74e Merge pull request #2223 from Mailaender/dune
Latest updates from the Dune 2000 mod
2012-06-16 22:30:00 -07:00
Matthias Mailänder
c804be6f01 fix passable edges in Cliff terrain tiles
made all special units equally expensive, found harvester unload
2012-06-16 21:19:46 +02:00
Matthias Mailänder
959875c709 added special infantry, fixed UI, added new map 2012-06-16 14:17:35 +02:00
Igor Popov
4d94cb5593 2 maps: Bomber John(minigame->new); Free Coasts(conquest->replace) 2012-06-16 14:46:32 +12:00
Matthias Mailänder
c1fb5dd5f5 added engineer, bazooka 2012-06-15 22:43:03 +02:00
Matthias Mailänder
db0e1eabc7 replace RA conyard with D2k carryall for colorpicker 2012-06-15 17:03:40 +02:00
Matthias Mailänder
801ff5cc17 make cursor always transparent, fix Arrakis tileset
transparency bugs some cnc cursors, slice BLOXBASE better
2012-06-15 11:06:59 +02:00
Chris Forbes
94f7f1c473 clean up game timeout 2012-06-15 15:14:56 +12:00
Chris Forbes
9862b8ccee remove sequence save junk 2012-06-15 15:06:52 +12:00
Matthias Mailänder
722c7a5f7d +resampled sounds, readded and completed Arrakis tileset
all tilesets combined into one without redundancy
2012-06-14 21:09:44 +02:00
Matthias Mailänder
72d038e04e fixes mouse cursor not being transparent 2012-06-11 23:28:42 +02:00
Matthias Mailänder
b83188d435 add the first Sounds
manually resampled to 16 bit 22050 Hz and converted to AUD
2012-06-11 21:19:40 +02:00
Matthias Mailänder
f9cbd1bbbf experimenting with auto-downloader, sandworm 2012-06-10 21:13:40 +02:00
Curtis Shmyr
4e88166673 Added two new RA maps by Tirili: Ice Woods & Nishnekolymsk 2012-06-10 12:56:24 -06:00
Chris Forbes
f3d68f4944 remove some junk ai profiles 2012-06-10 19:52:25 +12:00
Chris Forbes
3827a5436a #2191 fixed -- custom OGs canceled on win/lose 2012-06-10 17:17:38 +12:00
Igor Popov
4a7417347a fix #2199; Game Timer (min 10 seconds) 2012-06-10 17:08:49 +12:00
Matthias Mailänder
dc6b286d25 remove unneccessary dependencies, make SendTo less spammy 2012-06-10 16:46:19 +12:00
Matthias Mailänder
aa36a56b27 UPnP source code fixes
as suggested by Chris Forbes
2012-06-10 16:46:19 +12:00
Chris Forbes
a831e72fa2 Merge remote-tracking branch 'tuc/simplepause' 2012-06-10 16:35:41 +12:00
Matthias Mailänder
b96158adcb new AI with optimized build order
Eisenhower builds less refineries, more units and techs faster
2012-06-10 16:34:31 +12:00
Chris Forbes
5414875d00 update .gitignore; remove spurious mono file 2012-06-10 16:32:02 +12:00
Chris Forbes
fd4b10c6bd Merge remote-tracking branch 'matt/dune' 2012-06-10 16:27:19 +12:00
Matthias Mailänder
d110b45679 added install rules for d2k mod, fixes carryall landing 2012-06-09 22:46:13 +02:00
Matthias Mailänder
22e0828566 fixing BLOXBASE problems
t264 not found and BASE.tsx gets deleted too early
2012-06-09 20:57:22 +02:00
Matthias Mailänder
c3052d863a tsbuilder is required for mod_d2k
adding it to core
2012-06-09 20:39:06 +02:00
Matthias Mailänder
0b4455515d added utility reference to Makefile for d2k mod 2012-06-09 20:33:50 +02:00
Matthias Mailänder
4ed74c6cc0 adding in-game GUI gamefile extractor/converter
also fixing EOL for TilesetBuilder with monoDevelop
2012-06-09 19:53:59 +02:00
Matthias Mailänder
ebf64f67cf updated BLOXBAT terrain 2012-06-09 11:43:39 +02:00
Matthias Mailänder
b16849768d adding chrome/settings.yaml
was in gitignore
2012-06-08 21:07:20 +02:00
Matthias Mailänder
f140c6ec9c added TilesetBuilder command line, added Tileset extractor
removing all copyrighted raw tileset files
2012-06-08 19:31:10 +02:00
Matthias Mailänder
8f1d06ff31 added TilesetBuilder2 and fixed it for Dune 2000
does not support TerrainTypes other than "clear" yet
2012-06-07 19:22:45 +02:00
Igor Popov
3f0fafb380 Add banlist (Server.Ban settings item) support to game servers 2012-06-07 12:14:26 +12:00
Remco van der Zon
84124de79d Game can now be paused by pressing f3 as well. 2012-06-06 11:22:46 +02:00
Remco van der Zon
8ad4e08651 Unit order client != null check fixed (int != null -> always true!) .
Removed if-else branch in favour of sugar construct a?b:c.

Note: One should (at least) consider to move var client = ... to the
start of the switch construct. 4 branches of this switch are using this.
(DRY)
2012-06-06 10:54:21 +02:00
Remco van der Zon
8f981977e0 TimeWidget does not collide anymore with koth layout.
Screen resolution should be 1024x786+
2012-06-06 10:47:13 +02:00
Matthias Mailänder
676210422f added spice bloom
indestructable, seeds ressources like mine or blossom tree
2012-06-05 19:50:44 +02:00
Matthias Mailänder
749301899e added smudge
palette problems and engine does not care for terrain type
2012-06-05 18:14:17 +02:00
Chris Forbes
1bb1e00a0d fix #2195 - barrels should not be capturable or sellable 2012-06-05 19:41:30 +12:00
Matthias Mailänder
83ee6b758e fix CD rip logic a little
will still fail on setup.z
2012-06-02 21:17:42 +02:00
Matthias Mailänder
accaf027fe added (broken) content installer, moved instruction to GUI
still depends on the hacky bash script and CD extractor crashes
2012-06-02 17:46:31 +02:00
Matthias Mailänder
9b1e798b35 added spice as a ressource
still needs work though
2012-06-02 15:36:31 +02:00
Matthias Mailänder
cffaabb3bf added d2k mouse pointer, fixed aircrafts 2012-06-02 11:41:18 +02:00
Matthias Mailänder
5ab5bc9f7c removed need to define Harvester/BaseBuildingUnit manually 2012-05-28 23:36:46 +02:00
Matthias Mailänder
d9c4aada8a updated the README
so people can try this on their own
2012-05-28 20:29:15 +02:00
Matthias Mailänder
27fa99852b add D2k crates, started fixing infantry
infantry directions are correct, but movement is still wrong
2012-05-28 20:14:56 +02:00
Matthias Mailänder
ec7795fa99 added more Dune 2000 EVA voices
currently Atreides only
2012-05-28 14:00:43 +02:00
Matthias Mailänder
8e74df6155 fixing RALint.exe d2k and ordos missing defense buildings 2012-05-28 10:37:10 +02:00
Matthias Mailänder
4984d07960 made HackyAI more flexible for Dune 2000 mod 2012-05-28 10:36:17 +02:00
Matthias Mailänder
2a312911cb fixes repair pad
and update TODO
2012-05-27 18:28:52 +02:00
Matthias Mailänder
a20e30312e added Ordos 2012-05-27 15:17:03 +02:00
Matthias Mailänder
e0e1011d30 added Harkonnen 2012-05-27 12:45:35 +02:00
Matthias Mailänder
1fcf044980 added flags, worked on the UI
looks crappy, needs someone who is good at this
2012-05-27 10:40:08 +02:00
Matthias Mailänder
2287f1f662 inherit units that differ only slightly for each faction 2012-05-26 20:20:01 +02:00
Matthias Mailänder
ffbc76919e make Dune 2000 an independent mod
Arrakis tileset now loads properly
2012-05-26 18:13:51 +02:00
Matthias Mailänder
083952a531 added Dune 2000 music, voices 2012-05-26 13:06:02 +02:00
Curtis Shmyr
bd29d382c7 fix #2080 - added option to toggle shellmap in CNC 2012-05-26 18:40:55 +12:00
Curtis Shmyr
8df09da816 Spy - add voice when sending infiltrate order 2012-05-26 18:40:55 +12:00
Curtis Shmyr
4778ef803e Spy - don't reset exploration if team has GPS 2012-05-26 18:40:55 +12:00
Curtis Shmyr
37f91542a9 Change cargo ownership when capturing actors with cargo 2012-05-26 18:40:55 +12:00
Curtis Shmyr
e1907364e6 Fix #2086 - don't let player capture if that same player (or friendly ally) is already capturing 2012-05-26 18:40:55 +12:00
Matthias Mailänder
7f48a242db fixed refinery, factories
a little hacky though
2012-05-25 22:27:26 +02:00
Matthias Mailänder
4362a215d9 fixed wall, silo; add ornithocopter, sonic tank, infantry
orni does not flap, no sonic wave weapon, infantry frames broken
2012-05-25 17:46:58 +02:00
Matthias Mailänder
72b2e03dd0 added tech buildings, repair pad, startport, tanks 2012-05-24 16:26:38 +02:00
Matthias Mailänder
f7c1eb2933 +heavy factory, radar outpost, brick wall 2012-05-23 20:04:45 +02:00
psydev
5dd46b1b16 Give Mammoth 8-sec. cooldown for heal, like in RA. 2012-05-23 09:35:34 +12:00
Matthias Mailänder
68a731ed5e fixing MCV facings and flickering bug 2012-05-22 23:19:05 +02:00
Matthias Mailänder
4c667be946 fixed vehicles driving backwards
also fixed the bazooka for quad
2012-05-22 22:17:48 +02:00
Matthias Mailänder
66f82c6c2a added harvester, trike/quad now working, fixed mod inheritances
RenderCargo: works, moved R8Reader to Utility namespace
2012-05-22 21:02:25 +02:00
Chris Forbes
ff32864b47 #2160 fixed - RenderCargo support for relative altitude 2012-05-22 19:42:51 +12:00
Chris Forbes
e9656795a2 RenderCargo depends on IMove on the containing actor 2012-05-22 19:24:53 +12:00
Chris Forbes
3fbb81b4fc remove more spurious trait lookups in RenderCargo 2012-05-22 19:19:49 +12:00
Chris Forbes
442138e1f8 clean up spurious trait lookup in RenderCargo 2012-05-22 19:18:28 +12:00
Chris Forbes
2d39b1dfac #2089 fixed - Explodes filtering on InfDeath 2012-05-22 19:14:25 +12:00
Chris Forbes
3b704e25fa #2159 fixed -- missiles lose guidance and run out their remaining fuel if the target dies 2012-05-22 19:01:49 +12:00
Chris Forbes
c068be453a #2119 fixed - better error message for multiple definitions of the same yaml field 2012-05-22 18:17:03 +12:00
Chris Forbes
6f8f940f31 #2130 fixed -- #comments can be used at the end of any lines 2012-05-22 18:05:04 +12:00
Chris Forbes
c000640928 remove dead function from LobbyLogic 2012-05-22 17:42:19 +12:00
earthpig
059347af40 bots (once again) build pillboxes. 2012-05-22 17:20:23 +12:00
earthpig
f0001856bc To go along with introducing the 'cloaked hbox', ensure that the cloak is disabled if at low power. 2012-05-22 17:18:54 +12:00
earthpig
8c218b67ab Bring back hbox, with both the new garrison stuff and with stealth until firing. 2012-05-22 17:18:26 +12:00
Matthias Mailänder
5426a5fd3c put d2k mod stuff into it's own branch 2012-05-20 15:50:39 +02:00
psydev
d1241c438a Helicopters targetable when landed 2012-05-18 10:45:39 +12:00
Chris Forbes
bc7aa9a491 make Health.MaxHP not readonly; some people want to frob it at runtime 2012-05-17 10:04:06 +12:00
Remco van der Zon
ae94d7ecc7 Chat-text displayed when the game is paused and unpaused.
: The game is (un-)paused by <PLAYERNAME>
2012-05-16 19:11:46 +02:00
Remco van der Zon
7e1986ecbc Timer shows text "(paused)" when game is in pause. 2012-05-16 19:04:43 +02:00
Remco van der Zon
a07697be03 Pause the game option.
Game is paused when PAUSE on the keyboard has been hit. It can also be unpaused this way.
2012-05-16 17:35:10 +02:00
Remco van der Zon
b99e664726 A Game-tick can execute viewport.Tick itself,
removed this dependency from World.
2012-05-10 19:54:57 +02:00
psydev
881b4ba277 cnc - changed various unit speeds; gave increased sight to MCV and MSAM. 2012-05-07 07:42:48 +12:00
psydev
3058bfbc17 cnc - updated several building hitpoints 2012-05-07 07:42:48 +12:00
Remco van der Zon
8a08365666 Fixed bug in cash ticks, normal settings.
No sound was heared when repairing buildings or on low power.
Fixed.
2012-05-07 07:42:48 +12:00
Remco van der Zon
6c96a106e7 Red Alert CashTicks
Three options for cash ticks:
Extreme: current behavoir (every cash countdown tick is heard)
Normal: RedAlert countdown style (only one cash countdown tick every ~1 or 2 seconds)
Disabled: No cash tickdown or tickup is heard.

Thanks to Tirili for hints on the settings system.
2012-05-06 20:03:09 +12:00
psydev
6291c8396b cnc - add new explosion: chemball 2012-05-06 19:59:53 +12:00
psydev
79afa07118 cnc - made helicopter selection bounds a bit smaller 2012-05-06 19:58:13 +12:00
Chris Forbes
0e43043a33 cnc: fix crash loading yaml for ArtilleryShell.ContrailLength 2012-05-06 11:27:03 +12:00
psydev
c06fc02915 Changed production menu hotkeys from YUIOP to QWERT (what they are in C&C3). It's more ergonomic and close to the other command keys like A, S, Z, F. It is hard to use the YUIOP keys, because they're too far, even though they are very efficient.
The QWERT setup is a good way to run a menu. I think should reserve them for that and use other keys for unit commands.
2012-05-04 17:11:09 +12:00
psydev
8badbb3d60 Re-ordering the build menu a bit. Seems like guard tower should go before gun turret since it's more basic, cheaper and more often used. 2012-05-04 16:54:45 +12:00
psydev
57283b4a80 Increase range, cost and a modified damage on the MRLS (up vs. light armor, down vs. wood; 2 more bursts). Inaccuracy doubled from 30 to 60. Also increased MinRange from 2 to 4, and added burst delay while increasing rate of fire slightly (burst delay will add 24 to the rate of fire value, making it 70). Justification for these changes is to help fight against recon bike spam and stealth tank spam.
Increase APC gun damage from 6 to 12 (is currently pathetic against helis)

misc:
Made Artillery shell explosion appear bigger
Added contrail to Artillery shell
2012-05-04 16:54:36 +12:00
earthpig
d9992eea6a cnc - Increase rocket launcher cost from 800 to 1200 to reflect changes in range. 2012-05-04 16:51:52 +12:00
earthpig
c8c4507acf Few things with Zhukov AI. 2012-05-01 14:51:21 -07:00
psydev
5a37c84a8b improve chem warrior, flamethrower, grenadier and napalm drop 2012-05-02 09:10:53 +12:00
Chris Forbes
63898820f1 ra: drop mjolnir-1 map 2012-05-02 09:08:28 +12:00
psydev
63359e156c Increasing speed of flamethrowers and grenadiers 2012-05-02 09:01:26 +12:00
psydev
d683d69f3c Increase A-10 speed from 25 to 40 2012-05-02 09:01:05 +12:00
Chris Forbes
609d5bd611 ra: fix Flame Turret -> Flame Tower in unit name 2012-05-02 08:32:43 +12:00
psydev
0b894d3b31 Make silo first item in support/defense queue. 2012-05-02 08:30:38 +12:00
psydev
3a838a05cd Remove bib from HPAD 2012-05-02 08:29:06 +12:00
psydev
0a0b136b80 See ground beneath A-10 airstrike's flightpath 2012-05-02 08:27:26 +12:00
psydev
82549c6407 Increase Chinook capacity to 10 2012-05-02 08:26:27 +12:00
Chris Forbes
d737930bb0 #2076 fixed - missing widget id for WICW 2012-05-01 19:59:48 +12:00
Curtis Shmyr
dad67713fb Fix recent break in SupportPowerManager 2012-04-30 16:35:56 -06:00
psydev
a1082152a4 Urgent! Include in this release (fixes non-targeting of defensive towers/turrets). I made units no longer target ordinary buildings, but forgot to re-include targeting of the structures that shoot at you. 2012-05-01 07:26:06 +12:00
psydev
9f729b0c45 Made Chem Warriors walk through tiberium instead of around it and reduced their penalty for running through it to what would normally be "rough" terrain (80% instead of 70%).
Gave Commando Red Pip while passenger in APC/helicopter (can we get a more distinct color for engineer? Bright yellow or orange that contrasts from regular green, and/or pale blue).
Increased Commando shroud reveal to 6, since that will equal what 5 ought to be (infantry and vehicles have differences in sight range even when they have the same value, it seems http://i.imgur.com/Z6nWG.jpg)
2012-04-30 22:15:21 +12:00
psydev
ee7d8659d5 Removed bib from repair bay, to make it like the one from Red Alert.
Increased sight range of Construction Yard to 10.
2012-04-30 22:14:23 +12:00
psydev
4448c3e51b cnc: various balance changes, part 2
Infantry sight range +1 -- it seems that they have lower sight range than vehicles for some reason. See http://i.imgur.com/Z6nWG.jpg for infantry and vehicle, both with RevealsShroud: 5, but vehicle sees further. So, effectively 5 for infantry becomes 4, which seems reasonable.
Reduced probability of SpawnViceroid from 10% to 2%. 2% will still happen often enough if Chem Warriors are used predominantly, but with 10%, units were constantly turning to Viceroids, which was a pain. You could also send 10 infantry to opponent's tib field in early game and spawn a viceroid and kill their harvester or harass them.
Turned off units auto-targeting regular buildings, because often will attack silo over an obelisk or enemy unit. Auto-target should remain on for defensive towers/turrets, though.
2012-04-30 22:07:48 +12:00
psydev
174e925e5a cnc: various balance changes
As usual I'm trying to be conservative and only apply what I feel is suitable / minimally necessary.
Weapons:
Biggest change: Increased artillery range from 6 to 12, added contrail to bullet and changed impact sound to default C&C. Minimum range 2 given.
Napalm is currently very ineffective; increased spread to 20 range to make more likely to kill targets, ROF slightly increased
MRLS rocket ranged increased from 8 to 12, with minimum range 2.
Guard tower range increased from 4 to 5 (Pillbox is 6, for comparison) and damage increased from 20 to 40.
Grenadier death explosion reduced in damage from 25-10 and in blast radius.
2012-04-30 22:07:32 +12:00
earthpig
e7a8cdf951 Normal AI: Gone.
Zhukov AI: Bit of a turtle, but sends large attacks with arty/v2.
Rommel AI: Modified Hard AI.
2012-04-30 21:51:46 +12:00
Curtis Shmyr
45f5c054d5 Fix #2070; cannot sell when building is being captured 2012-04-30 21:37:09 +12:00
psydev
15dcd6a9f6 Harvester armor heavy 2012-04-30 21:35:35 +12:00
Chris Forbes
9c86196b16 fix crash in ChooseBuildTabOnSelect in replay 2012-04-30 21:32:57 +12:00
Curtis Shmyr
9185dc65d5 Initial pbox pax changes 2012-04-30 21:18:10 +12:00
Chris Forbes
e0bfa287ee new flamer integrated 2012-04-30 21:13:15 +12:00
Chris Forbes
80f142c8ea flamer that doesnt suck 2012-04-30 20:51:10 +12:00
Chris Forbes
7050fbc6e1 add napalm1 SHP and wiring in ra/sequences 2012-04-30 20:38:42 +12:00
Chris Forbes
2c938bc305 add sniper SHP 2012-04-30 20:33:36 +12:00
Chris Forbes
cd6bfb1b9a add better flame projectile SHP 2012-04-30 20:33:21 +12:00
Chris Forbes
11b253e4c3 add gate SHPs 2012-04-30 20:33:03 +12:00
earthpig
d625e2624a Fixed #2010 - arty in line now only has only 75% chance of exploding
When an arty in a group of them dies, each individual arty only has a 75% chance of perpetuating the genocide of arty.... so usually, it'll stop before killing your whole line but not before seriously hurting it.
2012-04-29 19:20:46 +12:00
earthpig
a544bc966b #2048 fixed: make AI behavior more varied 2012-04-29 19:15:55 +12:00
psydev
9a3aae6586 cnc: change AI to not be totally useless 2012-04-29 10:56:47 +12:00
psydev
390e607e66 cnc: remove nuke crate 2012-04-29 10:55:46 +12:00
psydev
22b18f99db cnc: remove hide-map crate 2012-04-29 10:54:51 +12:00
Chris Forbes
c30d46c014 #2051 fixed -- Widget.Get() throws by default 2012-04-27 19:39:07 +12:00
Chris Forbes
5d1a071287 fix crash in colorpicker 2012-04-26 21:42:07 +12:00
Chris Forbes
16e00c1f12 shimmering cloak in cnc 2012-04-25 22:24:38 +12:00
Chris Forbes
87271a0a56 make cloak palette configurable 2012-04-25 21:45:38 +12:00
Chris Forbes
dadc496c19 beef up OpenRA.FileFormats.Set a little; use it in CncMenuPaletteEffect rather than making new List<string> every frame 2012-04-25 21:43:00 +12:00
Chris Forbes
a0940e7ae5 unify water palette rotation 2012-04-25 21:32:33 +12:00
Chris Forbes
ca1fbb187b misc whitespace tidyups 2012-04-25 21:31:27 +12:00
Chris Forbes
89025a3042 make attackmove on spawn work properly for things that cant attackmove 2012-04-25 21:11:31 +12:00
earthpig
49f3f740e3 New units now AttackMove to their designated rally point. 2012-04-25 20:52:51 +12:00
Chris Forbes
4b4bbdf626 fix recent breakage in support powers 2012-04-25 01:58:37 +12:00
Chris Forbes
cebf908bb2 Fixed #2041 -- Force attack always targeted ground
Revert "Force attacks always go through, regardless of what is beneath them."

This reverts commit b2c72d6990.
2012-04-25 00:22:07 +12:00
Chris Forbes
75c105cb85 fix right edge of cheats close button 2012-04-25 00:06:48 +12:00
Chris Forbes
6669a66292 #2028 fixed - observer and dead map in cnc works again 2012-04-24 20:29:46 +12:00
Chris Forbes
6e3aa46008 #2039 fixed - add Sound.Engine config item, default is "AL" for OpenAL sound engine; "Null" gives you no sound 2012-04-24 20:23:41 +12:00
Chris Forbes
84a50e8e86 unify cheats panels 2012-04-24 20:04:21 +12:00
Chris Forbes
6559d8d8bc fix cnc direct connect panel 2012-04-24 19:47:04 +12:00
Chris Forbes
926686beff fix cnc cheats panel 2012-04-24 19:44:06 +12:00
Chris Forbes
6ab171af8b #2027 fixed - allow custom starting units for each faction 2012-04-24 19:29:53 +12:00
Chris Forbes
c4916bd997 #2038 fixed - add shadow to crates on the ground 2012-04-24 19:17:41 +12:00
Chris Forbes
f86332fd99 change pillbox hotkey to p 2012-04-20 14:41:45 +12:00
Chris Forbes
8d843cd8ad dropped map No Fly Zone 2012-04-19 11:04:51 +12:00
Chris Forbes
0904ac3a70 remove spurious trait lookup 2012-04-13 13:32:59 +12:00
Chris Forbes
8488223eee fix misspelling of Received 2012-04-13 13:28:31 +12:00
Chris Forbes
da3ba159db make failure of a lintpass nonfatal 2012-04-13 12:47:42 +12:00
Chris Forbes
3e0f52db1a fix cnc chrome yaml issues 2012-04-09 13:10:40 +12:00
Chris Forbes
062c49dac3 fix bogus widget id setup for resolution picker 2012-04-09 13:10:40 +12:00
Chris Forbes
533f9044cc strip redundant Id: elements from chrome yaml 2012-04-09 13:10:40 +12:00
Chris Forbes
b9eb3a0ad0 Patch widget loader to convert @key into Id member of widgets 2012-04-09 13:10:40 +12:00
Chris Forbes
dbd09ea843 Add building infiltrated sound to owner of spy on infiltrate 2012-04-09 10:33:39 +12:00
Chris Forbes
a4e1915aff warn the lobby when a client joins with DEV_VERSION 2012-04-09 09:40:22 +12:00
Chris Forbes
9d2833fc2b fix spelling error in comment 2012-04-09 09:39:57 +12:00
Chris Forbes
ab4c21f80c fix crash in server in StartGame if there are unvalidated connections 2012-04-09 09:18:54 +12:00
Chris Forbes
f7fea5ffce fix spelling error in Crate* comments 2012-04-07 11:06:26 +12:00
Chris Forbes
87e9a69ae0 fixed #2001: passengers shooting while in transports 2012-04-07 11:05:59 +12:00
Chris Forbes
25fb2a7be3 tidy 2012-04-07 10:29:25 +12:00
Chris Forbes
10c1b996ed tidy up disabled handling 2012-04-06 19:34:43 +12:00
Nukem
aa21ddaa4d Added new RA map: Tainted Peak 2012-04-06 18:36:50 +12:00
Chris Forbes
eab0e7ddf9 add range circle for gap generator 2012-04-06 18:35:04 +12:00
Curtis Shmyr
891cba456b give Gap Generator to allies 2012-04-06 18:23:30 +12:00
Chris Forbes
beb6b01796 show cashticks for DonateSupplies in spec 2012-04-06 18:14:58 +12:00
Chris Forbes
a52af4843e add cashtick for InfiltrateForCash 2012-04-06 18:14:11 +12:00
Chris Forbes
8dec48fee3 add spy reward for infiltrating refinery 2012-04-06 18:07:39 +12:00
Chris Forbes
b081103866 add infiltrate for exploration(reset) ability 2012-04-06 17:47:17 +12:00
Chris Forbes
4a76e2ad33 slight tidy in InfiltrateForSupportPower 2012-04-06 17:36:39 +12:00
Chris Forbes
b39eeddb45 adjust priority of Spy actions to prefer disguise/infiltrate when they match 2012-04-06 16:37:12 +12:00
Chris Forbes
7d4186c236 add SilencedPPK weapon for spy 2012-04-06 16:27:04 +12:00
Chris Forbes
01a724d632 only allow SpyInfiltrate/Disguise orders on Spy when not doing ForceAttack 2012-04-06 16:13:33 +12:00
Chris Forbes
ca1549df2a allow forceattack to be allowed/banned on UnitOrderTargeter 2012-04-06 16:05:35 +12:00
hasufell
0ae8e41612 add music themes which are available on cd-content 2012-04-06 14:47:04 +12:00
Curtis Shmyr
bc8c433a72 Modified Capturable to have a capture time; fixes #2002 2012-04-06 14:47:04 +12:00
Chris Forbes
7187b14459 drop Daejeon map 2012-04-03 16:21:19 +12:00
Chris Forbes
07d25d97ab fix missing escape keybinds in ra 2012-04-03 09:54:40 +12:00
Chris Forbes
4d5f89909e tanya is only available to allies 2012-04-03 09:54:29 +12:00
Chris Forbes
60fa61840d Spy drops disguise on attacking 2012-04-02 13:28:58 +12:00
Curtis Shmyr
499234e5dd Fixed #1321; no main menu after lobby disconnect/failed retry 2012-04-02 10:13:17 +12:00
hasufell
1010276cd5 make paths modifiable, fix broken install-rules, fix INSTALL 2012-04-02 09:21:51 +12:00
Curtis Shmyr
fdef80c53a Modify Cargo trait to support initial passengers 2012-03-23 15:16:48 +13:00
Kenny Hoxworth
22d3709967 Allow the targeting of water tiles by default. This still doesn't allow targeting of underwater, which is they way it should be. Now ground based units will be allowed to force-attack water tiles. 2012-03-23 10:07:11 +13:00
Kenny Hoxworth
b2c72d6990 Force attacks always go through, regardless of what is beneath them. 2012-03-23 10:06:59 +13:00
Chris Forbes
6f688275c5 include source location when complaining about bad miniyaml indents 2012-03-16 18:43:41 +13:00
Chris Forbes
5b8334b26d drop ILogicWithInit, no longer used 2012-03-16 18:43:41 +13:00
Chris Forbes
23ea8493ba fix crash in cnc replay viewing with radar 2012-03-16 18:43:40 +13:00
Chris Forbes
cc9dbd43c3 fix permissions on apc turrets 2012-03-13 09:11:35 +13:00
Chris Forbes
8308f82926 use the correct user for deployment 2012-03-04 13:08:50 +13:00
Chris Forbes
11f322a758 Fix smoke being triggered by healing as well as damage 2012-03-04 12:54:35 +13:00
Chris Forbes
6376615781 make 4tnk use damage cooldown for heal 2012-03-04 12:44:44 +13:00
Chris Forbes
f4b302e01a add support for damage cooldown on SelfHealing 2012-03-04 12:39:46 +13:00
Chris Forbes
703d6648d7 fix C2 ProximityCaptor sillyness 2012-03-04 12:31:02 +13:00
Curtis Shmyr
f19807f0ca Changed TTNK cost to 1500, hit points to 150 2012-03-03 16:18:11 -07:00
Curtis Shmyr
a523510922 Changed E4 (flamethrower) build prerequisite to FTUR 2012-03-03 16:12:13 -07:00
Chris Forbes
47194fab71 Add defend stance support for turreted units 2012-03-04 11:42:21 +13:00
Chris Forbes
75e32c0573 don't fetch IFacing unless we actually need it, in Attack 2012-03-04 11:17:46 +13:00
Chris Forbes
38b5a8d4f8 Fix #1327 - div/0 in Drag with extreme movement speeds 2012-03-03 18:17:21 +13:00
wuschel
522c88dcda Added map by wuschel: Ares National Park 2012-03-03 18:07:47 +13:00
Curtis Shmyr
3375a5de51 Oil derricks are not required to be destroyed when eliminating a player 2012-03-03 18:07:29 +13:00
Chris Forbes
68933880b9 Fix #1349 - Add configurable threshold for RepairableNear, default is 4 cells. 2012-03-03 18:05:31 +13:00
Chris Forbes
469a393585 give RepairableNear access to its info 2012-03-03 18:01:50 +13:00
Chris Forbes
be1fdbdd56 Fix #1348 -- Tesla Coils now support Stop (S) order 2012-03-03 17:44:41 +13:00
Curtis Shmyr
2972728b5e Ctrl-Shift-numkey performs unit grouping into existing groups 2012-02-19 08:47:43 +13:00
Sam Hegarty
78ba76250d Remove dependency on mesa-dri-drivers-experimental for the rpm package
- this package is no longer available in recent releases of Fedora
      and shouldn't be REQUIRED anymore.
2012-02-17 19:58:18 +13:00
Curtis Shmyr
603014b163 Added 3 maps by wuschel: Poseidon, Ares and Apollo 2012-02-13 09:11:54 +13:00
Nukem
6b85518b74 Added new map by Nukem: Breaking Point 2012-02-13 09:11:54 +13:00
Blarget2
d3578273db Added new map by Blarget2: Temperal 2012-02-13 09:11:54 +13:00
Curtis Shmyr
54f3c76da8 Removed random sbag in Mjolnir-2 2012-02-13 09:11:54 +13:00
Curtis Shmyr
95b908b234 Fixed bug where bots weren't given proper client index 2012-02-13 09:11:54 +13:00
Curtis Shmyr
3b94728869 Reduced amount of mines MNLY.AT carries from 5 to 3 2012-02-13 09:11:32 +13:00
Curtis Shmyr
b8b9d34404 Aircraft can use friendly service depots/airfields/helipads 2012-02-13 09:11:32 +13:00
Chris Forbes
a5cfc20e0b dont reinvent base64 decoding 2012-02-13 09:10:01 +13:00
Chris Forbes
3cf09e656f Add support for negative prerequisites (#1323) 2012-02-13 09:10:01 +13:00
Chris Forbes
1f8859f26b remove useless TUtil type alias from IronCurtainPower 2012-02-13 09:10:01 +13:00
Chris Forbes
6555bc9dbc use curl instead of wget 2012-02-13 09:10:01 +13:00
Chris Forbes
49fb0228fa fix upload script to use scp rather than ftp; ftp no longer available on the webserver 2012-02-13 09:10:00 +13:00
Nikita Tsukanov
ad29926391 Removed Connection.PlayerIndex == 0 checks if favor of Session.Player.IsAdmin 2012-01-09 15:37:55 +04:00
Chris Forbes
85293a482e remove spurious allowMovement parameter from ScanAndAttack 2012-01-07 20:33:56 +13:00
Chris Forbes
6315864f84 add Defend unit stance 2012-01-07 20:33:56 +13:00
Chris Forbes
c169bc3c51 fix #1320 bogus use of Game.CosmeticRandom from server thread 2012-01-07 20:33:56 +13:00
Chris Forbes
1de3db0903 Don't take a NRE in GiveUnitCrateAction.GetSuitableCells if not Mobile 2012-01-07 20:33:56 +13:00
Chris Forbes
965fe88755 #1284 fixed; don't show spawnpoints on serverbrowser thumbnails 2011-12-31 11:32:59 +13:00
Chris Forbes
809b716d0d tidy silly Enum.GetValues type nonsense 2011-12-31 11:02:38 +13:00
Chris Forbes
004c59d273 sort the serverlist by whether we can join the game 2011-12-31 10:58:31 +13:00
Chris Forbes
c34b254fd8 stop repairing a building if we don't like its owner (fixes interaction with capture) 2011-12-31 10:50:18 +13:00
Chris Forbes
0d25b6b5c9 use spacebar to go to last attack event 2011-12-31 10:48:30 +13:00
Chris Forbes
85eeb8b819 tidy 2011-12-28 08:16:51 +13:00
Chris Forbes
e84d90fc3a more general tidying 2011-12-28 08:13:36 +13:00
Chris Forbes
418b8d40f9 improve TraitDictionary error messages 2011-12-28 08:02:09 +13:00
Chris Forbes
9581595a3d remove spurious null checks in Shroud -- all actors have an owner, always. 2011-12-27 21:53:31 +13:00
Chris Forbes
0aa7ba6bd4 remove sillyness in DelayedAction.CompareTo 2011-12-27 21:48:42 +13:00
Chris Forbes
2793d1076a clean up inconsistency in InvisibleToEnemy 2011-12-27 21:23:25 +13:00
Chris Forbes
d57dfd1997 tidy 2011-12-27 21:23:25 +13:00
Chris Forbes
f8122047b6 ShpLoader is no longer IEnumerable 2011-12-27 18:10:52 +13:00
Chris Forbes
d115c6305c general tidying in ShpReader 2011-12-27 18:02:32 +13:00
Chris Forbes
f63cdf37d7 tidy usings in Graphics.Util 2011-12-27 14:53:18 +13:00
Chris Forbes
dd88a1269a move MakeArray to FileFormats.Exts 2011-12-27 14:52:11 +13:00
Chris Forbes
523183431b remove some duplication and dead code 2011-12-27 14:48:10 +13:00
Chris Forbes
132c678594 add --remap cmdlet to OpenRA Utility, remaps between ra/cnc/etc palettes. 2011-12-27 11:48:22 +13:00
Chris Forbes
f8127ab9df don't start writing replays until gamestart 2011-12-24 21:07:53 +13:00
Chris Forbes
d61055af8f work toward deferrable start of replay saving 2011-12-24 20:39:33 +13:00
Chris Forbes
4e6ff7616c tidy in FileSystem 2011-12-24 19:41:45 +13:00
Chris Forbes
f2dd5eb0a3 simplify UOG 2011-12-24 12:19:59 +13:00
Chris Forbes
f7e35899cf tidy ReplayConnection 2011-12-24 10:11:31 +13:00
Chris Forbes
727b897994 split ReplayRecorderConnection out into its own file 2011-12-24 10:05:14 +13:00
Chris Forbes
8029973e33 cull RA maps Paramount and Pandemonium, not played enough 2011-12-23 18:30:26 +13:00
Chris Forbes
bd4345c2d0 tidy in UnitOrders 2011-12-23 16:57:24 +13:00
Chris Forbes
4bcd19f57c remove bogus SurrenderOnDisconnect feature 2011-12-23 16:46:40 +13:00
Chris Forbes
bc38e99495 add base attack notification support to cnc 2011-12-23 16:43:10 +13:00
Chris Forbes
c1e6e3f9b9 don't announce self-damage 2011-12-23 16:41:29 +13:00
Chris Forbes
480c35ab58 add base attack notification 2011-12-23 16:31:29 +13:00
Chris Forbes
fdafb9d411 fix broken capitalization of variantExt 2011-12-19 14:40:05 +13:00
Chris Forbes
23a9e0503d don't crash on missing voice phrases 2011-12-19 14:39:00 +13:00
alzeih
aa9dd73fe5 Fix #1236 - Aircraft with full health landing on FIX costs the player money
Note: still allows a plane on full health to land on FIX.
2011-12-14 00:01:58 +13:00
alzeih
1b0724719d Make LineRenderer understand Zoom internally 2011-12-13 23:58:39 +13:00
alzeih
c8ae6127f3 Fix #1128 - Use Line Width support in LaserZap 2011-12-13 23:58:34 +13:00
Chris Forbes
40029c6688 use string.F() extension method everywhere possible; fix various small issues in error messages 2011-12-13 23:57:23 +13:00
Chris Forbes
af3d00836a remove spurious Clone() from TooltipContainerWidget; all it did was make the error message *worse* 2011-12-13 23:48:32 +13:00
Chris Forbes
bf5be88c75 rename Ui.RootWidget to just Ui.Root 2011-12-13 23:46:58 +13:00
Chris Forbes
58f6816d84 convert silly DoXXX names to just XXX 2011-12-13 23:44:40 +13:00
Chris Forbes
ed429a3b30 split Widget static bits into Ui static class 2011-12-13 23:38:59 +13:00
Chris Forbes
83055f0a17 convert RootWidget prop back to field, now that it has trivial get/set 2011-12-13 22:30:51 +13:00
Chris Forbes
dd55c0ad93 remove spurious parens on return 2011-12-13 22:27:10 +13:00
alzeih
1bea7e3286 Fix #1297 - CNC server browser status text placement is wrong 2011-12-13 22:09:59 +13:00
alzeih
b508f7c300 Fix #1269 - Transport Helicopter Loading while in the Air
Note that weight is now checked for cargo (this might break things)
2011-12-13 12:38:39 +13:00
Chris Forbes
7e590b05c1 fix broken 'burn' sequence for snow t11 2011-12-13 12:28:15 +13:00
Chris Forbes
6c027372ab fix naming of event handlers in editor 2011-12-10 09:08:31 +13:00
Chris Forbes
6bac11f071 fix formatting in editor.Form1 2011-12-10 09:08:31 +13:00
Chris Forbes
87a420623b tidy FileSystem.Exists 2011-12-10 09:08:31 +13:00
Chris Forbes
1e4f1a9f19 remove duplication in FileSystem.Open[WithExts] 2011-12-10 09:08:31 +13:00
Chris Forbes
410cad6f1e use priority correctly in FileSystem.OpenWithExts 2011-12-09 22:16:20 +13:00
Chris Forbes
69a869a44d fix empty array init style in Manifest 2011-12-09 22:08:25 +13:00
Chris Forbes
de88cb33f3 fix indent in Manifest 2011-12-09 22:07:15 +13:00
Chris Forbes
5ea756506b update comment in map save 2011-12-09 22:03:53 +13:00
Chris Forbes
fb1b7ac706 remove useless comments around actor loading 2011-12-09 22:02:07 +13:00
Chris Forbes
3003e49277 remove spurious extra FieldLoader.Load() call in Map.cs 2011-12-09 21:58:57 +13:00
Chris Forbes
a7c3052243 remove some silly duplication in Map.cs 2011-12-09 21:54:04 +13:00
751 changed files with 29752 additions and 10542 deletions

16
.gitignore vendored
View File

@@ -10,6 +10,9 @@ obj
*.manifest
mods/*/*.dll
# ReSharper crap
_ReSharper.*/
# Red Alert binary files
mods/*/packages/*.[mM][iI][xX]
@@ -22,6 +25,8 @@ mods/*/packages/*.[mM][iI][xX]
# backup files by various editors
*~
*.orig
\#*
.*.sw?
# dependency DLLs (different for every platform!)
cg.dll
cgGL.dll
@@ -32,8 +37,6 @@ cgGL.dll
*.pidb
*.userprefs
packaging/windows/*.exe
# osx crap
.DS_Store
@@ -52,9 +55,6 @@ OpenRA.Launcher.Mac/OpenRA.xcodeproj/*.mode1v3
*.config
*.resources
# other crap
Logs/
Replays/
settings.yaml
\#*
.*.sw?
# KDE crap
*.kate-swp
*.directory

View File

@@ -12,16 +12,19 @@ The OpenRA developers are:
Also thanks to:
* Akseli Virtanen (RAGEQUIT)
* Andrew Riedi
* Barnaby Smith (mvi)
* Bellator
* Christer Ulfsparre (Holloweye)
* Erasmus Schroder (rasco)
* Igor Popov (ihptru)
* James Dunne (jsd)
* Jeff Harris (jeff_1amstudios)
* Joakim Lindberg (booom3)
* Kenny Hoxworth (hoxworth)
* Lawrence Wang
* Mark Olson (markolson)
* Matthew Gatland (mgatland)
* Matthias Mailänder (Mailaender)
* Max Ugrumov (katzsmile)
* Max621
* Nukem

20
INSTALL
View File

@@ -41,23 +41,19 @@ UBUNTU (substitute comparable packages for other linux distros):
OpenRA does not work with some older versions of Compiz. On affected systems, disable desktop effects before playing. This is fixed in Ubuntu Natty and later.
You will additionally need to copy the third party dependencies (.dll and .config) from the
thirdparty and thirdparty/Tao directories into the game root:
cp -v thirdparty/*.dll thirdparty/Tao/* .
Alternatively, the dlls can be installed into your system GAC. This is not
The following dlls can also be installed into your system GAC. This is not
recommended because we ship a custom Tao.FreeType that can conflict with
other applications that use Tao:
gacutil -i thirdparty/Tao/Tao.Cg.dll
gacutil -i thirdparty/Tao/Tao.OpenGl.dll
gacutil -i thirdparty/Tao/Tao.OpenAl.dll
gacutil -i thirdparty/Tao/Tao.Sdl.dll
gacutil -i thirdparty/Tao/Tao.FreeType.dll
gacutil -i thirdparty/ICSharpCode.SharpZipLib.dll
gacutil -i Tao.Cg.dll
gacutil -i Tao.OpenGl.dll
gacutil -i Tao.OpenAl.dll
gacutil -i Tao.Sdl.dll
gacutil -i Tao.FreeType.dll
gacutil -i ICSharpCode.SharpZipLib.dll
To compile OpenRA, run `make' from the command line.
To install run 'make install'.
Run the game with `mono OpenRA.Game.exe Game.Mods=ra` for Red Alert
or `mono OpenRA.Game.exe Game.Mods=cnc` for Command & Conquer

View File

@@ -5,10 +5,10 @@ COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll third
PHONY = core tools package all mods clean distclean
.SUFFIXES:
core: game renderers mod_ra mod_cnc utility
core: game renderers mods utility tsbuild
tools: editor ralint tsbuild
package: core editor
mods: mod_ra mod_cnc
mods: mod_ra mod_cnc mod_d2k
all: core tools
clean:
@-rm -f *.exe *.dll *.mdb mods/**/*.dll mods/**/*.mdb *.resources
@@ -97,6 +97,16 @@ mod_cnc_EXTRA_CMDS = mono --debug RALint.exe cnc
PROGRAMS += mod_cnc
mod_cnc: $(mod_cnc_TARGET)
# Dune 2000
mod_d2k_SRCS := $(shell find OpenRA.Mods.D2k/ -iname '*.cs')
mod_d2k_TARGET = mods/d2k/OpenRA.Mods.D2k.dll
mod_d2k_KIND = library
mod_d2k_DEPS = $(STD_MOD_DEPS) $(mod_ra_TARGET) $(mod_cnc_TARGET) $(utility_TARGET)
mod_d2k_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(mod_ra_TARGET) $(utility_TARGET)
mod_d2k_EXTRA_CMDS = mono --debug RALint.exe d2k
PROGRAMS += mod_d2k
mod_d2k: $(mod_d2k_TARGET)
#
# Tools
#
@@ -127,15 +137,19 @@ ralint: $(ralint_TARGET)
# Builds and exports tilesets from a bitmap
tsbuild_SRCS := $(shell find OpenRA.TilesetBuilder/ -iname '*.cs')
tsbuild_TARGET = TilesetBuilder.exe
tsbuild_TARGET = OpenRA.TilesetBuilder.exe
tsbuild_KIND = winexe
tsbuild_DEPS = $(fileformats_TARGET) $(game_TARGET)
tsbuild_LIBS = $(COMMON_LIBS) $(tsbuild_DEPS) System.Windows.Forms.dll
tsbuild_EXTRA = -resource:OpenRA.TilesetBuilder.Form1.resources
tsbuild_EXTRA = -resource:OpenRA.TilesetBuilder.frmBuilder.resources -resource:OpenRA.TilesetBuilder.frmNew.resources -resource:OpenRA.TilesetBuilder.Surface.resources
PROGRAMS += tsbuild
OpenRA.TilesetBuilder.Form1.resources:
resgen2 OpenRA.TilesetBuilder/Form1.resx OpenRA.TilesetBuilder.Form1.resources 1> /dev/null
tsbuild: OpenRA.TilesetBuilder.Form1.resources $(tsbuild_TARGET)
OpenRA.TilesetBuilder.frmBuilder.resources:
resgen2 OpenRA.TilesetBuilder/frmBuilder.resx OpenRA.TilesetBuilder.frmBuilder.resources 1> /dev/null
OpenRA.TilesetBuilder.frmNew.resources:
resgen2 OpenRA.TilesetBuilder/frmNew.resx OpenRA.TilesetBuilder.frmNew.resources 1> /dev/null
OpenRA.TilesetBuilder.Surface.resources:
resgen2 OpenRA.TilesetBuilder/Surface.resx OpenRA.TilesetBuilder.Surface.resources 1> /dev/null
tsbuild: OpenRA.TilesetBuilder.frmBuilder.resources OpenRA.TilesetBuilder.frmNew.resources OpenRA.TilesetBuilder.Surface.resources $(tsbuild_TARGET)
#
# Launchers / Utilities
@@ -180,15 +194,15 @@ $(foreach prog,$(PROGRAMS),$(eval $(call BUILD_ASSEMBLY,$(prog))))
#
# Install / Uninstall for *nix
#
prefix = /usr/local
datarootdir = $(prefix)/share
datadir = $(datarootdir)
bindir = $(prefix)/bin
prefix ?= /usr/local
datarootdir ?= $(prefix)/share
datadir ?= $(datarootdir)
bindir ?= $(prefix)/bin
BIN_INSTALL_DIR = $(DESTDIR)$(bindir)
INSTALL_DIR = $(DESTDIR)$(datadir)/openra
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
CORE = fileformats rcg rgl rsdl rnull game editor utility
CORE = fileformats rcg rgl rsdl rnull game editor utility tsbuild
install: all
@-echo "Installing OpenRA to $(INSTALL_DIR)"
@@ -196,6 +210,10 @@ install: all
@$(INSTALL_PROGRAM) $(foreach prog,$(CORE),$($(prog)_TARGET)) $(INSTALL_DIR)
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/cnc
@$(INSTALL_PROGRAM) $(mod_cnc_TARGET) $(INSTALL_DIR)/mods/cnc
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/ra
@$(INSTALL_PROGRAM) $(mod_ra_TARGET) $(INSTALL_DIR)/mods/ra
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/d2k
@$(INSTALL_PROGRAM) $(mod_d2k_TARGET) $(INSTALL_DIR)/mods/d2k
@-cp $(foreach f,$(shell ls mods/cnc --hide=*.dll),mods/cnc/$(f)) $(INSTALL_DIR)/mods/cnc
@cp -r mods/cnc/maps $(INSTALL_DIR)/mods/cnc
@@ -205,8 +223,6 @@ install: all
@cp -r mods/cnc/sequences $(INSTALL_DIR)/mods/cnc
@cp -r mods/cnc/tilesets $(INSTALL_DIR)/mods/cnc
@cp -r mods/cnc/uibits $(INSTALL_DIR)/mods/cnc
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)/mods/ra
@$(INSTALL_PROGRAM) $(mod_ra_TARGET) $(INSTALL_DIR)/mods/ra
@-cp $(foreach f,$(shell ls mods/ra --hide=*.dll),mods/ra/$(f)) $(INSTALL_DIR)/mods/ra
@cp -r mods/ra/maps $(INSTALL_DIR)/mods/ra
@@ -215,20 +231,34 @@ install: all
@cp -r mods/ra/rules $(INSTALL_DIR)/mods/ra
@cp -r mods/ra/tilesets $(INSTALL_DIR)/mods/ra
@cp -r mods/ra/uibits $(INSTALL_DIR)/mods/ra
@-cp $(foreach f,$(shell ls mods/d2k --hide=*.dll),mods/d2k/$(f)) $(INSTALL_DIR)/mods/d2k
@cp -r mods/d2k/maps $(INSTALL_DIR)/mods/d2k
@cp -r mods/d2k/bits $(INSTALL_DIR)/mods/d2k
@cp -r mods/d2k/chrome $(INSTALL_DIR)/mods/d2k
@cp -r mods/d2k/rules $(INSTALL_DIR)/mods/d2k
@cp -r mods/d2k/tilesets $(INSTALL_DIR)/mods/d2k
@cp -r mods/d2k/uibits $(INSTALL_DIR)/mods/d2k
@cp -r glsl $(INSTALL_DIR)
@cp -r cg $(INSTALL_DIR)
@cp *.ttf $(INSTALL_DIR)
@cp --parents -r thirdparty/Tao $(INSTALL_DIR)
@cp thirdparty/Tao/* $(INSTALL_DIR)
@$(INSTALL_PROGRAM) thirdparty/ICSharpCode.SharpZipLib.dll $(INSTALL_DIR)
@echo "#!/bin/sh" > openra
@echo "cd "$(datadir)"/openra" >> openra
@echo "mono "$(datadir)"/openra/OpenRA.Game.exe \"$$""@\"" >> openra
@echo "exec mono "$(datadir)"/openra/OpenRA.Game.exe \"$$""@\"" >> openra
@echo "#!/bin/sh" > openra-editor
@echo "cd "$(datadir)"/openra" >> openra-editor
@echo "exec mono "$(datadir)"/openra/OpenRA.Editor.exe \"$$""@\"" >> openra-editor
@$(INSTALL_PROGRAM) -d $(BIN_INSTALL_DIR)
@$(INSTALL_PROGRAM) -m +rx openra $(BIN_INSTALL_DIR)
@$(INSTALL_PROGRAM) -m +rx openra-editor $(BIN_INSTALL_DIR)
uninstall:
@-rm -r $(INSTALL_DIR)
@-rm $(DESTDIR)$(bindir)/openra
@-rm $(DESTDIR)$(bindir)/openra-editor

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Editor
for (var u = 0; u < template.Size.X; u++)
for (var v = 0; v < template.Size.Y; v++)
{
if (surface.Map.IsInMap(new int2(u, v) + pos))
if (surface.Map.IsInMap(new CVec(u, v) + pos))
{
var z = u + v * template.Size.X;
if (tile.TileBitmapBytes[z] != null)
@@ -69,17 +69,17 @@ namespace OpenRA.Editor
Brush.Bitmap.Height * surface.Zoom);
}
void FloodFillWithBrush(Surface s, int2 pos)
void FloodFillWithBrush(Surface s, CPos pos)
{
var queue = new Queue<int2>();
var queue = new Queue<CPos>();
var replace = s.Map.MapTiles.Value[pos.X, pos.Y];
var touched = new bool[s.Map.MapSize.X, s.Map.MapSize.Y];
Action<int, int> MaybeEnqueue = (x, y) =>
Action<int, int> maybeEnqueue = (x, y) =>
{
if (s.Map.IsInMap(x, y) && !touched[x, y])
{
queue.Enqueue(new int2(x, y));
queue.Enqueue(new CPos(x, y));
touched[x, y] = true;
}
};
@@ -91,16 +91,16 @@ namespace OpenRA.Editor
if (!s.Map.MapTiles.Value[p.X, p.Y].Equals(replace))
continue;
var a = FindEdge(s, p, new int2(-1, 0), replace);
var b = FindEdge(s, p, new int2(1, 0), replace);
var a = FindEdge(s, p, new CVec(-1, 0), replace);
var b = FindEdge(s, p, new CVec(1, 0), replace);
for (var x = a.X; x <= b.X; x++)
{
s.Map.MapTiles.Value[x, p.Y] = new TileReference<ushort, byte> { type = Brush.N, index = (byte)0 };
if (s.Map.MapTiles.Value[x, p.Y - 1].Equals(replace))
MaybeEnqueue(x, p.Y - 1);
maybeEnqueue(x, p.Y - 1);
if (s.Map.MapTiles.Value[x, p.Y + 1].Equals(replace))
MaybeEnqueue(x, p.Y + 1);
maybeEnqueue(x, p.Y + 1);
}
}
@@ -109,7 +109,7 @@ namespace OpenRA.Editor
s.Chunks.Clear();
}
int2 FindEdge(Surface s, int2 p, int2 d, TileReference<ushort, byte> replace)
CPos FindEdge(Surface s, CPos p, CVec d, TileReference<ushort, byte> replace)
{
for (; ; )
{

View File

@@ -82,6 +82,9 @@ namespace OpenRA.Editor
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabelFiller = new System.Windows.Forms.ToolStripStatusLabel();
this.toolStripStatusLabelMousePosition = new System.Windows.Forms.ToolStripStatusLabel();
this.copySelectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
@@ -225,8 +228,8 @@ namespace OpenRA.Editor
this.actorOwnerChooser.Name = "actorOwnerChooser";
this.actorOwnerChooser.Size = new System.Drawing.Size(184, 21);
this.actorOwnerChooser.TabIndex = 3;
this.actorOwnerChooser.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.onDrawPlayerItem);
this.actorOwnerChooser.SelectionChangeCommitted += new System.EventHandler(this.onSelectOwner);
this.actorOwnerChooser.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.DrawPlayerListItem);
this.actorOwnerChooser.SelectionChangeCommitted += new System.EventHandler(this.OnSelectedPlayerChanged);
//
// tabPage3
//
@@ -417,8 +420,11 @@ namespace OpenRA.Editor
this.resizeToolStripMenuItem,
this.showActorNamesToolStripMenuItem,
this.showGridToolStripMenuItem,
this.toolStripSeparator5,
this.fixOpenAreasToolStripMenuItem,
this.setupDefaultPlayersMenuItem});
this.setupDefaultPlayersMenuItem,
this.toolStripSeparator4,
this.copySelectionToolStripMenuItem});
this.mapToolStripMenuItem.Name = "mapToolStripMenuItem";
this.mapToolStripMenuItem.Size = new System.Drawing.Size(43, 23);
this.mapToolStripMenuItem.Text = "&Map";
@@ -507,6 +513,23 @@ namespace OpenRA.Editor
this.toolStripStatusLabelMousePosition.Size = new System.Drawing.Size(22, 17);
this.toolStripStatusLabelMousePosition.Text = "0,0";
//
// copySelectionToolStripMenuItem
//
this.copySelectionToolStripMenuItem.Name = "copySelectionToolStripMenuItem";
this.copySelectionToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
this.copySelectionToolStripMenuItem.Text = "Copy Selection";
this.copySelectionToolStripMenuItem.Click += new System.EventHandler(this.copySelectionToolStripMenuItem_Click);
//
// toolStripSeparator4
//
this.toolStripSeparator4.Name = "toolStripSeparator4";
this.toolStripSeparator4.Size = new System.Drawing.Size(182, 6);
//
// toolStripSeparator5
//
this.toolStripSeparator5.Name = "toolStripSeparator5";
this.toolStripSeparator5.Size = new System.Drawing.Size(182, 6);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -520,9 +543,9 @@ namespace OpenRA.Editor
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "OpenRA Editor";
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
this.splitContainer1.ResumeLayout(false);
@@ -592,6 +615,9 @@ namespace OpenRA.Editor
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.FlowLayoutPanel actorPalette;
private System.Windows.Forms.ComboBox actorOwnerChooser;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
private System.Windows.Forms.ToolStripMenuItem copySelectionToolStripMenuItem;
}
}

View File

@@ -138,38 +138,62 @@ namespace OpenRA.Editor
Rules.LoadRules(manifest, map);
tileset = Rules.TileSets[map.Tileset];
tileset.LoadTiles();
var palette = new Palette(FileSystem.Open(tileset.Palette), true);
int[] ShadowIndex = { 3, 4 };
var palette = new Palette(FileSystem.Open(tileset.Palette), ShadowIndex);
surface1.Bind(map, tileset, palette);
// construct the palette of tiles
var palettes = new[] { tilePalette, actorPalette, resourcePalette };
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
foreach (var t in tileset.Templates)
foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category))
{
try
var category = tc.Key ?? "(Uncategorized)";
var categoryHeader = new Label
{
var bitmap = tileset.RenderTemplate((ushort)t.Key, palette);
var ibox = new PictureBox
BackColor = SystemColors.Highlight,
ForeColor = SystemColors.HighlightText,
Text = category,
AutoSize = false,
Height = 24,
TextAlign = ContentAlignment.MiddleLeft,
Width = tilePalette.ClientSize.Width,
};
// hook this manually, anchoring inside FlowLayoutPanel is flaky.
tilePalette.Resize += (_,e) => categoryHeader.Width = tilePalette.ClientSize.Width;
if (tilePalette.Controls.Count > 0)
tilePalette.SetFlowBreak(
tilePalette.Controls[tilePalette.Controls.Count - 1], true);
tilePalette.Controls.Add(categoryHeader);
foreach( var t in tc )
{
try
{
Image = bitmap,
Width = bitmap.Width / 2,
Height = bitmap.Height / 2,
SizeMode = PictureBoxSizeMode.StretchImage
};
var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key };
ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate));
var template = t.Value;
tilePalette.Controls.Add(ibox);
tt.SetToolTip(ibox,
"{1}:{0} ({2}x{3})".F(
template.Image,
template.Id,
template.Size.X,
template.Size.Y));
var bitmap = tileset.RenderTemplate((ushort)t.Key, palette);
var ibox = new PictureBox
{
Image = bitmap,
Width = bitmap.Width / 2,
Height = bitmap.Height / 2,
SizeMode = PictureBoxSizeMode.StretchImage
};
var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key };
ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate));
var template = t.Value;
tilePalette.Controls.Add(ibox);
tt.SetToolTip(ibox,
"{1}:{0} ({2}x{3})".F(
template.Image,
template.Id,
template.Size.X,
template.Size.Y));
}
catch { }
}
catch { }
}
var actorTemplates = new List<ActorTemplate>();
@@ -286,9 +310,9 @@ namespace OpenRA.Editor
return;
surface1.Map.ResizeCordon((int)rd.cordonLeft.Value,
(int)rd.cordonTop.Value,
(int)rd.cordonRight.Value,
(int)rd.cordonBottom.Value);
(int)rd.cordonTop.Value,
(int)rd.cordonRight.Value,
(int)rd.cordonBottom.Value);
if ((int)rd.width.Value != surface1.Map.MapSize.X || (int)rd.height.Value != surface1.Map.MapSize.Y)
{
@@ -499,7 +523,7 @@ namespace OpenRA.Editor
PopulateActorOwnerChooser();
}
void onDrawPlayerItem(object sender, DrawItemEventArgs e)
void DrawPlayerListItem(object sender, DrawItemEventArgs e)
{
// color block
var player = e.Index >= 0 ? (PlayerReference)(sender as ComboBox).Items[e.Index] : null;
@@ -517,10 +541,15 @@ namespace OpenRA.Editor
e.Graphics.DrawString( player.Name, e.Font, foreBrush, e.Bounds.Left + e.Bounds.Height + 12, e.Bounds.Top );
}
void onSelectOwner(object sender, EventArgs e)
void OnSelectedPlayerChanged(object sender, EventArgs e)
{
var player = actorOwnerChooser.SelectedItem as PlayerReference;
surface1.NewActorOwner = player.Name;
}
private void copySelectionToolStripMenuItem_Click(object sender, EventArgs e)
{
surface1.CopySelection();
}
}
}

View File

@@ -120,13 +120,45 @@
<metadata name="tt.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="saveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>76, 17</value>
</metadata>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>198, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="propertiesToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACCklE
QVQ4T6WT30tTUQDHz39QD0UQSpAPIkgPyR60AiUiyoGBL4qZjOyt0tZP9tBDk1AsXIhj93ILdd27DPPH
3VwrUrdK2ioJHAgVOdoPaQsarBg43L6ec+akuRsEPnw5D4fP5/vlXg4BQHaSf8LjjwdqaTA2cg+y1Ith
qxmi5Tas/SYWk+QRoPgmtNsLcPq7GYX8+XoTqaUL+KR2cAmDxeBgqeBv2NhWzwUFOBk4g5/zRxB3V8Es
38AtbzuIw/0RLMrMeyhTs2CzGdRtaOTn1dajvLkAR9VKLNvLcHmoExddzSDKzAfkcjkkEtEiOLxoQpdB
z+Er7ScQUg/DL5TD2bsfl5oPoKWnCZ3jehDZGeAC1hwL3uXNs55Jep7Gis/AJWxyTeVe1FXvhq5qH6oP
7nlw/NoxGByNIKPT77CezSEeD6Pn+jlEIiGk6X8N+F9zyfLYIZzUVUCwT0J36jy9yX83KjDq7zSADE8t
cGB7kpksFt76YDzbgMWVFLzBX0WCTcku8mjiTSm8lkUslcHnH2kK/+aw6k+UCJiESE+9XCApz2Gzu5Gk
sEVy4r6got82vRV5blVbIDyZ21rAZrPmL7w5P5s1KxQWXRFtgU15lV8ge2AbdXPY8pAuEIsXWJ6FtAVW
+SWSmXWssuZ4vnl+s5nNFl1hMLjP8U1bMGR/wS/+N9tf7o6eMpNtADko6xybtEXLAAAAAElFTkSuQmCC
</value>
</data>
<data name="resizeToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAADLklE
QVQ4T3WS60/ScRjFf39CL3rR1ovurduWbbU2t7ZqdlkXt7Lrym6O1VoXcdYqQ54wKlGxABE1CzWF0nIm
lZcoTbyUNJFIzDJSJK+E0qy8wInvz+i2erazfd+cz3m+zw4nTS+FLOeZNim3Vp6UU5sqvf5MSZqnyjhV
pfKUvEx54kqp8rCkWHVQVKSJPHtbs+tUgSYiOicVAMfEqfR1dVFCGSqrX94cHQeN/aXhbyD3Zz91uf3U
9tFHTQ4fzVtH9BOQVdKcW2F6/eKkWA1zcxu6vUAQMmCzk/3AErLtDyFrrY035z16T3PXin8B5LfqZE6P
HyZzKw5FX+Yh4XtjwZKZGV3lNPIkhhojplON3Uc3S9/Q7LDfADKtKYklMsgTkwV7joixKHQr2Nq2fSET
5uQwqtsyjcot45R510ozV8f/2iAhsyolCNh9WIyFoRGYHbIGfYN+SVd7Nznzk8ll0FLzKxdZO3xkaOjG
GYUxcIIfRxSlPU4N/rn1fS8JJVlU1WCT3npggVLfAIWuHjJtNRIyjIhTPEKM7D6OSop4RcXpwZ2Wl11l
gHanmze/c36ioc8jyRlFjSzljxl2daI9Pwuv1Cnw9PRjZeQ1cCcSS68Fza6+IXL2fCG7w0ssmc3o2IR8
gbc1PQU9NUp48sNRcUyAkPBL4AIlUbLk3gEvS6YXrW6p0dx9UZ5n4gHjzBmYAAPPYwRwazeiMXYWqjcs
wLSVInAHRYWq0TEf9Q+NUEsg+fr9t2nF1U71leyqn+u3vPuIl2298HZ2wnxkO5q2LYOtxoKpK86D23tW
r+7zfCVzywAVGT/QVV2LvNDo0Eo0j3mAtbUTiRnFOJ94Axp9LfIKK5Ctq0RDmw9TQuPAsW7bHYNUYLCQ
JL2GRAqjtMDYwV+8wzUAWeY9eIfHYW0fxNodxyGWZeOSPBvzl27C5OXnwG0T5irmr79wgdWTNYyVJFL8
kAeo8wyBA/rx2jGErBIH0nXPsWmPEHcM9YgURGPS0jMTZfiXGKDfM4Y0fVOgA/UgRQWECTpExaqxUyDF
wuUbJjb4H0AQfxtrDqiweLMUc8LEmLEqnv9zUMzM9B1/cM83lepxTAAAAABJRU5ErkJggg==
</value>
</data>
<data name="newToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
@@ -260,41 +292,6 @@
z2ki+Wo1CWklROkMCiT8wEm0kXEsCTmrAiTbDtcEpTVdZOS1oDfWk5xZ6RPeQZeUR8zxK0Qe1BO65xjr
t0YotXhjAEAeQ7It8ZSESUjkznIq2bYsTGYW29JZxIs2nFEdLOSdfwFwpvLxRKIY2AAAAABJRU5ErkJg
gg==
</value>
</data>
<data name="propertiesToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAACCklE
QVQ4T6WT30tTUQDHz39QD0UQSpAPIkgPyR60AiUiyoGBL4qZjOyt0tZP9tBDk1AsXIhj93ILdd27DPPH
3VwrUrdK2ioJHAgVOdoPaQsarBg43L6ec+akuRsEPnw5D4fP5/vlXg4BQHaSf8LjjwdqaTA2cg+y1Ith
qxmi5Tas/SYWk+QRoPgmtNsLcPq7GYX8+XoTqaUL+KR2cAmDxeBgqeBv2NhWzwUFOBk4g5/zRxB3V8Es
38AtbzuIw/0RLMrMeyhTs2CzGdRtaOTn1dajvLkAR9VKLNvLcHmoExddzSDKzAfkcjkkEtEiOLxoQpdB
z+Er7ScQUg/DL5TD2bsfl5oPoKWnCZ3jehDZGeAC1hwL3uXNs55Jep7Gis/AJWxyTeVe1FXvhq5qH6oP
7nlw/NoxGByNIKPT77CezSEeD6Pn+jlEIiGk6X8N+F9zyfLYIZzUVUCwT0J36jy9yX83KjDq7zSADE8t
cGB7kpksFt76YDzbgMWVFLzBX0WCTcku8mjiTSm8lkUslcHnH2kK/+aw6k+UCJiESE+9XCApz2Gzu5Gk
sEVy4r6got82vRV5blVbIDyZ21rAZrPmL7w5P5s1KxQWXRFtgU15lV8ge2AbdXPY8pAuEIsXWJ6FtAVW
+SWSmXWssuZ4vnl+s5nNFl1hMLjP8U1bMGR/wS/+N9tf7o6eMpNtADko6xybtEXLAAAAAElFTkSuQmCC
</value>
</data>
<data name="resizeToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6
JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsMAAALDAE/QCLIAAADLklE
QVQ4T3WS60/ScRjFf39CL3rR1ovurduWbbU2t7ZqdlkXt7Lrym6O1VoXcdYqQ54wKlGxABE1CzWF0nIm
lZcoTbyUNJFIzDJSJK+E0qy8wInvz+i2erazfd+cz3m+zw4nTS+FLOeZNim3Vp6UU5sqvf5MSZqnyjhV
pfKUvEx54kqp8rCkWHVQVKSJPHtbs+tUgSYiOicVAMfEqfR1dVFCGSqrX94cHQeN/aXhbyD3Zz91uf3U
9tFHTQ4fzVtH9BOQVdKcW2F6/eKkWA1zcxu6vUAQMmCzk/3AErLtDyFrrY035z16T3PXin8B5LfqZE6P
HyZzKw5FX+Yh4XtjwZKZGV3lNPIkhhojplON3Uc3S9/Q7LDfADKtKYklMsgTkwV7joixKHQr2Nq2fSET
5uQwqtsyjcot45R510ozV8f/2iAhsyolCNh9WIyFoRGYHbIGfYN+SVd7Nznzk8ll0FLzKxdZO3xkaOjG
GYUxcIIfRxSlPU4N/rn1fS8JJVlU1WCT3npggVLfAIWuHjJtNRIyjIhTPEKM7D6OSop4RcXpwZ2Wl11l
gHanmze/c36ioc8jyRlFjSzljxl2daI9Pwuv1Cnw9PRjZeQ1cCcSS68Fza6+IXL2fCG7w0ssmc3o2IR8
gbc1PQU9NUp48sNRcUyAkPBL4AIlUbLk3gEvS6YXrW6p0dx9UZ5n4gHjzBmYAAPPYwRwazeiMXYWqjcs
wLSVInAHRYWq0TEf9Q+NUEsg+fr9t2nF1U71leyqn+u3vPuIl2298HZ2wnxkO5q2LYOtxoKpK86D23tW
r+7zfCVzywAVGT/QVV2LvNDo0Eo0j3mAtbUTiRnFOJ94Axp9LfIKK5Ctq0RDmw9TQuPAsW7bHYNUYLCQ
JL2GRAqjtMDYwV+8wzUAWeY9eIfHYW0fxNodxyGWZeOSPBvzl27C5OXnwG0T5irmr79wgdWTNYyVJFL8
kAeo8wyBA/rx2jGErBIH0nXPsWmPEHcM9YgURGPS0jMTZfiXGKDfM4Y0fVOgA/UgRQWECTpExaqxUyDF
wuUbJjb4H0AQfxtrDqiweLMUc8LEmLEqnv9zUMzM9B1/cM83lepxTAAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">

View File

@@ -175,7 +175,7 @@ namespace OpenRA.Editor
foreach( var kv in wps )
{
var a = new ActorReference("mpspawn");
a.Add(new LocationInit(kv.Second));
a.Add(new LocationInit((CPos)kv.Second));
a.Add(new OwnerInit("Neutral"));
Map.Actors.Value.Add("spawn" + kv.First, a);
}
@@ -189,27 +189,27 @@ namespace OpenRA.Editor
static MemoryStream ReadPackedSection(IniSection mapPackSection)
{
StringBuilder sb = new StringBuilder();
var sb = new StringBuilder();
for (int i = 1; ; i++)
{
string line = mapPackSection.GetValue(i.ToString(), null);
var line = mapPackSection.GetValue(i.ToString(), null);
if (line == null)
break;
sb.Append(line.Trim());
}
byte[] data = Convert.FromBase64String(sb.ToString());
List<byte[]> chunks = new List<byte[]>();
BinaryReader reader = new BinaryReader(new MemoryStream(data));
var data = Convert.FromBase64String(sb.ToString());
var chunks = new List<byte[]>();
var reader = new BinaryReader(new MemoryStream(data));
try
{
while (true)
{
uint length = reader.ReadUInt32() & 0xdfffffff;
byte[] dest = new byte[8192];
byte[] src = reader.ReadBytes((int)length);
var length = reader.ReadUInt32() & 0xdfffffff;
var dest = new byte[8192];
var src = reader.ReadBytes((int)length);
/*int actualLength =*/
Format80.DecodeInto(src, dest);
@@ -219,8 +219,8 @@ namespace OpenRA.Editor
}
catch (EndOfStreamException) { }
MemoryStream ms = new MemoryStream();
foreach (byte[] chunk in chunks)
var ms = new MemoryStream();
foreach (var chunk in chunks)
ms.Write(chunk, 0, chunk.Length);
ms.Position = 0;
@@ -276,7 +276,7 @@ namespace OpenRA.Editor
Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(overlayActorMapping[raOverlayNames[o]])
{
new LocationInit( new int2(i, j) ),
new LocationInit( new CPos(i, j) ),
new OwnerInit( "Neutral" )
});
}
@@ -284,7 +284,7 @@ namespace OpenRA.Editor
void ReadRATrees(IniFile file)
{
IniSection terrain = file.GetSection("TERRAIN", true);
var terrain = file.GetSection("TERRAIN", true);
if (terrain == null)
return;
@@ -294,7 +294,7 @@ namespace OpenRA.Editor
Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(kv.Value.ToLowerInvariant())
{
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
new LocationInit(new CPos(loc % MapSize, loc / MapSize)),
new OwnerInit("Neutral")
});
}
@@ -316,14 +316,14 @@ namespace OpenRA.Editor
void ReadCncOverlay(IniFile file)
{
IniSection overlay = file.GetSection("OVERLAY", true);
var overlay = file.GetSection("OVERLAY", true);
if (overlay == null)
return;
foreach (KeyValuePair<string, string> kv in overlay)
{
var loc = int.Parse(kv.Key);
int2 cell = new int2(loc % MapSize, loc / MapSize);
var cell = new CPos(loc % MapSize, loc / MapSize);
var res = Pair.New((byte)0, (byte)0);
if (overlayResourceMapping.ContainsKey(kv.Value.ToLower()))
@@ -343,7 +343,7 @@ namespace OpenRA.Editor
void ReadCncTrees(IniFile file)
{
IniSection terrain = file.GetSection("TERRAIN", true);
var terrain = file.GetSection("TERRAIN", true);
if (terrain == null)
return;
@@ -353,7 +353,7 @@ namespace OpenRA.Editor
Map.Actors.Value.Add("Actor" + ActorCount++,
new ActorReference(kv.Value.Split(',')[0].ToLowerInvariant())
{
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
new LocationInit(new CPos(loc % MapSize, loc / MapSize)),
new OwnerInit("Neutral")
});
}
@@ -375,13 +375,12 @@ namespace OpenRA.Editor
if (parts[0] == "")
parts[0] = "Neutral";
if (!Players.Contains(parts[0]))
Players.Add(parts[0]);
var actor = new ActorReference(parts[1].ToLowerInvariant())
{
new LocationInit(new int2(loc % MapSize, loc / MapSize)),
new LocationInit(new CPos(loc % MapSize, loc / MapSize)),
new OwnerInit(parts[0]),
new HealthInit(float.Parse(parts[2], NumberFormatInfo.InvariantInfo)/256),
new FacingInit((section == "INFANTRY") ? int.Parse(parts[6]) : int.Parse(parts[4])),
@@ -433,7 +432,7 @@ namespace OpenRA.Editor
(byte)(color.Second.GetBrightness() * 255))
};
var Neutral = new [] {"Neutral"};
var neutral = new [] {"Neutral"};
foreach (var s in file.GetSection(section, true))
{
Console.WriteLine(s.Key);
@@ -443,8 +442,8 @@ namespace OpenRA.Editor
pr.InitialCash = int.Parse(s.Value);
break;
case "Allies":
pr.Allies = s.Value.Split(',').Intersect(Players).Except(Neutral).ToArray();
pr.Enemies = s.Value.Split(',').SymmetricDifference(Players).Except(Neutral).ToArray();
pr.Allies = s.Value.Split(',').Intersect(Players).Except(neutral).ToArray();
pr.Enemies = s.Value.Split(',').SymmetricDifference(Players).Except(neutral).ToArray();
break;
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -13,6 +13,25 @@
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ApplicationIcon>OpenRA.Editor.Icon.ico</ApplicationIcon>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -25,6 +44,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -35,6 +55,7 @@
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -122,6 +143,7 @@
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@@ -157,6 +179,23 @@
<ItemGroup>
<Content Include="OpenRA.Editor.Icon.ico" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,71 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.4927
// Runtime Version:4.0.30319.269
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OpenRA.Editor.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenRA.Editor.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
namespace OpenRA.Editor.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenRA.Editor.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@@ -1,30 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.4927
// Runtime Version:4.0.30319.269
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OpenRA.Editor.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
namespace OpenRA.Editor.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Editor
bitmap.Palette = p.AsSystemPalette();
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
var data = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe
@@ -84,7 +84,7 @@ namespace OpenRA.Editor
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
bitmap.Palette = p.AsSystemPalette();
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
var data = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe

View File

@@ -38,6 +38,12 @@ namespace OpenRA.Editor
public bool ShowActorNames;
public bool ShowGrid;
public bool IsPaste { get { return TileSelection != null && ResourceSelection != null; } }
public TileReference<ushort, byte>[,] TileSelection;
public TileReference<byte, byte>[,] ResourceSelection;
public CPos SelectionStart;
public CPos SelectionEnd;
public string NewActorOwner;
public event Action AfterChange = () => { };
@@ -59,7 +65,7 @@ namespace OpenRA.Editor
Tool = null;
}
public void SetTool(ITool tool) { Tool = tool; }
public void SetTool(ITool tool) { Tool = tool; ClearSelection(); }
public void BindActorTemplates(IEnumerable<ActorTemplate> templates)
{
@@ -83,6 +89,8 @@ namespace OpenRA.Editor
UpdateStyles();
}
static readonly Pen SelectionPen = new Pen(Color.Blue);
static readonly Pen PastePen = new Pen(Color.Green);
static readonly Pen CordonPen = new Pen(Color.Red);
int2 MousePos;
@@ -157,23 +165,23 @@ namespace OpenRA.Editor
void Erase()
{
// Crash preventing
var BrushLocation = GetBrushLocation();
var brushLocation = GetBrushLocation();
if (Map == null || BrushLocation.X >= Map.MapSize.X ||
BrushLocation.Y >= Map.MapSize.Y ||
BrushLocation.X < 0 ||
BrushLocation.Y < 0)
if (Map == null || brushLocation.X >= Map.MapSize.X ||
brushLocation.Y >= Map.MapSize.Y ||
brushLocation.X < 0 ||
brushLocation.Y < 0)
return;
Tool = null;
var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == BrushLocation);
var key = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == brushLocation);
if (key.Key != null) Map.Actors.Value.Remove(key.Key);
if (Map.MapResources.Value[BrushLocation.X, BrushLocation.Y].type != 0)
if (Map.MapResources.Value[brushLocation.X, brushLocation.Y].type != 0)
{
Map.MapResources.Value[BrushLocation.X, BrushLocation.Y] = new TileReference<byte, byte>();
var ch = new int2((BrushLocation.X) / ChunkSize, (BrushLocation.Y) / ChunkSize);
Map.MapResources.Value[brushLocation.X, brushLocation.Y] = new TileReference<byte, byte>();
var ch = new int2((brushLocation.X) / ChunkSize, (brushLocation.Y) / ChunkSize);
if (Chunks.ContainsKey(ch))
{
Chunks[ch].Dispose();
@@ -182,12 +190,20 @@ namespace OpenRA.Editor
}
AfterChange();
ClearSelection();
}
void Draw()
{
if (Tool != null) Tool.Apply(this);
AfterChange();
if (Tool != null)
{
Tool.Apply(this);
AfterChange();
}
else if (IsPaste)
PasteSelection();
else
SelectionEnd = GetBrushLocationBR();
}
protected override void OnMouseDown(MouseEventArgs e)
@@ -199,7 +215,12 @@ namespace OpenRA.Editor
if (!IsPanning)
{
if (e.Button == MouseButtons.Right) Erase();
if (e.Button == MouseButtons.Left) Draw();
if (e.Button == MouseButtons.Left)
{
Draw();
if (!IsPaste)
SelectionStart = SelectionEnd = GetBrushLocation();
}
}
Invalidate();
@@ -212,7 +233,7 @@ namespace OpenRA.Editor
var bitmap = new Bitmap(ChunkSize * TileSet.TileSize, ChunkSize * TileSet.TileSize);
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
var data = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
@@ -234,7 +255,7 @@ namespace OpenRA.Editor
if (Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].type != 0)
{
var resourceImage = ResourceTemplates[Map.MapResources.Value[u * ChunkSize + i, v * ChunkSize + j].type].Bitmap;
var srcdata = resourceImage.LockBits(new Rectangle(0, 0, resourceImage.Width, resourceImage.Height),
var srcdata = resourceImage.LockBits(resourceImage.Bounds(),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int* q = (int*)srcdata.Scan0.ToPointer();
@@ -267,31 +288,39 @@ namespace OpenRA.Editor
return bitmap;
}
public int2 GetBrushLocation()
public CPos GetBrushLocation()
{
var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom);
var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom);
return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize);
return new CPos(vX / TileSet.TileSize, vY / TileSet.TileSize);
}
public void DrawActor(SGraphics g, int2 p, ActorTemplate t, ColorPalette cp)
public CPos GetBrushLocationBR()
{
var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom);
var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom);
return new CPos((vX + TileSet.TileSize - 1) / TileSet.TileSize,
(vY + TileSet.TileSize - 1) / TileSet.TileSize);
}
public void DrawActor(SGraphics g, CPos p, ActorTemplate t, ColorPalette cp)
{
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
DrawImage(g, t.Bitmap, p, centered, cp);
}
float2 GetDrawPosition(int2 location, Bitmap bmp, bool centered)
float2 GetDrawPosition(CPos location, Bitmap bmp, bool centered)
{
float OffsetX = centered ? bmp.Width / 2 - TileSet.TileSize / 2 : 0;
float DrawX = TileSet.TileSize * location.X * Zoom + Offset.X - OffsetX;
float offsetX = centered ? bmp.Width / 2 - TileSet.TileSize / 2 : 0;
float drawX = TileSet.TileSize * location.X * Zoom + Offset.X - offsetX;
float OffsetY = centered ? bmp.Height / 2 - TileSet.TileSize / 2 : 0;
float DrawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - OffsetY;
float offsetY = centered ? bmp.Height / 2 - TileSet.TileSize / 2 : 0;
float drawY = TileSet.TileSize * location.Y * Zoom + Offset.Y - offsetY;
return new float2(DrawX, DrawY);
return new float2(drawX, drawY);
}
public void DrawImage(SGraphics g, Bitmap bmp, int2 location, bool centered, ColorPalette cp)
public void DrawImage(SGraphics g, Bitmap bmp, CPos location, bool centered, ColorPalette cp)
{
var drawPos = GetDrawPosition(location, bmp, centered);
@@ -304,7 +333,7 @@ namespace OpenRA.Editor
if (cp != null) bmp.Palette = restorePalette;
}
void DrawActorBorder(SGraphics g, int2 p, ActorTemplate t)
void DrawActorBorder(SGraphics g, CPos p, ActorTemplate t)
{
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
var drawPos = GetDrawPosition(p, t.Bitmap, centered);
@@ -318,7 +347,7 @@ namespace OpenRA.Editor
{
var pr = Map.Players[name];
var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>();
var remap = new PlayerColorRemap(pcpi.PaletteFormat, pr.ColorRamp);
var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.ColorRamp);
return new Palette(Palette, remap).AsSystemPalette();
}
@@ -367,6 +396,25 @@ namespace OpenRA.Editor
Map.Bounds.Width * TileSet.TileSize * Zoom,
Map.Bounds.Height * TileSet.TileSize * Zoom);
e.Graphics.DrawRectangle(SelectionPen,
(SelectionStart.X * TileSet.TileSize * Zoom) + Offset.X,
(SelectionStart.Y * TileSet.TileSize * Zoom) + Offset.Y,
(SelectionEnd - SelectionStart).X * TileSet.TileSize * Zoom,
(SelectionEnd - SelectionStart).Y * TileSet.TileSize * Zoom);
if (IsPaste)
{
var loc = GetBrushLocation();
var width = Math.Abs((SelectionStart - SelectionEnd).X);
var height = Math.Abs((SelectionStart - SelectionEnd).Y);
e.Graphics.DrawRectangle(PastePen,
(loc.X * TileSet.TileSize * Zoom) + Offset.X,
(loc.Y * TileSet.TileSize * Zoom) + Offset.Y,
width * (TileSet.TileSize * Zoom),
height * (TileSet.TileSize * Zoom));
}
foreach (var ar in Map.Actors.Value)
{
if (ActorTemplates.ContainsKey(ar.Value.Type))
@@ -395,13 +443,74 @@ namespace OpenRA.Editor
DrawActorBorder(e.Graphics, x.Value.Location(), ActorTemplates[x.Value.Type]);
}
}
public void CopySelection()
{
// Grab tiles and resources within selection (doesn't do actors)
var start = SelectionStart;
var end = SelectionEnd;
if (start == end) return;
int width = Math.Abs((start - end).X);
int height = Math.Abs((start - end).Y);
TileSelection = new TileReference<ushort, byte>[width, height];
ResourceSelection = new TileReference<byte, byte>[width, height];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
//todo: crash prevention
TileSelection[x, y] = Map.MapTiles.Value[start.X + x, start.Y + y];
ResourceSelection[x, y] = Map.MapResources.Value[start.X + x, start.Y + y];
}
}
}
void PasteSelection()
{
var loc = GetBrushLocation();
var width = Math.Abs((SelectionStart - SelectionEnd).X);
var height = Math.Abs((SelectionStart - SelectionEnd).Y);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
var mapX = loc.X + x;
var mapY = loc.Y + y;
//todo: crash prevention for outside of bounds
Map.MapTiles.Value[mapX, mapY] = TileSelection[x, y];
Map.MapResources.Value[mapX, mapY] = ResourceSelection[x, y];
var ch = new int2(mapX / ChunkSize, mapY / ChunkSize);
if (Chunks.ContainsKey(ch))
{
Chunks[ch].Dispose();
Chunks.Remove(ch);
}
}
}
AfterChange();
}
void ClearSelection()
{
SelectionStart = CPos.Zero;
SelectionEnd = CPos.Zero;
TileSelection = null;
ResourceSelection = null;
}
}
static class ActorReferenceExts
{
public static int2 Location(this ActorReference ar)
public static CPos Location(this ActorReference ar)
{
return ar.InitDict.Get<LocationInit>().value;
return (CPos)ar.InitDict.Get<LocationInit>().value;
}
public static void DrawStringContrast(this SGraphics g, Font f, string s, int x, int y, Brush fg, Brush bg)

View File

@@ -21,8 +21,6 @@ namespace OpenRA.FileFormats
H = h; S = s; L = l; R = r;
}
public static readonly ColorRamp Empty = new ColorRamp(0,0,0,0);
/* returns a color along the Lum ramp */
public Color GetColor( float t )
{
@@ -35,7 +33,7 @@ namespace OpenRA.FileFormats
}
// hk is hue in the range [0,1] instead of [0,360]
public static Color ColorFromHSL(float hk, float s, float l)
static Color ColorFromHSL(float hk, float s, float l)
{
// Convert from HSL to RGB
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);

View File

@@ -172,6 +172,8 @@ namespace OpenRA
return v;
}
public static Size NextPowerOf2(this Size s) { return new Size(NextPowerOf2(s.Width), NextPowerOf2(s.Height)); }
public static string JoinWith<T>(this IEnumerable<T> ts, string j)
{
return string.Join(j, ts.Select(t => t.ToString()).ToArray());
@@ -181,5 +183,83 @@ namespace OpenRA
{
return ts.Concat(moreTs);
}
public static Dictionary<TKey, TSource> ToDictionaryWithConflictLog<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, string debugName, Func<TKey, string> logKey, Func<TSource, string> logValue)
{
return ToDictionaryWithConflictLog(source, keySelector, x => x, debugName, logKey, logValue);
}
public static Dictionary<TKey, TElement> ToDictionaryWithConflictLog<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, string debugName, Func<TKey, string> logKey, Func<TElement, string> logValue)
{
// Fall back on ToString() if null functions are provided:
logKey = logKey ?? (s => s.ToString());
logValue = logValue ?? (s => s.ToString());
// Try to build a dictionary and log all duplicates found (if any):
var dupKeys = new Dictionary<TKey, List<string>>();
var d = new Dictionary<TKey, TElement>();
foreach (var item in source)
{
TKey key = keySelector(item);
TElement element = elementSelector(item);
// Check for a key conflict:
if (d.ContainsKey(key))
{
List<string> dupKeyMessages;
if (!dupKeys.TryGetValue(key, out dupKeyMessages))
{
// Log the initial conflicting value already inserted:
dupKeyMessages = new List<string>();
dupKeyMessages.Add(logValue(d[key]));
dupKeys.Add(key, dupKeyMessages);
}
// Log this conflicting value:
dupKeyMessages.Add(logValue(element));
continue;
}
d.Add(key, element);
}
// If any duplicates were found, log it and throw a descriptive error
if (dupKeys.Count > 0)
{
string badKeysFormatted = String.Join(", ", dupKeys.Select(p => "{0}: [{1}]".F(logKey(p.Key), String.Join(",", p.Value.ToArray()))).ToArray());
string msg = "{0}, duplicate values found for the following keys: {1}".F(debugName, badKeysFormatted);
Log.Write("debug", msg);
throw new ArgumentException(msg);
}
// Return the dictionary we built:
return d;
}
public static Color ColorLerp(float t, Color c1, Color c2)
{
return Color.FromArgb(
(int)(t * c2.A + (1 - t) * c1.A),
(int)(t * c2.R + (1 - t) * c1.R),
(int)(t * c2.G + (1 - t) * c1.G),
(int)(t * c2.B + (1 - t) * c1.B));
}
public static T[] MakeArray<T>(int count, Func<int, T> f)
{
T[] result = new T[count];
for (int i = 0; i < count; i++)
result[i] = f(i);
return result;
}
public static Rectangle Bounds(this Bitmap b) { return new Rectangle(0, 0, b.Width, b.Height); }
}
public static class Enum<T>
{
public static T Parse(string s) { return (T)Enum.Parse(typeof(T), s); }
public static T[] GetValues() { return (T[])Enum.GetValues(typeof(T)); }
}
}

View File

@@ -56,6 +56,11 @@ namespace OpenRA.FileFormats
ret = GetValue( fieldName, fieldType, n[ 0 ].Value.Value );
return true;
}
else if ( n.Count > 1 )
{
throw new InvalidOperationException("The field {0} has multiple definitions:\n{1}"
.F(fieldName, n.Select(m => "\t- " + m.Location).JoinWith("\n")));
}
throw new InvalidOperationException( "TryGetValueFromYaml: unable to load field {0} (of type {1})".F( fieldName, fieldType ) );
}
@@ -320,6 +325,10 @@ namespace OpenRA.FileFormats
((int)c.B).Clamp(0, 255));
}
// Don't save floats in settings.yaml using country-specific decimal separators which can be misunderstood as group seperators.
if (t == typeof(float))
return ((float)v).ToString(CultureInfo.InvariantCulture);
if (t == typeof(Rectangle))
{
var r = (Rectangle)v;

View File

@@ -19,24 +19,6 @@ namespace OpenRA.FileFormats
{
const string pubkeyStr = "AihRvNoIbTn85FZRYNZRcT+i6KpU+maCsEqr3Q5q+LDB5tH7Tz2qQ38V";
static sbyte[] char2num = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
class PublicKey
{
public uint[] key1 = new uint[64];
@@ -128,25 +110,9 @@ namespace OpenRA.FileFormats
void init_pubkey()
{
int i = 0;
uint i2, tmp;
byte[] keytmp = new byte[256];
init_bignum(pubkey.key2, 0x10001, 64);
i2 = 0;
while (i < pubkeyStr.Length)
{
tmp = (uint)char2num[pubkeyStr[i++]];
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
keytmp[i2++] = (byte)((tmp >> 16) & 0xff);
keytmp[i2++] = (byte)((tmp >> 8) & 0xff);
keytmp[i2++] = (byte)(tmp & 0xff);
}
key_to_bignum(pubkey.key1, keytmp, 64);
key_to_bignum(pubkey.key1, Convert.FromBase64String(pubkeyStr), 64);
pubkey.len = bitlen_bignum(pubkey.key1, 64) - 1;
}

View File

@@ -45,7 +45,7 @@ namespace OpenRA.FileFormats
static void ReplicatePrevious( byte[] dest, int destIndex, int srcIndex, int count )
{
if( srcIndex > destIndex )
throw new NotImplementedException( string.Format( "srcIndex > destIndex {0} {1}", srcIndex, destIndex ) );
throw new NotImplementedException("srcIndex > destIndex {0} {1}".F(srcIndex, destIndex));
if( destIndex - srcIndex == 1 )
{
@@ -105,7 +105,7 @@ namespace OpenRA.FileFormats
int count = ctx.ReadWord();
int srcIndex = ctx.ReadWord();
if( srcIndex >= destIndex )
throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) );
throw new NotImplementedException("srcIndex >= destIndex {0} {1}".F(srcIndex, destIndex));
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
dest[ destIndex ] = dest[ srcIndex++ ];
@@ -116,7 +116,7 @@ namespace OpenRA.FileFormats
int count = count3 + 3;
int srcIndex = ctx.ReadWord();
if( srcIndex >= destIndex )
throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) );
throw new NotImplementedException("srcIndex >= destIndex {0} {1}".F(srcIndex, destIndex));
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
dest[ destIndex ] = dest[ srcIndex++ ];

View File

@@ -123,25 +123,7 @@ namespace OpenRA.FileFormats
return null;
}
public static Stream Open(string filename)
{
if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 )
{
var ret = GetFromCache( allFiles, filename );
if( ret != null )
return ret;
}
var folder = mountedFolders
.Where(x => x.Exists(filename))
.OrderByDescending(x => x.Priority)
.FirstOrDefault();
if (folder != null)
return folder.GetContent(filename);
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
}
public static Stream Open(string filename) { return OpenWithExts(filename, ""); }
public static Stream OpenWithExts( string filename, params string[] exts )
{
@@ -157,42 +139,39 @@ namespace OpenRA.FileFormats
foreach( var ext in exts )
{
foreach( IFolder folder in mountedFolders )
if (folder.Exists(filename + ext))
return folder.GetContent( filename + ext );
var folder = mountedFolders
.Where(x => x.Exists(filename + ext))
.OrderByDescending(x => x.Priority)
.FirstOrDefault();
if (folder != null)
return folder.GetContent(filename + ext);
}
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
throw new FileNotFoundException("File not found: {0}".F(filename), filename);
}
public static bool Exists(string filename)
{
foreach (var folder in mountedFolders)
if (folder.Exists(filename))
return true;
return false;
}
public static bool Exists(string filename) { return mountedFolders.Any(f => f.Exists(filename)); }
static Dictionary<string, Assembly> assemblyCache = new Dictionary<string, Assembly>();
public static Assembly ResolveAssembly(object sender, ResolveEventArgs e)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (assembly.FullName == e.Name)
return assembly;
}
string[] frags = e.Name.Split(',');
var frags = e.Name.Split(',');
var filename = frags[0] + ".dll";
Assembly a;
if (assemblyCache.TryGetValue(filename, out a))
return a;
if (FileSystem.Exists(filename))
using (Stream s = FileSystem.Open(filename))
using (var s = FileSystem.Open(filename))
{
byte[] buf = new byte[s.Length];
var buf = new byte[s.Length];
s.Read(buf, 0, buf.Length);
a = Assembly.Load(buf);
assemblyCache.Add(filename, a);

View File

@@ -58,7 +58,9 @@ namespace OpenRA.FileFormats
isEncrypted = 0 != (signature & (uint)MixFileFlags.Encrypted);
if( isEncrypted )
{
index = ParseRaHeader( s, out dataStart ).ToDictionary(x => x.Hash);
index = ParseRaHeader(s, out dataStart).ToDictionaryWithConflictLog(x => x.Hash,
"MixFile.RaHeader", null, x => "(offs={0}, len={1})".F(x.Offset, x.Length)
);
return;
}
}
@@ -66,7 +68,9 @@ namespace OpenRA.FileFormats
s.Seek( 0, SeekOrigin.Begin );
isEncrypted = false;
index = ParseTdHeader(s, out dataStart).ToDictionary(x => x.Hash);
index = ParseTdHeader(s, out dataStart).ToDictionaryWithConflictLog(x => x.Hash,
"MixFile.TdHeader", null, x => "(offs={0}, len={1})".F(x.Offset, x.Length)
);
}
const long headerStart = 84;

View File

@@ -97,7 +97,7 @@ namespace OpenRA.FileFormats.Graphics
case "IEND":
{
var bits = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
var bits = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
using (var ns = new MemoryStream(data.ToArray()))

View File

@@ -8,10 +8,10 @@
*/
#endregion
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
namespace OpenRA.FileFormats
{
@@ -30,9 +30,9 @@ namespace OpenRA.FileFormats
public ImageHeader( BinaryReader reader )
{
Offset = reader.ReadUInt32();
Format = (Format)( Offset >> 24 );
Offset &= 0xFFFFFF;
var data = reader.ReadUInt32();
Offset = data & 0xffffff;
Format = (Format)(data >> 24);
RefOffset = reader.ReadUInt16();
RefFormat = (Format)reader.ReadUInt16();
@@ -48,14 +48,9 @@ namespace OpenRA.FileFormats
}
}
public enum Format
{
Format20 = 0x20,
Format40 = 0x40,
Format80 = 0x80,
}
public enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
public class ShpReader : IEnumerable<ImageHeader>
public class ShpReader
{
public readonly int ImageCount;
public readonly ushort Width;
@@ -69,40 +64,37 @@ namespace OpenRA.FileFormats
public ShpReader( Stream stream )
{
BinaryReader reader = new BinaryReader( stream );
ImageCount = reader.ReadUInt16();
reader.ReadUInt16();
reader.ReadUInt16();
Width = reader.ReadUInt16();
Height = reader.ReadUInt16();
reader.ReadUInt32();
for( int i = 0 ; i < ImageCount ; i++ )
headers.Add( new ImageHeader( reader ) );
new ImageHeader( reader ); // end-of-file header
new ImageHeader( reader ); // all-zeroes header
Dictionary<uint, ImageHeader> offsets = new Dictionary<uint, ImageHeader>();
foreach( ImageHeader h in headers )
offsets.Add( h.Offset, h );
for( int i = 0 ; i < ImageCount ; i++ )
using( var reader = new BinaryReader( stream ) )
{
ImageHeader h = headers[ i ];
if( h.Format == Format.Format20 )
h.RefImage = headers[ i - 1 ];
ImageCount = reader.ReadUInt16();
reader.ReadUInt16();
reader.ReadUInt16();
Width = reader.ReadUInt16();
Height = reader.ReadUInt16();
reader.ReadUInt32();
else if( h.Format == Format.Format40 )
for( int i = 0 ; i < ImageCount ; i++ )
headers.Add( new ImageHeader( reader ) );
new ImageHeader( reader ); // end-of-file header
new ImageHeader( reader ); // all-zeroes header
var offsets = headers.ToDictionary(h => h.Offset, h =>h);
for( int i = 0 ; i < ImageCount ; i++ )
{
if( !offsets.TryGetValue( h.RefOffset, out h.RefImage ) )
throw new InvalidDataException( string.Format( "Reference doesnt point to image data {0}->{1}", h.Offset, h.RefOffset ) );
}
}
var h = headers[ i ];
if( h.Format == Format.Format20 )
h.RefImage = headers[ i - 1 ];
foreach( ImageHeader h in headers )
Decompress( stream, h );
else if( h.Format == Format.Format40 )
if( !offsets.TryGetValue( h.RefOffset, out h.RefImage ) )
throw new InvalidDataException( "Reference doesnt point to image data {0}->{1}".F(h.Offset, h.RefOffset) );
}
foreach( ImageHeader h in headers )
Decompress( stream, h );
}
}
public ImageHeader this[ int index ]
@@ -133,7 +125,7 @@ namespace OpenRA.FileFormats
}
case Format.Format80:
{
byte[] imageBytes = new byte[ Width * Height ];
var imageBytes = new byte[ Width * Height ];
Format80.DecodeInto( ReadCompressedData( stream, h ), imageBytes );
h.Image = imageBytes;
break;
@@ -147,33 +139,24 @@ namespace OpenRA.FileFormats
{
stream.Position = h.Offset;
// Actually, far too big. There's no length field with the correct length though :(
int compressedLength = (int)( stream.Length - stream.Position );
var compressedLength = (int)( stream.Length - stream.Position );
byte[] compressedBytes = new byte[ compressedLength ];
var compressedBytes = new byte[ compressedLength ];
stream.Read( compressedBytes, 0, compressedLength );
//MemoryStream ms = new MemoryStream( compressedBytes );
return compressedBytes;
}
byte[] CopyImageData( byte[] baseImage )
{
byte[] imageData = new byte[ Width * Height ];
var imageData = new byte[ Width * Height ];
for( int i = 0 ; i < Width * Height ; i++ )
imageData[ i ] = baseImage[ i ];
return imageData;
}
public IEnumerator<ImageHeader> GetEnumerator()
{
return headers.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerable<ImageHeader> Frames { get { return headers; } }
public static ShpReader Load(string filename)
{

View File

@@ -20,7 +20,7 @@ namespace OpenRA.FileFormats
public readonly string[]
Mods, Folders, Packages, Rules, ServerTraits,
Sequences, Cursors, Chrome, Assemblies, ChromeLayout,
Weapons, Voices, Music, Movies, TileSets, ChromeMetrics;
Weapons, Voices, Notifications, Music, Movies, TileSets, ChromeMetrics;
public readonly MiniYaml LoadScreen;
public readonly Dictionary<string, Pair<string,int>> Fonts;
public readonly int TileSize = 24;
@@ -44,14 +44,17 @@ namespace OpenRA.FileFormats
ChromeLayout = YamlList(yaml, "ChromeLayout");
Weapons = YamlList(yaml, "Weapons");
Voices = YamlList(yaml, "Voices");
Notifications = YamlList(yaml, "Notifications");
Music = YamlList(yaml, "Music");
Movies = YamlList(yaml, "Movies");
TileSets = YamlList(yaml, "TileSets");
ChromeMetrics = YamlList(yaml, "ChromeMetrics");
LoadScreen = yaml["LoadScreen"];
Fonts = yaml["Fonts"].NodesDict.ToDictionary(x => x.Key, x => Pair.New(x.Value.NodesDict["Font"].Value,
int.Parse(x.Value.NodesDict["Size"].Value)));
Fonts = yaml["Fonts"].NodesDict.ToDictionary(x => x.Key,
x => Pair.New(x.Value.NodesDict["Font"].Value,
int.Parse(x.Value.NodesDict["Size"].Value)));
if (yaml.ContainsKey("TileSize"))
TileSize = int.Parse(yaml["TileSize"].Value);
}
@@ -59,7 +62,7 @@ namespace OpenRA.FileFormats
static string[] YamlList(Dictionary<string, MiniYaml> yaml, string key)
{
if (!yaml.ContainsKey(key))
return new string[ 0 ];
return new string[] {};
return yaml[key].NodesDict.Keys.ToArray();
}

View File

@@ -15,6 +15,7 @@ namespace OpenRA.FileFormats
public readonly string Type;
public readonly int2 Location;
public readonly int Depth;
public SmudgeReference( string type, int2 location, int depth )
{
Type = type;
@@ -22,10 +23,9 @@ namespace OpenRA.FileFormats
Depth = depth;
}
public override string ToString ()
public override string ToString()
{
return string.Format("{0} {1},{2} {3}", Type, Location.X,Location.Y, Depth);
return "{0} {1},{2} {3}".F(Type, Location.X, Location.Y, Depth);
}
}
}

View File

@@ -20,9 +20,10 @@ namespace OpenRA.FileFormats
public class TerrainTypeInfo
{
public string Type;
public bool AcceptSmudge = true;
public string[] AcceptsSmudgeType = { };
public bool IsWater = false;
public Color Color;
public string CustomCursor;
public TerrainTypeInfo() {}
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
@@ -36,6 +37,7 @@ namespace OpenRA.FileFormats
public string Image;
public int2 Size;
public bool PickAny;
public string Category;
[FieldLoader.LoadUsing( "LoadTiles" )]
public Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
@@ -166,7 +168,7 @@ namespace OpenRA.FileFormats
bitmap.Palette = p.AsSystemPalette();
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
var data = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe

View File

@@ -105,22 +105,26 @@ namespace OpenRA.FileFormats
levels.Add(new List<MiniYamlNode>());
var lineNo = 0;
foreach (var line in lines)
foreach (var ll in lines)
{
var line = ll;
++lineNo;
if (line.Contains('#'))
line = line.Substring(0, line.IndexOf('#')).TrimEnd(' ', '\t');
var t = line.TrimStart(' ', '\t');
if (t.Length == 0 || t[0] == '#')
if (t.Length == 0)
continue;
var level = line.Length - t.Length;
var location = new MiniYamlNode.SourceLocation { Filename = filename, Line = lineNo };
if (levels.Count <= level)
throw new YamlException("Bad indent in miniyaml");
throw new YamlException("Bad indent in miniyaml at {0}".F (location));
while (levels.Count > level + 1)
levels.RemoveAt(levels.Count - 1);
var d = new List<MiniYamlNode>();
var rhs = SplitAtColon( ref t );
levels[ level ].Add( new MiniYamlNode( t, rhs, d, new MiniYamlNode.SourceLocation { Filename = filename, Line = lineNo } ) );
levels[ level ].Add( new MiniYamlNode( t, rhs, d, location ) );
levels.Add(d);
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -12,10 +12,25 @@
<AssemblyName>OpenRA.FileFormats</AssemblyName>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -27,6 +42,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>bin\Release\</OutputPath>
@@ -37,6 +53,7 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -116,6 +133,23 @@
<Compile Include="Thirdparty\Random.cs" />
<Compile Include="TypeDictionary.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
@@ -124,4 +158,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -46,9 +46,9 @@ namespace OpenRA.FileFormats
{
string filename;
if (Names.TryGetValue(Hash, out filename))
return string.Format("{0} - offset 0x{1:x8} - length 0x{2:x8}", filename, Offset, Length);
return "{0} - offset 0x{1:x8} - length 0x{2:x8}".F(filename, Offset, Length);
else
return string.Format("0x{0:x8} - offset 0x{1:x8} - length 0x{2:x8}", Hash, Offset, Length);
return "0x{0:x8} - offset 0x{1:x8} - length 0x{2:x8}".F(Hash, Offset, Length);
}
public static uint HashFilename(string name)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -39,7 +39,7 @@ namespace OpenRA.FileFormats
get { return colors; }
}
public Palette(Stream s, bool remapTransparent)
public Palette(Stream s, int[] remapShadow)
{
colors = new uint[256];
@@ -54,13 +54,9 @@ namespace OpenRA.FileFormats
}
}
colors[0] = 0;
if (remapTransparent)
{
colors[1] = 178u << 24; // Hack for d2k; may have side effects
colors[3] = 178u << 24;
colors[4] = 140u << 24;
}
colors[0] = 0; //convert black background to transparency
foreach (int i in remapShadow)
colors[i] = 140u << 24;
}
public Palette(Palette p, IPaletteRemap r)
@@ -92,12 +88,12 @@ namespace OpenRA.FileFormats
return pal;
}
public static Palette Load( string filename, bool remap )
public static Palette Load(string filename, int[] remap)
{
using(var s = File.OpenRead(filename))
return new Palette(s, remap);
}
}
public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); }
public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); }
}

View File

@@ -14,33 +14,33 @@ using System.Linq;
namespace OpenRA.FileFormats
{
// TODO: ship this out of here.
public enum PaletteFormat { ra, cnc, d2k }
public class PlayerColorRemap : IPaletteRemap
{
Dictionary<int, Color> remapColors;
public PlayerColorRemap(PaletteFormat fmt, ColorRamp c)
public static int GetRemapIndex(int[] Ramp, int i)
{
var c1 = c.GetColor(0);
var c2 = c.GetColor(1); /* temptemp: this can be expressed better */
var baseIndex = (fmt == PaletteFormat.cnc) ? 0xb0 : (fmt == PaletteFormat.d2k) ? 240 : 80;
var ramp = (fmt == PaletteFormat.cnc)
? new[] { 0, 2, 4, 6, 8, 10, 13, 15, 1, 3, 5, 7, 9, 11, 12, 14 }
: new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
remapColors = ramp.Select((x, i) => Pair.New(baseIndex + i, ColorLerp(x / 16f, c1, c2)))
.ToDictionary(u => u.First, u => u.Second);
return Ramp[i];
}
public static Color ColorLerp(float t, Color c1, Color c2)
public PlayerColorRemap(int[] Ramp, ColorRamp c)
{
return Color.FromArgb(255,
(int)(t * c2.R + (1 - t) * c1.R),
(int)(t * c2.G + (1 - t) * c1.G),
(int)(t * c2.B + (1 - t) * c1.B));
var c1 = c.GetColor(0);
var c2 = c.GetColor(1); // temptemp: this can be expressed better
var baseIndex = Ramp[0];
var RemapRamp = Ramp.Select(r => r - Ramp[0]).ToArray();
if (Ramp[0] > Ramp[15]) // reversed remapping
{
baseIndex = Ramp[15];
for (int i=15; i>0; i--)
RemapRamp = Ramp.Select(r => r - Ramp[15]).ToArray();
}
remapColors = RemapRamp.Select((x, i) => Pair.New(baseIndex + i, Exts.ColorLerp(x / 16f, c1, c2)))
.ToDictionary(u => u.First, u => u.Second);
}
public Color GetRemappedColor(Color original, int index)

View File

@@ -56,7 +56,7 @@ namespace OpenRA.FileFormats
public int CompareTo(DelayedAction other)
{
return Math.Sign(Time - other.Time);
return Time.CompareTo(other.Time);
}
}
}

View File

@@ -12,7 +12,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
namespace OpenRA.Collections
namespace OpenRA.FileFormats
{
public class Set<T> : IEnumerable<T>
{
@@ -44,5 +44,13 @@ namespace OpenRA.Collections
{
return GetEnumerator();
}
public bool Contains( T obj ) { return data.ContainsKey(obj); }
public Set( params T[] ts )
{
foreach( var t in ts )
Add(t);
}
}
}

View File

@@ -92,7 +92,7 @@ namespace OpenRA
public static float Dot(float2 a, float2 b) { return a.X * b.X + a.Y * b.Y; }
public float2 Round() { return new float2((float)Math.Round(X), (float)Math.Round(Y)); }
public override string ToString() { return string.Format("({0},{1})", X, Y); }
public override string ToString() { return "({0},{1})".F(X, Y); }
public int2 ToInt2() { return new int2((int)X, (int)Y); }
public static float2 Max(float2 a, float2 b) { return new float2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }

View File

@@ -55,7 +55,7 @@ namespace OpenRA
public PointF ToPointF() { return new PointF(X, Y); }
public float2 ToFloat2() { return new float2(X, Y); }
public override string ToString() { return string.Format("{0},{1}", X, Y); }
public override string ToString() { return "{0},{1}".F(X, Y); }
// Change endianness of a uint32
public static uint Swap(uint orig)

View File

@@ -48,17 +48,17 @@ namespace OpenRA.FileFormats
public bool Contains<T>()
{
return dataSingular.ContainsKey( typeof( T ) ) || dataMultiple.ContainsKey( typeof( T ) );
return dataSingular.ContainsKey(typeof(T)) || dataMultiple.ContainsKey(typeof(T));
}
public T Get<T>()
{
if( dataMultiple.ContainsKey( typeof( T ) ) )
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
if (dataMultiple.ContainsKey(typeof(T)))
throw new InvalidOperationException("TypeDictionary contains multiple instance of type `{0}`".F(typeof(T)));
object ret;
if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
throw new InvalidOperationException(string.Format("TypeDictionary does not contain instance of type `{0}`", typeof(T)));
if (!dataSingular.TryGetValue(typeof(T), out ret))
throw new InvalidOperationException("TypeDictionary does not contain instance of type `{0}`".F(typeof(T)));
return (T)ret;
}
@@ -69,11 +69,11 @@ namespace OpenRA.FileFormats
public object GetOrDefault(Type t)
{
if( dataMultiple.ContainsKey(t) )
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", t ) );
if (dataMultiple.ContainsKey(t))
throw new InvalidOperationException("TypeDictionary contains multiple instances of type `{0}`".F(t));
object ret;
if( !dataSingular.TryGetValue(t, out ret ) )
if (!dataSingular.TryGetValue(t, out ret))
return null;
return ret;
}

View File

@@ -32,9 +32,9 @@ namespace OpenRA
public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } }
public int2 Location { get { return occupySpace.Value.TopLeft; } }
public CPos Location { get { return occupySpace.Value.TopLeft; } }
public int2 CenterLocation
public PPos CenterLocation
{
get
{
@@ -123,22 +123,30 @@ namespace OpenRA
// at its current altitude
Rectangle CalculateBounds(bool useAltitude)
{
var size = Size.Value;
var size = (PVecInt)(Size.Value);
var loc = CenterLocation - size / 2;
var si = Info.Traits.GetOrDefault<SelectableInfo>();
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
{
#if true
loc += new PVecInt(si.Bounds[2], si.Bounds[3]);
#else
loc.X += si.Bounds[2];
loc.Y += si.Bounds[3];
#endif
}
var move = Move.Value;
if (move != null)
{
#if true
loc -= new PVecInt(0, move.Altitude);
#else
loc.Y -= move.Altitude;
#endif
if (useAltitude)
size = new int2(size.X, size.Y + move.Altitude);
size = new PVecInt(size.X, size.Y + move.Altitude);
}
return new Rectangle(loc.X, loc.Y, size.X, size.Y);

View File

@@ -62,20 +62,28 @@ namespace OpenRA
public int Value( World world ) { return value; }
}
public class LocationInit : IActorInit<int2>
public class LocationInit : IActorInit<CPos>
{
[FieldFromYamlKey] public readonly int2 value = int2.Zero;
public LocationInit() { }
public LocationInit( int2 init ) { value = init; }
public int2 Value( World world ) { return value; }
public LocationInit( CPos init ) { value = init.ToInt2(); }
public CPos Value(World world) { return (CPos)value; }
}
public class CenterLocationInit : IActorInit<int2>
public class SubCellInit : IActorInit<SubCell>
{
[FieldFromYamlKey] public readonly int value = 0;
public SubCellInit() { }
public SubCellInit(int init) { value = init; }
public SubCell Value(World world) { return (SubCell)value; }
}
public class CenterLocationInit : IActorInit<PPos>
{
[FieldFromYamlKey] public readonly int2 value = int2.Zero;
public CenterLocationInit() { }
public CenterLocationInit( int2 init ) { value = init; }
public int2 Value( World world ) { return value; }
public CenterLocationInit(PPos init) { value = init.ToInt2(); }
public PPos Value(World world) { return (PPos)value; }
}
public class OwnerInit : IActorInit<Player>

View File

@@ -37,7 +37,7 @@ namespace OpenRA
world.ActorRemoved += a => Remove( a, a.OccupiesSpace );
}
public IEnumerable<Actor> GetUnitsAt( int2 a )
public IEnumerable<Actor> GetUnitsAt(CPos a)
{
if (!map.IsInMap(a)) yield break;
@@ -46,7 +46,7 @@ namespace OpenRA
yield return i.actor;
}
public IEnumerable<Actor> GetUnitsAt( int2 a, SubCell sub )
public IEnumerable<Actor> GetUnitsAt(CPos a, SubCell sub)
{
if (!map.IsInMap(a)) yield break;
@@ -55,7 +55,7 @@ namespace OpenRA
yield return i.actor;
}
public bool HasFreeSubCell(int2 a)
public bool HasFreeSubCell(CPos a)
{
if (!AnyUnitsAt(a))
return true;
@@ -64,12 +64,12 @@ namespace OpenRA
SubCell.BottomLeft, SubCell.BottomRight }.Any(b => !AnyUnitsAt(a,b));
}
public bool AnyUnitsAt(int2 a)
public bool AnyUnitsAt(CPos a)
{
return influence[ a.X, a.Y ] != null;
}
public bool AnyUnitsAt(int2 a, SubCell sub)
public bool AnyUnitsAt(CPos a, SubCell sub)
{
for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next )
if (i.subCell == sub || i.subCell == SubCell.FullCell)

71
OpenRA.Game/CPos.cs Normal file
View File

@@ -0,0 +1,71 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Cell coordinate position in the world (coarse).
/// </summary>
public struct CPos
{
public readonly int X, Y;
public CPos(int x, int y) { X = x; Y = y; }
public static readonly CPos Zero = new CPos(0, 0);
public static explicit operator CPos(int2 a) { return new CPos(a.X, a.Y); }
public static CPos operator +(CVec a, CPos b) { return new CPos(a.X + b.X, a.Y + b.Y); }
public static CPos operator +(CPos a, CVec b) { return new CPos(a.X + b.X, a.Y + b.Y); }
public static CPos operator -(CPos a, CVec b) { return new CPos(a.X - b.X, a.Y - b.Y); }
public static CVec operator -(CPos a, CPos b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(CPos me, CPos other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(CPos me, CPos other) { return !(me == other); }
public static CPos Max(CPos a, CPos b) { return new CPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static CPos Min(CPos a, CPos b) { return new CPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public PPos ToPPos() { return new PPos(Game.CellSize * X, Game.CellSize * Y); }
public CPos Clamp(Rectangle r)
{
return new CPos(Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top)));
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
CPos o = (CPos)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
public static class RectangleExtensions
{
public static CPos TopLeftAsCPos(this Rectangle r) { return new CPos(r.Left, r.Top); }
public static CPos BottomRightAsCPos(this Rectangle r) { return new CPos(r.Right, r.Bottom); }
}
}

76
OpenRA.Game/CVec.cs Normal file
View File

@@ -0,0 +1,76 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Cell coordinate vector (coarse).
/// </summary>
public struct CVec
{
public readonly int X, Y;
public CVec(int x, int y) { X = x; Y = y; }
public CVec(Size p) { X = p.Width; Y = p.Height; }
public static readonly CVec Zero = new CVec(0, 0);
public static explicit operator CVec(int2 a) { return new CVec(a.X, a.Y); }
public static explicit operator CVec(float2 a) { return new CVec((int)a.X, (int)a.Y); }
public static CVec operator +(CVec a, CVec b) { return new CVec(a.X + b.X, a.Y + b.Y); }
public static CVec operator -(CVec a, CVec b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static CVec operator *(int a, CVec b) { return new CVec(a * b.X, a * b.Y); }
public static CVec operator *(CVec b, int a) { return new CVec(a * b.X, a * b.Y); }
public static CVec operator /(CVec a, int b) { return new CVec(a.X / b, a.Y / b); }
public static CVec operator -(CVec a) { return new CVec(-a.X, -a.Y); }
public static bool operator ==(CVec me, CVec other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(CVec me, CVec other) { return !(me == other); }
public static CVec Max(CVec a, CVec b) { return new CVec(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static CVec Min(CVec a, CVec b) { return new CVec(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static int Dot(CVec a, CVec b) { return a.X * b.X + a.Y * b.Y; }
public CVec Sign() { return new CVec(Math.Sign(X), Math.Sign(Y)); }
public CVec Abs() { return new CVec(Math.Abs(X), Math.Abs(Y)); }
public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public CVec Clamp(Rectangle r)
{
return new CVec(
Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top))
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
CVec o = (CVec)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

View File

@@ -50,13 +50,8 @@ namespace OpenRA
public static void JoinServer(string host, int port)
{
var replayFilename = ChooseReplayFilename();
string path = Path.Combine( Platform.SupportDir, "Replays" );
if( !Directory.Exists( path ) ) Directory.CreateDirectory( path );
var replayFile = File.Create( Path.Combine( path, replayFilename ) );
JoinInner(new OrderManager(host, port,
new ReplayRecorderConnection(new NetworkConnection(host, port), replayFile)));
new ReplayRecorderConnection(new NetworkConnection(host, port), ChooseReplayFilename)));
}
static string ChooseReplayFilename()
@@ -95,14 +90,14 @@ namespace OpenRA
// Hacky workaround for orderManager visibility
public static Widget OpenWindow(World world, string widget)
{
return Widget.OpenWindow(widget, new WidgetArgs() {{ "world", world }, { "orderManager", orderManager }, { "worldRenderer", worldRenderer }});
return Ui.OpenWindow(widget, new WidgetArgs() {{ "world", world }, { "orderManager", orderManager }, { "worldRenderer", worldRenderer }});
}
// Who came up with the great idea of making these things
// impossible for the things that want them to access them directly?
public static Widget OpenWindow(string widget, WidgetArgs args)
{
return Widget.OpenWindow(widget, new WidgetArgs(args)
return Ui.OpenWindow(widget, new WidgetArgs(args)
{
{ "world", worldRenderer.world },
{ "orderManager", orderManager },
@@ -160,7 +155,7 @@ namespace OpenRA
using( new PerfSample( "tick_time" ) )
{
orderManager.LastTickTime += Settings.Game.Timestep;
Widget.DoTick();
Ui.Tick();
var world = orderManager.world;
if (orderManager.GameStarted)
++Viewport.TicksSinceLastMove;
@@ -171,7 +166,7 @@ namespace OpenRA
{
var isNetTick = LocalTick % NetTickScale == 0;
if (!isNetTick || orderManager.IsReadyForNextFrame)
if ((!isNetTick || orderManager.IsReadyForNextFrame) && !orderManager.GamePaused )
{
++orderManager.LocalFrameNumber;
@@ -193,6 +188,8 @@ namespace OpenRA
else
if (orderManager.NetFrameNumber == 0)
orderManager.LastTickTime = Environment.TickCount;
viewport.Tick();
}
}
}
@@ -215,7 +212,7 @@ namespace OpenRA
worldRenderer = new WorldRenderer(orderManager.world);
if (orderManager.GameStarted) return;
Widget.SelectedWidget = null;
Ui.SelectedWidget = null;
orderManager.LocalFrameNumber = 0;
orderManager.LastTickTime = Environment.TickCount;
@@ -225,7 +222,12 @@ namespace OpenRA
public static bool IsHost
{
get { return orderManager.Connection.LocalClientId == 0; }
get
{
var client= orderManager.LobbyInfo.ClientWithIndex (
orderManager.Connection.LocalClientId);
return ((client!=null) && client.IsAdmin);
}
}
public static Dictionary<String, Mod> CurrentMods
@@ -244,7 +246,6 @@ namespace OpenRA
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
Settings = new Settings(Platform.SupportDir + "settings.yaml", args);
Settings.Save();
Log.LogPath = Platform.SupportDir + "Logs" + Path.DirectorySeparatorChar;
Log.AddChannel("perf", "perf.log");
@@ -259,7 +260,7 @@ namespace OpenRA
foreach(var mod in Mod.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
Sound.Create();
Sound.Create(Settings.Sound.Engine);
InitializeWithMods(Settings.Game.Mods);
}
@@ -270,7 +271,7 @@ namespace OpenRA
AddChatLine = (a,b,c) => {};
ConnectionStateChanged = om => {};
BeforeGameStart = () => {};
Widget.ResetAll();
Ui.ResetAll();
worldRenderer = null;
if (server != null)
@@ -278,11 +279,11 @@ namespace OpenRA
if (orderManager != null)
orderManager.Dispose();
// Discard any invalid mods
// Discard any invalid mods, set RA as default
var mm = mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray();
if (mm.Length == 0) mm = new[] { "ra" };
Console.WriteLine("Loading mods: {0}", mm.JoinWith(","));
Settings.Game.Mods = mm;
Settings.Save();
Sound.StopMusic();
Sound.StopVideo();
@@ -302,6 +303,7 @@ namespace OpenRA
viewport = new Viewport(new int2(Renderer.Resolution), Rectangle.Empty, Renderer);
modData.LoadScreen.StartGame();
Settings.Save();
}
public static void LoadShellMap()
@@ -390,6 +392,7 @@ namespace OpenRA
// Work around a miscompile in mono 2.6.7:
// booleans that default to true cannot be set false by an initializer
settings.AdvertiseOnline = false;
settings.AllowUPnP = false;
server = new Server.Server(new IPEndPoint(IPAddress.Loopback, 0),
Game.Settings.Game.Mods, settings, modData);

View File

@@ -20,7 +20,8 @@ namespace OpenRA
{
public static Dictionary<string, ActorInfo> Info;
public static Dictionary<string, WeaponInfo> Weapons;
public static Dictionary<string, VoiceInfo> Voices;
public static Dictionary<string, SoundInfo> Voices;
public static Dictionary<string, SoundInfo> Notifications;
public static Dictionary<string, MusicInfo> Music;
public static Dictionary<string, string> Movies;
public static Dictionary<string, TileSet> TileSets;
@@ -30,7 +31,8 @@ namespace OpenRA
// Added support to extend the list of rules (add it to m.LocalRules)
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new VoiceInfo(k.Value));
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new SoundInfo(k.Value));
Notifications = LoadYamlRules(m.Notifications, map.Notifications, (k, _) => new SoundInfo(k.Value));
Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));
Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);

View File

@@ -19,6 +19,9 @@ using OpenRA.Server;
namespace OpenRA.GameRules
{
public enum MouseScrollType { Disabled, Standard, Inverted }
public enum SoundCashTicks { Disabled, Normal, Extreme }
public class ServerSettings
{
public string Name = "OpenRA Game";
@@ -26,8 +29,11 @@ namespace OpenRA.GameRules
public int ExternalPort = 1234;
public bool AdvertiseOnline = true;
public string MasterServer = "http://master.open-ra.org/";
public bool AllowUPnP = false;
public bool AllowCheats = false;
public string Map = null;
public string[] Ban = null;
public int TimeOut = 0;
public ServerSettings() { }
@@ -38,8 +44,11 @@ namespace OpenRA.GameRules
ExternalPort = other.ExternalPort;
AdvertiseOnline = other.AdvertiseOnline;
MasterServer = other.MasterServer;
AllowUPnP = other.AllowUPnP;
AllowCheats = other.AllowCheats;
Map = other.Map;
Ban = other.Ban;
TimeOut = other.TimeOut;
}
}
@@ -76,6 +85,9 @@ namespace OpenRA.GameRules
public bool Shuffle = false;
public bool Repeat = false;
public bool ShellmapMusic = true;
public string Engine = "AL";
public SoundCashTicks SoundCashTickType = SoundCashTicks.Extreme;
}
public class PlayerSettings
@@ -85,8 +97,6 @@ namespace OpenRA.GameRules
public string LastServer = "localhost:1234";
}
public enum MouseScrollType { Disabled, Standard, Inverted }
public class GameSettings
{
public string[] Mods = { "ra" };

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
@@ -15,12 +15,16 @@ using OpenRA.FileFormats;
namespace OpenRA.GameRules
{
public class VoiceInfo
public class SoundInfo
{
[FieldLoader.Ignore] public readonly Dictionary<string,string[]> Variants;
[FieldLoader.Ignore] public readonly Dictionary<string,string[]> Prefixes;
[FieldLoader.Ignore] public readonly Dictionary<string,string[]> Voices;
[FieldLoader.Ignore] public readonly Dictionary<string,string[]> Notifications;
public readonly string DefaultVariant = ".aud" ;
public readonly string DefaultPrefix = "" ;
public readonly string[] DisableVariants = { };
public readonly string[] DisablePrefixes = { };
static Dictionary<string, string[]> Load( MiniYaml y, string name )
{
@@ -31,30 +35,28 @@ namespace OpenRA.GameRules
: new Dictionary<string, string[]>();
}
public readonly OpenRA.FileFormats.Lazy<Dictionary<string, VoicePool>> Pools;
public readonly OpenRA.FileFormats.Lazy<Dictionary<string, SoundPool>> VoicePools;
public readonly OpenRA.FileFormats.Lazy<Dictionary<string, SoundPool>> NotificationsPools;
public VoiceInfo( MiniYaml y )
public SoundInfo( MiniYaml y )
{
FieldLoader.Load( this, y );
Variants = Load(y, "Variants");
Prefixes = Load(y, "Prefixes");
Voices = Load(y, "Voices");
Notifications = Load(y, "Notifications");
if (!Voices.ContainsKey("Attack"))
Voices.Add("Attack", Voices["Move"]);
if (!Voices.ContainsKey("AttackMove"))
Voices.Add("AttackMove", Voices["Move"]);
Pools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new VoicePool(a.Value) ));
VoicePools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new SoundPool(a.Value) ));
NotificationsPools = Lazy.New(() => Notifications.ToDictionary( a => a.Key, a => new SoundPool(a.Value) ));
}
}
public class VoicePool
public class SoundPool
{
readonly string[] clips;
readonly List<string> liveclips = new List<string>();
public VoicePool(params string[] clips)
public SoundPool(params string[] clips)
{
this.clips = clips;
}

View File

@@ -24,9 +24,9 @@ namespace OpenRA.GameRules
public readonly bool Ore = false; // can this damage ore?
public readonly string Explosion = null; // explosion effect to use
public readonly string WaterExplosion = null; // explosion effect on hitting water (usually a splash)
public readonly string SmudgeType = null; // type of smudge to apply
public readonly string[] SmudgeType = { }; // type of smudge to apply
public readonly int[] Size = { 0, 0 }; // size of the explosion. provide 2 values for a ring effect (outer/inner)
public readonly int InfDeath = 0; // infantry death animation to use
public readonly int InfDeath = 1; // infantry death animation to use
public readonly string ImpactSound = null; // sound to play on impact
public readonly string WaterImpactSound = null; // sound to play on impact with water
public readonly int Damage = 0; // how much (raw) damage to deal
@@ -72,11 +72,11 @@ namespace OpenRA.GameRules
{
public WeaponInfo weapon;
public Actor firedBy;
public int2 src;
public PPos src;
public int srcAltitude;
public int facing;
public Target target;
public int2 dest;
public PPos dest;
public int destAltitude;
public float firepowerModifier = 1.0f;
}
@@ -91,7 +91,7 @@ namespace OpenRA.GameRules
public readonly int Burst = 1;
public readonly bool Charges = false;
public readonly bool Underwater = false;
public readonly string[] ValidTargets = { "Ground" };
public readonly string[] ValidTargets = { "Ground", "Water" };
public readonly int BurstDelay = 5;
public readonly float MinRange = 0;

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Graphics
public Renderable Image(Actor self, string pal)
{
var p = self.CenterLocation;
var loc = p - 0.5f * Animation.Image.size
var loc = p.ToFloat2() - 0.5f * Animation.Image.size
+ (OffsetFunc != null ? OffsetFunc() : float2.Zero);
var r = new Renderable(Animation.Image, loc, pal, p.Y);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -25,9 +25,16 @@ namespace OpenRA.Graphics
{
cursors = new Dictionary<string, CursorSequence>();
var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
int[] ShadowIndex = { };
if (sequences.NodesDict.ContainsKey("ShadowIndex"))
{
Array.Resize(ref ShadowIndex, ShadowIndex.Length + 1);
ShadowIndex[ShadowIndex.Length - 1] = Convert.ToInt32(sequences.NodesDict["ShadowIndex"].Value);
}
foreach (var s in sequences.NodesDict["Palettes"].Nodes)
Game.modData.Palette.AddPalette(s.Key, new Palette(FileSystem.Open(s.Value.Value), false));
Game.modData.Palette.AddPalette(s.Key, new Palette(FileSystem.Open(s.Value.Value), ShadowIndex));
foreach (var s in sequences.NodesDict["Cursors"].Nodes)
LoadSequencesForCursor(s.Key, s.Value);

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Graphics
{
var vb = renderer.GetTempVertexBuffer();
vb.SetData( vertices, nv );
renderer.SetLineWidth(LineWidth);
renderer.SetLineWidth(LineWidth * Game.viewport.Zoom);
renderer.DrawBatch( vb, 0, nv, PrimitiveType.LineList );
} );

View File

@@ -32,13 +32,11 @@ namespace OpenRA.Graphics
var height = map.Bounds.Height;
if (!actualSize)
{
width = height = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
}
var terrain = new Bitmap(width, height);
var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height),
var bitmapData = terrain.LockBits(terrain.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
@@ -69,7 +67,7 @@ namespace OpenRA.Graphics
Bitmap terrain = new Bitmap(terrainBitmap);
var tileset = Rules.TileSets[map.Tileset];
var bitmapData = terrain.LockBits(new Rectangle(0, 0, terrain.Width, terrain.Height),
var bitmapData = terrain.LockBits(terrain.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
@@ -104,7 +102,7 @@ namespace OpenRA.Graphics
var map = world.Map;
var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
var bitmap = new Bitmap(size, size);
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
@@ -132,7 +130,7 @@ namespace OpenRA.Graphics
var map = world.Map;
var size = Exts.NextPowerOf2(Math.Max(map.Bounds.Width, map.Bounds.Height));
var bitmap = new Bitmap(size, size);
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
@@ -163,7 +161,7 @@ namespace OpenRA.Graphics
if (world.LocalShroud.Disabled)
return bitmap;
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
var shroud = Color.Black.ToArgb();

View File

@@ -76,8 +76,6 @@ namespace OpenRA.Graphics
public void BeginFrame(float2 scroll, float zoom)
{
device.Clear();
WorldLineRenderer.LineWidth = zoom;
float2 r1 = new float2(2f/Resolution.Width, -2f/Resolution.Height);
float2 r2 = new float2(-1, 1);
var zr1 = zoom*r1;

View File

@@ -27,10 +27,9 @@ namespace OpenRA.Graphics
public int Facings { get { return facings; } }
public int Tick { get { return tick; } }
string srcOverride;
public Sequence(string unit, string name, MiniYaml info)
{
srcOverride = info.Value;
var srcOverride = info.Value;
Name = name;
var d = info.NodesDict;
@@ -62,26 +61,6 @@ namespace OpenRA.Graphics
info.Nodes[0].Location));
}
public MiniYaml Save()
{
var root = new List<MiniYamlNode>();
root.Add(new MiniYamlNode("Start", start.ToString()));
if (length > 1 && (start != 0 || length != sprites.Length - start))
root.Add(new MiniYamlNode("Length", length.ToString()));
else if (length > 1 && length == sprites.Length - start)
root.Add(new MiniYamlNode("Length", "*"));
if (facings > 1)
root.Add(new MiniYamlNode("Facings", facings.ToString()));
if (tick != 40)
root.Add(new MiniYamlNode("Tick", tick.ToString()));
return new MiniYaml(srcOverride, root);
}
public Sprite GetSprite( int frame )
{
return GetSprite( frame, 0 );

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Graphics
Sprite[] LoadSprites(string filename)
{
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
return shp.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
return shp.Frames.Select(a => SheetBuilder.Add(a.Image, shp.Size)).ToArray();
}
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }

View File

@@ -8,40 +8,12 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using OpenRA.FileFormats.Graphics;
namespace OpenRA.Graphics
{
public static class Util
{
public static string[] ReadAllLines(Stream s)
{
List<string> result = new List<string>();
using (StreamReader reader = new StreamReader(s))
while(!reader.EndOfStream)
{
var line = reader.ReadLine();
if( !string.IsNullOrEmpty( line ) && line[0] != '#' )
result.Add( line );
}
return result.ToArray();
}
public static T[] MakeArray<T>(int count, Converter<int, T> f)
{
T[] result = new T[count];
for (int i = 0; i < count; i++)
result[i] = f(i);
return result;
}
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
public static void FastCreateQuad(Vertex[] vertices, float2 o, Sprite r, int palette, int nv, float2 size)
@@ -59,6 +31,7 @@ namespace OpenRA.Graphics
}
static readonly int[] channelMasks = { 2, 1, 0, 3 }; // yes, our channel order is nuts.
public static void FastCopyIntoChannel(Sprite dest, byte[] src)
{
var data = dest.sheet.Data;
@@ -79,28 +52,5 @@ namespace OpenRA.Graphics
destOffset += destSkip;
}
}
public static Color Lerp(float t, Color a, Color b)
{
return Color.FromArgb(
LerpChannel(t, a.A, b.A),
LerpChannel(t, a.R, b.R),
LerpChannel(t, a.G, b.G),
LerpChannel(t, a.B, b.B));
}
public static int LerpARGBColor(float t, int c1, int c2)
{
int a = LerpChannel(t, (c1 >> 24) & 255, (c2 >> 24) & 255);
int r = LerpChannel(t, (c1 >> 16) & 255, (c2 >> 16) & 255);
int g = LerpChannel(t, (c1 >> 8) & 255, (c2 >> 8) & 255);
int b = LerpChannel(t, c1 & 255, c2 & 255);
return (a << 24) | (r << 16) | (g << 8) | b;
}
public static int LerpChannel(float t, int a, int b)
{
return (int)((1 - t) * a + t * b);
}
}
}

View File

@@ -126,15 +126,15 @@ namespace OpenRA.Graphics
using( new PerfSample("render_widgets") )
{
Widget.DoDraw();
var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default";
Ui.Draw();
var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default";
var cursorSequence = CursorProvider.GetCursorSequence(cursorName);
var cursorSprite = cursorSequence.GetSprite((int)cursorFrame);
renderer.SpriteRenderer.DrawSprite(cursorSprite,
Viewport.LastMousePos - cursorSequence.Hotspot,
Game.modData.Palette.GetPaletteIndex(cursorSequence.Palette),
cursorSprite.size);
Viewport.LastMousePos - cursorSequence.Hotspot,
Game.modData.Palette.GetPaletteIndex(cursorSequence.Palette),
cursorSprite.size);
}
using( new PerfSample("render_flip") )
@@ -149,18 +149,18 @@ namespace OpenRA.Graphics
}
// Convert from viewport coords to cell coords (not px)
public float2 ViewToWorld(MouseInput mi) { return ViewToWorld(mi.Location); }
public float2 ViewToWorld(int2 loc)
public CPos ViewToWorld(MouseInput mi) { return ViewToWorld(mi.Location); }
public CPos ViewToWorld(int2 loc)
{
return (1f / Game.CellSize) * (1f/Zoom*loc.ToFloat2() + Location);
return (CPos)( (1f / Game.CellSize) * (1f/Zoom*loc.ToFloat2() + Location) ).ToInt2();
}
public int2 ViewToWorldPx(int2 loc) { return (1f/Zoom*loc.ToFloat2() + Location).ToInt2(); }
public int2 ViewToWorldPx(MouseInput mi) { return ViewToWorldPx(mi.Location); }
public PPos ViewToWorldPx(int2 loc) { return (PPos)(1f/Zoom*loc.ToFloat2() + Location).ToInt2(); }
public PPos ViewToWorldPx(MouseInput mi) { return ViewToWorldPx(mi.Location); }
public void Center(float2 loc)
{
scrollPosition = NormalizeScrollPosition((Game.CellSize*loc - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2());
scrollPosition = NormalizeScrollPosition((Game.CellSize * loc - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2());
}
public void Center(IEnumerable<Actor> actors)
@@ -168,9 +168,9 @@ namespace OpenRA.Graphics
if (!actors.Any()) return;
var avgPos = actors
.Select(a => a.CenterLocation)
.Select(a => (PVecInt)a.CenterLocation)
.Aggregate((a, b) => a + b) / actors.Count();
scrollPosition = NormalizeScrollPosition((avgPos - 1f/(2*Zoom)*screenSize.ToFloat2()).ToInt2());
scrollPosition = NormalizeScrollPosition(((PVecFloat)avgPos - (PVecFloat)(1f / (2 * Zoom) * screenSize.ToFloat2())).ToInt2());
}
// Rectangle (in viewport coords) that contains things to be drawn
@@ -194,7 +194,7 @@ namespace OpenRA.Graphics
{
if (cachedScroll != scrollPosition)
{
int2 boundary = new int2(1,1); // Add a curtain of cells around the viewport to account for rounding errors
var boundary = new int2(1,1); // Add a curtain of cells around the viewport to account for rounding errors
var tl = ViewToWorld(int2.Zero).ToInt2() - boundary;
var br = ViewToWorld(new int2(Width, Height)).ToInt2() + boundary;

View File

@@ -53,8 +53,9 @@ namespace OpenRA.Graphics
var comparer = new SpriteComparer();
var actors = world.FindUnits(
new int2(Game.CellSize*bounds.Left, Game.CellSize*bounds.Top),
new int2(Game.CellSize*bounds.Right, Game.CellSize*bounds.Bottom));
bounds.TopLeftAsCPos().ToPPos(),
bounds.BottomRightAsCPos().ToPPos()
);
var renderables = actors.SelectMany(a => a.Render())
.OrderBy(r => r, comparer);
@@ -140,25 +141,21 @@ namespace OpenRA.Graphics
selectable.DrawRollover(this, unit);
}
public void DrawLocus(Color c, int2[] cells)
public void DrawLocus(Color c, CPos[] cells)
{
var dict = cells.ToDictionary(a => a, a => 0);
var wlr = Game.Renderer.WorldLineRenderer;
foreach (var t in dict.Keys)
{
if (!dict.ContainsKey(t + new int2(-1, 0)))
wlr.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(0, 1)),
c, c);
if (!dict.ContainsKey(t + new int2(1, 0)))
wlr.DrawLine(Game.CellSize * (t + new int2(1, 0)), Game.CellSize * (t + new int2(1, 1)),
c, c);
if (!dict.ContainsKey(t + new int2(0, -1)))
wlr.DrawLine(Game.CellSize * t, Game.CellSize * (t + new int2(1, 0)),
c, c);
if (!dict.ContainsKey(t + new int2(0, 1)))
wlr.DrawLine(Game.CellSize * (t + new int2(0, 1)), Game.CellSize * (t + new int2(1, 1)),
c, c);
if (!dict.ContainsKey(t + new CVec(-1, 0)))
wlr.DrawLine(t.ToPPos().ToFloat2(), (t + new CVec(0, 1)).ToPPos().ToFloat2(), c, c);
if (!dict.ContainsKey(t + new CVec(1, 0)))
wlr.DrawLine((t + new CVec(1, 0)).ToPPos().ToFloat2(), (t + new CVec(1, 1)).ToPPos().ToFloat2(), c, c);
if (!dict.ContainsKey(t + new CVec(0, -1)))
wlr.DrawLine(t.ToPPos().ToFloat2(), (t + new CVec(1, 0)).ToPPos().ToFloat2(), c, c);
if (!dict.ContainsKey(t + new CVec(0, 1)))
wlr.DrawLine((t + new CVec(0, 1)).ToPPos().ToFloat2(), (t + new CVec(1, 1)).ToPPos().ToFloat2(), c, c);
}
}

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
@@ -35,18 +35,12 @@ namespace OpenRA
public void OnKeyInput( KeyInput input )
{
Sync.CheckSyncUnchanged( world, () =>
{
Widget.DoHandleKeyPress( input );
} );
Sync.CheckSyncUnchanged(world, () => Ui.HandleKeyPress(input));
}
public void OnMouseInput( MouseInput input )
{
Sync.CheckSyncUnchanged( world, () =>
{
Widget.DoHandleInput( input );
} );
Sync.CheckSyncUnchanged(world, () => Ui.HandleInput(input));
}
}
}

View File

@@ -56,17 +56,11 @@ namespace OpenRA
[FieldLoader.Ignore] public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
[FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges;
// Rules overrides
[FieldLoader.Ignore] public List<MiniYamlNode> Rules = new List<MiniYamlNode>();
// Sequences overrides
[FieldLoader.Ignore] public List<MiniYamlNode> Sequences = new List<MiniYamlNode>();
// Weapon overrides
[FieldLoader.Ignore] public List<MiniYamlNode> Weapons = new List<MiniYamlNode>();
// Voices overrides
[FieldLoader.Ignore] public List<MiniYamlNode> Voices = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> Notifications = new List<MiniYamlNode>();
// Binary map data
[FieldLoader.Ignore] public byte TileFormat = 1;
@@ -76,10 +70,7 @@ namespace OpenRA
[FieldLoader.Ignore] public Lazy<TileReference<byte, byte>[,]> MapResources;
[FieldLoader.Ignore] public string [,] CustomTerrain;
public Map()
{
// Do nothing; not a valid map (editor hack)
}
public Map() {} /* doesn't really produce a valid map, but enough for loading a mod */
public static Map FromTileset(string tileset)
{
@@ -121,9 +112,6 @@ namespace OpenRA
FieldLoader.Load(this, yaml);
Uid = ComputeHash();
// 'Simple' metadata
FieldLoader.Load( this, yaml );
// Support for formats 1-3 dropped 2011-02-11.
// Use release-20110207 to convert older maps to format 4
// Use release-20110511 to convert older maps to format 5
@@ -140,11 +128,8 @@ namespace OpenRA
Actors = Lazy.New(() =>
{
var ret = new Dictionary<string, ActorReference>();
// Load actors
foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict));
// Add waypoint actors
return ret;
});
@@ -162,18 +147,11 @@ namespace OpenRA
return ret;
});
// Rules
Rules = yaml.NodesDict["Rules"].Nodes;
// Sequences
Sequences = (yaml.NodesDict.ContainsKey("Sequences")) ? yaml.NodesDict["Sequences"].Nodes : new List<MiniYamlNode>();
// Weapons
Weapons = (yaml.NodesDict.ContainsKey("Weapons")) ? yaml.NodesDict["Weapons"].Nodes : new List<MiniYamlNode>();
// Voices
Voices = (yaml.NodesDict.ContainsKey("Voices")) ? yaml.NodesDict["Voices"].Nodes : new List<MiniYamlNode>();
Rules = NodesOrEmpty(yaml, "Rules");
Sequences = NodesOrEmpty(yaml, "Sequences");
Weapons = NodesOrEmpty(yaml, "Weapons");
Voices = NodesOrEmpty(yaml, "Voices");
Notifications = NodesOrEmpty(yaml, "Notifications");
CustomTerrain = new string[MapSize.X, MapSize.Y];
@@ -181,6 +159,11 @@ namespace OpenRA
MapResources = Lazy.New(() => LoadResourceTiles());
}
static List<MiniYamlNode> NodesOrEmpty(MiniYaml y, string s)
{
return y.NodesDict.ContainsKey(s) ? y.NodesDict[s].Nodes : new List<MiniYamlNode>();
}
public void Save(string toPath)
{
MapFormat = 5;
@@ -223,6 +206,7 @@ namespace OpenRA
root.Add(new MiniYamlNode("Sequences", null, Sequences));
root.Add(new MiniYamlNode("Weapons", null, Weapons));
root.Add(new MiniYamlNode("Voices", null, Voices));
root.Add(new MiniYamlNode("Notifications", null, Notifications));
var entries = new Dictionary<string, byte[]>();
entries.Add("map.bin", SaveBinaryData());
@@ -235,7 +219,7 @@ namespace OpenRA
Path = toPath;
// Create a new map package
// TODO: Add other files (resources, rules) to the entries list
// TODO: Add other files (custom assets) to the entries list
Container = FileSystem.CreatePackage(Path, int.MaxValue, entries);
}
@@ -357,7 +341,7 @@ namespace OpenRA
return dataStream.ToArray();
}
public bool IsInMap(int2 xy) { return IsInMap(xy.X, xy.Y); }
public bool IsInMap(CPos xy) { return IsInMap(xy.X, xy.Y); }
public bool IsInMap(int x, int y) { return Bounds.Contains(x,y); }
static T[,] ResizeArray<T>(T[,] ts, T t, int width, int height)

View File

@@ -100,6 +100,7 @@ namespace OpenRA
.Concat(mods.SelectMany(p => FindMapsIn("{1}maps{0}{2}{0}".F(Path.DirectorySeparatorChar, Platform.SupportDir, p))));
var ret = new Dictionary<string, Map>();
foreach (var path in paths)
{
try
@@ -113,6 +114,7 @@ namespace OpenRA
Console.WriteLine("Details: {0}", e.ToString());
}
}
return ret;
}

View File

@@ -39,15 +39,15 @@ namespace OpenRA
public readonly Actor Subject;
public readonly bool Queued;
public Actor TargetActor;
public int2 TargetLocation;
public CPos TargetLocation;
public string TargetString;
public int2 ExtraLocation;
public CPos ExtraLocation;
public bool IsImmediate;
public Player Player { get { return Subject.Owner; } }
Order(string orderString, Actor subject,
Actor targetActor, int2 targetLocation, string targetString, bool queued, int2 extraLocation)
Actor targetActor, CPos targetLocation, string targetString, bool queued, CPos extraLocation)
{
this.OrderString = orderString;
this.Subject = subject;
@@ -60,10 +60,10 @@ namespace OpenRA
// For scripting special powers
public Order()
: this(null, null, null, int2.Zero, null, false, int2.Zero) { }
: this(null, null, null, CPos.Zero, null, false, CPos.Zero) { }
public Order(string orderString, Actor subject, bool queued)
: this(orderString, subject, null, int2.Zero, null, queued, int2.Zero) { }
: this(orderString, subject, null, CPos.Zero, null, queued, CPos.Zero) { }
public Order(string orderstring, Order order)
: this(orderstring, order.Subject, order.TargetActor, order.TargetLocation,
@@ -98,21 +98,21 @@ namespace OpenRA
OrderFields fields = 0;
if (TargetActor != null) fields |= OrderFields.TargetActor;
if (TargetLocation != int2.Zero) fields |= OrderFields.TargetLocation;
if (TargetLocation != CPos.Zero) fields |= OrderFields.TargetLocation;
if (TargetString != null) fields |= OrderFields.TargetString;
if (Queued) fields |= OrderFields.Queued;
if (ExtraLocation != int2.Zero) fields |= OrderFields.ExtraLocation;
if (ExtraLocation != CPos.Zero) fields |= OrderFields.ExtraLocation;
w.Write((byte)fields);
if (TargetActor != null)
w.Write(UIntFromActor(TargetActor));
if (TargetLocation != int2.Zero)
w.Write(TargetLocation);
if (TargetLocation != CPos.Zero)
w.Write(TargetLocation.ToInt2());
if (TargetString != null)
w.Write(TargetString);
if (ExtraLocation != int2.Zero)
w.Write(ExtraLocation);
if (ExtraLocation != CPos.Zero)
w.Write(ExtraLocation.ToInt2());
return ret.ToArray();
}
@@ -130,10 +130,10 @@ namespace OpenRA
var flags = (OrderFields)r.ReadByte();
var targetActorId = flags.HasField(OrderFields.TargetActor) ? r.ReadUInt32() : 0xffffffff;
var targetLocation = flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero;
var targetLocation = (CPos)( flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero );
var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null;
var queued = flags.HasField(OrderFields.Queued);
var extraLocation = flags.HasField(OrderFields.ExtraLocation) ? r.ReadInt2() : int2.Zero;
var extraLocation = (CPos)(flags.HasField(OrderFields.ExtraLocation) ? r.ReadInt2() : int2.Zero);
Actor subject, targetActor;
if( !TryGetActorFromUInt( world, subjectId, out subject ) || !TryGetActorFromUInt( world, targetActorId, out targetActor ) )
@@ -199,7 +199,18 @@ namespace OpenRA
{
return new Order("HandshakeResponse", null, false) { IsImmediate = true, TargetString = text };
}
public static Order PauseRequest()
{
return new Order("PauseRequest", null, false) { IsImmediate = true, TargetString="" }; //TODO: targetbool?
}
public static Order PauseGame()
{
return new Order("PauseGame", null, false) { IsImmediate = true, TargetString=""}; //TODO: targetbool?
}
public static Order Command(string text)
{
return new Order("Command", null, false) { IsImmediate = true, TargetString = text };
@@ -207,17 +218,17 @@ namespace OpenRA
public static Order StartProduction(Actor subject, string item, int count)
{
return new Order("StartProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item };
return new Order("StartProduction", subject, false) { TargetLocation = new CPos(count, 0), TargetString = item };
}
public static Order PauseProduction(Actor subject, string item, bool pause)
{
return new Order("PauseProduction", subject, false) { TargetLocation = new int2(pause ? 1 : 0, 0), TargetString = item };
return new Order("PauseProduction", subject, false) { TargetLocation = new CPos(pause ? 1 : 0, 0), TargetString = item };
}
public static Order CancelProduction(Actor subject, string item, int count)
{
return new Order("CancelProduction", subject, false) { TargetLocation = new int2(count, 0), TargetString = item };
return new Order("CancelProduction", subject, false) { TargetLocation = new CPos(count, 0), TargetString = item };
}
}
}

View File

@@ -36,6 +36,7 @@ namespace OpenRA.Network
public int LastTickTime = Environment.TickCount;
public bool GameStarted { get { return NetFrameNumber != 0; } }
public bool GamePaused {get; set;}
public IConnection Connection { get; private set; }
public readonly int SyncHeaderSize = 9;

View File

@@ -10,35 +10,26 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.IO;
namespace OpenRA.Network
{
public class ReplayConnection : IConnection
{
//uint nextFrame = 1;
FileStream replayStream;
List<byte[]> sync = new List<byte[]>();
public ReplayConnection( string replayFilename )
{
replayStream = File.OpenRead( replayFilename );
}
public ReplayConnection( string replayFilename ) { replayStream = File.OpenRead( replayFilename ); }
public int LocalClientId
{
get { return 0; }
}
public ConnectionState ConnectionState
{
get { return ConnectionState.Connected; }
}
public int LocalClientId { get { return 0; } }
public ConnectionState ConnectionState { get { return ConnectionState.Connected; } }
// do nothing; ignore locally generated orders
public void Send( int frame, List<byte[]> orders ) { }
public void SendImmediate( List<byte[]> orders ) { }
public void SendSync( int frame, byte[] syncData )
{
var ms = new MemoryStream();
@@ -47,8 +38,6 @@ namespace OpenRA.Network
sync.Add( ms.ToArray() );
}
List<byte[]> sync = new List<byte[]>();
public void Receive( Action<int, byte[]> packetFn )
{
while( sync.Count != 0 )
@@ -56,9 +45,11 @@ namespace OpenRA.Network
packetFn( LocalClientId, sync[ 0 ] );
sync.RemoveAt( 0 );
}
if( replayStream == null ) return;
var reader = new BinaryReader( replayStream );
while( replayStream.Position < replayStream.Length )
{
var client = reader.ReadInt32();
@@ -66,56 +57,10 @@ namespace OpenRA.Network
var packet = reader.ReadBytes( packetLen );
packetFn( client, packet );
}
replayStream = null;
}
public void Dispose() { }
}
class ReplayRecorderConnection : IConnection
{
IConnection inner;
BinaryWriter writer;
public ReplayRecorderConnection( IConnection inner, FileStream replayFile )
{
this.inner = inner;
this.writer = new BinaryWriter( replayFile );
}
public int LocalClientId { get { return inner.LocalClientId; } }
public ConnectionState ConnectionState { get { return inner.ConnectionState; } }
public void Send( int frame, List<byte[]> orders ) { inner.Send( frame, orders ); }
public void SendImmediate( List<byte[]> orders ) { inner.SendImmediate( orders ); }
public void SendSync( int frame, byte[] syncData ) { inner.SendSync( frame, syncData ); }
public void Receive( Action<int, byte[]> packetFn )
{
inner.Receive( ( client, data ) =>
{
writer.Write( client );
writer.Write( data.Length );
writer.Write( data );
packetFn( client, data );
} );
}
bool disposed;
public void Dispose()
{
if( disposed )
return;
writer.Close();
inner.Dispose();
disposed = true;
}
~ReplayRecorderConnection()
{
Dispose();
}
}
}

View File

@@ -0,0 +1,103 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace OpenRA.Network
{
class ReplayRecorderConnection : IConnection
{
IConnection inner;
BinaryWriter writer;
Func<string> chooseFilename;
MemoryStream preStartBuffer = new MemoryStream();
public ReplayRecorderConnection( IConnection inner, Func<string> chooseFilename )
{
this.chooseFilename = chooseFilename;
this.inner = inner;
writer = new BinaryWriter(preStartBuffer);
}
void StartSavingReplay(byte[] initialContent)
{
var filename = chooseFilename();
var replayPath = Path.Combine(Platform.SupportDir, "Replays");
if (!Directory.Exists(replayPath))
Directory.CreateDirectory(replayPath);
var file = File.Create(Path.Combine(replayPath, filename));
file.Write(initialContent);
this.writer = new BinaryWriter(file);
}
public int LocalClientId { get { return inner.LocalClientId; } }
public ConnectionState ConnectionState { get { return inner.ConnectionState; } }
public void Send( int frame, List<byte[]> orders ) { inner.Send( frame, orders ); }
public void SendImmediate( List<byte[]> orders ) { inner.SendImmediate( orders ); }
public void SendSync( int frame, byte[] syncData ) { inner.SendSync( frame, syncData ); }
public void Receive( Action<int, byte[]> packetFn )
{
inner.Receive((client, data) =>
{
if (preStartBuffer != null && IsGameStart(data))
{
writer.Flush();
var preStartData = preStartBuffer.ToArray();
preStartBuffer = null;
StartSavingReplay(preStartData);
}
writer.Write(client);
writer.Write(data.Length);
writer.Write(data);
packetFn(client, data);
} );
}
bool IsGameStart(byte[] data)
{
if (data.Length == 5 && data[4] == 0xbf)
return false;
if (data.Length >= 5 && data[4] == 0x65)
return false;
var frame = BitConverter.ToInt32(data, 0);
return frame == 0 && data.ToOrderList(null).Any(
o => o.OrderString == "StartGame");
}
bool disposed;
public void Dispose()
{
if( disposed )
return;
writer.Close();
inner.Dispose();
disposed = true;
}
~ReplayRecorderConnection()
{
Dispose();
}
}
}

View File

@@ -50,7 +50,7 @@ namespace OpenRA.Network
public int Team;
public string Slot; // slot ID, or null for observer
public string Bot; // Bot type, null for real clients
public bool IsAdmin;
public bool IsReady { get { return State == ClientState.Ready; } }
}
@@ -70,6 +70,7 @@ namespace OpenRA.Network
{
public string ServerName;
public string Map;
public string[] Ban;
public string[] Mods = { "ra" }; // mod names
public int OrderLatency = 3;
public int RandomSeed = 0;

View File

@@ -50,6 +50,7 @@ namespace OpenRA.Network
Game.AddChatLine(Color.White, "(player {0})".F(clientId), order.TargetString);
break;
}
case "Disconnected": /* reports that the target player disconnected */
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
@@ -59,6 +60,7 @@ namespace OpenRA.Network
}
break;
}
case "TeamChat":
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
@@ -69,34 +71,43 @@ namespace OpenRA.Network
{
if (client.Team == orderManager.LocalClient.Team)
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + " (Team)",
order.TargetString);
order.TargetString);
}
else
{
var player = world.FindPlayerByClient(client);
var display = player != null
&&
(world.LocalPlayer != null &&
player.Stances[world.LocalPlayer] == Stance.Ally
|| player.WinState == WinState.Lost);
if (player == null) return;
if (display)
if (world.LocalPlayer != null && player.Stances[world.LocalPlayer] == Stance.Ally || player.WinState == WinState.Lost)
{
var suffix = (player != null && player.WinState == WinState.Lost)
? " (Dead)"
: " (Team)";
var suffix = player.WinState == WinState.Lost ? " (Dead)" : " (Team)";
Game.AddChatLine(client.ColorRamp.GetColor(0), client.Name + suffix, order.TargetString);
}
}
}
break;
}
case "StartGame":
{
Game.AddChatLine(Color.White, "Server", "The game has started.");
Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map, false);
break;
}
case "PauseGame":
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if(client != null)
{
orderManager.GamePaused = !orderManager.GamePaused;
var pausetext = "The game is {0} by {1}".F( orderManager.GamePaused ? "paused" : "un-paused", client.Name );
Game.AddChatLine(Color.White, "", pausetext);
}
break;
}
case "HandshakeRequest":
{
var request = HandshakeRequest.Deserialize(order.TargetString);
@@ -126,9 +137,11 @@ namespace OpenRA.Network
orderManager.IssueOrder(Order.HandshakeResponse(response.Serialize()));
break;
}
case "ServerError":
orderManager.ServerError = order.TargetString;
break;
case "SyncInfo":
{
orderManager.LobbyInfo = Session.Deserialize(order.TargetString);

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
@@ -12,9 +12,12 @@
<AssemblyName>OpenRA.Game</AssemblyName>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<IsWebBootstrapper>false</IsWebBootstrapper>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<ApplicationIcon>OpenRA.ico</ApplicationIcon>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@@ -27,11 +30,8 @@
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<ApplicationIcon>OpenRA.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
@@ -44,6 +44,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\Release\</OutputPath>
@@ -55,11 +56,11 @@
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
@@ -79,6 +80,11 @@
<Compile Include="ActorInitializer.cs" />
<Compile Include="ActorMap.cs" />
<Compile Include="ActorReference.cs" />
<Compile Include="PSubVec.cs" />
<Compile Include="PSubPos.cs" />
<Compile Include="PVecInt.cs" />
<Compile Include="PVecFloat.cs" />
<Compile Include="PPos.cs" />
<Compile Include="Download.cs" />
<Compile Include="Effects\DelayedAction.cs" />
<Compile Include="Effects\FlashTarget.cs" />
@@ -88,7 +94,7 @@
<Compile Include="GameRules\MusicInfo.cs" />
<Compile Include="GameRules\Rules.cs" />
<Compile Include="GameRules\Settings.cs" />
<Compile Include="GameRules\VoiceInfo.cs" />
<Compile Include="GameRules\SoundInfo.cs" />
<Compile Include="GameRules\WeaponInfo.cs" />
<Compile Include="Graphics\Animation.cs" />
<Compile Include="Graphics\AnimationWithOffset.cs" />
@@ -115,6 +121,8 @@
<Compile Include="Graphics\WorldRenderer.cs" />
<Compile Include="Group.cs" />
<Compile Include="InputHandler.cs" />
<Compile Include="CVec.cs" />
<Compile Include="CPos.cs" />
<Compile Include="Map.cs" />
<Compile Include="ModData.cs" />
<Compile Include="Network\Connection.cs" />
@@ -143,6 +151,7 @@
<Compile Include="Server\Server.cs" />
<Compile Include="Server\ServerOrder.cs" />
<Compile Include="Server\TraitInterfaces.cs" />
<Compile Include="Server\UPnP.cs" />
<Compile Include="Sound.cs" />
<Compile Include="Support\Arguments.cs" />
<Compile Include="Support\PerfHistory.cs" />
@@ -151,19 +160,18 @@
<Compile Include="TraitDictionary.cs" />
<Compile Include="Traits\Activity.cs" />
<Compile Include="Traits\Armor.cs" />
<Compile Include="Traits\CreatesShroud.cs" />
<Compile Include="Traits\DrawLineToTarget.cs" />
<Compile Include="Traits\EditorAppearance.cs" />
<Compile Include="Traits\EditorTilesetFilter.cs" />
<Compile Include="Traits\Health.cs" />
<Compile Include="Traits\LintAttributes.cs" />
<Compile Include="Traits\Player\DeveloperMode.cs" />
<Compile Include="Traits\Player\EvaAlerts.cs" />
<Compile Include="Traits\Player\PlayerResources.cs" />
<Compile Include="Traits\Render\RenderSimple.cs" />
<Compile Include="Traits\RevealsShroud.cs" />
<Compile Include="Traits\Selectable.cs" />
<Compile Include="Traits\SelectionDecorations.cs" />
<Compile Include="Traits\SubcellInit.cs" />
<Compile Include="Traits\Target.cs" />
<Compile Include="Traits\TraitsInterfaces.cs" />
<Compile Include="Traits\Util.cs" />
@@ -206,6 +214,7 @@
<Compile Include="Widgets\WorldInteractionControllerWidget.cs" />
<Compile Include="World.cs" />
<Compile Include="WorldUtils.cs" />
<Compile Include="Network\ReplayRecorderConnection.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
@@ -214,6 +223,11 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
<Visible>False</Visible>
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
@@ -229,6 +243,11 @@
<ProductName>.NET Framework 3.5</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="OpenRA.ico" />

View File

@@ -48,14 +48,14 @@ namespace OpenRA.Orders
}
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi)
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
if (mi.Button != expectedButton)
world.CancelInputMode();
return OrderInner(world, xy, mi);
}
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi)
IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
{
if (mi.Button == expectedButton && world.Map.IsInMap(xy))
{
@@ -68,6 +68,6 @@ namespace OpenRA.Orders
public virtual void Tick(World world) { }
public void RenderBeforeWorld(WorldRenderer wr, World world) { }
public void RenderAfterWorld(WorldRenderer wr, World world) { }
public string GetCursor(World world, int2 xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; }
public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; }
}
}

View File

@@ -15,10 +15,10 @@ namespace OpenRA
{
public interface IOrderGenerator
{
IEnumerable<Order> Order(World world, int2 xy, MouseInput mi);
IEnumerable<Order> Order(World world, CPos xy, MouseInput mi);
void Tick(World world);
void RenderBeforeWorld(WorldRenderer wr, World world);
void RenderAfterWorld(WorldRenderer wr, World world);
string GetCursor(World world, int2 xy, MouseInput mi);
string GetCursor(World world, CPos xy, MouseInput mi);
}
}

View File

@@ -17,15 +17,11 @@ namespace OpenRA.Orders
{
class UnitOrderGenerator : IOrderGenerator
{
public IEnumerable<Order> Order( World world, int2 xy, MouseInput mi )
public IEnumerable<Order> Order( World world, CPos xy, MouseInput mi )
{
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.HasTrait<ITargetable>())
.OrderByDescending(
a =>
a.Info.Traits.Contains<SelectableInfo>()
? a.Info.Traits.Get<SelectableInfo>().Priority
: int.MinValue)
.OrderByDescending(a => a.SelectionPriority())
.FirstOrDefault();
var orders = world.Selection.Actors
@@ -49,13 +45,13 @@ namespace OpenRA.Orders
public void RenderBeforeWorld( WorldRenderer wr, World world ) { }
public void RenderAfterWorld( WorldRenderer wr, World world ) { }
public string GetCursor( World world, int2 xy, MouseInput mi )
public string GetCursor(World world, CPos xy, MouseInput mi)
{
bool useSelect = false;
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.HasTrait<ITargetable>())
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
.OrderByDescending(a => a.SelectionPriority())
.FirstOrDefault();
if (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any())
@@ -67,12 +63,11 @@ namespace OpenRA.Orders
.Where(o => o != null)
.ToArray();
if( orders.Length == 0 ) return (useSelect) ? "select" : "default";
return orders[0].cursor ?? ((useSelect) ? "select" : "default");
var cursorName = orders.Select(o => o.cursor).FirstOrDefault();
return cursorName ?? (useSelect ? "select" : "default");
}
static UnitOrderResult OrderForUnit( Actor self, int2 xy, MouseInput mi, Actor underCursor )
static UnitOrderResult OrderForUnit(Actor self, CPos xy, MouseInput mi, Actor underCursor)
{
if (self.Owner != self.World.LocalPlayer)
return null;
@@ -130,4 +125,13 @@ namespace OpenRA.Orders
}
}
}
public static class SelectableExts
{
public static int SelectionPriority(this Actor a)
{
var selectableInfo = a.Info.Traits.GetOrDefault<SelectableInfo>();
return selectableInfo != null ? selectableInfo.Priority : int.MinValue;
}
}
}

71
OpenRA.Game/PPos.cs Normal file
View File

@@ -0,0 +1,71 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate position in the world (fine).
/// </summary>
public struct PPos
{
public readonly int X, Y;
public PPos(int x, int y) { X = x; Y = y; }
public static readonly PPos Zero = new PPos(0, 0);
public static explicit operator PPos(int2 a) { return new PPos(a.X, a.Y); }
public static explicit operator PVecInt(PPos a) { return new PVecInt(a.X, a.Y); }
public static explicit operator PVecFloat(PPos a) { return new PVecFloat(a.X, a.Y); }
public static PPos operator +(PPos a, PVecInt b) { return new PPos(a.X + b.X, a.Y + b.Y); }
public static PVecInt operator -(PPos a, PPos b) { return new PVecInt(a.X - b.X, a.Y - b.Y); }
public static PPos operator -(PPos a, PVecInt b) { return new PPos(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(PPos me, PPos other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PPos me, PPos other) { return !(me == other); }
public static PPos Max(PPos a, PPos b) { return new PPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PPos Min(PPos a, PPos b) { return new PPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static PPos Lerp(PPos a, PPos b, int mul, int div)
{
return a + ((PVecInt)(b - a) * mul / div);
}
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public CPos ToCPos() { return new CPos((int)(1f / Game.CellSize * X), (int)(1f / Game.CellSize * Y)); }
public PSubPos ToPSubPos() { return new PSubPos(X * PSubPos.PerPx, Y * PSubPos.PerPx); }
public PPos Clamp(Rectangle r)
{
return new PPos(Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top)));
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PPos o = (PPos)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

73
OpenRA.Game/PSubPos.cs Normal file
View File

@@ -0,0 +1,73 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Sub-pixel coordinate position in the world (very fine).
/// </summary>
public struct PSubPos
{
public readonly int X, Y;
public PSubPos(int x, int y) { X = x; Y = y; }
public const int PerPx = 1024;
public static readonly PSubPos Zero = new PSubPos(0, 0);
public static explicit operator PSubPos(int2 a) { return new PSubPos(a.X, a.Y); }
public static explicit operator PSubVec(PSubPos a) { return new PSubVec(a.X, a.Y); }
public static explicit operator PVecFloat(PSubPos a) { return new PVecFloat(a.X, a.Y); }
public static PSubPos operator +(PSubPos a, PSubVec b) { return new PSubPos(a.X + b.X, a.Y + b.Y); }
public static PSubVec operator -(PSubPos a, PSubPos b) { return new PSubVec(a.X - b.X, a.Y - b.Y); }
public static PSubPos operator -(PSubPos a, PSubVec b) { return new PSubPos(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(PSubPos me, PSubPos other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PSubPos me, PSubPos other) { return !(me == other); }
public static PSubPos Max(PSubPos a, PSubPos b) { return new PSubPos(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PSubPos Min(PSubPos a, PSubPos b) { return new PSubPos(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static PSubPos Lerp(PSubPos a, PSubPos b, int mul, int div)
{
return a + ((PSubVec)(b - a) * mul / div);
}
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public PPos ToPPos() { return new PPos(X / PerPx, Y / PerPx); }
public CPos ToCPos() { return ToPPos().ToCPos(); }
public PSubPos Clamp(Rectangle r)
{
return new PSubPos(Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top)));
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PSubPos o = (PSubPos)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

103
OpenRA.Game/PSubVec.cs Normal file
View File

@@ -0,0 +1,103 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Sub-pixel coordinate vector (very fine)
/// </summary>
public struct PSubVec
{
public readonly int X, Y;
public PSubVec(int x, int y) { X = x; Y = y; }
public PSubVec(Size p) { X = p.Width; Y = p.Height; }
public static readonly PSubVec Zero = new PSubVec(0, 0);
public static PSubVec OneCell { get { return new PSubVec(Game.CellSize, Game.CellSize); } }
public static explicit operator PSubVec(int2 a) { return new PSubVec(a.X, a.Y); }
public static explicit operator PSubVec(float2 a) { return new PSubVec((int)a.X, (int)a.Y); }
public static PSubVec FromRadius(int r) { return new PSubVec(r, r); }
public static PSubVec operator +(PSubVec a, PSubVec b) { return new PSubVec(a.X + b.X, a.Y + b.Y); }
public static PSubVec operator -(PSubVec a, PSubVec b) { return new PSubVec(a.X - b.X, a.Y - b.Y); }
public static PSubVec operator *(int a, PSubVec b) { return new PSubVec(a * b.X, a * b.Y); }
public static PSubVec operator *(PSubVec b, int a) { return new PSubVec(a * b.X, a * b.Y); }
public static PSubVec operator /(PSubVec a, int b) { return new PSubVec(a.X / b, a.Y / b); }
public static PSubVec operator -(PSubVec a) { return new PSubVec(-a.X, -a.Y); }
public static bool operator ==(PSubVec me, PSubVec other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PSubVec me, PSubVec other) { return !(me == other); }
public static PSubVec Max(PSubVec a, PSubVec b) { return new PSubVec(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PSubVec Min(PSubVec a, PSubVec b) { return new PSubVec(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static int Dot(PSubVec a, PSubVec b) { return a.X * b.X + a.Y * b.Y; }
public PSubVec Sign() { return new PSubVec(Math.Sign(X), Math.Sign(Y)); }
public PSubVec Abs() { return new PSubVec(Math.Abs(X), Math.Abs(Y)); }
public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public PVecInt ToPVecInt() { return new PVecInt(X / PSubPos.PerPx, Y / PSubPos.PerPx); }
public PSubVec Clamp(Rectangle r)
{
return new PSubVec(
Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top))
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PSubVec o = (PSubVec)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
public static class PSubVecExtensions
{
/// <summary>
/// Scales the float2 vector up to a subpixel vector.
/// </summary>
/// <param name="vec"></param>
/// <returns></returns>
public static PSubVec ToPSubVec(this float2 vec)
{
return new PSubVec((int)(vec.X * PSubPos.PerPx), (int)(vec.Y * PSubPos.PerPx));
}
public static PSubVec ToPSubVec(this PVecInt vec)
{
return new PSubVec((vec.X * PSubPos.PerPx), (vec.Y * PSubPos.PerPx));
}
public static PSubVec ToPSubVec(this PVecFloat vec)
{
return new PSubVec((int)(vec.X * PSubPos.PerPx), (int)(vec.Y * PSubPos.PerPx));
}
}
}

97
OpenRA.Game/PVecFloat.cs Normal file
View File

@@ -0,0 +1,97 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate vector (fine; float)
/// </summary>
public struct PVecFloat
{
public readonly float X, Y;
public PVecFloat(float x, float y) { X = x; Y = y; }
public PVecFloat(Size p) { X = p.Width; Y = p.Height; }
public static readonly PVecFloat Zero = new PVecFloat(0, 0);
public static explicit operator PVecInt(PVecFloat a) { return new PVecInt((int)a.X, (int)a.Y); }
public static explicit operator PVecFloat(float2 a) { return new PVecFloat(a.X, a.Y); }
public static PVecFloat operator +(PVecFloat a, PVecFloat b) { return new PVecFloat(a.X + b.X, a.Y + b.Y); }
public static PVecFloat operator -(PVecFloat a, PVecFloat b) { return new PVecFloat(a.X - b.X, a.Y - b.Y); }
public static PVecFloat operator *(float a, PVecFloat b) { return new PVecFloat(a * b.X, a * b.Y); }
public static PVecFloat operator *(PVecFloat b, float a) { return new PVecFloat(a * b.X, a * b.Y); }
public static PVecFloat operator /(PVecFloat a, float b) { return new PVecFloat(a.X / b, a.Y / b); }
public static PVecFloat operator -(PVecFloat a) { return new PVecFloat(-a.X, -a.Y); }
public static bool operator ==(PVecFloat me, PVecFloat other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PVecFloat me, PVecFloat other) { return !(me == other); }
public static PVecFloat Max(PVecFloat a, PVecFloat b) { return new PVecFloat(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PVecFloat Min(PVecFloat a, PVecFloat b) { return new PVecFloat(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static float Dot(PVecFloat a, PVecFloat b) { return a.X * b.X + a.Y * b.Y; }
public static PVecFloat FromAngle(float a) { return new PVecFloat((float)Math.Sin(a), (float)Math.Cos(a)); }
public static PVecFloat Lerp(PVecFloat a, PVecFloat b, float t)
{
return new PVecFloat(
float2.Lerp(a.X, b.X, t),
float2.Lerp(a.Y, b.Y, t)
);
}
public static PVecFloat Lerp(PVecFloat a, PVecFloat b, PVecFloat t)
{
return new PVecFloat(
float2.Lerp(a.X, b.X, t.X),
float2.Lerp(a.Y, b.Y, t.Y)
);
}
public PVecFloat Sign() { return new PVecFloat(Math.Sign(X), Math.Sign(Y)); }
public PVecFloat Abs() { return new PVecFloat(Math.Abs(X), Math.Abs(Y)); }
public PVecFloat Round() { return new PVecFloat((float)Math.Round(X), (float)Math.Round(Y)); }
public float LengthSquared { get { return X * X + Y * Y; } }
public float Length { get { return (float)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2((int)X, (int)Y); }
static float Constrain(float x, float a, float b) { return x < a ? a : x > b ? b : x; }
public PVecFloat Constrain(PVecFloat min, PVecFloat max)
{
return new PVecFloat(
Constrain(X, min.X, max.X),
Constrain(Y, min.Y, max.Y)
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PVecFloat o = (PVecFloat)obj;
return o == this;
}
public override string ToString() { return "({0},{1})".F(X, Y); }
}
}

80
OpenRA.Game/PVecInt.cs Normal file
View File

@@ -0,0 +1,80 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA
{
/// <summary>
/// Pixel coordinate vector (fine; integer)
/// </summary>
public struct PVecInt
{
public readonly int X, Y;
public PVecInt(int x, int y) { X = x; Y = y; }
public PVecInt(Size p) { X = p.Width; Y = p.Height; }
public static readonly PVecInt Zero = new PVecInt(0, 0);
public static PVecInt OneCell { get { return new PVecInt(Game.CellSize, Game.CellSize); } }
public static implicit operator PVecFloat(PVecInt a) { return new PVecFloat((float)a.X, (float)a.Y); }
public static explicit operator PVecInt(int2 a) { return new PVecInt(a.X, a.Y); }
public static PVecInt FromRadius(int r) { return new PVecInt(r, r); }
public static PVecInt operator +(PVecInt a, PVecInt b) { return new PVecInt(a.X + b.X, a.Y + b.Y); }
public static PVecInt operator -(PVecInt a, PVecInt b) { return new PVecInt(a.X - b.X, a.Y - b.Y); }
public static PVecInt operator *(int a, PVecInt b) { return new PVecInt(a * b.X, a * b.Y); }
public static PVecInt operator *(PVecInt b, int a) { return new PVecInt(a * b.X, a * b.Y); }
public static PVecInt operator /(PVecInt a, int b) { return new PVecInt(a.X / b, a.Y / b); }
public static PVecInt operator -(PVecInt a) { return new PVecInt(-a.X, -a.Y); }
public static bool operator ==(PVecInt me, PVecInt other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(PVecInt me, PVecInt other) { return !(me == other); }
public static PVecInt Max(PVecInt a, PVecInt b) { return new PVecInt(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
public static PVecInt Min(PVecInt a, PVecInt b) { return new PVecInt(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
public static int Dot(PVecInt a, PVecInt b) { return a.X * b.X + a.Y * b.Y; }
public PVecInt Sign() { return new PVecInt(Math.Sign(X), Math.Sign(Y)); }
public PVecInt Abs() { return new PVecInt(Math.Abs(X), Math.Abs(Y)); }
public int LengthSquared { get { return X * X + Y * Y; } }
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
public float2 ToFloat2() { return new float2(X, Y); }
public int2 ToInt2() { return new int2(X, Y); }
public CVec ToCVec() { return new CVec(X / Game.CellSize, Y / Game.CellSize); }
public PVecInt Clamp(Rectangle r)
{
return new PVecInt(
Math.Min(r.Right, Math.Max(X, r.Left)),
Math.Min(r.Bottom, Math.Max(Y, r.Top))
);
}
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)
{
if (obj == null)
return false;
PVecInt o = (PVecInt)obj;
return o == this;
}
public override string ToString() { return "{0},{1}".F(X, Y); }
}
}

View File

@@ -90,11 +90,6 @@ namespace OpenRA
}
}
public void GiveAdvice(string advice)
{
Sound.PlayToPlayer(this, advice);
}
public Dictionary<Player, Stance> Stances = new Dictionary<Player, Stance>();
}
}

View File

@@ -72,7 +72,8 @@ namespace OpenRA
if (actors.Count == 0)
return;
controlGroups[group].Clear();
if (!mods.HasModifier(Modifiers.Shift))
controlGroups[group].Clear();
for (var i = 0; i < 10; i++) /* all control groups */
controlGroups[i].RemoveAll(a => actors.Contains(a));

View File

@@ -44,6 +44,11 @@ namespace OpenRA.Server
{
try
{
// NOTE(jsd): Poll the socket first to see if there's anything there.
// This avoids the exception with SocketErrorCode == `SocketError.WouldBlock` thrown
// from `socket.Receive(rx)`.
if (!socket.Poll(0, SelectMode.SelectRead)) break;
if (0 < (len = socket.Receive(rx)))
data.AddRange(rx.Take(len));
else
@@ -52,11 +57,12 @@ namespace OpenRA.Server
server.DropClient(this);
break;
}
}
catch (SocketException e)
{
// NOTE(jsd): This should no longer be needed with the socket.Poll call above.
if (e.SocketErrorCode == SocketError.WouldBlock) break;
server.DropClient(this);
return false;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -15,11 +15,15 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using UPnP;
using System.Threading;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Network;
using XTimer = System.Timers.Timer;
namespace OpenRA.Server
{
public class Server
@@ -40,13 +44,18 @@ namespace OpenRA.Server
public readonly IPAddress Ip;
public readonly int Port;
int randomSeed;
public readonly Thirdparty.Random Random = new Thirdparty.Random();
public ServerSettings Settings;
public ModData ModData;
public Map Map;
XTimer gameTimeout;
volatile bool shutdown = false;
public void Shutdown() { shutdown = true; }
public void Shutdown()
{
shutdown = true;
}
public Server(IPEndPoint endpoint, string[] mods, ServerSettings settings, ModData modData)
{
@@ -63,6 +72,44 @@ namespace OpenRA.Server
randomSeed = (int)DateTime.Now.ToBinary();
if (Settings.AllowUPnP)
{
try
{
if (UPnP.NAT.Discover())
{
Log.Write("server", "UPnP-enabled router discovered.");
Log.Write("server", "Your IP is: {0}", UPnP.NAT.GetExternalIP() );
}
else
{
Log.Write("server", "No UPnP-enabled router detected.");
Settings.AllowUPnP = false;
}
}
catch (Exception e)
{
OpenRA.Log.Write("server", "Can't discover UPnP-enabled routers: {0}", e);
Settings.AllowUPnP = false;
}
}
if (Settings.AllowUPnP)
{
try
{
if (UPnP.NAT.ForwardPort(Port, ProtocolType.Tcp, "OpenRA"))
Log.Write("server", "Port {0} (TCP) has been forwarded.", Port);
else
Settings.AllowUPnP = false;
}
catch (Exception e)
{
OpenRA.Log.Write("server", "Can not forward ports via UPnP: {0}", e);
Settings.AllowUPnP = false;
}
}
foreach (var trait in modData.Manifest.ServerTraits)
ServerTraits.Add( modData.ObjectCreator.CreateObject<ServerTrait>(trait) );
@@ -70,6 +117,7 @@ namespace OpenRA.Server
lobbyInfo.GlobalSettings.RandomSeed = randomSeed;
lobbyInfo.GlobalSettings.Map = settings.Map;
lobbyInfo.GlobalSettings.ServerName = settings.Name;
lobbyInfo.GlobalSettings.Ban = settings.Ban;
foreach (var t in ServerTraits.WithInterface<INotifyServerStart>())
t.ServerStarted(this);
@@ -92,7 +140,11 @@ namespace OpenRA.Server
Socket.Select( checkRead, null, null, timeout );
if (shutdown)
{
if (Settings.AllowUPnP)
RemovePortforward();
break;
}
foreach( Socket s in checkRead )
if( s == listener.Server ) AcceptConnection();
@@ -107,7 +159,11 @@ namespace OpenRA.Server
t.Tick(this);
if (shutdown)
{
if (Settings.AllowUPnP)
RemovePortforward();
break;
}
}
GameStarted = false;
@@ -119,21 +175,30 @@ namespace OpenRA.Server
try { listener.Stop(); }
catch { }
} ) { IsBackground = true }.Start();
}
void RemovePortforward()
{
try
{
if (UPnP.NAT.DeleteForwardingRule(Port, ProtocolType.Tcp))
Log.Write("server", "Port {0} (TCP) forwarding rules has been removed.", Port);
}
catch (Exception e)
{
OpenRA.Log.Write("server", "Can not remove UPnP portforwarding rules: {0}", e);
}
}
/* lobby rework todo:
* - "teams together" option for team games -- will eliminate most need
* for manual spawnpoint choosing.
* - 256 max players is a dirty hack
*/
int nextPlayerIndex = 0;
public int ChooseFreePlayerIndex()
{
for (var i = 0; i < 256; i++)
if (conns.All(c => c.PlayerIndex != i) && preConns.All(c => c.PlayerIndex != i)
&& lobbyInfo.Clients.All(c => c.Index != i))
return i;
throw new InvalidOperationException("Already got 256 players");
return nextPlayerIndex++;
}
void AcceptConnection()
@@ -193,11 +258,12 @@ namespace OpenRA.Server
var client = handshake.Client;
var mods = handshake.Mods;
// Check that the client has compatable mods
// Check that the client has compatible mods
var valid = mods.All( m => m.Contains('@')) && //valid format
mods.Count() == Game.CurrentMods.Count() && //same number
mods.Select( m => Pair.New(m.Split('@')[0], m.Split('@')[1])).All(kv => Game.CurrentMods.ContainsKey(kv.First) &&
(kv.Second == "{DEV_VERSION}" || Game.CurrentMods[kv.First].Version == "{DEV_VERSION}" || kv.Second == Game.CurrentMods[kv.First].Version));
if (!valid)
{
Log.Write("server", "Rejected connection from {0}; mods do not match.",
@@ -208,6 +274,21 @@ namespace OpenRA.Server
return;
}
// Check if IP is banned
if (lobbyInfo.GlobalSettings.Ban != null)
{
var remote_addr = ((IPEndPoint)newConn.socket.RemoteEndPoint).Address.ToString();
if (lobbyInfo.GlobalSettings.Ban.Contains(remote_addr))
{
Console.WriteLine("Rejected connection from "+client.Name+"("+newConn.socket.RemoteEndPoint+"); Banned.");
Log.Write("server", "Rejected connection from {0}; Banned.",
newConn.socket.RemoteEndPoint);
SendOrderTo(newConn, "ServerError", "You are banned from the server!");
DropClient(newConn);
return;
}
}
// Promote connection to a valid client
preConns.Remove(newConn);
conns.Add(newConn);
@@ -220,6 +301,9 @@ namespace OpenRA.Server
SyncClientToPlayerReference(client, Map.Players[client.Slot]);
lobbyInfo.Clients.Add(client);
//Assume that first validated client is server admin
if(lobbyInfo.Clients.Count==1)
client.IsAdmin=true;
Log.Write("server", "Client {0}: Accepted connection from {1}",
newConn.PlayerIndex, newConn.socket.RemoteEndPoint);
@@ -229,6 +313,10 @@ namespace OpenRA.Server
SyncLobbyInfo();
SendChat(newConn, "has joined the game.");
if (mods.Any(m => m.Contains("{DEV_VERSION}")))
SendChat(newConn, "is running a development version, "+
"and may cause desync if they have any incompatible changes.");
}
catch (Exception) { DropClient(newConn); }
}
@@ -328,6 +416,9 @@ namespace OpenRA.Server
void InterpretServerOrder(Connection conn, ServerOrder so)
{
var fromClient = GetClient(conn);
var fromIndex = fromClient != null ? fromClient.Index : 0;
switch (so.Name)
{
case "Command":
@@ -343,17 +434,23 @@ namespace OpenRA.Server
}
break;
case "HandshakeResponse":
ValidateClient(conn, so.Data);
break;
case "Chat":
case "TeamChat":
var fromClient = GetClient(conn);
var fromIndex = fromClient != null ? fromClient.Index : 0;
foreach (var c in conns.Except(conn).ToArray())
DispatchOrdersToClient(c, fromIndex, 0, so.Serialize());
break;
break;
case "PauseRequest":
foreach (var c in conns.ToArray())
{ var x = Order.PauseGame();
DispatchOrdersToClient(c, fromIndex, 0, x.Serialize());
}
break;
}
}
@@ -402,12 +499,15 @@ namespace OpenRA.Server
public void StartGame()
{
GameStarted = true;
listener.Stop();
Console.WriteLine("Game started");
foreach( var c in conns )
foreach( var d in conns )
DispatchOrdersToClient( c, d.PlayerIndex, 0x7FFFFFFF, new byte[] { 0xBF } );
// Drop any unvalidated clients
foreach (var c in preConns)
foreach (var c in preConns.ToArray())
DropClient(c);
DispatchOrders(null, 0,
@@ -415,6 +515,18 @@ namespace OpenRA.Server
foreach (var t in ServerTraits.WithInterface<IStartGame>())
t.GameStarted(this);
// Check TimeOut
if ( Settings.TimeOut > 10000 )
{
gameTimeout = new XTimer(Settings.TimeOut);
gameTimeout.Elapsed += (_,e) =>
{
Console.WriteLine("Timeout at {0}!!!", e.SignalTime);
Environment.Exit(0);
};
gameTimeout.Enabled = true;
}
}
}
}

163
OpenRA.Game/Server/UPnP.cs Normal file
View File

@@ -0,0 +1,163 @@
#region Copyright & License Information
/*
* Copyright 2008-2009 http://www.codeproject.com/Members/Harold-Aptroot
* Source: http://www.codeproject.com/Articles/27992/NAT-Traversal-with-UPnP-in-C
* This file is licensed under A Public Domain dedication.
* For more information, see http://creativecommons.org/licenses/publicdomain/
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Xml;
using System.IO;
namespace UPnP
{
public class NAT
{
static string _serviceUrl;
public static bool Discover()
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
s.ReceiveTimeout = 3000; //3 seconds
string req = "M-SEARCH * HTTP/1.1\r\n" +
"HOST: 239.255.255.250:1900\r\n" +
"ST:upnp:rootdevice\r\n" +
"MAN:\"ssdp:discover\"\r\n" +
"MX:3\r\n\r\n";
byte[] data = Encoding.ASCII.GetBytes(req);
IPEndPoint ipe = new IPEndPoint(IPAddress.Broadcast, 1900);
byte[] buffer = new byte[0x1000];
try
{
s.SendTo(data, ipe);
int length = 0;
do
{
length = s.Receive(buffer);
string resp = Encoding.ASCII.GetString(buffer, 0, length).ToLower();
if (resp.Contains("upnp:rootdevice"))
{
resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
if (!string.IsNullOrEmpty(_serviceUrl = GetServiceUrl(resp)))
{
s.Close();
return true;
}
}
} while (length > 0);
s.Close();
return false;
}
catch
{
s.Close();
return false;
}
}
private static String GetServiceUrl(string resp)
{
XmlDocument desc = new XmlDocument();
HttpWebRequest r = (HttpWebRequest)WebRequest.Create(resp);
r.KeepAlive = false;
using (WebResponse wres = r.GetResponse())
{
using (Stream ress = wres.GetResponseStream())
{
desc.Load(ress);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(desc.NameTable);
nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0");
XmlNode typen = desc.SelectSingleNode("//tns:device/tns:deviceType/text()", nsMgr);
if (!typen.Value.Contains("InternetGatewayDevice"))
return null;
XmlNode node = desc.SelectSingleNode("//tns:service[tns:serviceType=\"urn:schemas-upnp-org:service:WANIPConnection:1\"]/tns:controlURL/text()", nsMgr);
if (node == null)
return null;
Uri respUri = new Uri(resp);
Uri combinedUri = new Uri(respUri, node.Value);
return combinedUri.AbsoluteUri;
}
}
}
public static bool ForwardPort(int port, ProtocolType protocol, string description)
{
if (string.IsNullOrEmpty(_serviceUrl))
throw new Exception("No UPnP service available or Discover() has not been called");
string body = String.Format("<u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">"+
"<NewRemoteHost></NewRemoteHost><NewExternalPort>{0}</NewExternalPort>"+
"<NewProtocol>{1}</NewProtocol><NewInternalPort>{0}</NewInternalPort>" +
"<NewInternalClient>{2}</NewInternalClient><NewEnabled>1</NewEnabled>" +
"<NewPortMappingDescription>{3}</NewPortMappingDescription>"+
"<NewLeaseDuration>0</NewLeaseDuration></u:AddPortMapping>",
port, protocol.ToString().ToUpper(),Dns.GetHostAddresses(Dns.GetHostName())[0], description);
if (SOAPRequest(_serviceUrl, body, "AddPortMapping") != null)
return true;
else
return false;
}
public static bool DeleteForwardingRule(int port, ProtocolType protocol)
{
if (string.IsNullOrEmpty(_serviceUrl))
throw new Exception("No UPnP service available or Discover() has not been called");
string body = String.Format("<u:DeletePortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" +
"<NewRemoteHost></NewRemoteHost><NewExternalPort>{0}</NewExternalPort>"+
"<NewProtocol>{1}</NewProtocol></u:DeletePortMapping>", port, protocol.ToString().ToUpper() );
if (SOAPRequest(_serviceUrl, body, "DeletePortMapping") != null)
return true;
else
return false;
}
public static IPAddress GetExternalIP()
{
if (string.IsNullOrEmpty(_serviceUrl))
throw new Exception("No UPnP service available or Discover() has not been called");
XmlDocument xdoc = SOAPRequest(_serviceUrl, "<u:GetExternalIPAddress xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" +
"</u:GetExternalIPAddress>", "GetExternalIPAddress");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xdoc.NameTable);
nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0");
string IP = xdoc.SelectSingleNode("//NewExternalIPAddress/text()", nsMgr).Value;
return IPAddress.Parse(IP);
}
private static XmlDocument SOAPRequest(string url, string soap, string function)
{
string body = "<?xml version=\"1.0\"?>" +
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
"<s:Body>" +
soap +
"</s:Body>" +
"</s:Envelope>";
HttpWebRequest r = (HttpWebRequest)WebRequest.Create(url);
r.KeepAlive = false;
r.Method = "POST";
byte[] b = Encoding.UTF8.GetBytes(body);
r.Headers.Add("SOAPACTION", "\"urn:schemas-upnp-org:service:WANIPConnection:1#" + function + "\"");
r.ContentType = "text/xml; charset=\"utf-8\"";
r.ContentLength = b.Length;
Stream newStream = r.GetRequestStream();
newStream.Write(b, 0, b.Length);
XmlDocument resp = new XmlDocument();
using (WebResponse wres = r.GetResponse())
{
using (Stream ress = wres.GetResponseStream())
{
resp.Load(ress);
return resp;
}
}
}
}
}

View File

@@ -29,6 +29,12 @@ namespace OpenRA
static ISoundSource LoadSound(string filename)
{
if (!FileSystem.Exists(filename))
{
Log.Write("debug", "LoadSound, file does not exist: {0}", filename);
return null;
}
return LoadSoundRaw(AudLoader.LoadSound(FileSystem.Open(filename)));
}
@@ -37,9 +43,21 @@ namespace OpenRA
return soundEngine.AddSoundSourceFromMemory(rawData, 1, 16, 22050);
}
public static void Create()
static ISoundEngine CreateEngine(string engine)
{
soundEngine = new OpenAlSoundEngine();
switch (engine)
{ /* todo: if someone cares about pluggable crap here, ship this out */
case "AL": return new OpenAlSoundEngine();
case "Null": return new NullSoundEngine();
default:
throw new InvalidOperationException("Unsupported sound engine: {0}".F (engine));
}
}
public static void Create(string engine)
{
soundEngine = CreateEngine(engine);
}
public static void Initialize()
@@ -52,29 +70,29 @@ namespace OpenRA
public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); }
static ISound Play(Player player, string name, bool headRelative, float2 pos, float volumeModifier)
static ISound Play(Player player, string name, bool headRelative, PPos pos, float volumeModifier)
{
if (player != null && player != player.World.LocalPlayer)
if (String.IsNullOrEmpty(name))
return null;
if (name == "" || name == null)
if (player != null && player != player.World.LocalPlayer)
return null;
return soundEngine.Play2D(sounds[name],
false, headRelative, pos,
InternalSoundVolume * volumeModifier);
false, headRelative, pos.ToFloat2(),
InternalSoundVolume * volumeModifier, true);
}
public static ISound Play(string name) { return Play(null, name, true, float2.Zero, 1); }
public static ISound Play(string name, float2 pos) { return Play(null, name, false, pos, 1); }
public static ISound Play(string name, float volumeModifier) { return Play(null, name, true, float2.Zero, volumeModifier); }
public static ISound Play(string name, float2 pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); }
public static ISound PlayToPlayer(Player player, string name) { return Play( player, name, true, float2.Zero, 1); }
public static ISound PlayToPlayer(Player player, string name, float2 pos) { return Play(player, name, false, pos, 1); }
public static ISound Play(string name) { return Play(null, name, true, PPos.Zero, 1); }
public static ISound Play(string name, PPos pos) { return Play(null, name, false, pos, 1); }
public static ISound Play(string name, float volumeModifier) { return Play(null, name, true, PPos.Zero, volumeModifier); }
public static ISound Play(string name, PPos pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); }
public static ISound PlayToPlayer(Player player, string name) { return Play(player, name, true, PPos.Zero, 1); }
public static ISound PlayToPlayer(Player player, string name, PPos pos) { return Play(player, name, false, pos, 1); }
public static void PlayVideo(byte[] raw)
{
rawSource = LoadSoundRaw(raw);
video = soundEngine.Play2D(rawSource, false, true, float2.Zero, InternalSoundVolume);
video = soundEngine.Play2D(rawSource, false, true, float2.Zero, InternalSoundVolume, false);
}
public static void PlayVideo()
@@ -128,10 +146,12 @@ namespace OpenRA
}
StopMusic();
var sound = sounds[m.Filename];
if (sound == null) return;
music = soundEngine.Play2D(sound, false, true, float2.Zero, MusicVolume, false);
currentMusic = m;
MusicPlaying = true;
var sound = sounds[m.Filename];
music = soundEngine.Play2D(sound, false, true, float2.Zero, MusicVolume);
}
public static void PlayMusic()
@@ -226,7 +246,48 @@ namespace OpenRA
get { return (video != null) ? video.SeekPosition : 0; }
}
// Returns true if it played a phrase
// Returns true if played successfully
public static bool PlayPredefined(Player p, Actor voicedUnit, string type, string definition, string variant)
{
if (definition == null) return false;
if (Rules.Voices == null) return false;
if (Rules.Notifications == null) return false;
var rules = (voicedUnit != null) ? Rules.Voices[type] : Rules.Notifications[type];
if (rules == null) return false;
var ID = (voicedUnit != null) ? voicedUnit.ActorID : 0;
var clip = (voicedUnit != null) ? rules.VoicePools.Value[definition].GetNext() : rules.NotificationsPools.Value[definition].GetNext();
if (clip == null) return false;
var suffix = rules.DefaultVariant;
var prefix = rules.DefaultPrefix;
if (voicedUnit != null)
{
if (!rules.VoicePools.Value.ContainsKey("Attack"))
rules.VoicePools.Value.Add("Attack", rules.VoicePools.Value["Move"]);
if (!rules.VoicePools.Value.ContainsKey("AttackMove"))
rules.VoicePools.Value.Add("AttackMove", rules.VoicePools.Value["Move"]);
}
if (variant != null)
{
if (rules.Variants.ContainsKey(variant) && !rules.DisableVariants.Contains(definition))
suffix = rules.Variants[variant][ID % rules.Variants[variant].Length];
if (rules.Prefixes.ContainsKey(variant) && !rules.DisablePrefixes.Contains(definition))
prefix = rules.Prefixes[variant][ID % rules.Prefixes[variant].Length];
}
if (p == null)
Play(prefix + clip + suffix);
else
PlayToPlayer(p, prefix + clip + suffix);
return true;
}
public static bool PlayVoice(string phrase, Actor voicedUnit, string variant)
{
if (voicedUnit == null) return false;
@@ -236,23 +297,24 @@ namespace OpenRA
if (mi == null) return false;
if (mi.Voice == null) return false;
var vi = Rules.Voices[mi.Voice.ToLowerInvariant()];
var type = mi.Voice.ToLowerInvariant();
var clip = vi.Pools.Value[phrase].GetNext();
if (clip == null)
return false;
return PlayPredefined(null, voicedUnit, type, phrase, variant);
}
var variantext = (vi.Variants.ContainsKey(variant) && !vi.DisableVariants.Contains(phrase)) ?
vi.Variants[variant][voicedUnit.ActorID % vi.Variants[variant].Length] : vi.DefaultVariant;
Play(clip + variantext);
return true;
public static bool PlayNotification(Player player, string type, string notification, string variant)
{
if (type == null) return false;
if (notification == null) return false;
return PlayPredefined(player, null, type.ToLowerInvariant(), notification, variant);
}
}
interface ISoundEngine
{
ISoundSource AddSoundSourceFromMemory(byte[] data, int channels, int sampleBits, int sampleRate);
ISound Play2D(ISoundSource sound, bool loop, bool relative, float2 pos, float volume);
ISound Play2D(ISoundSource sound, bool loop, bool relative, float2 pos, float volume, bool attenuateVolume);
float Volume { get; set; }
void PauseSound(ISound sound, bool paused);
void StopSound(ISound sound);
@@ -273,8 +335,17 @@ namespace OpenRA
class OpenAlSoundEngine : ISoundEngine
{
class PoolSlot
{
public bool isActive;
public int frameStarted;
public float2 pos;
public bool isRelative;
public ISoundSource sound;
}
float volume = 1f;
Dictionary<int, bool> sourcePool = new Dictionary<int, bool>();
Dictionary<int, PoolSlot> sourcePool = new Dictionary<int, PoolSlot>();
const int POOL_SIZE = 32;
public OpenAlSoundEngine()
@@ -298,7 +369,7 @@ namespace OpenRA
return;
}
sourcePool.Add(source, false);
sourcePool.Add(source, new PoolSlot() { isActive = false });
}
}
@@ -306,9 +377,9 @@ namespace OpenRA
{
foreach (var kvp in sourcePool)
{
if (!kvp.Value)
if (!kvp.Value.isActive)
{
sourcePool[kvp.Key] = true;
sourcePool[kvp.Key].isActive = true;
return kvp.Key;
}
}
@@ -326,9 +397,9 @@ namespace OpenRA
return -1;
foreach (int i in freeSources)
sourcePool[i] = false;
sourcePool[i].isActive = false;
sourcePool[freeSources[0]] = true;
sourcePool[freeSources[0]].isActive = true;
return freeSources[0];
}
@@ -338,10 +409,62 @@ namespace OpenRA
return new OpenAlSoundSource(data, channels, sampleBits, sampleRate);
}
public ISound Play2D(ISoundSource sound, bool loop, bool relative, float2 pos, float volume)
const int maxInstancesPerFrame = 3;
const int groupDistance = 64;
const int groupDistanceSqr = groupDistance * groupDistance;
public ISound Play2D(ISoundSource sound, bool loop, bool relative, float2 pos, float volume, bool attenuateVolume)
{
if (sound == null)
{
Log.Write("debug", "Attempt to Play2D a null `ISoundSource`");
return null;
}
var world = Game.orderManager.world;
int currFrame = world != null ? world.FrameNumber : 0;
float atten = 1f;
// Check if max # of instances-per-location reached:
if (attenuateVolume)
{
int instances = 0, activeCount = 0;
foreach (var s in sourcePool.Values)
{
if (!s.isActive)
continue;
if (s.isRelative != relative)
continue;
++activeCount;
if (s.sound != sound)
continue;
if (currFrame - s.frameStarted >= 5)
continue;
// Too far away to count?
var lensqr = (s.pos - pos).LengthSquared;
if (lensqr >= groupDistanceSqr)
continue;
// If we are starting too many instances of the same sound within a short time then stop this one:
if (++instances == maxInstancesPerFrame)
return null;
}
// Attenuate a little bit based on number of active sounds:
atten = 0.66f * ((POOL_SIZE - activeCount * 0.5f) / POOL_SIZE);
}
int source = GetSourceFromPool();
return new OpenAlSound(source, (sound as OpenAlSoundSource).buffer, loop, relative, pos, volume);
if (source == -1) return null;
var slot = sourcePool[source];
slot.pos = pos;
slot.frameStarted = currFrame;
slot.sound = sound;
slot.isRelative = relative;
return new OpenAlSound(source, (sound as OpenAlSoundSource).buffer, loop, relative, pos, volume * atten);
}
public float Volume
@@ -352,6 +475,8 @@ namespace OpenRA
public void PauseSound(ISound sound, bool paused)
{
if (sound == null) return;
int key = ((OpenAlSound)sound).source;
int state;
Al.alGetSourcei(key, Al.AL_SOURCE_STATE, out state);
@@ -393,6 +518,8 @@ namespace OpenRA
public void StopSound(ISound sound)
{
if (sound == null) return;
int key = ((OpenAlSound)sound).source;
int state;
Al.alGetSourcei(key, Al.AL_SOURCE_STATE, out state);
@@ -450,15 +577,14 @@ namespace OpenRA
if (source == -1) return;
this.source = source;
Al.alSourcef(source, Al.AL_PITCH, 1f);
Al.alSourcef(source, Al.AL_GAIN, 1f);
Volume = volume;
Al.alSource3f(source, Al.AL_POSITION, pos.X, pos.Y, 0f);
Al.alSource3f(source, Al.AL_VELOCITY, 0f, 0f, 0f);
Al.alSourcei(source, Al.AL_BUFFER, buffer);
Al.alSourcei(source, Al.AL_LOOPING, looping ? Al.AL_TRUE : Al.AL_FALSE);
Al.alSourcei(source, Al.AL_SOURCE_RELATIVE, relative ? 1 : 0);
Al.alSourcef(source, Al.AL_REFERENCE_DISTANCE, 200);
Al.alSourcef(source, Al.AL_MAX_DISTANCE, 1500);
Volume = volume;
Al.alSourcef(source, Al.AL_REFERENCE_DISTANCE, 160);
Al.alSourcef(source, Al.AL_MAX_DISTANCE, 3200 / Game.viewport.Zoom);
Al.alSourcePlay(source);
}
@@ -492,4 +618,35 @@ namespace OpenRA
}
}
}
class NullSoundEngine : ISoundEngine
{
public ISoundSource AddSoundSourceFromMemory(byte[] data, int channels, int sampleBits, int sampleRate)
{
return new NullSoundSource();
}
public ISound Play2D(ISoundSource sound, bool loop, bool relative, float2 pos, float volume, bool attenuateVolume)
{
return new NullSound();
}
public void PauseSound(ISound sound, bool paused) {}
public void StopSound(ISound sound) {}
public void SetAllSoundsPaused(bool paused) {}
public void StopAllSounds() {}
public void SetListenerPosition(float2 position) {}
public void SetSoundVolume(float volume, ISound music, ISound video) {}
public float Volume { get; set; }
}
class NullSoundSource : ISoundSource {}
class NullSound : ISound
{
public float Volume { get; set; }
public float SeekPosition { get { return 0; } }
public bool Playing { get { return false; } }
}
}

View File

@@ -13,13 +13,14 @@ using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
using System.Text;
namespace OpenRA
{
static class Program
{
[STAThread]
static void Main( string[] args )
static void Main(string[] args)
{
// brutal hack
Application.CurrentCulture = CultureInfo.InvariantCulture;
@@ -32,19 +33,60 @@ namespace OpenRA
try
{
Run( args );
Run(args);
}
catch( Exception e )
catch (Exception e)
{
Log.AddChannel("exception", "exception.log");
Log.Write("exception", "{0}", e.ToString());
throw;
var rpt = BuildExceptionReport(e).ToString();
Log.Write("exception", "{0}", rpt);
Console.Error.WriteLine(rpt);
}
}
static void Run( string[] args )
static StringBuilder BuildExceptionReport(Exception e)
{
Game.Initialize( new Arguments(args) );
return BuildExceptionReport(e, new StringBuilder(), 0);
}
static void Indent(StringBuilder sb, int d)
{
sb.Append(new string(' ', d * 2));
}
static StringBuilder BuildExceptionReport(Exception e, StringBuilder sb, int d)
{
if (e == null) return sb;
sb.AppendFormat("Exception of type `{0}`: {1}", e.GetType().FullName, e.Message);
if (e is TypeLoadException)
{
var tle = (TypeLoadException)e;
sb.AppendLine();
Indent(sb, d);
sb.AppendFormat("TypeName=`{0}`", tle.TypeName);
}
else // TODO: more exception types
{
}
if (e.InnerException != null)
{
sb.AppendLine();
Indent(sb, d); sb.Append("Inner ");
BuildExceptionReport(e.InnerException, sb, d + 1);
}
sb.AppendLine();
Indent(sb, d); sb.Append(e.StackTrace);
return sb;
}
static void Run(string[] args)
{
Game.Initialize(new Arguments(args));
GC.Collect();
Game.Run();
}

View File

@@ -50,6 +50,36 @@ namespace OpenRA
il.EmitCall(OpCodes.Call, ((Func<int2, int>)hash_int2).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(CPos))
{
il.EmitCall(OpCodes.Call, ((Func<CPos, int>)hash_CPos).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(CVec))
{
il.EmitCall(OpCodes.Call, ((Func<CVec, int>)hash_CVec).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(PPos))
{
il.EmitCall(OpCodes.Call, ((Func<PPos, int>)hash_PPos).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(PVecInt))
{
il.EmitCall(OpCodes.Call, ((Func<PVecInt, int>)hash_PVecInt).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(PSubPos))
{
il.EmitCall(OpCodes.Call, ((Func<PSubPos, int>)hash_PSubPos).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(PSubVec))
{
il.EmitCall(OpCodes.Call, ((Func<PSubVec, int>)hash_PSubVec).Method, null);
il.Emit(OpCodes.Xor);
}
else if (type == typeof(TypeDictionary))
{
il.EmitCall(OpCodes.Call, ((Func<TypeDictionary, int>)hash_tdict).Method, null);
@@ -110,6 +140,36 @@ namespace OpenRA
return ( ( i2.X * 5 ) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_CPos( CPos i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_CVec( CVec i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_PPos( PPos i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_PVecInt( PVecInt i2 )
{
return ( ( i2.X * 5) ^ ( i2.Y * 3 ) ) / 4;
}
public static int hash_PSubPos(PSubPos i2)
{
return ((i2.X * 5) ^ (i2.Y * 3)) / 4;
}
public static int hash_PSubVec(PSubVec i2)
{
return ((i2.X * 5) ^ (i2.Y * 3)) / 4;
}
public static int hash_tdict( TypeDictionary d )
{
int ret = 0;

View File

@@ -54,31 +54,33 @@ namespace OpenRA
InnerGet( t ).Add( actor, val );
}
void CheckDestroyed(Actor actor)
{
if (actor.Destroyed)
throw new InvalidOperationException("Attempted to get trait from destroyed object ({0})".F(actor));
}
public bool Contains<T>( Actor actor )
{
if( actor.Destroyed )
throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) );
CheckDestroyed(actor);
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetMultiple( actor.ActorID ).Count() != 0;
}
public T Get<T>( Actor actor )
{
if( actor.Destroyed )
throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) );
CheckDestroyed(actor);
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).Get( actor.ActorID );
}
public T GetOrDefault<T>( Actor actor )
{
if( actor.Destroyed )
throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) );
CheckDestroyed(actor);
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetOrDefault( actor.ActorID );
}
public IEnumerable<T> WithInterface<T>( Actor actor )
{
if( actor.Destroyed )
throw new InvalidOperationException( "Attempted to get trait from destroyed object ({0})".F( actor.ToString() ) );
CheckDestroyed(actor);
return ( (TraitContainer<T>)InnerGet( typeof( T ) ) ).GetMultiple( actor.ActorID );
}
@@ -118,14 +120,10 @@ namespace OpenRA
public T Get( uint actor )
{
++queries;
var index = actors.BinarySearchMany( actor );
if( index >= actors.Count || actors[ index ].ActorID != actor )
throw new InvalidOperationException( string.Format( "TraitDictionary does not contain instance of type `{0}`", typeof( T ) ) );
else if( index + 1 < actors.Count && actors[ index + 1 ].ActorID == actor )
throw new InvalidOperationException( string.Format( "TraitDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
else
return traits[ index ];
var result = GetOrDefault(actor);
if ((object)result == null)
throw new InvalidOperationException("Actor does not have trait of type `{0}`".F(typeof(T)));
return result;
}
public T GetOrDefault( uint actor )
@@ -135,7 +133,7 @@ namespace OpenRA
if( index >= actors.Count || actors[ index ].ActorID != actor )
return default( T );
else if( index + 1 < actors.Count && actors[ index + 1 ].ActorID == actor )
throw new InvalidOperationException( string.Format( "TraitDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
throw new InvalidOperationException("Actor has multiple traits of type `{0}`".F(typeof(T)));
else return traits[ index ];
}

View File

@@ -0,0 +1,36 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Linq;
namespace OpenRA.Traits
{
public class CreatesShroudInfo : ITraitInfo
{
public readonly int Range = 0;
public object Create(ActorInitializer init) { return new CreatesShroud(this); }
}
public class CreatesShroud : ITick
{
CreatesShroudInfo Info;
public CreatesShroud(CreatesShroudInfo info)
{
Info = info;
}
public void Tick(Actor self)
{
if (!self.IsDisabled())
self.World.WorldActor.Trait<Shroud>().HideActor(self, Info.Range);
}
}
}

View File

@@ -11,6 +11,7 @@
using System.Drawing;
using OpenRA.Graphics;
using OpenRA.Effects;
using System.Collections.Generic;
namespace OpenRA.Traits
{
@@ -25,7 +26,7 @@ namespace OpenRA.Traits
{
Actor self;
DrawLineToTargetInfo Info;
Target target;
List<Target> targets;
Color c;
int lifetime;
@@ -33,7 +34,16 @@ namespace OpenRA.Traits
public void SetTarget(Actor self, Target target, Color c, bool display)
{
this.target = target;
this.targets = new List<Target> { target };
this.c = c;
if (display)
lifetime = Info.Ticks;
}
public void SetTargets(Actor self, List<Target> targets, Color c, bool display)
{
this.targets = targets;
this.c = c;
if (display)
@@ -42,23 +52,29 @@ namespace OpenRA.Traits
public void RenderAfterWorld(WorldRenderer wr)
{
if (self.IsIdle) return;
//if (self.IsIdle) return;
var force = Game.GetModifierKeys().HasModifier(Modifiers.Alt);
if ((lifetime <= 0 || --lifetime <= 0) && !force)
return;
if (!target.IsValid)
if (targets == null || targets.Count == 0)
return;
var move = self.TraitOrDefault<IMove>();
var origin = move != null ? self.CenterLocation - new int2(0, move.Altitude) : self.CenterLocation;
var origin = (move != null ? self.CenterLocation - new PVecInt(0, move.Altitude) : self.CenterLocation).ToFloat2();
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(origin, target.CenterLocation, c, c);
DrawTargetMarker(wlr, target.CenterLocation);
DrawTargetMarker(wlr, origin);
foreach (var target in targets)
{
if (!target.IsValid)
continue;
wlr.DrawLine(origin, target.CenterLocation.ToFloat2(), c, c);
DrawTargetMarker(wlr, target.CenterLocation.ToFloat2());
DrawTargetMarker(wlr, origin);
}
}
void DrawTargetMarker(LineRenderer wlr, float2 p)
@@ -72,6 +88,18 @@ namespace OpenRA.Traits
public static class LineTargetExts
{
public static void SetTargetLines(this Actor self, List<Target> targets, Color color)
{
var line = self.TraitOrDefault<DrawLineToTarget>();
if (line != null)
{
self.World.AddFrameEndTask(w =>
{
line.SetTargets(self, targets, color, false);
});
}
}
public static void SetTargetLine(this Actor self, Target target, Color color)
{
self.SetTargetLine(target, color, true);

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Traits
}
public int HP { get { return hp; } }
public readonly int MaxHP;
public int MaxHP;
public bool IsDead { get { return hp <= 0; } }
public bool RemoveOnDeath = true;

View File

@@ -1,43 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
namespace OpenRA.Traits
{
public class EvaAlertsInfo : TraitInfo<EvaAlerts>
{
// Sound effects
public readonly string RadarUp = "radaron2.aud";
public readonly string RadarDown = "radardn1.aud";
public readonly string CashTickUp = "cashup1.aud";
public readonly string CashTickDown = "cashdn1.aud";
// Build Palette
public readonly string BuildingCannotPlaceAudio = "nodeply1.aud";
public readonly string NewOptions = "newopt1.aud";
// For manual powerup/down in ra-ng
public readonly string DisablePower = "bleep11.aud";
public readonly string EnablePower = "bleep12.aud";
// Eva speech
public readonly string Repairing = "repair1.aud";
public readonly string LowPower = "lopower1.aud";
public readonly string SilosNeeded = "silond1.aud";
public readonly string PrimaryBuildingSelected = "pribldg1.aud";
// Special powers
public readonly string AbilityInsufficientPower = "nopowr1.aud";
public readonly string LevelUp = "hydrod1.aud";
}
public class EvaAlerts {}
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2012 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -10,6 +10,7 @@
using System;
using System.Linq;
using OpenRA.GameRules;
namespace OpenRA.Traits
{
@@ -62,6 +63,8 @@ namespace OpenRA.Traits
{
readonly Player Owner;
int AdviceInterval;
int cashtickallowed = 0;
public PlayerResources(Actor self, PlayerResourcesInfo info)
{
@@ -133,8 +136,10 @@ namespace OpenRA.Traits
public void Tick(Actor self)
{
var eva = self.World.WorldActor.Info.Traits.Get<EvaAlertsInfo>();
if(cashtickallowed > 0) {
cashtickallowed = cashtickallowed - 1;
}
OreCapacity = self.World.ActorsWithTrait<IStoreOre>()
.Where(a => a.Actor.Owner == Owner)
.Sum(a => a.Trait.Capacity);
@@ -145,7 +150,7 @@ namespace OpenRA.Traits
if (--nextSiloAdviceTime <= 0)
{
if (Ore > 0.8*OreCapacity)
Owner.GiveAdvice(eva.SilosNeeded);
Sound.PlayNotification(Owner, "Speech", "SilosNeeded", Owner.Country.Race);
nextSiloAdviceTime = AdviceInterval;
}
@@ -158,12 +163,12 @@ namespace OpenRA.Traits
if (DisplayCash < Cash)
{
DisplayCash += move;
Sound.PlayToPlayer(self.Owner, eva.CashTickUp);
playCashTickUp(self);
}
else if (DisplayCash > Cash)
{
DisplayCash -= move;
Sound.PlayToPlayer(self.Owner, eva.CashTickDown);
playCashTickDown(self);
}
diff = Math.Abs(Ore - DisplayOre);
@@ -173,13 +178,34 @@ namespace OpenRA.Traits
if (DisplayOre < Ore)
{
DisplayOre += move;
Sound.PlayToPlayer(self.Owner, eva.CashTickUp);
playCashTickUp(self);
}
else if (DisplayOre > Ore)
{
DisplayOre -= move;
Sound.PlayToPlayer(self.Owner, eva.CashTickDown);
playCashTickDown(self);
}
}
public void playCashTickUp(Actor self)
{
if (Game.Settings.Sound.SoundCashTickType != SoundCashTicks.Disabled)
{
Sound.PlayNotification(self.Owner, "Sounds", "CashTickUp", self.Owner.Country.Race);
}
}
public void playCashTickDown(Actor self)
{
if (
Game.Settings.Sound.SoundCashTickType == SoundCashTicks.Extreme ||
(Game.Settings.Sound.SoundCashTickType == SoundCashTicks.Normal && cashtickallowed == 0)
) {
Sound.PlayNotification(self.Owner, "Sounds", "CashTickDown", self.Owner.Country.Race);
cashtickallowed = 3;
}
}
}
}

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Traits
class RevealsShroud : ITick
{
RevealsShroudInfo Info;
int2 previousLocation;
CPos previousLocation;
public RevealsShroud(RevealsShroudInfo info)
{

View File

@@ -146,12 +146,12 @@ namespace OpenRA.Traits
{
var alt = new float2(0, -mobile.Altitude);
var targets = activity.GetTargets(self);
var start = self.CenterLocation + alt;
var start = self.CenterLocation.ToFloat2() + alt;
var c = Color.Green;
var wlr = Game.Renderer.WorldLineRenderer;
foreach (var step in targets.Select(p => p.CenterLocation))
foreach (var step in targets.Select(p => p.CenterLocation.ToFloat2()))
{
var stp = step + alt;
wlr.DrawLine(stp + new float2(-1, -1), stp + new float2(-1, 1), c, c);

View File

@@ -1,36 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRA.FileFormats;
namespace OpenRA.Traits
{
public class SubCellInit : IActorInit<SubCell>
{
[FieldFromYamlKey]
public readonly int value = 0;
public SubCellInit() { }
public SubCellInit(int init)
{
value = init;
}
public SubCell Value(World world)
{
return (SubCell)value;
}
}
}

View File

@@ -16,7 +16,7 @@ namespace OpenRA.Traits
Actor actor;
Player owner;
int2 pos;
PPos pos;
bool valid;
public static Target FromActor(Actor a)
@@ -28,8 +28,8 @@ namespace OpenRA.Traits
owner = (a != null) ? a.Owner : null
};
}
public static Target FromPos(int2 p) { return new Target { pos = p, valid = true }; }
public static Target FromCell(int2 c) { return new Target { pos = Util.CenterOfCell(c), valid = true }; }
public static Target FromPos(PPos p) { return new Target { pos = p, valid = true }; }
public static Target FromCell(CPos c) { return new Target { pos = Util.CenterOfCell(c), valid = true }; }
public static Target FromOrder(Order o)
{
return o.TargetActor != null
@@ -40,8 +40,8 @@ namespace OpenRA.Traits
public static readonly Target None = new Target();
public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && actor.Owner == owner)); } }
public int2 PxPosition { get { return IsActor ? actor.Trait<IHasLocation>().PxPosition : pos; } }
public int2 CenterLocation { get { return PxPosition; } }
public PPos PxPosition { get { return IsActor ? actor.Trait<IHasLocation>().PxPosition : pos; } }
public PPos CenterLocation { get { return PxPosition; } }
public Actor Actor { get { return IsActor ? actor : null; } }
public bool IsActor { get { return actor != null && !actor.Destroyed; } }

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Graphics;
@@ -46,20 +47,21 @@ namespace OpenRA.Traits
string OrderID { get; }
int OrderPriority { get; }
bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueue, ref string cursor);
bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueue, ref string cursor);
bool CanTargetLocation(Actor self, CPos location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueue, ref string cursor);
bool IsQueued { get; }
}
public interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
public interface IValidateOrder { bool OrderValidation(OrderManager orderManager, World world, int clientId, Order order); }
public interface IOrderVoice { string VoicePhraseForOrder(Actor self, Order order); }
public interface INotify { void Play(Player p, string notification); }
public interface INotifySold { void Selling(Actor self); void Sold(Actor self); }
public interface INotifyDamage { void Damaged(Actor self, AttackInfo e); }
public interface INotifyDamageStateChanged { void DamageStateChanged(Actor self, AttackInfo e); }
public interface INotifyKilled { void Killed(Actor self, AttackInfo e); }
public interface INotifyAppliedDamage { void AppliedDamage(Actor self, Actor damaged, AttackInfo e); }
public interface INotifyBuildComplete { void BuildingComplete(Actor self); }
public interface INotifyProduction { void UnitProduced(Actor self, Actor other, int2 exit); }
public interface INotifyProduction { void UnitProduced(Actor self, Actor other, CPos exit); }
public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); }
public interface INotifyOtherCaptured { void OnActorCaptured(Actor self, Actor captured, Actor captor, Player oldOwner, Player newOwner); }
public interface IAcceptSpy { void OnInfiltrate(Actor self, Actor spy); }
@@ -74,27 +76,26 @@ namespace OpenRA.Traits
public interface IDisable { bool Disabled { get; } }
public interface IExplodeModifier { bool ShouldExplode(Actor self); }
public interface IHuskModifier { string HuskActor(Actor self); }
public interface INudge { void OnNudge(Actor self, Actor nudger, bool force); }
public interface IRadarSignature
{
IEnumerable<int2> RadarSignatureCells(Actor self);
IEnumerable<CPos> RadarSignatureCells(Actor self);
Color RadarSignatureColor(Actor self);
}
public interface IVisibilityModifier { bool IsVisible(Actor self); }
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
public interface IHasLocation { int2 PxPosition { get; } }
public interface IHasLocation { PPos PxPosition { get; } }
public interface IOccupySpace : IHasLocation
{
int2 TopLeft { get; }
IEnumerable<Pair<int2, SubCell>> OccupiedCells();
CPos TopLeft { get; }
IEnumerable<Pair<CPos, SubCell>> OccupiedCells();
}
public static class IOccupySpaceExts
{
public static int2 NearestCellTo(this IOccupySpace ios, int2 other)
public static CPos NearestCellTo(this IOccupySpace ios, CPos other)
{
var nearest = ios.TopLeft;
var nearestDistance = int.MaxValue;
@@ -124,13 +125,14 @@ namespace OpenRA.Traits
public interface ITeleportable : IHasLocation /* crap name! */
{
bool CanEnterCell(int2 location);
void SetPosition(Actor self, int2 cell);
void SetPxPosition(Actor self, int2 px);
void AdjustPxPosition(Actor self, int2 px); /* works like SetPxPosition, but visual only */
bool CanEnterCell(CPos location);
void SetPosition(Actor self, CPos cell);
void SetPxPosition(Actor self, PPos px);
void AdjustPxPosition(Actor self, PPos px); /* works like SetPxPosition, but visual only */
}
public interface IMove : ITeleportable { int Altitude { get; set; } }
public interface INotifyBlockingMove { void OnNotifyBlockingMove(Actor self, Actor blocking); }
public interface IFacing
{
@@ -211,7 +213,7 @@ namespace OpenRA.Traits
public interface ITargetable
{
string[] TargetTypes { get; }
IEnumerable<int2> TargetableCells(Actor self);
IEnumerable<CPos> TargetableCells(Actor self);
bool TargetableBy(Actor self, Actor byActor);
}
@@ -224,4 +226,12 @@ namespace OpenRA.Traits
public interface ILintPass { void Run(Action<string> emitError, Action<string> emitWarning); }
public interface IObjectivesPanel { string ObjectivesPanel { get; } }
public static class DisableExts
{
public static bool IsDisabled(this Actor a)
{
return a.TraitsImplementing<IDisable>().Any(d => d.Disabled);
}
}
}

View File

@@ -30,6 +30,16 @@ namespace OpenRA.Traits
return ( facing - rot ) & 0xFF;
}
public static int GetFacing(PVecInt d, int currentFacing)
{
return GetFacing(d.ToInt2(), currentFacing);
}
public static int GetFacing(CVec d, int currentFacing)
{
return GetFacing(d.ToInt2(), currentFacing);
}
public static int GetFacing( int2 d, int currentFacing )
{
if (d == int2.Zero)
@@ -80,14 +90,14 @@ namespace OpenRA.Traits
ecc * (cosAngle * v.Y - sinAngle * v.X));
}
public static int2 CenterOfCell(int2 loc)
public static PPos CenterOfCell(CPos loc)
{
return new int2( Game.CellSize / 2, Game.CellSize / 2 ) + Game.CellSize * loc;
return loc.ToPPos() + new PVecInt(Game.CellSize / 2, Game.CellSize / 2);
}
public static int2 BetweenCells(int2 from, int2 to)
public static PPos BetweenCells(CPos from, CPos to)
{
return int2.Lerp( CenterOfCell( from ), CenterOfCell( to ), 1, 2 );
return PPos.Lerp(CenterOfCell(from), CenterOfCell(to), 1, 2);
}
public static int2 AsInt2(this int[] xs) { return new int2(xs[0], xs[1]); }
@@ -120,6 +130,7 @@ namespace OpenRA.Traits
public static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2]); }
[Obsolete("Use ToCPos() method", true)]
public static int2 CellContaining(float2 pos) { return (1f / Game.CellSize * pos).ToInt2(); }
/* pretty crap */
@@ -134,39 +145,39 @@ namespace OpenRA.Traits
}
}
static IEnumerable<int2> Neighbours(int2 c, bool allowDiagonal)
static IEnumerable<CPos> Neighbours(CPos c, bool allowDiagonal)
{
yield return c;
yield return new int2(c.X - 1, c.Y);
yield return new int2(c.X + 1, c.Y);
yield return new int2(c.X, c.Y - 1);
yield return new int2(c.X, c.Y + 1);
yield return new CPos(c.X - 1, c.Y);
yield return new CPos(c.X + 1, c.Y);
yield return new CPos(c.X, c.Y - 1);
yield return new CPos(c.X, c.Y + 1);
if (allowDiagonal)
{
yield return new int2(c.X - 1, c.Y - 1);
yield return new int2(c.X + 1, c.Y - 1);
yield return new int2(c.X - 1, c.Y + 1);
yield return new int2(c.X + 1, c.Y + 1);
yield return new CPos(c.X - 1, c.Y - 1);
yield return new CPos(c.X + 1, c.Y - 1);
yield return new CPos(c.X - 1, c.Y + 1);
yield return new CPos(c.X + 1, c.Y + 1);
}
}
public static IEnumerable<int2> ExpandFootprint(IEnumerable<int2> cells, bool allowDiagonal)
public static IEnumerable<CPos> ExpandFootprint(IEnumerable<CPos> cells, bool allowDiagonal)
{
var result = new Dictionary<int2, bool>();
var result = new Dictionary<CPos, bool>();
foreach (var c in cells.SelectMany(c => Neighbours(c, allowDiagonal)))
result[c] = true;
return result.Keys;
}
public static IEnumerable<int2> AdjacentCells( Target target )
public static IEnumerable<CPos> AdjacentCells(Target target)
{
var cells = target.IsActor
? target.Actor.OccupiesSpace.OccupiedCells().Select(c => c.First).ToArray()
: new int2[] {};
: new CPos[] {};
if (cells.Length == 0)
cells = new [] { Util.CellContaining(target.CenterLocation) };
cells = new CPos[] { target.CenterLocation.ToCPos() };
return Util.ExpandFootprint(cells, true);
}
@@ -208,264 +219,264 @@ namespace OpenRA.Traits
};
public static readonly int2[] SubPxVector =
public static readonly PSubVec[] SubPxVector =
{
new int2( 0, 1024 ),
new int2( 25, 1023 ),
new int2( 50, 1022 ),
new int2( 75, 1021 ),
new int2( 100, 1019 ),
new int2( 125, 1016 ),
new int2( 150, 1012 ),
new int2( 175, 1008 ),
new int2( 199, 1004 ),
new int2( 224, 999 ),
new int2( 248, 993 ),
new int2( 273, 986 ),
new int2( 297, 979 ),
new int2( 321, 972 ),
new int2( 344, 964 ),
new int2( 368, 955 ),
new int2( 391, 946 ),
new int2( 414, 936 ),
new int2( 437, 925 ),
new int2( 460, 914 ),
new int2( 482, 903 ),
new int2( 504, 890 ),
new int2( 526, 878 ),
new int2( 547, 865 ),
new int2( 568, 851 ),
new int2( 589, 837 ),
new int2( 609, 822 ),
new int2( 629, 807 ),
new int2( 649, 791 ),
new int2( 668, 775 ),
new int2( 687, 758 ),
new int2( 706, 741 ),
new int2( 724, 724 ),
new int2( 741, 706 ),
new int2( 758, 687 ),
new int2( 775, 668 ),
new int2( 791, 649 ),
new int2( 807, 629 ),
new int2( 822, 609 ),
new int2( 837, 589 ),
new int2( 851, 568 ),
new int2( 865, 547 ),
new int2( 878, 526 ),
new int2( 890, 504 ),
new int2( 903, 482 ),
new int2( 914, 460 ),
new int2( 925, 437 ),
new int2( 936, 414 ),
new int2( 946, 391 ),
new int2( 955, 368 ),
new int2( 964, 344 ),
new int2( 972, 321 ),
new int2( 979, 297 ),
new int2( 986, 273 ),
new int2( 993, 248 ),
new int2( 999, 224 ),
new int2( 1004, 199 ),
new int2( 1008, 175 ),
new int2( 1012, 150 ),
new int2( 1016, 125 ),
new int2( 1019, 100 ),
new int2( 1021, 75 ),
new int2( 1022, 50 ),
new int2( 1023, 25 ),
new int2( 1024, 0 ),
new int2( 1023, -25 ),
new int2( 1022, -50 ),
new int2( 1021, -75 ),
new int2( 1019, -100 ),
new int2( 1016, -125 ),
new int2( 1012, -150 ),
new int2( 1008, -175 ),
new int2( 1004, -199 ),
new int2( 999, -224 ),
new int2( 993, -248 ),
new int2( 986, -273 ),
new int2( 979, -297 ),
new int2( 972, -321 ),
new int2( 964, -344 ),
new int2( 955, -368 ),
new int2( 946, -391 ),
new int2( 936, -414 ),
new int2( 925, -437 ),
new int2( 914, -460 ),
new int2( 903, -482 ),
new int2( 890, -504 ),
new int2( 878, -526 ),
new int2( 865, -547 ),
new int2( 851, -568 ),
new int2( 837, -589 ),
new int2( 822, -609 ),
new int2( 807, -629 ),
new int2( 791, -649 ),
new int2( 775, -668 ),
new int2( 758, -687 ),
new int2( 741, -706 ),
new int2( 724, -724 ),
new int2( 706, -741 ),
new int2( 687, -758 ),
new int2( 668, -775 ),
new int2( 649, -791 ),
new int2( 629, -807 ),
new int2( 609, -822 ),
new int2( 589, -837 ),
new int2( 568, -851 ),
new int2( 547, -865 ),
new int2( 526, -878 ),
new int2( 504, -890 ),
new int2( 482, -903 ),
new int2( 460, -914 ),
new int2( 437, -925 ),
new int2( 414, -936 ),
new int2( 391, -946 ),
new int2( 368, -955 ),
new int2( 344, -964 ),
new int2( 321, -972 ),
new int2( 297, -979 ),
new int2( 273, -986 ),
new int2( 248, -993 ),
new int2( 224, -999 ),
new int2( 199, -1004 ),
new int2( 175, -1008 ),
new int2( 150, -1012 ),
new int2( 125, -1016 ),
new int2( 100, -1019 ),
new int2( 75, -1021 ),
new int2( 50, -1022 ),
new int2( 25, -1023 ),
new int2( 0, -1024 ),
new int2( -25, -1023 ),
new int2( -50, -1022 ),
new int2( -75, -1021 ),
new int2( -100, -1019 ),
new int2( -125, -1016 ),
new int2( -150, -1012 ),
new int2( -175, -1008 ),
new int2( -199, -1004 ),
new int2( -224, -999 ),
new int2( -248, -993 ),
new int2( -273, -986 ),
new int2( -297, -979 ),
new int2( -321, -972 ),
new int2( -344, -964 ),
new int2( -368, -955 ),
new int2( -391, -946 ),
new int2( -414, -936 ),
new int2( -437, -925 ),
new int2( -460, -914 ),
new int2( -482, -903 ),
new int2( -504, -890 ),
new int2( -526, -878 ),
new int2( -547, -865 ),
new int2( -568, -851 ),
new int2( -589, -837 ),
new int2( -609, -822 ),
new int2( -629, -807 ),
new int2( -649, -791 ),
new int2( -668, -775 ),
new int2( -687, -758 ),
new int2( -706, -741 ),
new int2( -724, -724 ),
new int2( -741, -706 ),
new int2( -758, -687 ),
new int2( -775, -668 ),
new int2( -791, -649 ),
new int2( -807, -629 ),
new int2( -822, -609 ),
new int2( -837, -589 ),
new int2( -851, -568 ),
new int2( -865, -547 ),
new int2( -878, -526 ),
new int2( -890, -504 ),
new int2( -903, -482 ),
new int2( -914, -460 ),
new int2( -925, -437 ),
new int2( -936, -414 ),
new int2( -946, -391 ),
new int2( -955, -368 ),
new int2( -964, -344 ),
new int2( -972, -321 ),
new int2( -979, -297 ),
new int2( -986, -273 ),
new int2( -993, -248 ),
new int2( -999, -224 ),
new int2( -1004, -199 ),
new int2( -1008, -175 ),
new int2( -1012, -150 ),
new int2( -1016, -125 ),
new int2( -1019, -100 ),
new int2( -1021, -75 ),
new int2( -1022, -50 ),
new int2( -1023, -25 ),
new int2( -1024, 0 ),
new int2( -1023, 25 ),
new int2( -1022, 50 ),
new int2( -1021, 75 ),
new int2( -1019, 100 ),
new int2( -1016, 125 ),
new int2( -1012, 150 ),
new int2( -1008, 175 ),
new int2( -1004, 199 ),
new int2( -999, 224 ),
new int2( -993, 248 ),
new int2( -986, 273 ),
new int2( -979, 297 ),
new int2( -972, 321 ),
new int2( -964, 344 ),
new int2( -955, 368 ),
new int2( -946, 391 ),
new int2( -936, 414 ),
new int2( -925, 437 ),
new int2( -914, 460 ),
new int2( -903, 482 ),
new int2( -890, 504 ),
new int2( -878, 526 ),
new int2( -865, 547 ),
new int2( -851, 568 ),
new int2( -837, 589 ),
new int2( -822, 609 ),
new int2( -807, 629 ),
new int2( -791, 649 ),
new int2( -775, 668 ),
new int2( -758, 687 ),
new int2( -741, 706 ),
new int2( -724, 724 ),
new int2( -706, 741 ),
new int2( -687, 758 ),
new int2( -668, 775 ),
new int2( -649, 791 ),
new int2( -629, 807 ),
new int2( -609, 822 ),
new int2( -589, 837 ),
new int2( -568, 851 ),
new int2( -547, 865 ),
new int2( -526, 878 ),
new int2( -504, 890 ),
new int2( -482, 903 ),
new int2( -460, 914 ),
new int2( -437, 925 ),
new int2( -414, 936 ),
new int2( -391, 946 ),
new int2( -368, 955 ),
new int2( -344, 964 ),
new int2( -321, 972 ),
new int2( -297, 979 ),
new int2( -273, 986 ),
new int2( -248, 993 ),
new int2( -224, 999 ),
new int2( -199, 1004 ),
new int2( -175, 1008 ),
new int2( -150, 1012 ),
new int2( -125, 1016 ),
new int2( -100, 1019 ),
new int2( -75, 1021 ),
new int2( -50, 1022 ),
new int2( -25, 1023 )
new PSubVec( 0, 1024 ),
new PSubVec( 25, 1023 ),
new PSubVec( 50, 1022 ),
new PSubVec( 75, 1021 ),
new PSubVec( 100, 1019 ),
new PSubVec( 125, 1016 ),
new PSubVec( 150, 1012 ),
new PSubVec( 175, 1008 ),
new PSubVec( 199, 1004 ),
new PSubVec( 224, 999 ),
new PSubVec( 248, 993 ),
new PSubVec( 273, 986 ),
new PSubVec( 297, 979 ),
new PSubVec( 321, 972 ),
new PSubVec( 344, 964 ),
new PSubVec( 368, 955 ),
new PSubVec( 391, 946 ),
new PSubVec( 414, 936 ),
new PSubVec( 437, 925 ),
new PSubVec( 460, 914 ),
new PSubVec( 482, 903 ),
new PSubVec( 504, 890 ),
new PSubVec( 526, 878 ),
new PSubVec( 547, 865 ),
new PSubVec( 568, 851 ),
new PSubVec( 589, 837 ),
new PSubVec( 609, 822 ),
new PSubVec( 629, 807 ),
new PSubVec( 649, 791 ),
new PSubVec( 668, 775 ),
new PSubVec( 687, 758 ),
new PSubVec( 706, 741 ),
new PSubVec( 724, 724 ),
new PSubVec( 741, 706 ),
new PSubVec( 758, 687 ),
new PSubVec( 775, 668 ),
new PSubVec( 791, 649 ),
new PSubVec( 807, 629 ),
new PSubVec( 822, 609 ),
new PSubVec( 837, 589 ),
new PSubVec( 851, 568 ),
new PSubVec( 865, 547 ),
new PSubVec( 878, 526 ),
new PSubVec( 890, 504 ),
new PSubVec( 903, 482 ),
new PSubVec( 914, 460 ),
new PSubVec( 925, 437 ),
new PSubVec( 936, 414 ),
new PSubVec( 946, 391 ),
new PSubVec( 955, 368 ),
new PSubVec( 964, 344 ),
new PSubVec( 972, 321 ),
new PSubVec( 979, 297 ),
new PSubVec( 986, 273 ),
new PSubVec( 993, 248 ),
new PSubVec( 999, 224 ),
new PSubVec( 1004, 199 ),
new PSubVec( 1008, 175 ),
new PSubVec( 1012, 150 ),
new PSubVec( 1016, 125 ),
new PSubVec( 1019, 100 ),
new PSubVec( 1021, 75 ),
new PSubVec( 1022, 50 ),
new PSubVec( 1023, 25 ),
new PSubVec( 1024, 0 ),
new PSubVec( 1023, -25 ),
new PSubVec( 1022, -50 ),
new PSubVec( 1021, -75 ),
new PSubVec( 1019, -100 ),
new PSubVec( 1016, -125 ),
new PSubVec( 1012, -150 ),
new PSubVec( 1008, -175 ),
new PSubVec( 1004, -199 ),
new PSubVec( 999, -224 ),
new PSubVec( 993, -248 ),
new PSubVec( 986, -273 ),
new PSubVec( 979, -297 ),
new PSubVec( 972, -321 ),
new PSubVec( 964, -344 ),
new PSubVec( 955, -368 ),
new PSubVec( 946, -391 ),
new PSubVec( 936, -414 ),
new PSubVec( 925, -437 ),
new PSubVec( 914, -460 ),
new PSubVec( 903, -482 ),
new PSubVec( 890, -504 ),
new PSubVec( 878, -526 ),
new PSubVec( 865, -547 ),
new PSubVec( 851, -568 ),
new PSubVec( 837, -589 ),
new PSubVec( 822, -609 ),
new PSubVec( 807, -629 ),
new PSubVec( 791, -649 ),
new PSubVec( 775, -668 ),
new PSubVec( 758, -687 ),
new PSubVec( 741, -706 ),
new PSubVec( 724, -724 ),
new PSubVec( 706, -741 ),
new PSubVec( 687, -758 ),
new PSubVec( 668, -775 ),
new PSubVec( 649, -791 ),
new PSubVec( 629, -807 ),
new PSubVec( 609, -822 ),
new PSubVec( 589, -837 ),
new PSubVec( 568, -851 ),
new PSubVec( 547, -865 ),
new PSubVec( 526, -878 ),
new PSubVec( 504, -890 ),
new PSubVec( 482, -903 ),
new PSubVec( 460, -914 ),
new PSubVec( 437, -925 ),
new PSubVec( 414, -936 ),
new PSubVec( 391, -946 ),
new PSubVec( 368, -955 ),
new PSubVec( 344, -964 ),
new PSubVec( 321, -972 ),
new PSubVec( 297, -979 ),
new PSubVec( 273, -986 ),
new PSubVec( 248, -993 ),
new PSubVec( 224, -999 ),
new PSubVec( 199, -1004 ),
new PSubVec( 175, -1008 ),
new PSubVec( 150, -1012 ),
new PSubVec( 125, -1016 ),
new PSubVec( 100, -1019 ),
new PSubVec( 75, -1021 ),
new PSubVec( 50, -1022 ),
new PSubVec( 25, -1023 ),
new PSubVec( 0, -1024 ),
new PSubVec( -25, -1023 ),
new PSubVec( -50, -1022 ),
new PSubVec( -75, -1021 ),
new PSubVec( -100, -1019 ),
new PSubVec( -125, -1016 ),
new PSubVec( -150, -1012 ),
new PSubVec( -175, -1008 ),
new PSubVec( -199, -1004 ),
new PSubVec( -224, -999 ),
new PSubVec( -248, -993 ),
new PSubVec( -273, -986 ),
new PSubVec( -297, -979 ),
new PSubVec( -321, -972 ),
new PSubVec( -344, -964 ),
new PSubVec( -368, -955 ),
new PSubVec( -391, -946 ),
new PSubVec( -414, -936 ),
new PSubVec( -437, -925 ),
new PSubVec( -460, -914 ),
new PSubVec( -482, -903 ),
new PSubVec( -504, -890 ),
new PSubVec( -526, -878 ),
new PSubVec( -547, -865 ),
new PSubVec( -568, -851 ),
new PSubVec( -589, -837 ),
new PSubVec( -609, -822 ),
new PSubVec( -629, -807 ),
new PSubVec( -649, -791 ),
new PSubVec( -668, -775 ),
new PSubVec( -687, -758 ),
new PSubVec( -706, -741 ),
new PSubVec( -724, -724 ),
new PSubVec( -741, -706 ),
new PSubVec( -758, -687 ),
new PSubVec( -775, -668 ),
new PSubVec( -791, -649 ),
new PSubVec( -807, -629 ),
new PSubVec( -822, -609 ),
new PSubVec( -837, -589 ),
new PSubVec( -851, -568 ),
new PSubVec( -865, -547 ),
new PSubVec( -878, -526 ),
new PSubVec( -890, -504 ),
new PSubVec( -903, -482 ),
new PSubVec( -914, -460 ),
new PSubVec( -925, -437 ),
new PSubVec( -936, -414 ),
new PSubVec( -946, -391 ),
new PSubVec( -955, -368 ),
new PSubVec( -964, -344 ),
new PSubVec( -972, -321 ),
new PSubVec( -979, -297 ),
new PSubVec( -986, -273 ),
new PSubVec( -993, -248 ),
new PSubVec( -999, -224 ),
new PSubVec( -1004, -199 ),
new PSubVec( -1008, -175 ),
new PSubVec( -1012, -150 ),
new PSubVec( -1016, -125 ),
new PSubVec( -1019, -100 ),
new PSubVec( -1021, -75 ),
new PSubVec( -1022, -50 ),
new PSubVec( -1023, -25 ),
new PSubVec( -1024, 0 ),
new PSubVec( -1023, 25 ),
new PSubVec( -1022, 50 ),
new PSubVec( -1021, 75 ),
new PSubVec( -1019, 100 ),
new PSubVec( -1016, 125 ),
new PSubVec( -1012, 150 ),
new PSubVec( -1008, 175 ),
new PSubVec( -1004, 199 ),
new PSubVec( -999, 224 ),
new PSubVec( -993, 248 ),
new PSubVec( -986, 273 ),
new PSubVec( -979, 297 ),
new PSubVec( -972, 321 ),
new PSubVec( -964, 344 ),
new PSubVec( -955, 368 ),
new PSubVec( -946, 391 ),
new PSubVec( -936, 414 ),
new PSubVec( -925, 437 ),
new PSubVec( -914, 460 ),
new PSubVec( -903, 482 ),
new PSubVec( -890, 504 ),
new PSubVec( -878, 526 ),
new PSubVec( -865, 547 ),
new PSubVec( -851, 568 ),
new PSubVec( -837, 589 ),
new PSubVec( -822, 609 ),
new PSubVec( -807, 629 ),
new PSubVec( -791, 649 ),
new PSubVec( -775, 668 ),
new PSubVec( -758, 687 ),
new PSubVec( -741, 706 ),
new PSubVec( -724, 724 ),
new PSubVec( -706, 741 ),
new PSubVec( -687, 758 ),
new PSubVec( -668, 775 ),
new PSubVec( -649, 791 ),
new PSubVec( -629, 807 ),
new PSubVec( -609, 822 ),
new PSubVec( -589, 837 ),
new PSubVec( -568, 851 ),
new PSubVec( -547, 865 ),
new PSubVec( -526, 878 ),
new PSubVec( -504, 890 ),
new PSubVec( -482, 903 ),
new PSubVec( -460, 914 ),
new PSubVec( -437, 925 ),
new PSubVec( -414, 936 ),
new PSubVec( -391, 946 ),
new PSubVec( -368, 955 ),
new PSubVec( -344, 964 ),
new PSubVec( -321, 972 ),
new PSubVec( -297, 979 ),
new PSubVec( -273, 986 ),
new PSubVec( -248, 993 ),
new PSubVec( -224, 999 ),
new PSubVec( -199, 1004 ),
new PSubVec( -175, 1008 ),
new PSubVec( -150, 1012 ),
new PSubVec( -125, 1016 ),
new PSubVec( -100, 1019 ),
new PSubVec( -75, 1021 ),
new PSubVec( -50, 1022 ),
new PSubVec( -25, 1023 )
};
}
}

View File

@@ -20,16 +20,16 @@ namespace OpenRA.Traits
class Waypoint : IOccupySpace, ISync
{
[Sync] int2 location;
[Sync] CPos location;
public Waypoint(ActorInitializer init)
{
this.location = init.Get<LocationInit,int2>();
this.location = init.Get<LocationInit, CPos>();
}
public int2 TopLeft { get { return location; } }
public CPos TopLeft { get { return location; } }
public IEnumerable<Pair<int2, SubCell>> OccupiedCells() { yield break; }
public int2 PxPosition { get { return Util.CenterOfCell( location ); } }
public IEnumerable<Pair<CPos, SubCell>> OccupiedCells() { yield break; }
public PPos PxPosition { get { return Util.CenterOfCell(location); } }
}
}

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Traits
{
public readonly string BasePalette = null;
public readonly string BaseName = "player";
public readonly PaletteFormat PaletteFormat = PaletteFormat.ra;
public readonly int[] RemapIndex = {};
public object Create( ActorInitializer init ) { return new PlayerColorPalette( init.self.Owner, this ); }
}
@@ -37,7 +37,7 @@ namespace OpenRA.Traits
{
var paletteName = "{0}{1}".F( info.BaseName, owner.InternalName );
var newpal = new Palette(wr.GetPalette(info.BasePalette),
new PlayerColorRemap(info.PaletteFormat, owner.ColorRamp));
new PlayerColorRemap(info.RemapIndex, owner.ColorRamp));
wr.AddPalette(paletteName, newpal);
}
}

View File

@@ -12,12 +12,13 @@ using System;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using System.Collections.Generic;
namespace OpenRA.Traits
{
public class ResourceLayerInfo : TraitInfo<ResourceLayer> { }
public class ResourceLayer: IRenderOverlay, IWorldLoaded
public class ResourceLayer : IRenderOverlay, IWorldLoaded
{
World world;
@@ -26,12 +27,12 @@ namespace OpenRA.Traits
bool hasSetupPalettes;
public void Render( WorldRenderer wr )
public void Render(WorldRenderer wr)
{
if (!hasSetupPalettes)
{
hasSetupPalettes = true;
foreach( var rt in world.WorldActor.TraitsImplementing<ResourceType>() )
foreach (var rt in world.WorldActor.TraitsImplementing<ResourceType>())
rt.info.PaletteIndex = wr.GetPaletteIndex(rt.info.Palette);
}
@@ -39,13 +40,13 @@ namespace OpenRA.Traits
for (int x = clip.Left; x < clip.Right; x++)
for (int y = clip.Top; y < clip.Bottom; y++)
{
if (!world.LocalShroud.IsExplored(new int2(x, y)))
if (!world.LocalShroud.IsExplored(new CPos(x, y)))
continue;
var c = content[x, y];
if (c.image != null)
c.image[c.density].DrawAt(
Game.CellSize * new int2(x, y),
new CPos(x, y).ToPPos().ToFloat2(),
c.type.info.PaletteIndex);
}
}
@@ -70,7 +71,7 @@ namespace OpenRA.Traits
if (type == null)
continue;
if (!AllowResourceAt(type, new int2(x,y)))
if (!AllowResourceAt(type, new CPos(x,y)))
continue;
content[x, y].type = type;
@@ -86,7 +87,7 @@ namespace OpenRA.Traits
}
}
public bool AllowResourceAt(ResourceType rt, int2 a)
public bool AllowResourceAt(ResourceType rt, CPos a)
{
if (!world.Map.IsInMap(a.X, a.Y)) return false;
if (!rt.info.AllowedTerrainTypes.Contains(world.GetTerrainInfo(a).Type)) return false;
@@ -104,7 +105,7 @@ namespace OpenRA.Traits
int sum = 0;
for (var u = -1; u < 2; u++)
for (var v = -1; v < 2; v++)
if (content[i+u, j+v].type == t)
if (content[i + u, j + v].type == t)
++sum;
return sum;
}
@@ -131,14 +132,14 @@ namespace OpenRA.Traits
content[i, j].image.Length - 1,
content[i, j].density + n);
world.Map.CustomTerrain[i,j] = t.info.TerrainType;
world.Map.CustomTerrain[i, j] = t.info.TerrainType;
}
public bool IsFull(int i, int j) { return content[i, j].density == content[i, j].image.Length - 1; }
public ResourceType Harvest(int2 p)
public ResourceType Harvest(CPos p)
{
var type = content[p.X,p.Y].type;
var type = content[p.X, p.Y].type;
if (type == null) return null;
if (--content[p.X, p.Y].density < 0)
@@ -150,7 +151,7 @@ namespace OpenRA.Traits
return type;
}
public void Destroy(int2 p)
public void Destroy(CPos p)
{
// Don't break other users of CustomTerrain if there are no resources
if (content[p.X, p.Y].type == null)
@@ -162,7 +163,13 @@ namespace OpenRA.Traits
world.Map.CustomTerrain[p.X, p.Y] = null;
}
public ResourceType GetResource(int2 p) { return content[p.X, p.Y].type; }
public ResourceType GetResource(CPos p) { return content[p.X, p.Y].type; }
public int GetResourceDensity(CPos p) { return content[p.X, p.Y].density; }
public int GetMaxResourceDensity(CPos p)
{
if (content[p.X, p.Y].image == null) return 0;
return content[p.X, p.Y].image.Length - 1;
}
public struct CellContents
{

View File

@@ -54,22 +54,22 @@ namespace OpenRA.Traits
// cache of positions that were added, so no matter what crazy trait code does, it
// can't make us invalid.
class ActorVisibility { public int range; public int2[] vis; }
class ActorVisibility { public int range; public CPos[] vis; }
Dictionary<Actor, ActorVisibility> vis = new Dictionary<Actor, ActorVisibility>();
static IEnumerable<int2> FindVisibleTiles(World world, int2 a, int r)
static IEnumerable<CPos> FindVisibleTiles(World world, CPos a, int r)
{
var min = a - new int2(r, r);
var max = a + new int2(r, r);
if (min.X < world.Map.Bounds.Left - 1) min.X = world.Map.Bounds.Left - 1;
if (min.Y < world.Map.Bounds.Top - 1) min.Y = world.Map.Bounds.Top - 1;
if (max.X > world.Map.Bounds.Right) max.X = world.Map.Bounds.Right;
if (max.Y > world.Map.Bounds.Bottom) max.Y = world.Map.Bounds.Bottom;
var min = a - new CVec(r, r);
var max = a + new CVec(r, r);
if (min.X < world.Map.Bounds.Left - 1) min = new CPos(world.Map.Bounds.Left - 1, min.Y);
if (min.Y < world.Map.Bounds.Top - 1) min = new CPos(min.X, world.Map.Bounds.Top - 1);
if (max.X > world.Map.Bounds.Right) max = new CPos(world.Map.Bounds.Right, max.Y);
if (max.Y > world.Map.Bounds.Bottom) max = new CPos(max.X, world.Map.Bounds.Bottom);
for (var j = min.Y; j <= max.Y; j++)
for (var i = min.X; i <= max.X; i++)
if (r * r >= (new int2(i, j) - a).LengthSquared)
yield return new int2(i, j);
if (r * r >= (new CPos(i, j) - a).LengthSquared)
yield return new CPos(i, j);
}
void AddActor(Actor a)
@@ -77,7 +77,7 @@ namespace OpenRA.Traits
if (!a.HasTrait<RevealsShroud>())
return;
if (a.Owner == null || a.Owner.World.LocalPlayer == null
if (a.Owner.World.LocalPlayer == null
|| a.Owner.Stances[a.Owner.World.LocalPlayer] != Stance.Ally) return;
if (vis.ContainsKey(a))
@@ -112,6 +112,24 @@ namespace OpenRA.Traits
Dirty();
}
public void HideActor(Actor a, int range)
{
if (a.Owner.World.LocalPlayer == null
|| a.Owner.Stances[a.Owner.World.LocalPlayer] == Stance.Ally) return;
var v = new ActorVisibility
{
vis = GetVisOrigins(a).ToArray()
};
foreach (var p in v.vis)
foreach (var q in FindVisibleTiles(a.World, p, range))
exploredCells[q.X, q.Y] = visibleCells[q.X, q.Y] > 0;
if (!Disabled)
Dirty();
}
public void UpdatePlayerStance(World w, Player player, Stance oldStance, Stance newStance)
{
if (oldStance == newStance)
@@ -130,7 +148,7 @@ namespace OpenRA.Traits
AddActor(a);
}
public static IEnumerable<int2> GetVisOrigins(Actor a)
public static IEnumerable<CPos> GetVisOrigins(Actor a)
{
var ios = a.OccupiesSpace;
if (ios != null)
@@ -139,7 +157,7 @@ namespace OpenRA.Traits
if (cells.Any()) return cells.Select(c => c.First);
}
return new[] { a.CenterLocation / Game.CellSize };
return new[] { a.CenterLocation.ToCPos() };
}
void RemoveActor(Actor a)
@@ -159,13 +177,13 @@ namespace OpenRA.Traits
public void UpdateActor(Actor a)
{
if (a.Owner == null || a.Owner.World.LocalPlayer == null
if (a.Owner.World.LocalPlayer == null
|| a.Owner.Stances[a.Owner.World.LocalPlayer] != Stance.Ally) return;
RemoveActor(a); AddActor(a);
}
public void Explore(World world, int2 center, int range)
public void Explore(World world, CPos center, int range)
{
foreach (var q in FindVisibleTiles(world, center, range))
exploredCells[q.X, q.Y] = true;
@@ -198,7 +216,7 @@ namespace OpenRA.Traits
Dirty();
}
public bool IsExplored(int2 xy) { return IsExplored(xy.X, xy.Y); }
public bool IsExplored(CPos xy) { return IsExplored(xy.X, xy.Y); }
public bool IsExplored(int x, int y)
{
if (!map.IsInMap(x, y))
@@ -210,7 +228,7 @@ namespace OpenRA.Traits
return exploredCells[x,y];
}
public bool IsVisible(int2 xy) { return IsVisible(xy.X, xy.Y); }
public bool IsVisible(CPos xy) { return IsVisible(xy.X, xy.Y); }
public bool IsVisible(int x, int y)
{
if (Disabled)

View File

@@ -75,7 +75,7 @@ namespace OpenRA.Traits
yield return a;
}
public IEnumerable<Actor> ActorsInBox(int2 a, int2 b)
public IEnumerable<Actor> ActorsInBox(PPos a, PPos b)
{
var r = Rectangle.FromLTRB(a.X, a.Y, b.X, b.Y);

View File

@@ -22,10 +22,9 @@ namespace OpenRA.Widgets
public bool Depressed = false;
public int VisualHeight = ChromeMetrics.Get<int>("ButtonDepth");
public string Font = ChromeMetrics.Get<string>("ButtonFont");
public string ClickSound = null;
public string ClickDisabledSound = null;
public bool Disabled = false;
public Func<string> GetText;
public Func<bool> IsDisabled = () => false;
public Func<bool> IsDisabled;
public Action<MouseInput> OnMouseDown = _ => {};
public Action<MouseInput> OnMouseUp = _ => {};
@@ -39,6 +38,7 @@ namespace OpenRA.Widgets
GetText = () => { return Text; };
OnMouseUp = _ => OnClick();
OnKeyPress = _ => OnClick();
IsDisabled = () => Disabled;
}
protected ButtonWidget(ButtonWidget widget)
@@ -50,6 +50,8 @@ namespace OpenRA.Widgets
VisualHeight = widget.VisualHeight;
GetText = widget.GetText;
OnMouseDown = widget.OnMouseDown;
Disabled = widget.Disabled;
IsDisabled = widget.IsDisabled;
OnMouseUp = mi => OnClick();
OnKeyPress = _ => OnClick();
@@ -69,10 +71,10 @@ namespace OpenRA.Widgets
if (!IsDisabled())
{
OnKeyPress(e);
Sound.Play(ClickSound);
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
}
else
Sound.Play(ClickDisabledSound);
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
return true;
}
@@ -101,12 +103,12 @@ namespace OpenRA.Widgets
{
OnMouseDown(mi);
Depressed = true;
Sound.Play(ClickSound);
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
}
else
{
LoseFocus(mi);
Sound.Play(ClickDisabledSound);
Sound.PlayNotification(null, "Sounds", "ClickDisabledSound", null);
}
}
else if (mi.Event == MouseInputEvent.Move && Focused)
@@ -128,7 +130,7 @@ namespace OpenRA.Widgets
var s = font.Measure(text);
var stateOffset = (Depressed) ? new int2(VisualHeight, VisualHeight) : new int2(0, 0);
DrawBackground(rb, disabled, Depressed, Widget.MouseOverWidget == this);
DrawBackground(rb, disabled, Depressed, Ui.MouseOverWidget == this);
font.DrawText(text, new int2(rb.X + (UsableWidth - s.X)/ 2, rb.Y + (Bounds.Height - s.Y) / 2) + stateOffset,
disabled ? Color.Gray : Color.White);
}

Some files were not shown because too many files have changed in this diff Show More