Compare commits

...

549 Commits

Author SHA1 Message Date
Scott_NZ
2f3def3f86 Updated CHANGELOG 2013-03-04 01:08:55 +13:00
Chris Forbes
5426e2c831 Merge pull request #2718 from Mailaender/admin-indicator
remove admin indicator icon to avoid confusion/overlapping
2013-03-03 01:35:15 -08:00
Chris Forbes
38b2b6cb4e Merge pull request #2557 from ihptru/fix2480
fix #2480; Direct Connect to different mod causes crash (saying 'missing...
2013-03-02 13:45:28 -08:00
Chris Forbes
94415d9cfb Merge pull request #2717 from Mailaender/gems-terrain
fixes #2716
2013-03-02 13:37:06 -08:00
Chris Forbes
2fb822e1c1 Merge pull request #2719 from Mailaender/hotkeys
Additional Hotkeys
2013-03-02 13:35:38 -08:00
Matthias Mailänder
0978d21439 fix problems in MultiTapDetection 2013-03-02 16:52:59 +01:00
Matthias Mailänder
775b0409c4 don't hard-code the pause-key 2013-03-02 15:56:13 +01:00
Matthias Mailänder
1083f8cf55 double-tap 0-9: select and center the control group 2013-03-02 15:55:42 +01:00
Matthias Mailänder
4cf8f9a434 remove admin indicator icon to avoid confusion/overlapping
print admin names in bold text instead
2013-03-02 15:01:11 +01:00
Matthias Mailänder
6152fa2890 fixes #2716
Gems were non-pathable and therefore also uncollectible
2013-03-02 14:58:17 +01:00
Matthias Mailänder
c0a702a386 new hotkey to center your view on the current selection 2013-03-02 11:53:45 +01:00
Chris Forbes
336076c248 Merge pull request #2665 from Mailaender/pvecfloat-combat
Fix floating point inconsistencies to reduce desyncs
2013-03-02 00:01:53 -08:00
Chris Forbes
c21b60f555 Merge pull request #2675 from Mailaender/simple-hotkey-config
user-configurable hotkey via in-game settings
2013-03-02 00:01:01 -08:00
Chris Forbes
efd0d81dca Merge pull request #2714 from ScottNZ/lobby
Revert client colours to their preferred colours after the map is changed
2013-03-02 00:00:04 -08:00
Scott_NZ
63467cd000 Revert client colours to their preferred colours after the map is changed to a map which doesn't lock colours. 2013-03-02 16:18:09 +13:00
Chris Forbes
46f4685eec Merge pull request #2712 from Mailaender/gems-minimap-color
Render crystals in a different color on the mini-map
2013-03-01 15:06:07 -08:00
Chris Forbes
af3a5cf939 Merge pull request #2713 from pchote/parachute-fix
Fix crash when an opponent uses Paratroopers.
2013-03-01 14:41:23 -08:00
Paul Chote
fb0ce8c06a Fix crash when an opponent uses Paratroopers. 2013-03-02 10:09:38 +13:00
Matthias Mailänder
8358597fd2 render crystals in a different color on the mini-map 2013-03-01 21:06:09 +01:00
Matthias Mailänder
b31f830cb1 key config settings code cleanup
- move label and textfield widget lookup into SetupKeyBinding
- fix wonkey indentions
- remove explicit private in WorldCommandWidget
2013-03-01 19:13:21 +01:00
Chris Forbes
561d47a6a1 Merge pull request #2705 from Mailaender/low-power-gap-crashfix
Fix NullReferenceException in UnHideActor
2013-03-01 01:57:23 -08:00
Chris Forbes
b8b0111aa2 Merge pull request #2706 from Mailaender/cnc-proc-desync-fix
Remove custom build time for Tiberium refinery to fix desyncs
2013-03-01 01:54:51 -08:00
Chris Forbes
f204f25474 Merge pull request #2707 from Mailaender/cnc-lobby-crashfix
Fix #2663 Crash when displaying the spawn tooltip in cnc mod
2013-03-01 01:54:18 -08:00
Matthias Mailänder
47075e1cd0 generate random numbers as floats
as they get converted from double before use anyway
2013-03-01 10:53:41 +01:00
Matthias Mailänder
793dfa5748 don't convert cell size to float for bullet inaccuracy
change it back to int / int / float
from int / float / float
was int / int / float before
2013-03-01 10:49:51 +01:00
Matthias Mailänder
0b493bcb09 remove redundant int to int conversion in rendered circles 2013-03-01 10:48:28 +01:00
Matthias Mailänder
dd476bbf5c add the total number of values extracted from RNG to sync report 2013-03-01 10:48:28 +01:00
Matthias Mailänder
fc5350c9f8 fix #2663 crash when displaying the spawn tooltip in cnc
don't hard-code ra border chrome in shared lobbyutils
2013-03-01 10:30:41 +01:00
Matthias Mailänder
b2c867bf2b remove custom build time for tiberium refinery
- this can be enabled again in cnc-classic
- needs a fix as it causes desyncs
2013-03-01 10:10:26 +01:00
Matthias Mailänder
3d8d116106 fix NullReferenceException in UnHideActor 2013-03-01 10:07:33 +01:00
Matthias Mailänder
4b2f08f21f convert start to int2 as CellContaining() spit that out before 2013-02-28 21:59:18 +01:00
Matthias Mailänder
233088077b don't convert to float2 in ReturnToBase as it was int2 before 2013-02-28 21:59:18 +01:00
Matthias Mailänder
a59621910e avoid floating point operation with heli fly int coordinates 2013-02-28 21:59:18 +01:00
Matthias Mailänder
05b6b59dad use Combat.IsInRange instead of float2.WithinEpsilon for heli 2013-02-28 21:59:18 +01:00
Matthias Mailänder
2bc7570674 remove conditional compile left-over junk 2013-02-28 21:59:18 +01:00
Matthias Mailänder
0085ac130b use PVecFloat in Combat sub-routines 2013-02-28 21:59:18 +01:00
Chris Forbes
7e1ee0e2e5 fix #2661: desyncs with shroud/exploration cheats 2013-03-01 09:29:03 +13:00
Chris Forbes
6bd3de8ec8 Fixed #2696: Sequences: Allow stride to be specified.
This allows you to use just some of the frames of an animation
which has multiple facings.

For example, if you have an animation which has 8 facings, and 6 frames
of animation per facing, but you only want to show 3 of them, you can now do:

    Facings: 8
    Length: 3       # the number of frames in each facing to actually use
    Stride: 6       # the number of frames per facing present in the SHP

If Stride is not specified, it defaults to Length, which is the old behavior.
It is an error to specify a stride less than the length -- this would produce
overlapping facings, or weirder.
2013-02-28 09:08:41 +13:00
Chris Forbes
fab7f2c4b6 Merge pull request #2684 from xaionaro/bleed
fixed a issue with pinging Master-server
2013-02-27 11:50:18 -08:00
Chris Forbes
ea799e5735 Merge pull request #2701 from psydev/patch-49
[cnc] structure sequences tick-rates corrected
2013-02-27 11:49:37 -08:00
Chris Forbes
3ab4112631 Merge remote-tracking branch 'pchote/cleanup' 2013-02-28 08:45:47 +13:00
Scott_NZ
817e6f1ec1 Have Tanya not shoot her pistols at buildings, and have her shoot pistols at barrels instead of using C4 on them 2013-02-27 17:57:53 +13:00
Scott_NZ
81c8f0360f Let's not crash if WeaponInfo.Report[] is empty 2013-02-26 18:08:55 +13:00
psydev
bec29d81c5 cnc-structure sequences tickrate fixed
Strucutre animations were too fast in many cases. These values seem to match up correctly to C&C 95.

Obelisk - Have not yet fixed (will do so when I fix how it fires)
SAM site - Someone may later decide to speed up how fast it pops up, for gameplay purposes
2013-02-25 16:05:11 -08:00
Paul Chote
3a11aeb434 Cache PaletteReference in RenderSimple. 2013-02-26 09:35:41 +13:00
Paul Chote
dddec1ec61 Add INotifyOwnerChanged interface 2013-02-26 09:35:41 +13:00
Paul Chote
82426e0e45 Move Palette from ModData to WorldRenderer. 2013-02-26 09:35:41 +13:00
Paul Chote
3033eb8be0 Die with a helpful error if a palette doesn't exist. 2013-02-26 09:35:41 +13:00
Paul Chote
e9665cf9f3 Remove WorldRenderer.GetPaletteIndex. 2013-02-26 09:35:41 +13:00
Paul Chote
9bc743068a Remove WorldRenderer.GetPalette. 2013-02-26 09:35:41 +13:00
Paul Chote
72a9954491 Simplify PaletteReference interface. 2013-02-26 09:35:40 +13:00
Paul Chote
f2fe30a7bb Remove PaletteReference.FromName from TeslaZap. 2013-02-26 09:35:39 +13:00
Paul Chote
ce39c79477 Apply consistent formatting to PBOG (no code changes). 2013-02-26 09:32:16 +13:00
Paul Chote
6fc4807a10 Remove PaletteReference.FromName from PBOG. 2013-02-26 09:31:19 +13:00
Paul Chote
f890ea010e Pass WorldRenderer to RenderAsTerrain for palette lookup. 2013-02-26 09:24:43 +13:00
Paul Chote
5b360a7fe2 Use PaletteReferences in ShroudRenderer. 2013-02-26 09:24:43 +13:00
Paul Chote
55efd53ef7 Make RenderSimple.Palette protected. 2013-02-26 09:24:43 +13:00
Paul Chote
fa5cf96f40 Ditto for Corpse. 2013-02-26 09:24:43 +13:00
Paul Chote
e33c783fc1 Ditto for GpsDot. 2013-02-26 09:24:42 +13:00
Scott_NZ
1438030e82 Add mood haze effect for Allies 04 2013-02-26 00:10:03 +13:00
Scott_NZ
09e4d64f99 Fix Allies 02 warnings 2013-02-25 23:40:31 +13:00
Scott_NZ
b5bd6191c2 Don't crash (due to replay file being in use) if we have two instances of the game playing 2013-02-25 21:24:17 +13:00
Scott_NZ
e57de0ebce Allies 02 code maintenance. Add FreeActorInit so free harvesters with procs can be disabled etc 2013-02-25 21:24:17 +13:00
Scott_NZ
3bc9e7d2e4 Fix some playerstatistics related crashes for other mods 2013-02-25 21:24:17 +13:00
Scott_NZ
6b636b166c Check Crates setting in CrateSpawner too 2013-02-25 21:24:17 +13:00
Scott_NZ
026a86ba75 Add 'Crates' lobby checkbox and setting for enabling/disabling crate drops 2013-02-25 21:24:17 +13:00
Paul Chote
5a4bd14835 Ditto for RallyPoint. 2013-02-25 21:12:01 +13:00
Paul Chote
43159a0e05 Remove RepairIndicator dependence on target RenderSimple.
This also fixes the case where the building palette doesn't
match the indicator, and saves 2 trait lookups per tick.
2013-02-25 21:12:01 +13:00
Paul Chote
3380817865 Pass WorldRenderer to Render(). 2013-02-25 21:11:33 +13:00
Paul Chote
d6fcaafd78 Let parachute cargo render themselves.
This allows for tanks and other multi-sprite
actors to render correctly while dropping.
2013-02-25 21:10:16 +13:00
Paul Chote
0703f3f164 Extract auto-selection-size into its own interface. 2013-02-25 21:10:08 +13:00
Chris Forbes
a083554218 Merge pull request #2669 from Generalcamo/patch-7
Add support for Nyergud's Music Upgrade pack
2013-02-24 18:20:31 -08:00
Chris Forbes
c34c62ad42 Merge pull request #2672 from psydev/patch-48
[cnc] inftry detect cloaked in next tile(C&C orig)
2013-02-24 18:16:24 -08:00
Chris Forbes
fc3c091a48 Merge pull request #2670 from psydev/patch-47
[cnc] added names for explosions
2013-02-24 18:14:00 -08:00
Paul Chote
000a5eaa56 Pass WorldRenderer to IRenderModifiers and replace more palette lookups. 2013-02-24 15:45:03 +13:00
Paul Chote
48d713aafd Pass a PaletteReference to RenderPreview. 2013-02-24 15:43:20 +13:00
Paul Chote
885eec7444 Move effects to WorldRenderer palette lookup. 2013-02-24 15:43:20 +13:00
Paul Chote
95871e6cc1 Add a cache of PaletteReferences to WorldRenderer.
I don't expect any perf improvements by using this
cache, as you're simply moving the row lookup from
render-time to fetch-time. However, this is a
cleaner abstraction, and allows us to fail early
if the palette doesn't exist.
2013-02-24 15:43:19 +13:00
Paul Chote
f0ba0ce2e8 Wrap palette references with a PaletteRef object. 2013-02-24 15:43:15 +13:00
Paul Chote
a166815348 Remove duplication between world/chrome shaders. 2013-02-23 09:53:46 +13:00
Paul Chote
35a149ea87 Apply consistent formatting to Renderer (no code changes). 2013-02-23 09:46:16 +13:00
Paul Chote
0287993c31 Add bitmap export to palette (for debugging). 2013-02-22 17:11:18 +13:00
Paul Chote
2d10f6b739 Remove unnecessary indirection from palette creation. 2013-02-22 17:06:29 +13:00
Paul Chote
db7887687b Remove hardcoded list of palette mod exclusions. 2013-02-22 15:04:41 +13:00
Paul Chote
f593807617 Rework color picker palette modification.
The old method had the lobby code dig around inside
the palette modification machinery, which was a giant
hack preventing necessary streamlining.
2013-02-22 15:04:41 +13:00
Chris Forbes
6da02b7b92 Merge pull request #2662 from psydev/patch-40
[cnc] Obelisk AutoTargeted, airstrike cooldown, +misc.
2013-02-20 12:24:57 -08:00
xaionaro
86c99c47c9 https://github.com/OpenRA/OpenRA/issues/2564
fixed a issue with pinging Master-server

Sometimes initial TickCount is less than zero, so (Environment.TickCount - lastPing) can be less than "MasterPingInterval * 1000". That's why PingMasterServer() is not calling for a long time until somebody connected.
2013-02-13 20:51:37 +04:00
Scott_NZ
3b3e39b375 Don't allow MCV/FACT to be sold
This is almost always done to exploit the `free mcv` logic in the crates.
2013-02-13 15:25:47 +13:00
Scott_NZ
4b3feed324 Make a lack of random map yaml be non-fatal 2013-02-12 22:47:34 +13:00
Scott_NZ
57dd8bb91e Add Random Map lobby button 2013-02-12 22:21:34 +13:00
Scott_NZ
34b1f90200 Anti-basewalk balance adjustments. Includes moving fact over to wood and giving it 500 more health, increasing superweapon healths and moving mslo to wood, moving pbox to heavy 2013-02-11 18:00:30 +13:00
Scott_NZ
128e2c9e1f Add objectives to MonsterTankMadness 2013-02-11 00:54:53 +13:00
psydev
d0669823a2 changing name of big_poof, for consistency
Changed "big_poof" to simply "poof". 

The word "big" will only appear if there are small, medium and large versions of the explosion.
Otherwise, it will just be "explosion" and "small_explosion".
2013-02-09 15:26:41 -08:00
Matthias Mailänder
1f99b1ec8e make hotkey user-configurable via in-game settings 2013-02-09 14:08:36 +01:00
Scott_NZ
2c5eeb551e Adjust MonsterTankMadnessScript super tank movement times 2013-02-09 12:19:41 +13:00
Scott_NZ
54906702bd Fix alliedBaseProc unused variable warning 2013-02-09 12:19:41 +13:00
Scott_NZ
ec56311a3d Fix victory on start of MMM 2013-02-09 12:19:41 +13:00
Scott_NZ
cdd09ea24f Finish early version of Monster Tank Madness 2013-02-09 12:19:40 +13:00
Scott_NZ
1ecdbc1d90 Fix spyvoice/reveal range for truk.hijackable in Allies 04 2013-02-09 12:19:40 +13:00
Scott_NZ
b1a5195c51 Let's not fail right at the beginning, count units too ;) 2013-02-09 12:19:40 +13:00
Scott_NZ
03f03ff501 More MonsterTankMadness work. Add routines for super tanks, civilian evacuees, proving grounds camera, base transfer, Demitri extraction 2013-02-09 12:19:40 +13:00
Scott_NZ
3c5967a623 Add ore capping to MissionUtils. Add world.CreateActor extension in MissionUtils. 2013-02-09 12:19:40 +13:00
Scott_NZ
9013e8376c Start work on Monster Tank Madness mission 2013-02-09 12:19:40 +13:00
Scott_NZ
9b5b054297 Add delphi. Have einstein/delphi panic 2013-02-09 12:19:39 +13:00
Scott_NZ
4e161f0c91 Change V19 tooltip to Oil Pump 2013-02-09 12:19:39 +13:00
Scott_NZ
6bbd54ab93 Put e1 inside the soviet 01 classic pillboxes. Add check for mission complete 2013-02-09 12:19:39 +13:00
Scott_NZ
87190762d1 Add V19 civilian building 2013-02-09 12:19:39 +13:00
Scott_NZ
f4da36065f Add ability to have randomised reports for weapons 2013-02-09 12:19:39 +13:00
Scott_NZ
e71135b511 Better error messages when merging duplicate yaml 2013-02-09 12:17:16 +13:00
psydev
dfc880807e [cnc] Airstrike cooldown 3 mins. (from 4). tweaks.
Air Strike cooldown time reduced from 4 minutes to 3. (Ion Cannon is 3). [games are short in CNC, and waiting 4 minutes for your first airstrike is a long time.]
HQ's hitpoints reduced to 750, so it can be nuked in one shot. (but not Ion Cannon'd) 
Airfield HP reduced to 1500, so Ion + Airstrike can destroy it. (For some reason, it doesn't die as easily as Weapons Factory, despite having the same HP)
2013-02-06 16:06:47 -08:00
psydev
d12853ddf7 [cnc] inftry detect cloaked in next tile(C&C orig)
Infantry can detect cloaked units in the next tile. This behaviour was in the original C&C Gold.
(Even though it says range=2, it is actually just in the next tile)

Fixed GrenadierExplode.
2013-02-06 14:20:09 -08:00
psydev
f1019ab332 [cnc] added names for explosions
Easier-to-understand names for explosions, which can be used in the future. Can phase out old names/numbers slowly.
Also included some explosions from the C&C Content which were not in use and did not have names.
2013-02-06 12:21:04 -08:00
Cody Brittain
96d1f8d83b Update mods/cnc/mod.yaml
Add support for Nyergud's Music Upgrade Pack
2013-02-06 08:35:27 -05:00
psydev
c4fc0e57b3 [cnc] Obelisk now AutoTargeted by units, etc.
Obelisk of light was missing "-AutoTargetIgnore". All the guard towers have it, but for some reason the Obelisk didn't.
2013-02-04 18:39:26 -08:00
Chris Forbes
6403c5e6af Fixed #2651: Units not in world should not be added to the attack force
Otherwise, a pillbox's e1 passenger is counted as part of the attack
force and ends up jamming HackyAI's attack logic until it is destroyed.
2013-02-05 07:09:05 +13:00
Scott_NZ
b3fbafad59 Use Action<bool> for objective delegate type 2013-02-03 14:27:43 +13:00
Scott_NZ
7594c4eab2 Clamp reveal range to 0-50 in PlayerStatistics to stop crashes for actors with reveal ranges > 50 2013-02-03 14:27:43 +13:00
Scott_NZ
4163f1d6b0 Clean up Allies 04 yaml. Adjust hero spy reveal range from 5 to 6. Add TRUK as buildable unit 2013-02-03 14:27:43 +13:00
Scott_NZ
ea716200a7 Allies 04: Fix multiple waves of spies being able to infiltrate the lab 2013-02-03 14:27:43 +13:00
Kenny
2bd9b7a640 Enabling mobile gap generators. 2013-01-31 16:57:04 +13:00
Kenny
4f670d516d Shroud creators now only temporarily block explored shroud.
On powerdown or removal from the game, any previously explored terrain will become visible once again.
2013-01-31 16:57:04 +13:00
Matthias Mailänder
f5835244c7 use markdown for readme and contributing guidelines
- https://github.com/github/markup
- https://github.com/blog/1184-contributing-guidelines
2013-01-31 16:32:46 +13:00
psydev
b00b1c36bc Helipad reduced to $1000. Palette order fixed.
Helipad price reduced to $1000. Should make helicopter transports more accessible. Should also make having a few "support helis" flying around a more viable strategy, for non-standard builds.
Fixed palette order to be better grouped and in more progressive order. 
Re-arranged document so that it's sorted better.
2013-01-31 16:30:48 +13:00
psydev
b2ddc6cfd8 [CNC] Chinook priced reduced to $750
Halved Chinook price, $1500 to $750.
Infantry should be a more feasible strategy, and transporting them quickly will make them more usable.
This should be good for Nod especially since they don't have APCs.
2013-01-31 16:29:52 +13:00
Matthias Mailänder
0d6dbdc58b increment debian copyright year 2013-01-31 16:28:14 +13:00
Matthias Mailänder
78baf76ae1 adhere to SPDX for RPM 2013-01-31 16:28:14 +13:00
Matthias Mailänder
43c43e25c4 adhere to opendesktop menu-spec
Version= is the version of the .desktop file specification!
2013-01-31 16:28:14 +13:00
Cody Brittain
32daf025ab cnc: Update cloaking, building destroyed sounds
- Use trans1.aud as the cloak sound, on both STNK and cloak
  given from crates

- Use crumble.aud rather than xplobig4.aud for building destruction
2013-01-31 16:23:03 +13:00
ScottNZ
750bdb7bba Update CHANGELOG
Some typos/wording issues fixed
2013-01-28 19:47:31 +13:00
Scott_NZ
8a796416a4 Remove AutoTargetIgnore for stek after Einstein is freed 2013-01-28 00:33:09 +13:00
Scott_NZ
691e6cf9e8 Have the Soviets build infantry after Einstein is found. Remove jeep cargo limit 2013-01-28 00:33:08 +13:00
Scott_NZ
de208e7a2f Fix nonworking attack code in Allies 01 2013-01-28 00:33:08 +13:00
Scott_NZ
63a72c5d28 Remove unused variable 2013-01-28 00:33:08 +13:00
Scott_NZ
b6b4b89008 Refactor cash code in Allies campaign. Adjust starting cash to 10000 in SP Allies 03 2013-01-28 00:33:08 +13:00
Scott_NZ
0b65735d86 Make the LSTs unbuildable 2013-01-28 00:33:07 +13:00
Scott_NZ
44215ae6f1 Add new trait interface INotifyTransformed and use it in Allies 04 to make the transport remove its cargo capacity after it unloads its passengers 2013-01-28 00:33:07 +13:00
Scott_NZ
fba5b80980 Allies 04: Add more town stuff. Remove leftover hind stuff. Only have patrol 3 on hard difficulty 2013-01-28 00:33:07 +13:00
Scott_NZ
3f6af59612 Add AutoTargetIgnore for the new bridges 2013-01-28 00:33:07 +13:00
Scott_NZ
693a622322 Fix Soviets not attacking town properly. Remove hind patrol. 2013-01-28 00:33:07 +13:00
Scott_NZ
60e9d3f660 Add c3 civilian, made by JOo 2013-01-28 00:33:06 +13:00
Scott_NZ
1d40858f70 Have the Soviets attack the town in Allies 04 2013-01-28 00:33:06 +13:00
Scott_NZ
5188529ff6 Allies 04: Adjust one of the patrol routes 2013-01-28 00:33:06 +13:00
Scott_NZ
2079db79f7 Allies 04: Hack in a fix to stop player hero spies infiltrating buildings they shouldn't 2013-01-28 00:33:05 +13:00
Scott_NZ
d73eec068f Fix some bad Allies 01 bounty yaml 2013-01-28 00:33:05 +13:00
Scott_NZ
8a32e5761c Change map player clientindex to 0 2013-01-28 00:33:05 +13:00
Scott_NZ
12e1a531fe Tidy campaign stuff 2013-01-28 00:33:05 +13:00
Scott_NZ
32830da3c2 Remove bounties from things in Allies 01 2013-01-28 00:33:05 +13:00
Scott_NZ
9f47e75492 Allies 01: only set eligible units to defensive stance 2013-01-28 00:33:04 +13:00
Scott_NZ
e975681c16 Add more time to complete Allies 04 - the bridge destruction makes the mission more difficult 2013-01-28 00:33:04 +13:00
Scott_NZ
a968d296bb Remove v01.sniper from Allies 04 2013-01-28 00:33:04 +13:00
Scott_NZ
031240ffc1 Campaign: reduce failed/accomplished code duplication 2013-01-28 00:33:04 +13:00
Scott_NZ
dfc4b07b1a Campaign: Don't rely on world.issueorder anymore 2013-01-28 00:33:04 +13:00
Scott_NZ
63241dbf69 Allies 04. Make the v01.sniper trivial so players can ignore it. 2013-01-28 00:33:03 +13:00
Scott_NZ
5b7523b9e0 Allies 04: Make Soviets sell buildings when they are low on health. Have the bridge be destroyed by a Soviet tank 2013-01-28 00:33:03 +13:00
Matthias Mailänder
4b228a71ef Update CHANGELOG
- Dune 2000
- Editor/Remapping
- GUI improvements by Carko
- More verbose about Volkov changes
- Preparations for i18n
2013-01-27 12:17:20 +01:00
Cody Brittain
1635ace182 Update CHANGELOG
Just a couple things added
2013-01-18 11:09:26 +13:00
Matthias Mailänder
b4e3ce5de6 fix make for mono 3
error CS1902: Invalid debug option `+'.
Valid options are `full' or `pdbonly'
2013-01-18 11:08:10 +13:00
Carko
50ceb7c4dd Fixed the asynchronous map loading behavior when changing filter 2013-01-18 11:00:56 +13:00
Carko
4395a04d57 Asynchronous loading of map previews in the map chooser dialog 2013-01-18 11:00:56 +13:00
Matthias Mailänder
c5313375f0 pull mouse button preference from global property 2013-01-18 10:57:41 +13:00
Matthias Mailänder
2503ddfde4 let Chronotank/Minelayer accept left-click-orders 2013-01-18 10:57:41 +13:00
Matthias Mailänder
b356cca528 improve the classic mouse behaivor
- don't require to deselect units to change selection
- fix issue with broken building placement on right-click orders
- don't select enemy units when left-click attacking
- build palette won't interfere with unit orders anymore
2013-01-18 10:57:41 +13:00
Matthias Mailänder
d52394bb47 add classic left-click orders 2013-01-18 10:57:40 +13:00
Scott_NZ
1da2d89ced Only play movies in Allies 01 and Soviet 01 Classic if there's one client 2013-01-15 17:43:39 +13:00
ScottNZ
a88a7d9834 Update CHANGELOG 2013-01-13 16:06:05 +13:00
Scott_NZ
9507fde91d Fix untargetable barrel in Soviet 01 2013-01-13 00:24:28 +13:00
Scott_NZ
742a27158a Make oil derricks repairable by engineers 2013-01-12 18:55:59 +13:00
Scott_NZ
5ed383e3e2 Change mech hotkey to c 2013-01-12 18:35:01 +13:00
Scott_NZ
1679837e46 Fix mechanic being able to repair infantry. Adjust mechanic repair damage from 20 to 10 2013-01-11 17:17:14 +13:00
Scott_NZ
eb3685fe67 Fix a lack of difficulty dropdown yaml in other mods (d2k/cnc) causing crashes 2013-01-09 21:50:20 +13:00
Carko
50f8465d1e Removed mouse capture while composing text in chat (fixes #2486) 2013-01-09 16:47:39 +13:00
Cody Brittain
5502864a1f Update mods/ra/music.yaml
Mud no longer crashes: Bring it back in.
2013-01-09 07:56:30 +13:00
Carko
d572e59d2e Checking for build prerequisites before showing them in a tooltip 2013-01-09 07:54:01 +13:00
Carko
e313bbfb31 Added a build limit of 1 to Tanya and Volkov
Added the build limit of 1 to MSLO
2013-01-09 07:54:01 +13:00
Carko
a51c5fd9ca Added Buildable->BuildLimit option to limit the number of actors a player can build of the type 2013-01-09 07:54:01 +13:00
Sam Hegarty
0c104cfc3a Add a 'Shutting down' state to the gameserver.
Tell the masterserver about it, so it can quickly remove games
from the list when they are finished, rather than waiting for the
5 minute TTL to expire.
2013-01-08 23:02:28 +13:00
Chris Forbes
3a77082c66 silence warnings in allies03/04 2013-01-08 22:54:38 +13:00
Scott_NZ
975e4db452 Change facing of the 2 guarding heavy tanks in Allies 04 2013-01-08 22:44:10 +13:00
Scott_NZ
d92f184bc9 Add civilian movement and balance changes in Allies 04 2013-01-08 22:44:10 +13:00
Scott_NZ
2eea5cc3b2 Give SAM sites turret facings in Allies 04 2013-01-08 22:44:09 +13:00
Scott_NZ
0e8cb14099 Allies 04: Give money to players after they receive mcvs 2013-01-08 22:44:09 +13:00
Scott_NZ
1ec3b2ffe2 Fix whitespace in objectives 2013-01-08 22:44:09 +13:00
Scott_NZ
c836d69385 Add easy mode to Allies 01 which is like the classic mission 2013-01-08 22:44:09 +13:00
Scott_NZ
11c45e4388 Start unbreaking ScaredyCat 2013-01-08 22:44:08 +13:00
Scott_NZ
3b9fac9c84 Prevent warning in Allies 04 code 2013-01-08 22:44:08 +13:00
Scott_NZ
185558985e Have civilians come out of disturbed buildings 2013-01-08 22:44:08 +13:00
Scott_NZ
e3d25f6fed Give MISS a tooltip 2013-01-08 22:44:07 +13:00
Scott_NZ
200071e713 Add reinforcements paradrops 2013-01-08 22:44:07 +13:00
Scott_NZ
bdb7bb97cd Split long objective strings over several lines 2013-01-08 22:44:07 +13:00
Scott_NZ
82809f27f7 Reduce mission music code duplication 2013-01-08 22:44:06 +13:00
Scott_NZ
c8e84b3a11 Add license notice 2013-01-08 22:44:06 +13:00
Scott_NZ
9581f07242 Add first version of Soviet 01 classic 2013-01-08 22:44:06 +13:00
Scott_NZ
411aedafa0 Setup c3-c10 placeholder civilians. 2013-01-08 22:44:05 +13:00
Scott_NZ
f7f307c3bf LegacyMapImporter: Remove Italy as it's a bogus country. Change Germany to black. Collapse some duplicate cases. 2013-01-08 22:44:05 +13:00
Scott_NZ
c10df031bd Convert classic waypoints to waypoint not mpspawn 2013-01-08 22:44:05 +13:00
Scott_NZ
a56228aba1 Add Italy country 2013-01-08 22:44:05 +13:00
Scott_NZ
1b09544314 Default to allies for neutral in ra, gdi in cnc 2013-01-08 22:44:04 +13:00
Scott_NZ
2dc18594a2 Handle RA with GoodGuy/BadGuy players 2013-01-08 22:44:04 +13:00
Scott_NZ
baa7a58a10 Don't blow up if classic maps have Multi{0} in them either 2013-01-08 22:44:04 +13:00
Scott_NZ
bb5212d2bb Fix classic SP maps failing to import into the editor 2013-01-08 22:44:03 +13:00
Scott_NZ
38db7d1e50 Make the Soviets repair their buildings in Allies 04 2013-01-08 22:44:03 +13:00
Scott_NZ
3371085da0 Move viewport to reinforcements location after infiltration 2013-01-08 22:44:03 +13:00
Scott_NZ
5c688370ed Add difficulty options to Allies 04 2013-01-08 22:44:03 +13:00
Scott_NZ
ab01722d96 Clean up the patrol code 2013-01-08 22:44:02 +13:00
Scott_NZ
ae5cb9864a Adjust timer text 2013-01-08 22:44:02 +13:00
Scott_NZ
43e5838555 Adjusted wording of objectives 2013-01-08 22:44:02 +13:00
Scott_NZ
cf8b02de26 Add 25 min countdown timer for destroying the enemy base. 2013-01-08 22:44:01 +13:00
Scott_NZ
d3ede583c2 Make OILB trivial too 2013-01-08 22:44:01 +13:00
Scott_NZ
cda871d2eb Add missing colon 2013-01-08 22:44:01 +13:00
Scott_NZ
2ea3b77b7a Create new actors so the effects aren't carried over to built units in Allies 04. Make yak buildable by Allies again in Allies 02. Make STEK autotargetignore in Allies 01. Make MISS autotargetignore in Allies 04. 2013-01-08 22:44:00 +13:00
Scott_NZ
3ab04e4c30 Fix crash with patrols. Add more room for the Allied base 2013-01-08 22:44:00 +13:00
Scott_NZ
3b2190d720 Fixed the supply truck not being able to carry 2 passengers 2013-01-08 22:44:00 +13:00
Scott_NZ
b3691dcce9 Add base guard, hind and second objective 2013-01-08 22:44:00 +13:00
Scott_NZ
722bc00c9b Add checkpoint at the large base 2013-01-08 22:43:59 +13:00
Scott_NZ
fe07da8634 Give control of the hijacked vehicle to another passenger if the driver leaves 2013-01-08 22:43:59 +13:00
Scott_NZ
54feab66e0 Add hijackable truck to Allies 04 2013-01-08 22:43:59 +13:00
Scott_NZ
fda897c69e Add more patrols 2013-01-08 22:43:58 +13:00
Scott_NZ
31d3616b8d Actually add the Allies 04 script. Also we have dog patrols now 2013-01-08 22:43:58 +13:00
Scott_NZ
eb6bab36a0 Begin Allies 04 script 2013-01-08 22:43:58 +13:00
Scott_NZ
81f9798307 More mapping of Allies 04 2013-01-08 22:43:58 +13:00
Scott_NZ
d1dafd5782 More Allies 04 mapping 2013-01-08 22:43:57 +13:00
Scott_NZ
799a2ea541 Fixed difficulty code indentation 2013-01-08 22:43:57 +13:00
Scott_NZ
4b2e45bbae Refactor default difficulty setting into its own method 2013-01-08 22:43:57 +13:00
Scott_NZ
32721ac8cb Reposition info widgets/countdown timer widgets in centre top of vp 2013-01-08 22:43:56 +13:00
Scott_NZ
6871d2ed37 Have paradrops and mammoths come sooner if we're on hard difficulty 2013-01-08 22:43:56 +13:00
Scott_NZ
bdfa6f6ecc Slight refactor 2013-01-08 22:43:56 +13:00
Scott_NZ
c59fbd5f9d Adjust Allies 03 difficulties 2013-01-08 22:43:56 +13:00
Scott_NZ
54916cc548 Add Easy difficulty to Allies 03 2013-01-08 22:43:55 +13:00
Scott_NZ
3ff3ed39fb Fix slight logic error with difficulty 2013-01-08 22:43:55 +13:00
Scott_NZ
a8dbedd486 Fix default difficulty not being serialised 2013-01-08 22:43:55 +13:00
Scott_NZ
988a68dae5 Attempt to fix NRE that hamb got 2013-01-08 22:43:55 +13:00
Scott_NZ
9a9c5911a6 Hard difficulty for allies 03 2013-01-08 22:43:54 +13:00
Scott_NZ
bfb07e9948 Add support for mission difficulties 2013-01-08 22:43:54 +13:00
Scott_NZ
dda4e2c33a Add objective for MGG 2013-01-08 22:42:50 +13:00
Scott_NZ
05e143662d Make Allies 02 easier in SP mode 2013-01-08 22:42:50 +13:00
Scott_NZ
9e2f15bde4 Allies 03 code cleanup 2013-01-08 22:42:50 +13:00
Scott_NZ
8f90423793 Update units evacuated immediately in Allies 03 2013-01-08 22:42:50 +13:00
Scott_NZ
eecc002236 More balancing improvements to Allies 03: remove arty, agun, reduce number of yaks and paradrops 2013-01-08 22:42:49 +13:00
Scott_NZ
4167d3291a Offset MGG husk spinner 2013-01-08 22:42:49 +13:00
Scott_NZ
3be6229cf2 Add MGG husk 2013-01-08 22:42:49 +13:00
Scott_NZ
5f693945f0 Take all ore/cash from Allies 01 player 2013-01-08 22:42:49 +13:00
Scott_NZ
82f478716c Add AutoTargetIgnore to barrels 2013-01-08 22:42:48 +13:00
Scott_NZ
6544069aa2 More Allies 03 balancing adjustments 2013-01-08 22:42:48 +13:00
Scott_NZ
8486a4fbae Adjust Allies 03 balancing 2013-01-08 22:42:48 +13:00
Scott_NZ
edd1138556 Use classic RA country colours in missions 2013-01-08 22:42:48 +13:00
Scott_NZ
14ed3ae816 Add paradropping at endgame in Allies 03 2013-01-08 22:42:47 +13:00
Scott_NZ
d5db9e88d4 Put bridge across water 2013-01-08 22:42:47 +13:00
Scott_NZ
f0a4fa7712 Add more airfields to destroy in Allies 03, and have reinforcements in Allies 02 and Allies 03 come in gradually. 2013-01-08 22:42:47 +13:00
Scott_NZ
1f92768193 Remove FirstUnshroudedOrDefault from MissionUtils.cs 2013-01-08 22:42:46 +13:00
Scott_NZ
ccfcf0a1ee Have the minimum difference between attack frames in Allies 03 be lower for 2 players 2013-01-08 22:42:46 +13:00
Scott_NZ
51626bf0db Outlined Allies 04 map 2013-01-08 22:42:46 +13:00
Scott_NZ
be6da2452a Change Allies map types to Campaign 2013-01-08 22:42:46 +13:00
Scott_NZ
ec423db4e5 Don't hog the CPU trying to path to the enemy base in Allies 03, to line up with Allies 02 2013-01-08 22:42:45 +13:00
Scott_NZ
4c7f215559 Rename 'economic' to 'economy' in stats panel 2013-01-08 22:42:45 +13:00
Scott_NZ
0f9da06309 Have graph lines not draw over the axes 2013-01-08 22:42:45 +13:00
Scott_NZ
4ce6cabc46 Better numbers for the LineGraph y axis 2013-01-08 22:42:45 +13:00
Scott_NZ
b2b13b98b7 Use a default max value of 5000 on the line graph if it's too low 2013-01-08 22:42:44 +13:00
Scott_NZ
4c729ca5ed Refactored GraphWidget to LineGraphWidget 2013-01-08 22:42:44 +13:00
Scott_NZ
a78f8865b8 Moved the graph widget into OpenRA.Game - it doesn't really have any dependencies on the RA mod 2013-01-08 22:42:44 +13:00
Scott_NZ
d5b37d4343 Cleanup, refactoring of stats graph widget. 2013-01-08 22:42:44 +13:00
Scott_NZ
e424883857 Improve graph. Add things like scales/axis labelling. 2013-01-08 22:42:43 +13:00
Scott_NZ
b6e8c9c9ea Start implementing graphs for the stats panel 2013-01-08 22:42:43 +13:00
Scott_NZ
ed9bb72dbe Add more things to the Combat tab 2013-01-08 22:42:43 +13:00
Scott_NZ
9753808936 Renamed OrderCounter to PlayerStatistics. Simplify income to simply earned/min. 2013-01-08 22:42:43 +13:00
Scott_NZ
82fdbc4bc6 Move OrderCounter into Orders subnamespace 2013-01-08 22:42:42 +13:00
Scott_NZ
d7f3b81e4c Add Map Control statistic 2013-01-08 22:42:42 +13:00
Scott_NZ
36f349ecba Add Order counter for rough APM estimation. Rename Support to Production and move the production icons there 2013-01-08 22:42:42 +13:00
Scott_NZ
30a374b9e9 Add total earned/spent tracking 2013-01-08 22:42:42 +13:00
Scott_NZ
2a0b9a8596 Display support powers 2013-01-08 22:42:41 +13:00
Scott_NZ
9a9324946f Add dropdown for economic information 2013-01-08 22:42:41 +13:00
Scott_NZ
babf1556e3 Refactor the stats YAML and logic to more easily support swapping in data 2013-01-08 22:42:41 +13:00
Scott_NZ
bb1c87b084 Add clocks and text overlays for the production icons 2013-01-08 22:42:41 +13:00
Scott_NZ
1c584fb158 Consolidate the production icons into a single widget. Add income tracking for players. 2013-01-08 22:42:40 +13:00
Scott_NZ
83e1855919 Add indication of what players are building 2013-01-08 22:42:40 +13:00
Scott_NZ
4bc04769ec Subscribe to click event directly in the setup method 2013-01-08 22:42:40 +13:00
Scott_NZ
178358c29a Fixed Stats panel player selection silliness 2013-01-08 22:42:40 +13:00
Scott_NZ
42b16f74a1 Slightly adjust the width of the templates 2013-01-08 22:42:39 +13:00
Scott_NZ
9b493ad9e7 Remove unused usings 2013-01-08 22:42:39 +13:00
Scott_NZ
d7d5baae0e Add an observer stats panel 2013-01-08 22:42:39 +13:00
Scott_NZ
a8e434b74d Add radar for spectators 2013-01-08 22:42:39 +13:00
Scott_NZ
07d5ba8405 Remove Soviet econ hacks and power checks in Allies 02. 2013-01-08 22:42:39 +13:00
Scott_NZ
a5141f9908 proc.nofreeactor was causing harv to not unload properly. Just spawn a normal proc after we've changed the owner of the Allied base. 2013-01-08 22:42:38 +13:00
Scott_NZ
d15fb82b08 Allies 02 SP mode bug fixes 2013-01-08 22:42:38 +13:00
Scott_NZ
947b27a227 Make Allies 02 work in SP mode 2013-01-08 22:42:38 +13:00
Scott_NZ
b49110bf5c Ignore spies if they are disguised in Allies 03 2013-01-08 22:42:38 +13:00
Scott_NZ
8578958e40 Difficulty/balance changes 2013-01-08 22:42:37 +13:00
Scott_NZ
65e78ca8b0 Additional ore mines 2013-01-08 22:42:37 +13:00
Scott_NZ
608bf9ada1 Have the mggs come offmap, we don't want the player building too many. 2013-01-08 22:42:37 +13:00
Scott_NZ
4373831317 Remove econ hacks in Allies 03 and have the Soviets actually build their yaks. 2013-01-08 22:42:37 +13:00
Scott_NZ
aa78d63d72 Increased minimum attack increment 2013-01-08 22:42:36 +13:00
Scott_NZ
400d94caba Give the Soviets a Soviet construction yard in case the Allies lose theirs - they can capture this as a last resort. Make yaks buildable by Allies if they capture the Airfield buildings. 2013-01-08 22:42:36 +13:00
Scott_NZ
1660c4fe7c Reduce some code duplication 2013-01-08 22:42:36 +13:00
Scott_NZ
e643f12371 Attempted fix for Allies 03 crash (#2471) 2013-01-08 22:42:36 +13:00
Scott_NZ
339c0bc520 Fix weird plane spawn/management logic. Have Soviets ignore units that are concealed by gap generators 2013-01-08 22:42:36 +13:00
Scott_NZ
e15c240a8f Remove some old noise from the map 2013-01-08 22:42:35 +13:00
Scott_NZ
7bd66c2560 Render the shroud range circle for mgg 2013-01-08 22:42:35 +13:00
Scott_NZ
1f8fd404e5 Much better yak management. Map improvements. 2013-01-08 22:42:35 +13:00
Scott_NZ
93e951eb75 Added mobile gap generator. It is currently unbuildable and it does not generate shroud - this requires some additional shroud work since you can paint shroud across the map by moving it. 2013-01-08 22:42:35 +13:00
Scott_NZ
c52cd77c4c Add mechanic 2013-01-08 22:42:34 +13:00
Scott_NZ
0da911c9f8 Delete mods/d2k/bits/turret1.aud (not mods/d2k/bits/TURRET1.aud). This old, unused file was causing oddities for users with NTFS since we had two different files in the repository with filenames that differ only by case, and NTFS has case-insensitive filenames. 2013-01-08 22:42:34 +13:00
Igor Popov
395aa0fc10 dedicated: never let Bot become an admin 2013-01-08 22:34:03 +13:00
Carko
e10920d4ea Added the spawnpoint map tooltip that displays players name in the lobby (closes #2024) 2013-01-08 22:22:25 +13:00
Carko
914afa2dee Removed StringSplitOptions.RemoveEmptyEntries when counting wrapped text lines 2013-01-08 22:11:56 +13:00
Carko
ca1e0b4c48 Added word wrapping to in-game chat (fixes #2093) 2013-01-08 22:11:56 +13:00
Carko
70cf48dcaf Added a power bin tooltip that shows provided and drained power 2013-01-08 22:08:12 +13:00
Igor Popov
68130c85f3 fix #2453; MOTD for lobby (to be fetched from file); different motd for each mod 2013-01-08 21:57:25 +13:00
Chris Forbes
d0aea18b3e Added new map: "Bad Neighbors" from Nukem 2013-01-08 21:57:09 +13:00
Curtis Shmyr
ac301b22e2 Editor - Template categories are now ordered by whats specified in the tileset yaml 2013-01-08 20:11:22 +13:00
Curtis Shmyr
b56125fa39 Added terrain category types to RA Snow tileset 2013-01-08 20:11:22 +13:00
Curtis Shmyr
b362ddac15 Fixed terrain categories for two river tiles in RA Temperat 2013-01-08 20:11:22 +13:00
Curtis Shmyr
5f2aa810b1 Add terrain category types to RA desert tileset 2013-01-08 20:11:22 +13:00
Curtis Shmyr
189a6c337e Fix Water Cliff terrain types in temperate / desert tilesets 2013-01-08 20:11:22 +13:00
Curtis Shmyr
9c552839ea update CHANGELOG 2013-01-08 20:11:22 +13:00
Curtis Shmyr
79aa7901cf Added RA map: ghost town 2013-01-08 20:11:22 +13:00
Igor Popov
ad2dbffe75 fix #2480; Direct Connect to different mod causes crash (saying 'missing map') 2013-01-07 00:27:45 +04:00
Carko
88959b2e6c Changed scroll velocity in the map chooser to be better suited for mouse scrolling 2013-01-03 11:37:59 +13:00
Carko
f256742a0d Fixed repairing landed airplanes (most likely #2365)
When an airplane was landed and ordered to another airstrip or service depot, the aproach distance was not properly calculated since it was not taken into effect that its current altitude is zero.
2013-01-03 11:36:11 +13:00
Chris Forbes
22e2d3d0f4 Merge pull request #2507 from Lookingglass/per-player-shrouds
Per-player shrouds
2012-12-22 12:26:40 -08:00
Chris Forbes
3eed137117 Merge pull request #2526 from Mailaender/strings
made all in-game strings customisable via .yaml files
2012-12-22 12:25:33 -08:00
Chris Forbes
e28be10dd4 Merge pull request #2525 from Mailaender/custom-tech
don't hardcode custom prerequisites anymore
2012-12-22 12:25:03 -08:00
Chris Forbes
90361cb631 Merge pull request #2524 from hunnybunny95/patch-1
Fixed airfield name.
2012-12-22 12:24:42 -08:00
Matthias Mailänder
c3b959846c customisable Ready/Hold text for CnC mod
make those strings also translatable
2012-12-22 19:21:05 +01:00
Matthias Mailänder
39884e16fa customisable text printed on RA support power icons 2012-12-22 18:59:45 +01:00
Matthias Mailänder
f107f8a87b expose strings from build palette widget to chrome yaml
prepare for localisation efforts
2012-12-22 18:25:18 +01:00
Matthias Mailänder
8246b2f35f don't hardcode custom prerequisites anymore
to make those strings translatable
2012-12-22 17:42:57 +01:00
hunnybunny95
f13d12acec Fixed airfield name.
The name of the airfield was airstrip... which is wrong since the icon says airfield whilte the building is called airstrip... its even called AFLD in the code so... just a simple fix :)
2012-12-21 21:57:19 +01:00
Kenny
4090be72d4 Adding Shroud trait to CNC / D2K mods 2012-12-16 20:00:17 -08:00
Chris Forbes
90d30005f6 Merge pull request #2498 from Mailaender/volkov
make Volkov a true Cyborg
2012-12-16 18:16:39 -08:00
Chris Forbes
7c968a8f88 Merge pull request #2509 from Lookingglass/lg-maps
Three new 5-player RA maps
2012-12-16 12:35:04 -08:00
Kenny
e4ab86e6f9 Three new 5-player RA maps:
- The White Pentagon - snow based land/water map with minimal obstructions.
- Black Gold - Resource starved map with each starting position receiving 8 oil derricks.
- Texas Sea - Similar to Black Gold, but every starting position is on a tiny island.
2012-12-13 15:39:14 -08:00
Kenny
f41fb32d60 Introducing per-player shrouds.
- Each player has their own shroud and their visibility does not extend outside of the shroud. 
- Units and buildings can no longer target other units outside of their visibility. Buildings can still be targetted if they have been explored.
- GPS will provide visibility in the fog-of-war.
- Spies that infiltrate radar domes will gain their victim's exploration and reset it on all clients (if the victim does not have GPS)
2012-12-13 15:16:56 -08:00
Matthias Mailänder
5249a17d48 d2k: add Tuck's Sietch remake
by DraLUSAD from
http://www.sleipnirstuff.com/forum/viewtopic.php?f=83&t=16009
2012-12-12 09:46:26 +13:00
Matthias Mailänder
99256bcad0 cnc: fix wrong civilian field remapping at least in-game
the editor hack is RA specific
2012-12-12 09:43:45 +13:00
Matthias Mailänder
f402c37b14 Don't remap civilian buildings/fields in-game.
V16 field was mostly affected because it consists mostly of remapped colors.
2012-12-12 09:43:45 +13:00
Matthias Mailänder
494ab2db4d add @Generalcamo to AUTHORS
original Volkov contribution came from
http://content.open-ra.org/index.php?p=detail&table=units&id=132
2012-12-10 23:12:49 +01:00
Matthias Mailänder
5d4160bc82 make Volkov a true Cyborg
- Added new Armor value: Cybernetic
- Use sounds/graphics from DE censored version
- Heals near repair pad (instead of hospital)
- Medic can't heal him
- Dogs can't eat him
- Tanks need to attempts to crush him
- +25% HP (now same factor as 4tnk:1tnk compared to e1)
2012-12-10 16:42:43 +01:00
Chris Forbes
b9194e4305 d2k: fix crash on attackmove medic 2012-12-04 11:39:37 +13:00
Chris Forbes
8ab1fbe83a Merge pull request #2482 from reaperrr/patch-1
Update mods/cnc/music.yaml
2012-12-03 13:11:11 -08:00
Matthias Mailänder
96a088f998 merge Dune 2000 "Rounded Edges" mod
Changes include:
 - bibs have been removed
 - building offset and selection boxes adapted
 - units and turrets leave husks
 - siege tank barrel won't rotate anymore
 - AI capable of building all units using all queues
 - bullet traces
 - windtrap animations
 - unit balance (mix of Dune II, Dune 2000 and Red Alert)
 - repair pad animation
 - no more obsessive "silos needed"
 - defense building queue → heavy armor queue
 - medics (using thumper graphics)
 - no buildable aircrafts anymore
 - harvesting has been slowed down
2012-12-04 10:08:14 +13:00
Matthias Mailänder
7d4399d7cc fixes #2481
Don't save in system pathes because UNIX needs root and shipped maps
should not be changed. Use $HOME/maps/$MOD instead.
2012-12-04 10:06:42 +13:00
Matthias Mailänder
107c37f33d RA: Snow craters fix by MrFlibble
Small graphical patch fixing some snow craters and scorch marks
2012-12-04 10:05:31 +13:00
Matthias Mailänder
88949024e6 RA: add shadow to supply truck
copied from the demolition truck
2012-12-04 10:04:12 +13:00
Matthias Mailänder
aad0b3d2d8 fixed wrong palette remapping for neutral buildings in editor
for TEMPERAT (fields) and DESERT (buildings, trees, rocks)
2012-11-26 12:21:50 +01:00
Matthias Mailänder
4e0e53c714 Merge pull request #8 from cjshmyr/desert
RA Desert patches by Curtis
2012-11-26 01:04:53 -08:00
Curtis Shmyr
87a2817234 RA Desert - Use ExcludeTileset instead of RequiresTileset for specific tileset actors (looks cleaner) 2012-11-25 18:16:08 -07:00
Curtis Shmyr
f3e796e972 RA Desert - Removed fenc.des which was another barbed wire shp 2012-11-25 17:33:29 -07:00
Curtis Shmyr
7d5a843684 RA Desert - Added a missing shrub. Added building yaml definitions. Hide Temperate and Snow actors from Desert tileset editor. 2012-11-25 17:30:19 -07:00
Matthias Mailänder
f914929eb7 Merge pull request #7 from cjshmyr/desert
Add patches by Curtis:
- fixes desert shorelines
- found missing wc13.des
- remove ice redundancy in sequences.yaml
2012-11-25 09:09:24 -08:00
Curtis Shmyr
8f7b776556 Desert tileset - use proper wc13.des tile 2012-11-21 20:51:33 -07:00
reaperrr
aeaa58a01b Update mods/cnc/music.yaml
'I Am' was the name of the band that made this song (with Mr. Klepacki on drums), the track is actually called Destructible Times. Also brought titles of Warfare/Full Stop as well as Heavy Gear/Demolition in line with other double-named tracks.
2012-11-22 00:21:41 +01:00
Curtis Shmyr
4dacd3be26 Fix up shoreline pieces to have beach terrain types (for water transport use) 2012-11-20 21:21:31 -07:00
Curtis Shmyr
05929bdfe9 Remove extra sequence entries for ice01 ice02 ice03 ice04 ice05 2012-11-20 21:14:52 -07:00
Matthias Mailänder
0690041347 fix most of the palette issues with RA desert in OpenRA.Editor
TODO: use the palette as defined in YAML;
defaults are wrong for DESERT rocks, trees, walls and ore mine
2012-11-19 14:53:25 +01:00
Matthias Mailänder
842fd8b4e5 update VS project file 2012-11-17 13:16:34 +01:00
Matthias Mailänder
7a89e3d67a added DESERT rocks 2012-11-17 13:16:26 +01:00
Matthias Mailänder
5ecc6224b0 add bridges to DESERT 2012-11-17 13:15:16 +01:00
Matthias Mailänder
f5c592291c add Harisson to AUTHORS 2012-11-17 13:15:16 +01:00
Matthias Mailänder
7f229a3fde add ice sequences, fixes related crash 2012-11-17 13:15:16 +01:00
Matthias Mailänder
c859fb1186 fix the remaining issues with the ra desert terrain
- extract mix file as it is easier to work with SHPs
- light palette rotator now excludes terrain palette
- water palette rotator now excludes player palette
- use wire fence, sand bags and brick wall from cnc
- draw ressources with player palette (workaround)
- delete all test maps
2012-11-17 13:15:16 +01:00
Matthias Mailänder
6dceb30632 add 2 testmaps for desert tileset 2012-11-17 13:15:16 +01:00
Matthias Mailänder
f3dc31be40 add PlayerPaletteFromCurrentTileset and desert tileset for RA
some things left to do:
ore, walls and silo/hbox need some work
2012-11-17 13:15:06 +01:00
Matthias Mailänder
a2f5ffd59e made WaterPaletteRotation more configurable
Base is now configurable per terrain
ExcludePalettes is now exposed to yaml
2012-11-17 13:13:32 +01:00
hunnybunny95
a2c66a32b0 Fixed hotkeys for aircraft 2012-11-16 04:47:50 +01:00
hunnybunny95
72139675ac Fixed hotkeys for vehicles 2012-11-16 04:46:00 +01:00
hunnybunny95
2b57f04dc0 Fixed hotkeys for ships 2012-11-16 04:45:15 +01:00
hunnybunny95
15e09fa83b Fixed hotkeys for infantry 2012-11-16 04:44:34 +01:00
Sunny Sproket
55ee1d41f3 Added "room-convergence" map 2012-11-13 09:38:26 +13:00
Matthias Mailänder
2e7908366a fixes #2465
gpsdot.shp shadow uses index 3
2012-11-13 09:26:59 +13:00
Chris Forbes
6ab4fda9a6 Balanced "Bombardment Islands" map (from czech army) 2012-11-13 09:26:59 +13:00
Curtis Shmyr
a5ba41cae8 Make ctnks missiles explode a bit sooner (still reaching their target) 2012-11-10 19:53:10 -07:00
Curtis Shmyr
5e9cdad044 No more sound attentuation for PlayNotification - fixes #2466 2012-11-10 19:52:21 -07:00
Curtis Shmyr
c14de26c07 Actually fixed RA map bomber-john 2012-11-04 10:27:45 -07:00
Curtis Shmyr
e5f506c81d update CHANGELOG 2012-11-03 23:06:27 -06:00
Curtis Shmyr
4160f08c6c Fix bomber-john RA map crash #2439 2012-11-03 22:53:11 -06:00
Curtis Shmyr
4ad0d1682e Improve ctnk health and damage vs heavy armor, reduce damage vs inf 2012-11-04 17:47:03 +13:00
NukemBro
8fb4fc9a14 Re-add RA map Chaos Canyon now with proper cordon - fixes #2432 2012-11-04 17:47:03 +13:00
Curtis Shmyr
5a0187e1db Temporarily drop RA map chaos canyon 2012-11-04 17:47:03 +13:00
Curtis Shmyr
7f5141c338 #2447 - Disguised spies are now hidden under GPS 2012-11-04 17:47:03 +13:00
Iran
354cabf8d1 -- add ice tile entries to sequences.yaml
fixes crashes on maps using these ice tiles.
2012-11-04 17:47:03 +13:00
Scott_NZ
fd734c8553 Improve the Soviet attacks more 2012-11-04 16:20:46 +13:00
Scott_NZ
9238de6a47 Add airbase and airbase secondary objective. Improve Soviet attacks. Enable players to capture sam sites as well as destroy them to complete the objective in Allies 02 2012-11-03 21:41:46 +13:00
Scott_NZ
b2c5f488a7 Rename Evacuees player to Allies. Make AA gun buildable. 2012-11-03 13:33:38 +13:00
Scott_NZ
c634867cdd Reduce threshold, unused variables 2012-11-03 13:33:38 +13:00
Scott_NZ
d7f2273788 Increase duration between spawn for SP 2012-11-03 13:33:38 +13:00
Scott_NZ
5c1a982fdd Remove evacuee buildings to stop the players building on the other side of the map 2012-11-03 13:33:38 +13:00
Scott_NZ
0300a67da8 The Allies 02 Soviet reinforcements at 16 minutes are a bit too insane 2012-11-03 13:33:37 +13:00
Scott_NZ
862dfb3275 Improvements to map layout 2012-11-03 13:33:37 +13:00
Scott_NZ
03121ed826 Add yak strafing, support for SP as well as MP, additional Soviet spawn point 2012-11-03 13:33:37 +13:00
Scott_NZ
0cdff00cb6 First version of Allies 03 2012-11-03 13:33:36 +13:00
Scott_NZ
787facec65 Allies02: Make Allied infantry buildable by the Allies1 player when they capture the Soviet barracks. Remove ctnk from the build menu 2012-11-03 13:33:36 +13:00
Scott_NZ
44d63b9103 Barrels were not scorching the terrain 2012-11-03 13:33:36 +13:00
Scott_NZ
49571fc78a Increase deaths threshold to 200 2012-11-03 13:33:35 +13:00
Scott_NZ
60569bc97c Fix open areas for allies maps 2012-11-03 13:33:35 +13:00
Chris Forbes
b37510c30e nerf dtrk speed from 8 to 6 2012-10-23 19:26:51 +13:00
Kenny
343b7bf3e1 Increasing cost to $2500 as well as reducing armor to 50 hit points. 2012-10-22 14:42:36 +13:00
Curtis Shmyr
7a2423a742 Fix #2449 - ctnk line of sight improved 2012-10-21 16:50:01 -06:00
Curtis Shmyr
57dfc739c6 Fix #2433 - crash when ctnk order generator was active if ctnk dies 2012-10-21 16:46:58 -06:00
Curtis Shmyr
f3d4b6541c Fixed ctnk desync #2448 2012-10-21 15:43:30 -06:00
Curtis Shmyr
d1c20d6c72 Fix #2434 and #2442 2012-10-21 14:55:25 -06:00
Curtis Shmyr
e4beb8236e Update CHANGELOG 2012-10-20 12:28:45 -06:00
Chris Forbes
7574124ff0 added forest-path map for tournament 2012-10-19 11:56:39 +13:00
Scott_NZ
e1cb4d60c4 Fix crash when spectators are present 2012-10-15 16:28:38 +13:00
Igor Popov
1d62329969 fix #2425; Bots should be removed when switching to a map which doesn't allow them 2012-10-15 08:17:04 +13:00
Curtis Shmyr
36813ff52f Fix chronotank's missiles from exploding too soon 2012-10-13 17:31:12 -06:00
Curtis Shmyr
267141749d Chronotank charge pips down from 5->2, pips are blue and jump radius is blue 2012-10-13 16:50:11 -06:00
Curtis Shmyr
edd41c5be1 Chronotank jump cooldown lowered from 60 seconds to 30 2012-10-13 16:50:10 -06:00
Curtis Shmyr
5dc0439173 Fix flak truck description 2012-10-13 16:50:10 -06:00
Curtis Shmyr
4dbee1c0e3 Lower cost of TTNK (1500->1350) and update description to reflect current balance 2012-10-13 16:50:09 -06:00
Curtis Shmyr
76baba89c1 Retune chronotank's weapons to match its description 2012-10-13 16:50:08 -06:00
Curtis Shmyr
5da96941e1 Fix demo truck description 2012-10-13 16:50:07 -06:00
Curtis Shmyr
c2ec8cd372 Fix Volkov's description 2012-10-13 16:50:06 -06:00
Chris Forbes
b73a0a9720 fix off-by-one in new tile query 2012-10-14 10:07:08 +13:00
Chris Forbes
6f3b21616f fix warnings in allies scripts 2012-10-13 14:31:45 +13:00
Chris Forbes
1792f16929 Merge remote-tracking branch 'scott/allies' 2012-10-13 13:52:21 +13:00
Chris Forbes
8dfd02e69e fix HackyAI's husk fetish 2012-10-13 13:45:35 +13:00
Chris Forbes
c8b1c1b999 tidy slightly in idle harv handler 2012-10-13 13:42:34 +13:00
Curtis Shmyr
da9422824a Trans heli now costs 900, increased health, increased cargo count to 8 2012-10-13 13:30:36 +13:00
Chris Forbes
403b51ca4b remove duplication in Mobile 2012-10-13 12:55:51 +13:00
Chris Forbes
3fad0983b9 simplify Mobile using new ordering from FindTilesInCircle 2012-10-13 12:55:51 +13:00
Chris Forbes
bbab5237d1 get rid of crazy wasted work in HackyAI 2012-10-13 12:55:51 +13:00
Chris Forbes
699838332d Order results from FindTilesInCircle by distance 2012-10-13 12:55:51 +13:00
Chris Forbes
6e237b53e1 remove unused trait lookup in ChronoshiftDeploy.ResolveOrder 2012-10-13 11:43:06 +13:00
Curtis Shmyr
36990601db Remove extra newline on Volkov's description 2012-10-13 11:38:00 +13:00
Curtis Shmyr
82f9549f01 Improve mammoth tank tusk turn rate (5->10) 2012-10-13 11:37:55 +13:00
Curtis Shmyr
656503c0c5 Increase range of Tanya's colt45 from 5.75 to 7 2012-10-13 11:37:52 +13:00
Curtis Shmyr
83fc70f415 Added Chrono Tank to Allies 2012-10-13 11:37:46 +13:00
Scott_NZ
bd8ba636c9 Shift v2s to 4 minutes; improve the additional units code 2012-10-12 20:59:35 +13:00
Scott_NZ
6eb2f2bffe Don't hard code 100 into the objectives string 2012-10-12 16:06:43 +13:00
Scott_NZ
d9a6cc6b1c Should be greater than or equal to when comparing with death threshold 2012-10-11 22:57:19 +13:00
Scott_NZ
8c3aabb215 Support for updating objectives without flashing the objectives button. Added a secondary objective: lose fewer than 100 units. 2012-10-11 22:55:02 +13:00
Scott_NZ
d44d9f67f2 Promote the 'MainPresence' objective to primary. 2012-10-11 22:36:40 +13:00
Scott_NZ
8f8800803b Make the Soviet V2s buildable immediately. Fix the Soviet reinforcements not arriving properly. Remove the Soviet reinforcements timer. Rework the bottom left of the map. 2012-10-11 22:35:13 +13:00
Scott_NZ
52007b6277 Move the timer positions 2012-10-09 20:56:11 +13:00
Scott_NZ
795008011e Explosive barrel explosions now cascade with a small delay between each explosion. 2012-10-09 01:51:25 +13:00
Scott_NZ
ec6b8646e9 Improve barrel explosions in Allies 01 by increasing the explosion damage and the health of the power plants/oil derrick. 2012-10-09 00:25:49 +13:00
Scott_NZ
40206f8280 Improved control over the 'final' Soviet wave 2012-10-08 23:34:38 +13:00
Scott_NZ
887a9e7c9c Make medic/spy available to the Allies1 player 2012-10-08 23:34:02 +13:00
Scott_NZ
e4218ede41 Improve the Soviet base, and rebalance the power. 2012-10-08 21:16:30 +13:00
Scott_NZ
f4d0f80cd3 Increase the difficulty of the final wave and shift some of the Soviet power plants around 2012-10-08 20:51:03 +13:00
Scott_NZ
8661fb6b8d Add final attack for Soviets 2012-10-08 19:39:18 +13:00
Scott_NZ
c212095a40 Improve the stability of CountdownTimer 2012-10-08 17:16:42 +13:00
Chris Forbes
f337c7fb40 fix 2422; tesla ignoring weapon offset 2012-10-07 19:23:50 +13:00
Scott_NZ
073a8ee079 Sync up the countdown timer and the objectives button flash with the game speed 2012-10-05 22:03:35 +13:00
Scott_NZ
a4b01cf114 Improved the Allies 02 map layout 2012-10-05 22:02:51 +13:00
Scott_NZ
cba069a039 Improve the effectiveness of the parabombs 2012-10-05 16:23:58 +13:00
Scott_NZ
bf4829205c Have the parabomber come from a different direction. Have the Soviet tanks go straight for the enemy base structures. 2012-10-04 23:59:33 +13:00
Scott_NZ
328dce26ba Add some dogs around the Soviet base to make it harder to use spies 2012-10-04 22:57:34 +13:00
Scott_NZ
0524708e05 Add Yak harrassment 2012-10-02 21:52:45 +13:00
Scott_NZ
7e376330d0 Have the reinforcements money come in as supply trucks instead 2012-10-02 21:52:45 +13:00
Scott_NZ
762db8b304 Have the countdown timer flash in the last 10 seconds, and increase the money amount when reinforcements arrive 2012-10-02 21:52:44 +13:00
Scott_NZ
37479b3cfd Tank wave at 11 minutes, just before the reinforcements arrive 2012-10-02 21:52:44 +13:00
Scott_NZ
07c2330245 Add 2 additional paradrop badgers to the paradrop attack, and a parabomb attack 2012-10-02 21:52:44 +13:00
Scott_NZ
0c6daf191c Add button highlighting/glow effect, to be used for the objective button when the objectives update 2012-10-02 21:52:43 +13:00
Scott_NZ
b897579a20 Send the waves instantly 2012-10-02 21:52:43 +13:00
Scott_NZ
fcc0bcf438 Improve the Soviet attack routines for Allies 01 2012-10-02 21:52:43 +13:00
Scott_NZ
0cd258f24f Dynamically position the timer so that it isn't cut off 2012-10-02 21:52:43 +13:00
Scott_NZ
43e99bf9f5 Add heal animation for the heal crate 2012-10-02 21:52:42 +13:00
Scott_NZ
83d10ba838 Add mission objectives logic/backend 2012-10-02 21:52:42 +13:00
Scott_NZ
48997725c3 Don't let tran reveal shroud 2012-10-02 21:52:42 +13:00
Scott_NZ
631f899f18 Begin work on objectives UI 2012-10-02 21:52:42 +13:00
Scott_NZ
2a4a9d778f Redo some of the fencing near the Soviet base 2012-10-02 21:52:41 +13:00
Scott_NZ
2e2b4d04db Small map/behaviour adjustments 2012-10-02 21:52:41 +13:00
Scott_NZ
deede92fbc Update objective code for Einstein helicopter, avoid race condition with checking if allies2 has been killed 2012-10-02 21:52:41 +13:00
Scott_NZ
e3b2e84792 Focus on the town more; create additional crash site there and and move Einstein there for players to save. 2012-10-02 21:52:41 +13:00
Scott_NZ
e07d55f5f4 Open up the rear of the Soviet base for infiltration by the allies1 player. 2012-10-02 21:52:40 +13:00
Scott_NZ
1803b412c3 Convert Allies 02 over to enum objectives 2012-10-02 21:52:40 +13:00
Scott_NZ
8dd7bfdb67 Move the objective flag stuff to MissionUtils 2012-10-02 21:52:40 +13:00
Scott_NZ
d1400ab4fa Set the enum values explicitly 2012-10-02 21:52:40 +13:00
Scott_NZ
67c40f3119 Use enum-based objectives for Allies 01 2012-10-02 21:52:39 +13:00
Scott_NZ
68d0201538 Add more utils to MissionUtils. Extract Allies 02 countdown timer to its own class file 2012-10-02 21:52:39 +13:00
Scott_NZ
d30d3ed05a Create MissionUtils.cs for shared mission code 2012-10-02 21:52:39 +13:00
Scott_NZ
43f2895eb8 Put reinf ticks back to 12 minutes 2012-10-02 21:52:39 +13:00
Scott_NZ
185e3cffb4 Repackage maps 2012-10-02 21:52:38 +13:00
Scott_NZ
d68196a3b0 Fixed some constant naming 2012-10-02 21:52:38 +13:00
Scott_NZ
4551302c09 Reduce Tanya's and Einstein's weights to 0 so they can still board chinook helicopters if they are full 2012-10-02 21:52:38 +13:00
Scott_NZ
56f36e45db New crate type 'HealUnitsCrateAction' which heals all of the units that the collecting player has. Very rare. New 'ContainsCrate' trait which goes along with this - could be used to hide crates inside churches for example like in the original RA missions. 2012-10-02 21:52:38 +13:00
Scott_NZ
8fabf1504a Add a nearEnough field for RallyPoints (to be used as an argument for their AttackMove activities) so the Soviets don't get stuck on their rally point, and scatter the units a bit before they attack 2012-10-02 21:52:37 +13:00
Scott_NZ
fd96d08ce8 Smoke effect for the chinook husk 2012-10-02 21:52:37 +13:00
Scott_NZ
0e801f9d3a Rework bottom right of Allies 2 map: add more space, more Soviet soldiers, put the captive Engineer outside. Move the southern Soviet outpost up to where the second SAM site is. Move the Soviet rally point up a bit. 2012-10-02 21:52:37 +13:00
Scott_NZ
e5ab56e843 Rework bottom right of the Allies 02 map, move captive Engineer outside. Set Tanya's stance to ReturnFire so attack-move works. 2012-10-02 21:52:37 +13:00
Scott_NZ
ff0ad9cb41 Set fcom tooltip to Forward Command 2012-10-02 21:52:36 +13:00
Chris Forbes
3e81a4bd70 remove PowerBarWidget entirely 2012-09-25 19:51:03 +12:00
Chris Forbes
84f7aa56e1 make ResourceBarWidget generic 2012-09-25 19:44:20 +12:00
Chris Forbes
c42f270ce0 move all databinding for the silobar into ui logic 2012-09-25 19:39:33 +12:00
Chris Forbes
af31ae4931 tidy up SiloBarWidget to be almost completely independent of ore 2012-09-25 19:27:33 +12:00
Chris Forbes
8b6308d3a2 reduce differences between PowerBarWidget and SiloBarWidget 2012-09-25 18:56:24 +12:00
Chris Forbes
6ecc4c18dc fixed 2036 -- add targetlines for defenses 2012-09-25 18:42:36 +12:00
Chris Forbes
56557b8766 convert dtrk to use MiniNuke 2012-09-24 21:07:16 +12:00
Chris Forbes
83ba80f4c9 add MiniNuke weapon for dtrk 2012-09-24 21:06:49 +12:00
Chris Forbes
65227c3c09 remove nuke crate 2012-09-24 21:03:33 +12:00
Chris Forbes
1b5474f377 retune nuke 2012-09-24 21:02:22 +12:00
Chris Forbes
38b5e2f7ca set up demo truck to explode on chronoshift 2012-09-24 20:36:03 +12:00
Chris Forbes
0ff3c56d4f add Chronoshiftable:ExplodeInstead option 2012-09-24 20:34:54 +12:00
Chris Forbes
4888732fb7 fix reversed ordernames in DemoTruck 2012-09-24 20:24:35 +12:00
Chris Forbes
3079e2b488 fixed Explodes dep on demotruck 2012-09-24 20:22:36 +12:00
Curtis Shmyr
34d96878b8 Added demo truck to soviet's arensal; still problems to fix 2012-09-24 20:08:56 +12:00
Chris Forbes
61e548151b clear queue-per-building production queue on mcv repack 2012-09-23 18:00:06 +12:00
Chris Forbes
7cc7dcc559 add INotifyTransform hook for just before something transforms 2012-09-23 17:58:53 +12:00
Chris Forbes
757c9ca63c Fixed 2387 - dont shade possible build items in cnc just because something else is building 2012-09-23 17:45:13 +12:00
Chris Forbes
5cb86f8937 repair cost for units is always at least 1 per tick 2012-09-23 17:38:23 +12:00
Chris Forbes
cd1a29f1ea repair cost is always at least 1 per tick 2012-09-23 17:37:35 +12:00
Igor Popov
79b4765d9f fix: port in Direct Connect was dumped to default by force 2012-09-23 17:27:19 +12:00
Igor Popov
05e9dcd5ce dedicated: load another initial map if current key is not present in dictionary 2012-09-23 17:20:47 +12:00
Igor Popov
4c915ce8fe dedicated: configurable MOTD 2012-09-23 17:20:47 +12:00
Igor Popov
5d5fe3f5a1 dedicated: proper reason why DEV_VERSION is kicked. 2012-09-23 17:20:46 +12:00
Igor Popov
5bacf69445 dedicated: cleaner 2012-09-23 17:20:46 +12:00
Igor Popov
0a858ac353 cleaner 2012-09-23 17:20:46 +12:00
Igor Popov
b7258e61f3 remove bogus comment 2012-09-23 17:20:46 +12:00
Igor Popov
bd45ffa022 dedicated: start a new server instance once previous game is finished (configurable) 2012-09-23 17:20:46 +12:00
Igor Popov
b45f9568d0 dedicated: force tell master server if amount of clients is 0 2012-09-23 17:20:46 +12:00
Igor Popov
f8290b8a7e dedicated: handle admin 2012-09-23 17:20:46 +12:00
Igor Popov
21b002ce22 dedicated: drop DEV_VERSION 2012-09-23 17:20:45 +12:00
Igor Popov
1fbd8f6cc6 dedicated: null SoundEngine 2012-09-23 17:20:45 +12:00
Igor Popov
2798f0d841 dedicated: handle non-existing map 2012-09-23 17:20:45 +12:00
Igor Popov
bf73cdbd01 basic dedicated server support 2012-09-23 17:20:45 +12:00
Chris Forbes
03229eca0c remove sounds from sniper cloak/uncloak; enable uncloak-on-move for sniper. 2012-09-23 17:17:07 +12:00
Chris Forbes
489fdc1893 add CloakInfo.UncloakOnMove option 2012-09-23 17:15:16 +12:00
Chris Forbes
e2b2082660 fix armor types on war factory and airfield 2012-09-20 10:14:44 +12:00
Chris Forbes
5ab2e2b225 adjust building prices 2012-09-20 10:13:14 +12:00
Chris Forbes
caa58e46c3 buff 4tank self-heal; nerf turret rotation 2012-09-19 17:35:06 +12:00
Chris Forbes
e9f4338852 remove vestigial mods/*/packages handling from installer 2012-09-16 14:13:24 +12:00
Scott_NZ
f146cedad5 Improve the thresholds a bit 2012-09-16 12:27:33 +12:00
Scott_NZ
cc449f81f8 Describe the map size in words 2012-09-16 12:27:33 +12:00
Chris Forbes
085e29d22b dead things are no longer valid targets 2012-09-16 11:24:36 +12:00
Chris Forbes
f8427fa242 refuse to start the game unless required slots are full. 2012-09-16 11:05:00 +12:00
Chris Forbes
eb9b6a3842 propagate Required flag to Slot 2012-09-16 10:58:48 +12:00
Chris Forbes
43fc1219f0 add Required field to PlayerReference 2012-09-16 10:51:49 +12:00
Igor Popov
1469620831 new interior map by sunny_s: room-warzone 2012-09-16 10:43:40 +12:00
Chris Forbes
036997a7a0 update authors file 2012-09-16 10:17:51 +12:00
Kyrre Soerensen
b4d9c40dc8 maps: Replace Baywatch with Hasselhoff (better ore distribution)
Signed-off-by: Kyrre Soerensen <kyrre@ksorensen.net>
2012-09-16 10:14:32 +12:00
Chris Forbes
62257459fd fix NRE in ReturnToBase bailout if no suitable building is found 2012-09-14 23:20:39 +12:00
Chris Forbes
ea641f081f use ChooseAirfield in ReturnToBase.Tick bailout 2012-09-14 23:20:18 +12:00
Chris Forbes
a641c7a87d add parameter to ReturnToBase.ChooseAirfield for whether the building must be unreserved 2012-09-14 23:14:02 +12:00
Chris Forbes
605a1eacf6 fix Gl renderer; texture binding was totally busted 2012-09-13 08:14:21 +12:00
Chris Forbes
da3adf4f8e fix bogus extra death sounds in ra VolkovVoice 2012-09-13 07:35:25 +12:00
Chris Forbes
8680405b68 show no-deploy cursor if locked 2012-09-13 07:27:15 +12:00
Chris Forbes
5ad2d1892f take lock in DeployTransform if we're a building 2012-09-13 07:25:39 +12:00
Chris Forbes
b723e350c8 remove spurious interlock in Sell 2012-09-13 07:16:04 +12:00
Chris Forbes
0b665bc35b move counter-capture logic down into Capturable; remove spurious interlock on CaptureInProgress 2012-09-13 07:14:56 +12:00
Chris Forbes
c012ea90dd get rid of capturing lock in Sellable 2012-09-13 07:10:28 +12:00
Chris Forbes
b0b0fac847 get rid of Sellable.Selling state 2012-09-13 07:09:44 +12:00
Chris Forbes
c253e59c57 take lock while capture in progress 2012-09-13 07:08:02 +12:00
Chris Forbes
952e277d35 take lock in Sellable.ResolveOrder 2012-09-13 07:05:58 +12:00
Chris Forbes
f984934270 add Building.Locked, and Lock()/Unlock() conveniences 2012-09-13 07:05:58 +12:00
Chris Forbes
fb58840cea ignore spectators for readiness check 2012-09-04 11:24:59 +12:00
Chris Forbes
3d8dc80f03 complain about junk values like the recent volkov breakage 2012-09-04 10:55:26 +12:00
Chris Forbes
d970195394 fix bogus armor definition for Volkov 2012-09-03 09:26:27 +12:00
Scott_NZ
c33c9e9f69 Fixes #2386 (Add map size to map list) 2012-08-28 16:18:15 +12:00
Chris Forbes
6d3a932453 Revert "Removed the "tip" jutting out of 3 buildings, so they are rectangular instead of awkwardly shaped."
This reverts commit 22bddf9645.
2012-08-25 15:32:29 +12:00
821 changed files with 25290 additions and 4460 deletions

3
.gitignore vendored
View File

@@ -13,9 +13,6 @@ mods/*/*.dll
# ReSharper crap
_ReSharper.*/
# Red Alert binary files
mods/*/packages/*.[mM][iI][xX]
#binary stuff
/*.dll
*.pdb

View File

@@ -15,12 +15,16 @@ Also thanks to:
* Barnaby Smith (mvi)
* Bellator
* Christer Ulfsparre (Holloweye)
* Cody Brittain (Generalcamo)
* Daniel Derejvanik (Harisson)
* Erasmus Schroder (rasco)
* Igor Popov (ihptru)
* James Dunne (jsd)
* Jeff Harris (jeff_1amstudios)
* Jes (-Jes-)
* Joakim Lindberg (booom3)
* Kenny Hoxworth (hoxworth)
* Kyrre Soerensen (zypres)
* Lawrence Wang
* Mark Olson (markolson)
* Matthew Gatland (mgatland)
@@ -33,6 +37,7 @@ Also thanks to:
* Raymond Martineau (mart0258)
* Riderr3
* Tim Mylemans (gecko)
* Tirili
Past developers included:
* Paul Chote (pchote)

1151
CHANGELOG

File diff suppressed because it is too large Load Diff

19
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,19 @@
# OpenRA Contributing Guidelines
## Bug reports
* Have you read the [FAQ](https://github.com/OpenRA/OpenRA/wiki/FAQ)?
* Add the appropriate log files on crashes.
* Please be specific on how to reproduce the problem.
## Patches
* [Coding standard](https://github.com/OpenRA/OpenRA/wiki/Coding-Standard)
* [Branches and Releases](https://github.com/OpenRA/OpenRA/wiki/Branches-and-Releases)
* [Licensing](http://www.gnu.org/licenses/quick-guide-gplv3.html)
Please `git rebase` to the latest revision of the bleed branch.
Don't forget to add youself to [AUTHORS](https://github.com/OpenRA/OpenRA/blob/bleed/AUTHORS).
While your pull-request is in review it will be helpful if you join [IRC](irc://chat.freenode.net/openra) to discuss the changes.

View File

@@ -1,5 +1,5 @@
CSC = gmcs
CSFLAGS = -nologo -warn:4 -debug:+ -debug:full -optimize- -codepage:utf8 -unsafe
CSFLAGS = -nologo -warn:4 -debug:full -optimize- -codepage:utf8 -unsafe
DEFINE = DEBUG;TRACE
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll thirdparty/ICSharpCode.SharpZipLib.dll
PHONY = core tools package all mods clean distclean

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
@@ -42,7 +42,7 @@ namespace OpenRA.Editor
tilePalette.ResumeLayout();
actorPalette.ResumeLayout();
resourcePalette.ResumeLayout();
surface1.Bind(null, null, null);
surface1.Bind(null, null, null, null);
pmMiniMap.Image = null;
currentMod = toolStripComboBox1.SelectedItem as string;
@@ -141,12 +141,17 @@ namespace OpenRA.Editor
int[] ShadowIndex = { 3, 4 };
var palette = new Palette(FileSystem.Open(tileset.Palette), ShadowIndex);
surface1.Bind(map, tileset, palette);
// required for desert terrain in RA
var playerPalette = tileset.PlayerPalette ?? tileset.Palette;
var PlayerPalette = new Palette(FileSystem.Open(playerPalette), ShadowIndex);
surface1.Bind(map, tileset, palette, PlayerPalette);
// construct the palette of tiles
var palettes = new[] { tilePalette, actorPalette, resourcePalette };
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category))
string[] templateOrder = tileset.EditorTemplateOrder ?? new string[]{};
foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => templateOrder.ToList().IndexOf(t.Key)))
{
var category = tc.Key ?? "(Uncategorized)";
var categoryHeader = new Label
@@ -211,7 +216,13 @@ namespace OpenRA.Editor
if (etf != null && etf.RequireTilesets != null
&& !etf.RequireTilesets.Contains(tileset.Id)) continue;
var template = RenderUtils.RenderActor(info, tileset, palette);
var TemplatePalette = PlayerPalette;
var rsi = info.Traits.GetOrDefault<RenderSimpleInfo>();
// exception for desert buildings
if (rsi != null && rsi.Palette != null && rsi.Palette.Contains("terrain"))
TemplatePalette = palette;
var template = RenderUtils.RenderActor(info, tileset, TemplatePalette);
var ibox = new PictureBox
{
Image = template.Bitmap,
@@ -242,7 +253,7 @@ namespace OpenRA.Editor
{
try
{
var template = RenderUtils.RenderResourceType(a, tileset.Extensions, palette);
var template = RenderUtils.RenderResourceType(a, tileset.Extensions, PlayerPalette);
var ibox = new PictureBox
{
Image = template.Bitmap,
@@ -317,7 +328,7 @@ namespace OpenRA.Editor
if ((int)rd.width.Value != surface1.Map.MapSize.X || (int)rd.height.Value != surface1.Map.MapSize.Y)
{
surface1.Map.Resize((int)rd.width.Value, (int)rd.height.Value);
surface1.Bind(surface1.Map, surface1.TileSet, surface1.Palette); // rebind it to invalidate all caches
surface1.Bind(surface1.Map, surface1.TileSet, surface1.Palette, surface1.PlayerPalette); // rebind it to invalidate all caches
}
surface1.Invalidate();
@@ -386,6 +397,7 @@ namespace OpenRA.Editor
map.ResizeCordon((int)nmd.cordonLeft.Value, (int)nmd.cordonTop.Value,
(int)nmd.cordonRight.Value, (int)nmd.cordonBottom.Value);
map.Players.Clear();
map.MakeDefaultPlayers();
NewMap(map);
@@ -515,6 +527,7 @@ namespace OpenRA.Editor
void SetupDefaultPlayers(object sender, EventArgs e)
{
dirty = true;
surface1.Map.Players.Clear();
surface1.Map.MakeDefaultPlayers();
surface1.Chunks.Clear();

View File

@@ -174,10 +174,10 @@ namespace OpenRA.Editor
// Add waypoint actors
foreach( var kv in wps )
{
var a = new ActorReference("mpspawn");
var a = new ActorReference("waypoint");
a.Add(new LocationInit((CPos)kv.Second));
a.Add(new OwnerInit("Neutral"));
Map.Actors.Value.Add("spawn" + kv.First, a);
Map.Actors.Value.Add("waypoint" + kv.First, a);
}
}
@@ -414,8 +414,51 @@ namespace OpenRA.Editor
void LoadPlayer(IniFile file, string section, bool isRA)
{
var c = section == "BadGuy" ? "red" :
isRA ? "blue" : "gold";
string c;
string race;
switch (section)
{
case "Spain":
c = "gold";
race = "allies";
break;
case "England":
c = "green";
race = "allies";
break;
case "Ukraine":
c = "orange";
race = "soviet";
break;
case "Germany":
c = "black";
race = "allies";
break;
case "France":
c = "teal";
race = "allies";
break;
case "Turkey":
c = "salmon";
race = "allies";
break;
case "Greece":
case "GoodGuy":
c = isRA? "blue" : "gold";
race = isRA ? "allies" : "gdi";
break;
case "USSR":
case "BadGuy":
c = "red";
race = isRA ? "soviet" : "nod";
break;
case "Special":
case "Neutral":
default:
c = "neutral";
race = isRA ? "allies" : "gdi";
break;
}
var color = namedColorMapping[c];
@@ -424,7 +467,7 @@ namespace OpenRA.Editor
Name = section,
OwnsWorld = section == "Neutral",
NonCombatant = section == "Neutral",
Race = isRA ? (section == "BadGuy" ? "soviet" : "allies") : (section == "BadGuy" ? "nod" : "gdi"),
Race = race,
ColorRamp = new ColorRamp(
(byte)((color.First.GetHue() / 360.0f) * 255),
(byte)(color.First.GetSaturation() * 255),

View File

@@ -20,11 +20,19 @@ namespace OpenRA.Editor
{
public string MapFolderPath;
public bool DirectoryIsEmpty(string path)
{
return !Directory.GetFileSystemEntries(path).Any();
}
public MapSelect(string currentMod)
{
MapFolderPath = new string[] { Environment.CurrentDirectory, "mods", currentMod, "maps" }
MapFolderPath = new string[] { Platform.SupportDir, "maps", currentMod }
.Aggregate(Path.Combine);
if (!Directory.Exists(MapFolderPath))
Directory.CreateDirectory(MapFolderPath);
InitializeComponent();
MapIconsList.Images.Add(pictureBox1.Image);
}
@@ -34,6 +42,9 @@ namespace OpenRA.Editor
MapList.Items.Clear();
txtPathOut.Text = MapFolderPath;
if (DirectoryIsEmpty(MapFolderPath))
return;
foreach (var map in ModData.FindMapsIn(MapFolderPath))
{
ListViewItem map1 = new ListViewItem();

View File

@@ -26,6 +26,7 @@ namespace OpenRA.Editor
public Map Map { get; private set; }
public TileSet TileSet { get; private set; }
public Palette Palette { get; private set; }
public Palette PlayerPalette { get; private set; }
public int2 Offset;
public int2 GetOffset() { return Offset; }
@@ -55,11 +56,12 @@ namespace OpenRA.Editor
public Keys GetModifiers() { return ModifierKeys; }
public void Bind(Map m, TileSet ts, Palette p)
public void Bind(Map m, TileSet ts, Palette p, Palette pp)
{
Map = m;
TileSet = ts;
Palette = p;
PlayerPalette = pp;
PlayerPalettes = null;
Chunks.Clear();
Tool = null;
@@ -306,7 +308,10 @@ namespace OpenRA.Editor
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);
var actorPalette = cp;
if (t.Appearance != null && t.Appearance.UseTerrainPalette)
actorPalette = Palette.AsSystemPalette();
DrawImage(g, t.Bitmap, p, centered, actorPalette);
}
float2 GetDrawPosition(CPos location, Bitmap bmp, bool centered)
@@ -348,7 +353,7 @@ namespace OpenRA.Editor
var pr = Map.Players[name];
var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>();
var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.ColorRamp);
return new Palette(Palette, remap).AsSystemPalette();
return new Palette(PlayerPalette, remap).AsSystemPalette();
}
Cache<string, ColorPalette> PlayerPalettes;

View File

@@ -23,6 +23,7 @@ namespace OpenRA.FileFormats
public string Bot = null;
public bool DefaultStartingUnits = false;
public bool AllowBots = true;
public bool Required = false;
public bool LockRace = false;
public string Race;

View File

@@ -78,10 +78,13 @@ namespace OpenRA.FileFormats
public string Name;
public string Id;
public string Palette;
public string PlayerPalette;
public int TileSize = 24;
public string[] Extensions;
public int WaterPaletteRotationBase = 0x60;
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
public string[] EditorTemplateOrder;
static readonly string[] fields = {"Name", "TileSize", "Id", "Palette", "Extensions"};

View File

@@ -200,8 +200,8 @@ namespace OpenRA.FileFormats
var ret = new List<MiniYamlNode>();
var aDict = a.ToDictionary( x => x.Key );
var bDict = b.ToDictionary( x => x.Key );
var aDict = a.ToDictionaryWithConflictLog(x => x.Key, "MiniYaml.Merge", null, x => "{0} (at {1})".F(x.Key, x.Location));
var bDict = b.ToDictionaryWithConflictLog(x => x.Key, "MiniYaml.Merge", null, x => "{0} (at {1})".F(x.Key, x.Location));
var keys = aDict.Keys.Union( bDict.Keys ).ToList();
var noInherit = keys.Where(x => x.Length > 0 && x[0] == '-')

View File

@@ -39,6 +39,12 @@ namespace OpenRA.FileFormats
get { return colors; }
}
public void ApplyRemap(IPaletteRemap r)
{
for(int i = 0; i < 256; i++)
colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)colors[i]),i).ToArgb();
}
public Palette(Stream s, int[] remapShadow)
{
colors = new uint[256];
@@ -61,9 +67,8 @@ namespace OpenRA.FileFormats
public Palette(Palette p, IPaletteRemap r)
{
colors = new uint[256];
for(int i = 0; i < 256; i++)
colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)p.colors[i]),i).ToArgb();
colors = (uint[])p.colors.Clone();
ApplyRemap(r);
}
public Palette(Palette p)
@@ -71,6 +76,13 @@ namespace OpenRA.FileFormats
colors = (uint[])p.colors.Clone();
}
public Palette(uint[] data)
{
if (data.Length != 256)
throw new InvalidDataException("Attempting to create palette with incorrect array size");
colors = (uint[])data.Clone();
}
public ColorPalette AsSystemPalette()
{
ColorPalette pal;
@@ -88,6 +100,21 @@ namespace OpenRA.FileFormats
return pal;
}
public Bitmap AsBitmap()
{
var b = new Bitmap(256, 1, PixelFormat.Format32bppArgb);
var data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
uint* c = (uint*)data.Scan0;
for (var x = 0; x < 256; x++)
*(c + x) = colors[x];
}
b.UnlockBits(data);
return b;
}
public static Palette Load(string filename, int[] remap)
{
using(var s = File.OpenRead(filename))

View File

@@ -101,4 +101,18 @@ namespace OpenRA
public float LengthSquared { get { return X * X + Y * Y; } }
public float Length { get { return (float)Math.Sqrt(LengthSquared); } }
}
public class EWMA
{
readonly float animRate;
float? value;
public EWMA(float animRate) { this.animRate = animRate; }
public float Update(float newValue)
{
value = float2.Lerp(value ?? newValue, newValue, animRate);
return value.Value;
}
}
}

View File

@@ -20,6 +20,7 @@ namespace OpenRA.Thirdparty
int index = 0;
public int Last;
public int TotalCount = 0;
public Random() : this(Environment.TickCount) { }
@@ -41,13 +42,14 @@ namespace OpenRA.Thirdparty
y ^= y >> 18;
index = (index + 1) % 624;
TotalCount++;
Last = (int)(y % int.MaxValue);
return Last;
}
public int Next(int low, int high) { return low + Next() % (high - low); }
public int Next(int high) { return Next() % high; }
public double NextDouble() { return Math.Abs(Next() / (double)0x7fffffff); }
public float NextFloat() { return Math.Abs(Next() / (float)0x7fffffff); }
void Generate()
{

View File

@@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA
@@ -43,6 +44,8 @@ namespace OpenRA
return HasLocation.PxPosition;
}
}
public Shroud.ActorVisibility Sight;
[Sync]
public Player Owner;
@@ -71,7 +74,7 @@ namespace OpenRA
AddTrait(trait.Create(init));
}
Move = Lazy.New( () => TraitOrDefault<IMove>() );
Move = Lazy.New(() => TraitOrDefault<IMove>());
Size = Lazy.New(() =>
{
@@ -79,17 +82,23 @@ namespace OpenRA
if (si != null && si.Bounds != null)
return new int2(si.Bounds[0], si.Bounds[1]);
// auto size from render
var firstSprite = TraitsImplementing<IRender>().SelectMany(ApplyIRender).FirstOrDefault();
if (firstSprite.Sprite == null) return int2.Zero;
return (firstSprite.Sprite.size * firstSprite.Scale).ToInt2();
return TraitsImplementing<IAutoSelectionSize>().Select(x => x.SelectionSize(this)).FirstOrDefault();
});
ApplyIRender = x => x.Render(this);
ApplyRenderModifier = (m, p) => p.ModifyRender(this, m);
if (this.HasTrait<RevealsShroud>())
{
Sight = new Shroud.ActorVisibility
{
range = this.Trait<RevealsShroud>().RevealRange,
vis = Shroud.GetVisOrigins(this).ToArray()
};
}
Bounds = Cached.New( () => CalculateBounds(false) );
ExtendedBounds = Cached.New( () => CalculateBounds(true) );
ApplyIRender = (x, wr) => x.Render(this, wr);
ApplyRenderModifier = (m, p, wr) => p.ModifyRender(this, wr, m);
Bounds = Cached.New(() => CalculateBounds(false));
ExtendedBounds = Cached.New(() => CalculateBounds(true));
}
public void Tick()
@@ -97,7 +106,12 @@ namespace OpenRA
Bounds.Invalidate();
ExtendedBounds.Invalidate();
currentActivity = Util.RunActivity( this, currentActivity );
currentActivity = Traits.Util.RunActivity( this, currentActivity );
}
public void UpdateSight()
{
Sight.vis = Shroud.GetVisOrigins(this).ToArray();
}
public bool IsIdle
@@ -108,13 +122,13 @@ namespace OpenRA
OpenRA.FileFormats.Lazy<int2> Size;
// note: these delegates are cached to avoid massive allocation.
Func<IRender, IEnumerable<Renderable>> ApplyIRender;
Func<IEnumerable<Renderable>, IRenderModifier, IEnumerable<Renderable>> ApplyRenderModifier;
public IEnumerable<Renderable> Render()
Func<IRender, WorldRenderer, IEnumerable<Renderable>> ApplyIRender;
Func<IEnumerable<Renderable>, IRenderModifier, WorldRenderer, IEnumerable<Renderable>> ApplyRenderModifier;
public IEnumerable<Renderable> Render(WorldRenderer wr)
{
var mods = TraitsImplementing<IRenderModifier>();
var sprites = TraitsImplementing<IRender>().SelectMany(ApplyIRender);
return mods.Aggregate(sprites, ApplyRenderModifier);
var sprites = TraitsImplementing<IRender>().SelectMany(x => ApplyIRender(x, wr));
return mods.Aggregate(sprites, (m,p) => ApplyRenderModifier(m,p,wr));
}
// When useAltitude = true, the bounding box is extended
@@ -129,22 +143,14 @@ namespace OpenRA
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 PVecInt(size.X, size.Y + move.Altitude);
}
@@ -240,10 +246,15 @@ namespace OpenRA
{
World.AddFrameEndTask(w =>
{
var oldOwner = Owner;
// momentarily remove from world so the ownership queries don't get confused
w.Remove(this);
Owner = newOwner;
w.Add(this);
foreach (var t in this.TraitsImplementing<INotifyOwnerChanged>())
t.OnOwnerChanged(this, oldOwner, newOwner);
});
}
}

View File

@@ -10,6 +10,7 @@
using System;
using System.Collections.Generic;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Effects
@@ -25,12 +26,12 @@ namespace OpenRA.Effects
this.delay = delay;
}
public void Tick( World world )
public void Tick(World world)
{
if (--delay <= 0)
world.AddFrameEndTask(w => { w.Remove(this); a(); });
}
public IEnumerable<Renderable> Render() { yield break; }
public IEnumerable<Renderable> Render(WorldRenderer wr) { yield break; }
}
}

View File

@@ -10,6 +10,7 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Effects
@@ -32,14 +33,14 @@ namespace OpenRA.Effects
world.AddFrameEndTask(w => w.Remove(this));
}
public IEnumerable<Renderable> Render()
public IEnumerable<Renderable> Render(WorldRenderer wr)
{
if (!target.IsInWorld)
yield break;
if (remainingTicks % 2 == 0)
foreach (var r in target.Render())
yield return r.WithPalette("highlight");
foreach (var r in target.Render(wr))
yield return r.WithPalette(wr.Palette("highlight"));
}
}
}

View File

@@ -9,13 +9,14 @@
#endregion
using System.Collections.Generic;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Effects
{
public interface IEffect
{
void Tick( World world );
IEnumerable<Renderable> Render();
void Tick(World world);
IEnumerable<Renderable> Render(WorldRenderer r);
}
}

View File

@@ -29,6 +29,8 @@ namespace OpenRA
{
public static int CellSize { get { return modData.Manifest.TileSize; } }
public static MouseButtonPreference mouseButtonPreference = new MouseButtonPreference();
public static ModData modData;
static WorldRenderer worldRenderer;
@@ -56,7 +58,7 @@ namespace OpenRA
static string ChooseReplayFilename()
{
return DateTime.UtcNow.ToString("OpenRA-yyyy-MM-ddTHHmmssZ.rep");
return DateTime.UtcNow.ToString("OpenRA-yyyy-MM-ddTHHmmssZ");
}
static void JoinInner(OrderManager om)
@@ -302,8 +304,40 @@ namespace OpenRA
JoinLocal();
viewport = new Viewport(new int2(Renderer.Resolution), Rectangle.Empty, Renderer);
modData.LoadScreen.StartGame();
Settings.Save();
if (Game.Settings.Server.Dedicated)
{
while (true)
{
Game.Settings.Server.Map = WidgetUtils.ChooseInitialMap(Game.Settings.Server.Map);
Game.Settings.Save();
Game.CreateServer(new ServerSettings(Game.Settings.Server));
while(true)
{
System.Threading.Thread.Sleep(100);
if((server.State == Server.ServerState.GameStarted)
&& (server.conns.Count<=1))
{
Console.WriteLine("No one is playing, shutting down...");
server.Shutdown();
break;
}
}
if (Game.Settings.Server.DedicatedLoop)
{
Console.WriteLine("Starting a new server instance...");
continue;
}
else
break;
}
System.Environment.Exit(0);
}
else
{
modData.LoadScreen.StartGame();
Settings.Save();
}
}
public static void LoadShellMap()

View File

@@ -70,6 +70,9 @@ namespace OpenRA
static ITraitInfo LoadTraitInfo(string traitName, MiniYaml my)
{
if (!string.IsNullOrEmpty(my.Value))
throw new YamlException("Junk value `{0}` on trait node {1}"
.F(my.Value, traitName));
var info = Game.CreateObject<ITraitInfo>(traitName + "Info");
FieldLoader.Load(info, my);
return info;

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2013 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,
@@ -34,6 +34,8 @@ namespace OpenRA.GameRules
public string Map = null;
public string[] Ban = null;
public int TimeOut = 0;
public bool Dedicated = false;
public bool DedicatedLoop = true;
public ServerSettings() { }
@@ -49,6 +51,8 @@ namespace OpenRA.GameRules
Map = other.Map;
Ban = other.Ban;
TimeOut = other.TimeOut;
Dedicated = other.Dedicated;
DedicatedLoop = other.DedicatedLoop;
}
}
@@ -108,12 +112,35 @@ namespace OpenRA.GameRules
public MouseScrollType MouseScroll = MouseScrollType.Standard;
public float ViewportEdgeScrollStep = 10f;
public bool UseClassicMouseStyle = false;
// Internal game settings
public int Timestep = 40;
public string ConnectTo = "";
}
public class KeySettings
{
public string PauseKey = "f3";
public string CycleBaseKey = "backspace";
public string ToLastEventKey = "space";
public string ToSelectionKey = "home";
public string SellKey = "v";
public string PowerDownKey = "b";
public string RepairKey = "n";
public string AttackMoveKey = "a";
public string StopKey = "s";
public string ScatterKey = "x";
public string StanceCycleKey = "z";
public string DeployKey = "f";
public string CycleTabsKey = "tab";
}
public class Settings
{
string SettingsFile;
@@ -124,6 +151,7 @@ namespace OpenRA.GameRules
public GraphicSettings Graphics = new GraphicSettings();
public ServerSettings Server = new ServerSettings();
public DebugSettings Debug = new DebugSettings();
public KeySettings Keys = new KeySettings();
public Dictionary<string, object> Sections;
@@ -138,6 +166,7 @@ namespace OpenRA.GameRules
{"Graphics", Graphics},
{"Server", Server},
{"Debug", Debug},
{"Keys", Keys},
};
// Override fieldloader to ignore invalid entries

View File

@@ -86,7 +86,7 @@ namespace OpenRA.GameRules
public class WeaponInfo
{
public readonly float Range = 0;
public readonly string Report = null;
public readonly string[] Report = null;
public readonly int ROF = 1;
public readonly int Burst = 1;
public readonly bool Charges = false;

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Graphics
this.DisableFunc = d;
}
public Renderable Image(Actor self, string pal)
public Renderable Image(Actor self, PaletteReference pal)
{
var p = self.CenterLocation;
var loc = p.ToFloat2() - 0.5f * Animation.Image.size

View File

@@ -19,6 +19,7 @@ namespace OpenRA.Graphics
{
public static class CursorProvider
{
public static Dictionary<string, Palette> Palettes { get; private set; }
static Dictionary<string, CursorSequence> cursors;
public static void Initialize(string[] sequenceFiles)
@@ -28,13 +29,14 @@ namespace OpenRA.Graphics
int[] ShadowIndex = { };
if (sequences.NodesDict.ContainsKey("ShadowIndex"))
{
Array.Resize(ref ShadowIndex, ShadowIndex.Length + 1);
ShadowIndex[ShadowIndex.Length - 1] = Convert.ToInt32(sequences.NodesDict["ShadowIndex"].Value);
}
{
Array.Resize(ref ShadowIndex, ShadowIndex.Length + 1);
ShadowIndex[ShadowIndex.Length - 1] = Convert.ToInt32(sequences.NodesDict["ShadowIndex"].Value);
}
Palettes = new Dictionary<string, Palette>();
foreach (var s in sequences.NodesDict["Palettes"].Nodes)
Game.modData.Palette.AddPalette(s.Key, new Palette(FileSystem.Open(s.Value.Value), ShadowIndex));
Palettes.Add(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

@@ -25,11 +25,13 @@ namespace OpenRA.Graphics
ITexture texture;
Dictionary<string, Palette> palettes;
Dictionary<string, int> indices;
Dictionary<string, bool> allowsMods;
public HardwarePalette()
{
palettes = new Dictionary<string, Palette>();
indices = new Dictionary<string, int>();
allowsMods = new Dictionary<string, bool>();
texture = Game.Renderer.Device.CreateTexture();
}
@@ -49,22 +51,24 @@ namespace OpenRA.Graphics
return ret;
}
public void AddPalette(string name, Palette p)
public void AddPalette(string name, Palette p, bool allowModifiers)
{
if (palettes.ContainsKey(name))
throw new InvalidOperationException("Palette {0} has already been defined".F(name));
palettes.Add(name, p);
indices.Add(name, allocated++);
allowsMods.Add(name, allowModifiers);
}
uint[,] data = new uint[MaxPalettes, 256];
public void Update(IEnumerable<IPaletteModifier> paletteMods)
{
var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value));
var modifiable = copy.Where(p => allowsMods[p.Key]).ToDictionary(p => p.Key, p => p.Value);
foreach (var mod in paletteMods)
mod.AdjustPalette(copy);
mod.AdjustPalette(modifiable);
foreach (var pal in copy)
{

View File

@@ -139,7 +139,7 @@ namespace OpenRA.Graphics
foreach (var t in world.ActorsWithTrait<IRadarSignature>())
{
if (!world.LocalShroud.IsVisible(t.Actor))
if (!world.RenderedShroud.IsVisible(t.Actor))
continue;
var color = t.Trait.RadarSignatureColor(t.Actor);
@@ -158,7 +158,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);
if (world.LocalShroud.Disabled)
if (world.RenderedShroud.Disabled)
return bitmap;
var bitmapData = bitmap.LockBits(bitmap.Bounds(),
@@ -176,9 +176,9 @@ namespace OpenRA.Graphics
{
var mapX = x + map.Bounds.Left;
var mapY = y + map.Bounds.Top;
if (!world.LocalShroud.IsExplored(mapX, mapY))
if (!world.RenderedShroud.IsExplored(mapX, mapY))
*(c + (y * bitmapData.Stride >> 2) + x) = shroud;
else if (!world.LocalShroud.IsVisible(mapX,mapY))
else if (!world.RenderedShroud.IsVisible(mapX,mapY))
*(c + (y * bitmapData.Stride >> 2) + x) = fog;
}
}

View File

@@ -50,20 +50,20 @@ namespace OpenRA.Graphics
TempBufferCount = Game.Settings.Graphics.NumTempBuffers;
SheetSize = Game.Settings.Graphics.SheetSize;
WorldSpriteShader = device.CreateShader("world-shp");
WorldLineShader = device.CreateShader("world-line");
LineShader = device.CreateShader("chrome-line");
RgbaSpriteShader = device.CreateShader("chrome-rgba");
SpriteShader = device.CreateShader("chrome-shp");
WorldSpriteShader = device.CreateShader("shp");
WorldLineShader = device.CreateShader("line");
LineShader = device.CreateShader("line");
RgbaSpriteShader = device.CreateShader("rgba");
SpriteShader = device.CreateShader("shp");
WorldSpriteRenderer = new SpriteRenderer( this, WorldSpriteShader );
WorldSpriteRenderer = new SpriteRenderer(this, WorldSpriteShader);
WorldLineRenderer = new LineRenderer(this, WorldLineShader);
LineRenderer = new LineRenderer(this, LineShader);
RgbaSpriteRenderer = new SpriteRenderer( this, RgbaSpriteShader );
SpriteRenderer = new SpriteRenderer( this, SpriteShader );
RgbaSpriteRenderer = new SpriteRenderer(this, RgbaSpriteShader);
SpriteRenderer = new SpriteRenderer(this, SpriteShader);
for( int i = 0 ; i < TempBufferCount ; i++ )
tempBuffers.Enqueue( device.CreateVertexBuffer( TempBufferSize ) );
for (int i = 0; i < TempBufferCount; i++)
tempBuffers.Enqueue(device.CreateVertexBuffer(TempBufferSize));
}
public void InitializeFonts(Manifest m)
@@ -80,22 +80,22 @@ namespace OpenRA.Graphics
float2 r2 = new float2(-1, 1);
var zr1 = zoom*r1;
SetShaderParams( WorldSpriteShader, zr1, r2, scroll );
SetShaderParams( WorldLineShader, zr1, r2, scroll );
SetShaderParams( LineShader, r1, r2, scroll );
SetShaderParams( RgbaSpriteShader, r1, r2, scroll );
SetShaderParams( SpriteShader, r1, r2, scroll );
SetShaderParams(WorldSpriteShader, zr1, r2, scroll);
SetShaderParams(WorldLineShader, zr1, r2, scroll);
SetShaderParams(LineShader, r1, r2, float2.Zero);
SetShaderParams(RgbaSpriteShader, r1, r2, float2.Zero);
SetShaderParams(SpriteShader, r1, r2, float2.Zero);
}
void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll )
void SetShaderParams(IShader s, float2 r1, float2 r2, float2 scroll)
{
s.SetValue( "Palette", PaletteTexture );
s.SetValue( "Scroll", (int) scroll.X, (int) scroll.Y );
s.SetValue( "r1", r1.X, r1.Y );
s.SetValue( "r2", r2.X, r2.Y );
s.SetValue("Palette", PaletteTexture);
s.SetValue("Scroll", (int)scroll.X, (int)scroll.Y);
s.SetValue("r1", r1.X, r1.Y);
s.SetValue("r2", r2.X, r2.Y);
}
public void EndFrame( IInputHandler inputHandler )
public void EndFrame(IInputHandler inputHandler)
{
Flush();
device.PumpInput(inputHandler);
@@ -129,14 +129,17 @@ namespace OpenRA.Graphics
// which makes the window non-interactive in Windowed/Pseudofullscreen mode.
static Screen FixOSX() { return Screen.PrimaryScreen; }
internal static void Initialize( WindowMode windowMode )
internal static void Initialize(WindowMode windowMode)
{
if (Platform.CurrentPlatform == PlatformType.OSX)
FixOSX();
var resolution = GetResolution( windowMode );
var rendererPath = Path.GetFullPath( "OpenRA.Renderer.{0}.dll".F(Game.Settings.Graphics.Renderer) );
device = CreateDevice( Assembly.LoadFile( rendererPath ), resolution.Width, resolution.Height, windowMode );
var resolution = GetResolution(windowMode);
string renderer = Game.Settings.Server.Dedicated ? "Null" : Game.Settings.Graphics.Renderer;
var rendererPath = Path.GetFullPath("OpenRA.Renderer.{0}.dll".F(renderer));
device = CreateDevice(Assembly.LoadFile(rendererPath), resolution.Width, resolution.Height, windowMode);
}
static Size GetResolution(WindowMode windowmode)
@@ -147,12 +150,12 @@ namespace OpenRA.Graphics
return new Size(size.X, size.Y);
}
static IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, WindowMode window )
static IGraphicsDevice CreateDevice(Assembly rendererDll, int width, int height, WindowMode window)
{
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
foreach (RendererAttribute r in rendererDll.GetCustomAttributes(typeof(RendererAttribute), false))
{
var factory = (IDeviceFactory) r.Type.GetConstructor( Type.EmptyTypes ).Invoke( null );
return factory.Create( new Size( width, height ), window );
var factory = (IDeviceFactory)r.Type.GetConstructor(Type.EmptyTypes).Invoke(null);
return factory.Create(new Size(width, height), window);
}
throw new InvalidOperationException("Renderer DLL is missing RendererAttribute to tell us what type to use!");
@@ -161,7 +164,7 @@ namespace OpenRA.Graphics
internal IVertexBuffer<Vertex> GetTempVertexBuffer()
{
var ret = tempBuffers.Dequeue();
tempBuffers.Enqueue( ret );
tempBuffers.Enqueue(ret);
return ret;
}
@@ -173,8 +176,8 @@ namespace OpenRA.Graphics
get { return currentBatchRenderer; }
set
{
if( currentBatchRenderer == value ) return;
if( currentBatchRenderer != null )
if (currentBatchRenderer == value) return;
if (currentBatchRenderer != null)
currentBatchRenderer.Flush();
currentBatchRenderer = value;
}
@@ -183,7 +186,7 @@ namespace OpenRA.Graphics
public void EnableScissor(int left, int top, int width, int height)
{
Flush();
Device.EnableScissor( left, top, width, height );
Device.EnableScissor(left, top, width, height);
}
public void DisableScissor()

View File

@@ -18,12 +18,13 @@ namespace OpenRA.Graphics
public class Sequence
{
readonly Sprite[] sprites;
readonly int start, length, facings, tick;
readonly int start, length, stride, facings, tick;
public readonly string Name;
public int Start { get { return start; } }
public int End { get { return start + length; } }
public int Length { get { return length; } }
public int Stride { get { return stride; } }
public int Facings { get { return facings; } }
public int Tick { get { return tick; } }
@@ -43,6 +44,10 @@ namespace OpenRA.Graphics
else
length = int.Parse(d["Length"].Value);
if (d.ContainsKey("Stride"))
stride = int.Parse(d["Stride"].Value);
else
stride = length;
if(d.ContainsKey("Facings"))
facings = int.Parse(d["Facings"].Value);
@@ -54,10 +59,15 @@ namespace OpenRA.Graphics
else
tick = 40;
if (start < 0 || start + facings * length > sprites.Length)
if (length > stride)
throw new InvalidOperationException(
"{0}: Sequence {1}.{2}: Length must be <= stride"
.F(info.Nodes[0].Location, unit, name));
if (start < 0 || start + facings * stride > sprites.Length)
throw new InvalidOperationException(
"{6}: Sequence {0}.{1} uses frames [{2}..{3}] of SHP `{4}`, but only 0..{5} actually exist"
.F(unit, name, start, start + facings * length - 1, srcOverride ?? unit, sprites.Length - 1,
.F(unit, name, start, start + facings * stride - 1, srcOverride ?? unit, sprites.Length - 1,
info.Nodes[0].Location));
}
@@ -69,7 +79,7 @@ namespace OpenRA.Graphics
public Sprite GetSprite(int frame, int facing)
{
var f = Traits.Util.QuantizeFacing( facing, facings );
return sprites[ (f * length) + ( frame % length ) + start ];
return sprites[ (f * stride) + ( frame % length ) + start ];
}
}
}

View File

@@ -15,21 +15,25 @@ namespace OpenRA.Graphics
{
public class ShroudRenderer
{
Traits.Shroud shroud;
World world;
Traits.Shroud shroud {
get {
return world.RenderedShroud;
}
}
Sprite[] shadowBits = Game.modData.SpriteLoader.LoadAllSprites("shadow");
Sprite[,] sprites, fogSprites;
bool dirty = true;
Map map;
public ShroudRenderer(World world)
{
this.shroud = world.LocalShroud;
this.world = world;
this.map = world.Map;
sprites = new Sprite[map.MapSize.X, map.MapSize.Y];
fogSprites = new Sprite[map.MapSize.X, map.MapSize.Y];
shroud.Dirty += () => dirty = true;
}
static readonly byte[][] SpecialShroudTiles =
@@ -101,11 +105,20 @@ namespace OpenRA.Graphics
return shadowBits[SpecialShroudTiles[u ^ uSides][v]];
}
internal void Draw( WorldRenderer wr )
bool initializePalettes = true;
PaletteReference fogPalette, shroudPalette;
internal void Draw(WorldRenderer wr)
{
if (dirty)
if (initializePalettes)
{
dirty = false;
fogPalette = wr.Palette("fog");
shroudPalette = wr.Palette("shroud");
initializePalettes = false;
}
if (shroud != null && shroud.dirty)
{
shroud.dirty = false;
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++)
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
sprites[i, j] = ChooseShroud(i, j);
@@ -116,14 +129,12 @@ namespace OpenRA.Graphics
}
var clipRect = Game.viewport.WorldBounds(wr.world);
DrawShroud( wr, clipRect, fogSprites, "fog" );
DrawShroud( wr, clipRect, sprites, "shroud" );
DrawShroud(wr, clipRect, fogSprites, fogPalette);
DrawShroud(wr, clipRect, sprites, shroudPalette);
}
void DrawShroud( WorldRenderer wr, Rectangle clip, Sprite[,] s, string pal )
void DrawShroud(WorldRenderer wr, Rectangle clip, Sprite[,] s, PaletteReference pal)
{
var shroudPalette = wr.GetPaletteIndex(pal);
for (var j = clip.Top; j < clip.Bottom; j++)
{
var starti = clip.Left;
@@ -138,14 +149,14 @@ namespace OpenRA.Graphics
{
s[starti, j].DrawAt(
Game.CellSize * new float2(starti, j),
shroudPalette,
pal.Index,
new float2(Game.CellSize * (i - starti), Game.CellSize));
starti = i + 1;
}
s[i, j].DrawAt(
Game.CellSize * new float2(i, j),
shroudPalette);
pal.Index);
starti = i + 1;
last = s[i, j];
}
@@ -153,7 +164,7 @@ namespace OpenRA.Graphics
if (starti < clip.Right)
s[starti, j].DrawAt(
Game.CellSize * new float2(starti, j),
shroudPalette,
pal.Index,
new float2(Game.CellSize * (clip.Right - starti), Game.CellSize));
}
}

View File

@@ -49,12 +49,12 @@ namespace OpenRA.Graphics
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette)
{
DrawSprite(s, location, wr.GetPaletteIndex(palette), s.size);
DrawSprite(s, location, wr.Palette(palette).Index, s.size);
}
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette, float2 size)
{
DrawSprite(s, location, wr.GetPaletteIndex(palette), size);
DrawSprite(s, location, wr.Palette(palette).Index, size);
}
public void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Graphics
int nv = 0;
var terrainPalette = Game.modData.Palette.GetPaletteIndex("terrain");
var terrainPalette = wr.Palette("terrain").Index;
for( int j = map.Bounds.Top; j < map.Bounds.Bottom; j++ )
for( int i = map.Bounds.Left; i < map.Bounds.Right; i++ )
@@ -72,9 +72,9 @@ namespace OpenRA.Graphics
if (firstRow < 0) firstRow = 0;
if (lastRow > map.Bounds.Height) lastRow = map.Bounds.Height;
if (world.LocalPlayer != null && !world.LocalShroud.Disabled && world.LocalShroud.Bounds.HasValue)
if (world.RenderedPlayer != null && !world.RenderedShroud.Disabled && world.RenderedShroud.Bounds.HasValue)
{
var r = world.LocalShroud.Bounds.Value;
var r = world.RenderedShroud.Bounds.Value;
if (firstRow < r.Top - map.Bounds.Top)
firstRow = r.Top - map.Bounds.Top;

View File

@@ -133,7 +133,7 @@ namespace OpenRA.Graphics
renderer.SpriteRenderer.DrawSprite(cursorSprite,
Viewport.LastMousePos - cursorSequence.Hotspot,
Game.modData.Palette.GetPaletteIndex(cursorSequence.Palette),
wr.Palette(cursorSequence.Palette).Index,
cursorSprite.size);
}
@@ -202,7 +202,7 @@ namespace OpenRA.Graphics
cachedScroll = scrollPosition;
}
var b = world.LocalShroud.Bounds;
var b = world.RenderedShroud.Bounds;
return (b.HasValue) ? Rectangle.Intersect(cachedRect, b.Value) : cachedRect;
}
}

View File

@@ -17,27 +17,56 @@ using OpenRA.Traits;
namespace OpenRA.Graphics
{
public class PaletteReference
{
public readonly string Name;
public readonly int Index;
public readonly Palette Palette;
public PaletteReference(string name, int index, Palette palette)
{
Name = name;
Index = index;
Palette = palette;
}
}
public class WorldRenderer
{
public readonly World world;
internal readonly TerrainRenderer terrainRenderer;
internal readonly ShroudRenderer shroudRenderer;
internal readonly HardwarePalette palette;
internal Cache<string, PaletteReference> palettes;
internal WorldRenderer(World world)
{
this.world = world;
this.palette = Game.modData.Palette;
foreach( var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>( world ) )
palette = new HardwarePalette();
foreach (var p in CursorProvider.Palettes)
palette.AddPalette(p.Key, p.Value, false);
palettes = new Cache<string, PaletteReference>(CreatePaletteReference);
foreach (var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>(world))
pal.Trait.InitPalette( this );
// Generate initial palette texture
palette.Update(new IPaletteModifier[] {});
terrainRenderer = new TerrainRenderer(world, this);
shroudRenderer = new ShroudRenderer(world);
}
public int GetPaletteIndex(string name) { return palette.GetPaletteIndex(name); }
public Palette GetPalette(string name) { return palette.GetPalette(name); }
public void AddPalette(string name, Palette pal) { palette.AddPalette(name, pal); }
PaletteReference CreatePaletteReference(string name)
{
var pal = palette.GetPalette(name);
if (pal == null)
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
}
public PaletteReference Palette(string name) { return palettes[name]; }
public void AddPalette(string name, Palette pal, bool allowModifiers) { palette.AddPalette(name, pal, allowModifiers); }
class SpriteComparer : IComparer<Renderable>
{
@@ -57,10 +86,10 @@ namespace OpenRA.Graphics
bounds.BottomRightAsCPos().ToPPos()
);
var renderables = actors.SelectMany(a => a.Render())
var renderables = actors.SelectMany(a => a.Render(this))
.OrderBy(r => r, comparer);
var effects = world.Effects.SelectMany(e => e.Render());
var effects = world.Effects.SelectMany(e => e.Render(this));
return renderables.Concat(effects);
}
@@ -77,8 +106,8 @@ namespace OpenRA.Graphics
terrainRenderer.Draw(this, Game.viewport);
foreach (var a in world.traitDict.ActorsWithTraitMultiple<IRenderAsTerrain>(world))
foreach (var r in a.Trait.RenderAsTerrain(a.Actor))
r.Sprite.DrawAt(r.Pos, this.GetPaletteIndex(r.Palette), r.Scale);
foreach (var r in a.Trait.RenderAsTerrain(this, a.Actor))
r.Sprite.DrawAt(r.Pos, r.Palette.Index, r.Scale);
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
@@ -91,7 +120,7 @@ namespace OpenRA.Graphics
world.OrderGenerator.RenderBeforeWorld(this, world);
foreach (var image in SpritesToRender())
image.Sprite.DrawAt(image.Pos, this.GetPaletteIndex(image.Palette), image.Scale);
image.Sprite.DrawAt(image.Pos, image.Palette.Index, image.Scale);
// added for contrails
foreach (var a in world.ActorsWithTrait<IPostRender>())

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2013 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,32 +15,53 @@ namespace OpenRA
public class NullInputHandler : IInputHandler
{
// ignore all input
public void ModifierKeys( Modifiers mods ) { }
public void OnKeyInput( KeyInput input ) { }
public void OnMouseInput( MouseInput input ) { }
public void ModifierKeys(Modifiers mods) { }
public void OnKeyInput(KeyInput input) { }
public void OnMouseInput(MouseInput input) { }
}
public class DefaultInputHandler : IInputHandler
{
readonly World world;
public DefaultInputHandler( World world )
public DefaultInputHandler(World world)
{
this.world = world;
}
public void ModifierKeys( Modifiers mods )
public void ModifierKeys(Modifiers mods)
{
Game.HandleModifierKeys( mods );
Game.HandleModifierKeys(mods);
}
public void OnKeyInput( KeyInput input )
public void OnKeyInput(KeyInput input)
{
Sync.CheckSyncUnchanged(world, () => Ui.HandleKeyPress(input));
}
public void OnMouseInput( MouseInput input )
public void OnMouseInput(MouseInput input)
{
Sync.CheckSyncUnchanged(world, () => Ui.HandleInput(input));
}
}
public class MouseButtonPreference
{
public MouseButton Action
{
get
{
return Game.Settings.Game.UseClassicMouseStyle ? MouseButton.Left : MouseButton.Right;
}
}
public MouseButton Cancel
{
get
{
return Game.Settings.Game.UseClassicMouseStyle ? MouseButton.Right : MouseButton.Left;
}
}
}
}

View File

@@ -37,6 +37,7 @@ namespace OpenRA
public string Description;
public string Author;
public string Tileset;
public string[] Difficulties;
[FieldLoader.Ignore] public Lazy<Dictionary<string, ActorReference>> Actors;
@@ -178,6 +179,7 @@ namespace OpenRA
"Description",
"Author",
"Tileset",
"Difficulties",
"MapSize",
"Bounds",
"UseAsShellmap",
@@ -383,22 +385,24 @@ namespace OpenRA
public void MakeDefaultPlayers()
{
Players.Clear();
var firstRace = OpenRA.Rules.Info["world"].Traits
.WithInterface<CountryInfo>().First(c => c.Selectable).Race;
Players.Add("Neutral", new PlayerReference
{
Name = "Neutral",
Race = firstRace,
OwnsWorld = true,
NonCombatant = true
});
if (!Players.ContainsKey("Neutral"))
Players.Add("Neutral", new PlayerReference
{
Name = "Neutral",
Race = firstRace,
OwnsWorld = true,
NonCombatant = true
});
var numSpawns = GetSpawnPoints().Length;
for (var index = 0; index < numSpawns; index++)
{
if (Players.ContainsKey("Multi{0}".F(index)))
continue;
var p = new PlayerReference
{
Name = "Multi{0}".F(index),

View File

@@ -28,7 +28,6 @@ namespace OpenRA
public ILoadScreen LoadScreen = null;
public SheetBuilder SheetBuilder;
public SpriteLoader SpriteLoader;
public HardwarePalette Palette { get; private set; }
public ModData( params string[] mods )
{
@@ -51,13 +50,11 @@ namespace OpenRA
AvailableMaps = FindMaps(Manifest.Mods);
Palette = new HardwarePalette();
ChromeMetrics.Initialize(Manifest.ChromeMetrics);
ChromeProvider.Initialize(Manifest.Chrome);
SheetBuilder = new SheetBuilder(TextureChannel.Red);
SpriteLoader = new SpriteLoader(new string[] { ".shp" }, SheetBuilder);
CursorProvider.Initialize(Manifest.Cursors);
Palette.Update(new IPaletteModifier[] { });
}
public Map PrepareMap(string uid)

View File

@@ -34,12 +34,23 @@ namespace OpenRA.Network
void StartSavingReplay(byte[] initialContent)
{
var filename = chooseFilename();
var replayPath = Path.Combine(Platform.SupportDir, "Replays");
var replaysDirectory = Path.Combine(Platform.SupportDir, "Replays");
if (!Directory.Exists(replayPath))
Directory.CreateDirectory(replayPath);
if (!Directory.Exists(replaysDirectory))
Directory.CreateDirectory(replaysDirectory);
var file = File.Create(Path.Combine(replayPath, filename));
string fullFilename;
var id = -1;
do
{
fullFilename = Path.Combine(replaysDirectory, id < 0
? "{0}.rep".F(filename)
: "{0}-{1}.rep".F(filename, id));
id++;
}
while (File.Exists(fullFilename));
var file = File.Create(fullFilename);
file.Write(initialContent);
this.writer = new BinaryWriter(file);
}

View File

@@ -42,7 +42,9 @@ namespace OpenRA.Network
public class Client
{
public int Index;
public ColorRamp ColorRamp;
public ColorRamp PreferredColorRamp; // Color that the client normally uses from settings.yaml.
public ColorRamp ColorRamp; // Actual color that the client is using.
// Usually the same as PreferredColorRamp but can be different on maps with locked colors.
public string Country;
public int SpawnPoint;
public string Name;
@@ -64,6 +66,7 @@ namespace OpenRA.Network
public bool LockColor;
public bool LockTeam;
public bool LockSpawn;
public bool Required;
}
public class Global
@@ -76,6 +79,9 @@ namespace OpenRA.Network
public int RandomSeed = 0;
public bool LockTeams = true; // don't allow team changes after game start.
public bool AllowCheats = false;
public bool Dedicated;
public string Difficulty;
public bool Crates = true;
}
public Session(string[] mods)

View File

@@ -36,6 +36,7 @@ namespace OpenRA.Network
{
report.Frame = orderManager.NetFrameNumber;
report.SyncedRandom = orderManager.world.SharedRandom.Last;
report.TotalCount = orderManager.world.SharedRandom.TotalCount;
report.Traits.Clear();
foreach (var a in orderManager.world.ActorsWithTrait<ISync>())
{
@@ -58,7 +59,7 @@ namespace OpenRA.Network
if (r.Frame == frame)
{
Log.Write("sync", "Sync for net frame {0} -------------", r.Frame);
Log.Write("sync", "SharedRandom: "+r.SyncedRandom);
Log.Write("sync", "SharedRandom: {0} (#{1})", r.SyncedRandom, r.TotalCount);
Log.Write("sync", "Synced Traits:");
foreach (var a in r.Traits)
Log.Write("sync", "\t {0} {1} {2} {3} ({4})".F(
@@ -77,6 +78,7 @@ namespace OpenRA.Network
{
public int Frame;
public int SyncedRandom;
public int TotalCount;
public List<TraitReport> Traits = new List<TraitReport>();
}

View File

@@ -111,7 +111,11 @@ namespace OpenRA.Network
case "HandshakeRequest":
{
var request = HandshakeRequest.Deserialize(order.TargetString);
var localMods = orderManager.LobbyInfo.GlobalSettings.Mods.Select(m => "{0}@{1}".F(m,Mod.AllMods[m].Version)).ToArray();
// Check if mods match
if (localMods.FirstOrDefault().ToString().Split('@')[0] != request.Mods.FirstOrDefault().ToString().Split('@')[0])
throw new InvalidOperationException("Server's mod ({0}) and yours ({1}) don't match".F(localMods.FirstOrDefault().ToString().Split('@')[0], request.Mods.FirstOrDefault().ToString().Split('@')[0]));
// Check that the map exists on the client
if (!Game.modData.AvailableMaps.ContainsKey(request.Map))
throw new InvalidOperationException("Missing map {0}".F(request.Map));
@@ -119,6 +123,7 @@ namespace OpenRA.Network
var info = new Session.Client()
{
Name = Game.Settings.Player.Name,
PreferredColorRamp = Game.Settings.Player.ColorRamp,
ColorRamp = Game.Settings.Player.ColorRamp,
Country = "random",
SpawnPoint = 0,
@@ -126,7 +131,6 @@ namespace OpenRA.Network
State = Session.ClientState.NotReady
};
var localMods = orderManager.LobbyInfo.GlobalSettings.Mods.Select(m => "{0}@{1}".F(m,Mod.AllMods[m].Version)).ToArray();
var response = new HandshakeResponse()
{
Client = info,
@@ -198,8 +202,7 @@ namespace OpenRA.Network
{
var oldStance = p.Stances[target];
p.Stances[target] = s;
if (target == w.LocalPlayer)
w.WorldActor.Trait<Shroud>().UpdatePlayerStance(w, p, oldStance, s);
target.Shroud.UpdatePlayerStance(w, p, oldStance, s);
foreach (var nsc in w.ActorsWithTrait<INotifyStanceChanged>())
nsc.Trait.StanceChanged(nsc.Actor, p, target, oldStance, s);

View File

@@ -194,7 +194,8 @@
<Compile Include="Widgets\DropDownButtonWidget.cs" />
<Compile Include="Widgets\GridLayout.cs" />
<Compile Include="Widgets\ImageWidget.cs" />
<Compile Include="Widgets\LabelWidget.cs" />
<Compile Include="Widgets\LabelWidget.cs" />
<Compile Include="Widgets\LineGraphWidget.cs" />
<Compile Include="Widgets\ListLayout.cs" />
<Compile Include="Widgets\MapPreviewWidget.cs" />
<Compile Include="Widgets\PasswordFieldWidget.cs" />

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2013 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,
@@ -17,7 +17,7 @@ namespace OpenRA.Orders
{
class UnitOrderGenerator : IOrderGenerator
{
public IEnumerable<Order> Order( World world, CPos xy, MouseInput mi )
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.HasTrait<ITargetable>())
@@ -41,9 +41,9 @@ namespace OpenRA.Orders
yield return CheckSameOrder(o.iot, o.trait.IssueOrder(o.self, o.iot, o.target, mi.Modifiers.HasModifier(Modifiers.Shift)));
}
public void Tick( World world ) { }
public void RenderBeforeWorld( WorldRenderer wr, World world ) { }
public void RenderAfterWorld( WorldRenderer wr, World world ) { }
public void Tick(World world) { }
public void RenderBeforeWorld(WorldRenderer wr, World world) { }
public void RenderAfterWorld(WorldRenderer wr, World world) { }
public string GetCursor(World world, CPos xy, MouseInput mi)
{
@@ -75,35 +75,35 @@ namespace OpenRA.Orders
if (self.Destroyed)
return null;
if( mi.Button == MouseButton.Right )
if (mi.Button == Game.mouseButtonPreference.Action)
{
foreach( var o in self.TraitsImplementing<IIssueOrder>()
.SelectMany( trait => trait.Orders
.Select( x => new { Trait = trait, Order = x } ) )
.OrderByDescending( x => x.Order.OrderPriority ) )
.SelectMany(trait => trait.Orders
.Select(x => new { Trait = trait, Order = x } ))
.OrderByDescending(x => x.Order.OrderPriority))
{
var actorsAt = self.World.ActorMap.GetUnitsAt( xy ).ToList();
var actorsAt = self.World.ActorMap.GetUnitsAt(xy).ToList();
var forceAttack = mi.Modifiers.HasModifier(Modifiers.Ctrl);
var forceQueue = mi.Modifiers.HasModifier(Modifiers.Shift);
string cursor = null;
if( underCursor != null )
if (underCursor != null)
if (o.Order.CanTargetActor(self, underCursor, forceAttack, forceQueue, ref cursor))
return new UnitOrderResult( self, o.Order, o.Trait, cursor, Target.FromActor( underCursor ) );
return new UnitOrderResult(self, o.Order, o.Trait, cursor, Target.FromActor(underCursor));
if (o.Order.CanTargetLocation(self, xy, actorsAt, forceAttack, forceQueue, ref cursor))
return new UnitOrderResult( self, o.Order, o.Trait, cursor, Target.FromCell( xy ) );
return new UnitOrderResult(self, o.Order, o.Trait, cursor, Target.FromCell(xy));
}
}
return null;
}
static Order CheckSameOrder( IOrderTargeter iot, Order order )
static Order CheckSameOrder(IOrderTargeter iot, Order order)
{
if( order == null && iot.OrderID != null )
Game.Debug( "BUG: in order targeter - decided on {0} but then didn't order", iot.OrderID );
else if( iot.OrderID != order.OrderString )
Game.Debug( "BUG: in order targeter - decided on {0} but ordered {1}", iot.OrderID, order.OrderString );
if (order == null && iot.OrderID != null)
Game.Debug("BUG: in order targeter - decided on {0} but then didn't order", iot.OrderID);
else if (iot.OrderID != order.OrderString)
Game.Debug("BUG: in order targeter - decided on {0} but ordered {1}", iot.OrderID, order.OrderString);
return order;
}
@@ -115,7 +115,7 @@ namespace OpenRA.Orders
public readonly string cursor;
public readonly Target target;
public UnitOrderResult( Actor self, IOrderTargeter iot, IIssueOrder trait, string cursor, Target target )
public UnitOrderResult(Actor self, IOrderTargeter iot, IIssueOrder trait, string cursor, Target target)
{
this.self = self;
this.iot = iot;

View File

@@ -36,7 +36,7 @@ namespace OpenRA
public readonly PlayerReference PlayerReference;
public bool IsBot;
public Shroud Shroud { get { return World.LocalShroud; } }
public Shroud Shroud;
public World World { get; private set; }
static CountryInfo ChooseCountry(World world, string name)
@@ -76,7 +76,8 @@ namespace OpenRA
Country = ChooseCountry(world, pr.Race);
}
PlayerActor = world.CreateActor("Player", new TypeDictionary { new OwnerInit(this) });
Shroud = PlayerActor.Trait<Shroud>();
Shroud.Owner = this;
// Enable the bot logic on the host
IsBot = botType != null;
if (IsBot && Game.IsHost)

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2013 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,
@@ -64,7 +64,7 @@ namespace OpenRA
Cache<int, List<Actor>> controlGroups = new Cache<int, List<Actor>>(_ => new List<Actor>());
public void DoControlGroup(World world, int group, Modifiers mods)
public void DoControlGroup(World world, int group, Modifiers mods, int MultiTapCount)
{
var addModifier = Platform.CurrentPlatform == PlatformType.OSX ? Modifiers.Meta : Modifiers.Ctrl;
if (mods.HasModifier(addModifier))
@@ -82,7 +82,7 @@ namespace OpenRA
return;
}
if (mods.HasModifier(Modifiers.Alt))
if (mods.HasModifier(Modifiers.Alt) || MultiTapCount >= 2)
{
Game.viewport.Center(controlGroups[group]);
return;

View File

@@ -26,6 +26,13 @@ using XTimer = System.Timers.Timer;
namespace OpenRA.Server
{
public enum ServerState : int
{
WaitingPlayers = 1,
GameStarted = 2,
ShuttingDown = 3
}
public class Server
{
// Valid player connections
@@ -40,7 +47,7 @@ namespace OpenRA.Server
TypeDictionary ServerTraits = new TypeDictionary();
public Session lobbyInfo;
public bool GameStarted = false;
public readonly IPAddress Ip;
public readonly int Port;
int randomSeed;
@@ -51,16 +58,31 @@ namespace OpenRA.Server
public Map Map;
XTimer gameTimeout;
volatile bool shutdown = false;
protected volatile ServerState pState = new ServerState();
public ServerState State
{
get { return pState; }
protected set { pState = value; }
}
public void Shutdown()
{
shutdown = true;
State = ServerState.ShuttingDown;
}
public void EndGame()
{
foreach (var t in ServerTraits.WithInterface<IEndGame>())
t.GameEnded(this);
if (Settings.AllowUPnP)
RemovePortforward();
}
public Server(IPEndPoint endpoint, string[] mods, ServerSettings settings, ModData modData)
{
Log.AddChannel("server", "server.log");
pState = ServerState.WaitingPlayers;
listener = new TcpListener(endpoint);
listener.Start();
var localEndpoint = (IPEndPoint)listener.LocalEndpoint;
@@ -118,6 +140,7 @@ namespace OpenRA.Server
lobbyInfo.GlobalSettings.Map = settings.Map;
lobbyInfo.GlobalSettings.ServerName = settings.Name;
lobbyInfo.GlobalSettings.Ban = settings.Ban;
lobbyInfo.GlobalSettings.Dedicated = settings.Dedicated;
foreach (var t in ServerTraits.WithInterface<INotifyServerStart>())
t.ServerStarted(this);
@@ -139,10 +162,9 @@ namespace OpenRA.Server
foreach( var c in preConns ) checkRead.Add( c.socket );
Socket.Select( checkRead, null, null, timeout );
if (shutdown)
if (State == ServerState.ShuttingDown)
{
if (Settings.AllowUPnP)
RemovePortforward();
EndGame();
break;
}
@@ -158,15 +180,13 @@ namespace OpenRA.Server
foreach (var t in ServerTraits.WithInterface<ITick>())
t.Tick(this);
if (shutdown)
if (State == ServerState.ShuttingDown)
{
if (Settings.AllowUPnP)
RemovePortforward();
EndGame();
break;
}
}
GameStarted = false;
foreach (var t in ServerTraits.WithInterface<INotifyServerShutdown>())
t.ServerShutdown(this);
@@ -244,7 +264,7 @@ namespace OpenRA.Server
{
try
{
if (GameStarted)
if (State == ServerState.GameStarted)
{
Log.Write("server", "Rejected connection from {0}; game is already started.",
newConn.socket.RemoteEndPoint);
@@ -263,7 +283,7 @@ namespace OpenRA.Server
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.",
@@ -273,6 +293,17 @@ namespace OpenRA.Server
DropClient(newConn);
return;
}
// Drop DEV_VERSION if it's a Dedicated
if ( lobbyInfo.GlobalSettings.Dedicated && mods.Any(m => m.Contains("{DEV_VERSION}")) )
{
Log.Write("server", "Rejected connection from {0}; DEV_VERSION is not allowed here.",
newConn.socket.RemoteEndPoint);
SendOrderTo(newConn, "ServerError", "DEV_VERSION is not allowed here");
DropClient(newConn);
return;
}
// Check if IP is banned
if (lobbyInfo.GlobalSettings.Ban != null)
@@ -302,9 +333,11 @@ namespace OpenRA.Server
lobbyInfo.Clients.Add(client);
//Assume that first validated client is server admin
if(lobbyInfo.Clients.Count==1)
if(lobbyInfo.Clients.Where(c1 => c1.Bot == null).Count()==1)
client.IsAdmin=true;
OpenRA.Network.Session.Client clientAdmin = lobbyInfo.Clients.Where(c1 => c1.IsAdmin).Single();
Log.Write("server", "Client {0}: Accepted connection from {1}",
newConn.PlayerIndex, newConn.socket.RemoteEndPoint);
@@ -314,6 +347,20 @@ namespace OpenRA.Server
SyncLobbyInfo();
SendChat(newConn, "has joined the game.");
if ( File.Exists("{0}motd_{1}.txt".F(Platform.SupportDir, lobbyInfo.GlobalSettings.Mods[0])) )
{
var motd = System.IO.File.ReadAllText("{0}motd_{1}.txt".F(Platform.SupportDir, lobbyInfo.GlobalSettings.Mods[0]));
SendChatTo(newConn, motd);
}
if ( lobbyInfo.GlobalSettings.Dedicated )
{
if (client.IsAdmin)
SendChatTo(newConn, " You are admin now!");
else
SendChatTo(newConn, " Current admin is {0}".F(clientAdmin.Name));
}
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.");
@@ -327,6 +374,8 @@ namespace OpenRA.Server
return;
if (pr.LockColor)
c.ColorRamp = pr.ColorRamp;
else
c.ColorRamp = c.PreferredColorRamp;
if (pr.LockRace)
c.Country = pr.Race;
if (pr.LockSpawn)
@@ -467,15 +516,29 @@ namespace OpenRA.Server
{
conns.Remove(toDrop);
SendChat(toDrop, "Connection Dropped");
if (GameStarted)
OpenRA.Network.Session.Client dropClient = lobbyInfo.Clients.Where(c1 => c1.Index == toDrop.PlayerIndex).Single();
if (State == ServerState.GameStarted)
SendDisconnected(toDrop); /* Report disconnection */
lobbyInfo.Clients.RemoveAll(c => c.Index == toDrop.PlayerIndex);
// reassign admin if necessary
if ( lobbyInfo.GlobalSettings.Dedicated && dropClient.IsAdmin && State == ServerState.WaitingPlayers)
{
if (lobbyInfo.Clients.Where(c1 => c1.Bot == null).Count() > 0)
{
// client was not alone on the server but he was admin: set admin to the last connected client
OpenRA.Network.Session.Client lastClient = lobbyInfo.Clients.Where(c1 => c1.Bot == null).Last();
lastClient.IsAdmin = true;
SendChat(toDrop, "Admin left! {0} is a new admin now!".F(lastClient.Name));
}
}
DispatchOrders( toDrop, toDrop.MostRecentFrame, new byte[] { 0xbf } );
if (conns.Count != 0)
if (conns.Count != 0 || lobbyInfo.GlobalSettings.Dedicated)
SyncLobbyInfo();
}
@@ -488,7 +551,7 @@ namespace OpenRA.Server
public void SyncLobbyInfo()
{
if (!GameStarted) /* don't do this while the game is running, it breaks things. */
if (State != ServerState.GameStarted) /* don't do this while the game is running, it breaks things. */
DispatchOrders(null, 0,
new ServerOrder("SyncInfo", lobbyInfo.Serialize()).Serialize());
@@ -498,8 +561,9 @@ namespace OpenRA.Server
public void StartGame()
{
GameStarted = true;
State = ServerState.GameStarted;
listener.Stop();
Console.WriteLine("Game started");
foreach( var c in conns )

View File

@@ -20,6 +20,7 @@ namespace OpenRA.Server
public interface INotifyServerShutdown { void ServerShutdown(Server server); }
public interface IStartGame { void GameStarted(Server server); }
public interface IClientJoined { void ClientJoined(Server server, Connection conn); }
public interface IEndGame { void GameEnded(Server server); }
public interface ITick
{
void Tick(Server server);
@@ -28,7 +29,7 @@ namespace OpenRA.Server
public abstract class ServerTrait {}
public class DebugServerTrait : ServerTrait, IInterpretCommand, IStartGame, INotifySyncLobbyInfo, INotifyServerStart, INotifyServerShutdown
public class DebugServerTrait : ServerTrait, IInterpretCommand, IStartGame, INotifySyncLobbyInfo, INotifyServerStart, INotifyServerShutdown, IEndGame
{
public bool InterpretCommand(Server server, Connection conn, Session.Client client, string cmd)
{
@@ -55,5 +56,10 @@ namespace OpenRA.Server
{
Console.WriteLine("ServerShutdown()");
}
public void GameEnded(Server server)
{
Console.WriteLine("GameEnded()");
}
}
}

View File

@@ -45,6 +45,7 @@ namespace OpenRA
static ISoundEngine CreateEngine(string engine)
{
engine = Game.Settings.Server.Dedicated?"Null":engine;
switch (engine)
{ /* todo: if someone cares about pluggable crap here, ship this out */
case "AL": return new OpenAlSoundEngine();
@@ -247,7 +248,7 @@ namespace OpenRA
}
// Returns true if played successfully
public static bool PlayPredefined(Player p, Actor voicedUnit, string type, string definition, string variant)
public static bool PlayPredefined(Player p, Actor voicedUnit, string type, string definition, string variant, bool attentuateVolume)
{
if (definition == null) return false;
@@ -281,10 +282,13 @@ namespace OpenRA
prefix = rules.Prefixes[variant][ID % rules.Prefixes[variant].Length];
}
if (p == null)
Play(prefix + clip + suffix);
else
PlayToPlayer(p, prefix + clip + suffix);
var name = prefix + clip + suffix;
if (!String.IsNullOrEmpty(name) && (p == null || p == p.World.LocalPlayer))
soundEngine.Play2D(sounds[name],
false, true, float2.Zero,
InternalSoundVolume, attentuateVolume);
return true;
}
@@ -297,9 +301,9 @@ namespace OpenRA
if (mi == null) return false;
if (mi.Voice == null) return false;
var type = mi.Voice.ToLowerInvariant();
var type = mi.Voice.ToLowerInvariant();
return PlayPredefined(null, voicedUnit, type, phrase, variant);
return PlayPredefined(null, voicedUnit, type, phrase, variant, true);
}
public static bool PlayNotification(Player player, string type, string notification, string variant)
@@ -307,7 +311,7 @@ namespace OpenRA
if (type == null) return false;
if (notification == null) return false;
return PlayPredefined(player, null, type.ToLowerInvariant(), notification, variant);
return PlayPredefined(player, null, type.ToLowerInvariant(), notification, variant, false);
}
}

View File

@@ -21,6 +21,8 @@ namespace OpenRA.Traits
public class CreatesShroud : ITick
{
CreatesShroudInfo Info;
CPos previousLocation;
Shroud.ActorVisibility v;
public CreatesShroud(CreatesShroudInfo info)
{
@@ -29,8 +31,34 @@ namespace OpenRA.Traits
public void Tick(Actor self)
{
if (!self.IsDisabled())
self.World.WorldActor.Trait<Shroud>().HideActor(self, Info.Range);
// todo: don't tick all the time.
if(self.Owner == null) return;
if (previousLocation != self.Location && v != null) {
previousLocation = self.Location;
var shrouds = self.World.ActorsWithTrait<Traits.Shroud>().Select(s => s.Actor.Owner.Shroud);
foreach (var shroud in shrouds) {
shroud.UnhideActor(self, v, Info.Range);
}
}
if (!self.TraitsImplementing<IDisable>().Any(d => d.Disabled)) {
var shrouds = self.World.ActorsWithTrait<Traits.Shroud>().Select(s => s.Actor.Owner.Shroud);
foreach (var shroud in shrouds) {
shroud.HideActor(self, Info.Range);
}
}
else {
var shrouds = self.World.ActorsWithTrait<Traits.Shroud>().Select(s => s.Actor.Owner.Shroud);
foreach (var shroud in shrouds) {
shroud.UnhideActor(self, v, Info.Range);
}
}
v = new Shroud.ActorVisibility {
vis = Shroud.GetVisOrigins(self).ToArray()
};
}
}
}

View File

@@ -13,6 +13,7 @@ namespace OpenRA.Traits
public class EditorAppearanceInfo : TraitInfo<EditorAppearance>
{
public readonly bool RelativeToTopLeft = false;
public readonly bool UseTerrainPalette = false;
}
public class EditorAppearance { }

View File

@@ -76,8 +76,7 @@ namespace OpenRA.Traits
case "DevShroud":
{
DisableShroud ^= true;
if (self.World.LocalPlayer == self.Owner)
self.World.LocalShroud.Disabled = DisableShroud;
self.Owner.Shroud.Disabled = DisableShroud;
break;
}
case "DevPathDebug":
@@ -87,8 +86,7 @@ namespace OpenRA.Traits
}
case "DevGiveExploration":
{
if (self.World.LocalPlayer == self.Owner)
self.World.WorldActor.Trait<Shroud>().ExploreAll(self.World);
self.Owner.Shroud.ExploreAll(self.World);
break;
}
case "DevUnlimitedPower":

View File

@@ -86,6 +86,9 @@ namespace OpenRA.Traits
public int DisplayCash;
public int DisplayOre;
public int Earned;
public int Spent;
public bool CanGiveOre(int amount)
{
return Ore + amount <= OreCapacity;
@@ -94,10 +97,13 @@ namespace OpenRA.Traits
public void GiveOre(int num)
{
Ore += num;
Earned += num;
if (Ore > OreCapacity)
{
nextSiloAdviceTime = 0;
Earned -= Ore - OreCapacity;
Ore = OreCapacity;
}
}
@@ -106,6 +112,7 @@ namespace OpenRA.Traits
{
if (Ore < num) return false;
Ore -= num;
Spent += num;
return true;
}
@@ -113,6 +120,7 @@ namespace OpenRA.Traits
public void GiveCash(int num)
{
Cash += num;
Earned += num;
}
public bool TakeCash(int num)
@@ -121,6 +129,7 @@ namespace OpenRA.Traits
// Spend ore before cash
Ore -= num;
Spent += num;
if (Ore < 0)
{
Cash += Ore;
@@ -184,7 +193,7 @@ namespace OpenRA.Traits
{
DisplayOre -= move;
playCashTickDown(self);
}
}
}

View File

@@ -10,6 +10,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA.Traits
@@ -23,16 +24,16 @@ namespace OpenRA.Traits
public virtual object Create(ActorInitializer init) { return new RenderSimple(init.self); }
public virtual IEnumerable<Renderable> RenderPreview(ActorInfo building, Player owner)
public virtual IEnumerable<Renderable> RenderPreview(ActorInfo building, PaletteReference pr)
{
var anim = new Animation(RenderSimple.GetImage(building), () => 0);
anim.PlayRepeating("idle");
yield return new Renderable(anim.Image, 0.5f * anim.Image.size * (1 - Scale),
Palette ?? (owner != null ? PlayerPalette + owner.InternalName : null), 0, Scale);
yield return new Renderable(anim.Image, 0.5f * anim.Image.size * (1 - Scale), pr, 0, Scale);
}
}
public class RenderSimple : IRender, ITick
public class RenderSimple : IRender, IAutoSelectionSize, ITick, INotifyOwnerChanged
{
public Dictionary<string, AnimationWithOffset> anims = new Dictionary<string, AnimationWithOffset>();
@@ -55,7 +56,6 @@ namespace OpenRA.Traits
return Info.Image ?? actor.Name;
}
string cachedImage = null;
public string GetImage(Actor self)
{
if (cachedImage != null)
@@ -65,6 +65,9 @@ namespace OpenRA.Traits
}
RenderSimpleInfo Info;
string cachedImage = null;
bool initializePalette = true;
protected PaletteReference palette;
public RenderSimple(Actor self, Func<int> baseFacing)
{
@@ -77,20 +80,40 @@ namespace OpenRA.Traits
anim.PlayRepeating("idle");
}
public string Palette(Player p) { return Info.Palette ?? Info.PlayerPalette + p.InternalName; }
public virtual IEnumerable<Renderable> Render(Actor self)
protected virtual string PaletteName(Actor self)
{
return Info.Palette ?? Info.PlayerPalette + self.Owner.InternalName;
}
protected void UpdatePalette() { initializePalette = true; }
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) { UpdatePalette(); }
public virtual IEnumerable<Renderable> Render(Actor self, WorldRenderer wr)
{
if (initializePalette)
{
palette = wr.Palette(PaletteName(self));
initializePalette = false;
}
foreach (var a in anims.Values)
if (a.DisableFunc == null || !a.DisableFunc())
{
Renderable ret = a.Image(self, Palette(self.Owner));
Renderable ret = a.Image(self, palette);
if (Info.Scale != 1f)
ret = ret.WithScale(Info.Scale).WithPos(ret.Pos + 0.5f * ret.Sprite.size * (1 - Info.Scale));
yield return ret;
}
}
public int2 SelectionSize(Actor self)
{
return anims.Values.Where(b => (b.DisableFunc == null || !b.DisableFunc())
&& b.Animation.CurrentSequence != null)
.Select(a => (a.Animation.Image.size*Info.Scale).ToInt2())
.FirstOrDefault();
}
public virtual void Tick(Actor self)
{
foreach (var a in anims.Values)

View File

@@ -10,13 +10,13 @@
namespace OpenRA.Traits
{
class RevealsShroudInfo : ITraitInfo
public class RevealsShroudInfo : ITraitInfo
{
public readonly int Range = 0;
public object Create(ActorInitializer init) { return new RevealsShroud(this); }
}
class RevealsShroud : ITick
public class RevealsShroud : ITick
{
RevealsShroudInfo Info;
CPos previousLocation;
@@ -29,11 +29,22 @@ namespace OpenRA.Traits
public void Tick(Actor self)
{
// todo: don't tick all the time.
World w = self.World;
if(self.Owner == null) return;
if (previousLocation != self.Location)
{
previousLocation = self.Location;
self.World.WorldActor.Trait<Shroud>().UpdateActor(self);
var actors = w.ActorsWithTrait<Shroud>();
foreach( var s in actors )
s.Actor.Owner.Shroud.RemoveActor(self);
self.UpdateSight();
foreach( var s in actors )
s.Actor.Owner.Shroud.AddActor(self);
}
}

View File

@@ -54,7 +54,7 @@ namespace OpenRA.Traits
void DrawPips(WorldRenderer wr, Actor self, float2 basePosition)
{
if (self.Owner != self.World.LocalPlayer) return;
if (self.Owner != self.World.RenderedPlayer) return;
var pipSources = self.TraitsImplementing<IPips>();
if (pipSources.Count() == 0)
@@ -95,7 +95,7 @@ namespace OpenRA.Traits
void DrawTags(WorldRenderer wr, Actor self, float2 basePosition)
{
if (self.Owner != self.World.LocalPlayer) return;
if (self.Owner != self.World.RenderedPlayer) return;
// If a mod wants to implement a unit with multiple tags, then they are placed on multiple rows
var tagxyBase = basePosition + new float2(-16, 2); // Correct for the offset in the shp file

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Traits
public static readonly Target None = new Target();
public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && actor.Owner == owner)); } }
public bool IsValid { get { return valid && (actor == null || (actor.IsInWorld && !actor.IsDead() && actor.Owner == owner)); } }
public PPos PxPosition { get { return IsActor ? actor.Trait<IHasLocation>().PxPosition : pos; } }
public PPos CenterLocation { get { return PxPosition; } }

View File

@@ -34,7 +34,8 @@ namespace OpenRA.Traits
}
public interface ITick { void Tick(Actor self); }
public interface IRender { IEnumerable<Renderable> Render(Actor self); }
public interface IRender { IEnumerable<Renderable> Render(Actor self, WorldRenderer wr); }
public interface IAutoSelectionSize { int2 SelectionSize(Actor self); }
public interface IIssueOrder
{
@@ -62,6 +63,7 @@ namespace OpenRA.Traits
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, CPos exit); }
public interface INotifyOwnerChanged { void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner); }
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); }
@@ -83,7 +85,7 @@ namespace OpenRA.Traits
Color RadarSignatureColor(Actor self);
}
public interface IVisibilityModifier { bool IsVisible(Actor self); }
public interface IVisibilityModifier { bool IsVisible(Shroud s, Actor self); }
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
public interface IHasLocation { PPos PxPosition { get; } }
@@ -113,7 +115,7 @@ namespace OpenRA.Traits
}
public interface INotifyAttack { void Attacking(Actor self, Target target); }
public interface IRenderModifier { IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r); }
public interface IRenderModifier { IEnumerable<Renderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<Renderable> r); }
public interface IDamageModifier { float GetDamageModifier(Actor attacker, WarheadInfo warhead); }
public interface ISpeedModifier { decimal GetSpeedModifier(); }
public interface IFirepowerModifier { float GetFirepowerModifier(); }
@@ -154,12 +156,12 @@ namespace OpenRA.Traits
{
public readonly Sprite Sprite;
public readonly float2 Pos;
public readonly string Palette;
public readonly PaletteReference Palette;
public readonly int Z;
public readonly int ZOffset;
public float Scale;
public Renderable(Sprite sprite, float2 pos, string palette, int z, int zOffset, float scale)
public Renderable(Sprite sprite, float2 pos, PaletteReference palette, int z, int zOffset, float scale)
{
Sprite = sprite;
Pos = pos;
@@ -169,14 +171,14 @@ namespace OpenRA.Traits
Scale = scale; /* default */
}
public Renderable(Sprite sprite, float2 pos, string palette, int z)
public Renderable(Sprite sprite, float2 pos, PaletteReference palette, int z)
: this(sprite, pos, palette, z, 0, 1f) { }
public Renderable(Sprite sprite, float2 pos, string palette, int z, float scale)
public Renderable(Sprite sprite, float2 pos, PaletteReference palette, int z, float scale)
: this(sprite, pos, palette, z, 0, scale) { }
public Renderable WithScale(float newScale) { return new Renderable(Sprite, Pos, Palette, Z, ZOffset, newScale); }
public Renderable WithPalette(string newPalette) { return new Renderable(Sprite, Pos, newPalette, Z, ZOffset, Scale); }
public Renderable WithPalette(PaletteReference newPalette) { return new Renderable(Sprite, Pos, newPalette, Z, ZOffset, Scale); }
public Renderable WithZOffset(int newOffset) { return new Renderable(Sprite, Pos, Palette, Z, newOffset, Scale); }
public Renderable WithPos(float2 newPos) { return new Renderable(Sprite, newPos, Palette, Z, ZOffset, Scale); }
}
@@ -208,7 +210,7 @@ namespace OpenRA.Traits
public interface IPostRenderSelection { void RenderAfterWorld(WorldRenderer wr); }
public interface IPreRenderSelection { void RenderBeforeWorld(WorldRenderer wr, Actor self); }
public interface IRenderAsTerrain { IEnumerable<Renderable> RenderAsTerrain(Actor self); }
public interface IRenderAsTerrain { IEnumerable<Renderable> RenderAsTerrain(WorldRenderer wr, Actor self); }
public interface ITargetable
{
@@ -226,7 +228,7 @@ 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)

View File

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

View File

@@ -33,21 +33,21 @@ namespace OpenRA.Traits
{
hasSetupPalettes = true;
foreach (var rt in world.WorldActor.TraitsImplementing<ResourceType>())
rt.info.PaletteIndex = wr.GetPaletteIndex(rt.info.Palette);
rt.info.PaletteRef = wr.Palette(rt.info.Palette);
}
var clip = Game.viewport.WorldBounds(world);
for (int x = clip.Left; x < clip.Right; x++)
for (int y = clip.Top; y < clip.Bottom; y++)
{
if (!world.LocalShroud.IsExplored(new CPos(x, y)))
if (!world.RenderedShroud.IsExplored(new CPos(x, y)))
continue;
var c = content[x, y];
if (c.image != null)
c.image[c.density].DrawAt(
new CPos(x, y).ToPPos().ToFloat2(),
c.type.info.PaletteIndex);
c.type.info.PaletteRef.Index);
}
}

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Traits
public readonly bool AllowUnderActors = false;
public Sprite[][] Sprites;
public int PaletteIndex;
public PaletteReference PaletteRef;
public PipType PipColor = PipType.Yellow;

View File

@@ -25,16 +25,24 @@ namespace OpenRA.Traits
Map map;
World world;
public Player Owner;
public int[,] visibleCells;
public bool[,] exploredCells;
Rectangle? exploredBounds;
public bool[,] foggedCells;
public Rectangle? exploredBounds;
bool disabled = false;
public bool dirty = true;
public bool Disabled
{
get { return disabled || world.LocalPlayer == null; }
get { return disabled; }
set { disabled = value; Dirty(); }
}
public bool Observing
{
get { return world.IsShellmap || (world.LocalPlayer == null && Owner == null);; }
}
public Rectangle? Bounds
{
get { return Disabled ? null : exploredBounds; }
@@ -42,20 +50,28 @@ namespace OpenRA.Traits
public event Action Dirty = () => { };
public void Jank()
{
Dirty();
}
public Shroud(World world)
{
this.world = world;
map = world.Map;
visibleCells = new int[map.MapSize.X, map.MapSize.Y];
exploredCells = new bool[map.MapSize.X, map.MapSize.Y];
foggedCells = new bool[map.MapSize.X, map.MapSize.Y];
world.ActorAdded += AddActor;
world.ActorRemoved += RemoveActor;
Dirty += () => dirty = true;
}
// 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 CPos[] vis; }
Dictionary<Actor, ActorVisibility> vis = new Dictionary<Actor, ActorVisibility>();
public class ActorVisibility { public int range; public CPos[] vis; }
public Dictionary<Actor, ActorVisibility> vis = new Dictionary<Actor, ActorVisibility>();
static IEnumerable<CPos> FindVisibleTiles(World world, CPos a, int r)
{
@@ -72,25 +88,13 @@ namespace OpenRA.Traits
yield return new CPos(i, j);
}
void AddActor(Actor a)
public void AddActor(Actor a)
{
if (!a.HasTrait<RevealsShroud>())
return;
if (!a.HasTrait<RevealsShroud>()) return;
if (a.Owner == null || Owner == null) return;
if(a.Owner.Stances[Owner] != Stance.Ally) return;
if (a.Owner.World.LocalPlayer == null
|| a.Owner.Stances[a.Owner.World.LocalPlayer] != Stance.Ally) return;
if (vis.ContainsKey(a))
{
Game.Debug("Warning: Actor {0}:{1} at {2} bad vis".F(a.Info.Name, a.ActorID, a.Location));
RemoveActor(a);
}
var v = new ActorVisibility
{
range = a.Trait<RevealsShroud>().RevealRange,
vis = GetVisOrigins(a).ToArray()
};
ActorVisibility v = a.Sight;
if (v.range == 0) return; // don't bother for things that can't see
@@ -100,14 +104,13 @@ namespace OpenRA.Traits
{
++visibleCells[q.X, q.Y];
exploredCells[q.X, q.Y] = true;
foggedCells[q.X, q.Y] = true;
}
var box = new Rectangle(p.X - v.range, p.Y - v.range, 2 * v.range + 1, 2 * v.range + 1);
exploredBounds = (exploredBounds.HasValue) ? Rectangle.Union(exploredBounds.Value, box) : box;
}
vis[a] = v;
if (!Disabled)
Dirty();
}
@@ -124,12 +127,39 @@ namespace OpenRA.Traits
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;
foggedCells[q.X, q.Y] = visibleCells[q.X, q.Y] > 0;
if (!Disabled)
Dirty();
}
public void UnhideActor(Actor a, ActorVisibility v, int range) {
if (a.Owner.World.LocalPlayer == null
|| a.Owner.Stances[a.Owner.World.LocalPlayer] == Stance.Ally) return;
if (v == null)
return;
foreach (var p in v.vis)
foreach (var q in FindVisibleTiles(a.World, p, range))
foggedCells[q.X, q.Y] = exploredCells[q.X, q.Y];
if (!Disabled)
Dirty();
}
public void MergeShroud(Shroud s) {
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++) {
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++) {
if (s.exploredCells[i,j] == true)
exploredCells[i, j] = true;
if (s.foggedCells[i,j] == true)
foggedCells[i, j] = true;
}
exploredBounds = Rectangle.Union(exploredBounds.Value, s.exploredBounds.Value);
}
}
public void UpdatePlayerStance(World w, Player player, Stance oldStance, Stance newStance)
{
if (oldStance == newStance)
@@ -138,7 +168,7 @@ namespace OpenRA.Traits
// No longer our ally; remove unit vis
if (oldStance == Stance.Ally)
{
var toRemove = vis.Select(a => a.Key).Where(a => a.Owner == player).ToList();
var toRemove = w.Actors.Where(a => a.Owner == player).ToList();
foreach (var a in toRemove)
RemoveActor(a);
}
@@ -148,6 +178,16 @@ namespace OpenRA.Traits
AddActor(a);
}
public int Explored()
{
int seen = 0;
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++)
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
if(foggedCells[i, j]) seen++;
return seen;
}
public static IEnumerable<CPos> GetVisOrigins(Actor a)
{
var ios = a.OccupiesSpace;
@@ -160,17 +200,26 @@ namespace OpenRA.Traits
return new[] { a.CenterLocation.ToCPos() };
}
void RemoveActor(Actor a)
public void RemoveActor(Actor a)
{
ActorVisibility v;
if (!vis.TryGetValue(a, out v)) return;
if (!a.HasTrait<RevealsShroud>())return;
if (a.Owner == null || Owner == null) return;
ActorVisibility v = a.Sight;
if(a.Owner.Stances[Owner] != Stance.Ally) {
if (a.HasTrait<CreatesShroud>()) {
foreach (var p in v.vis)
foreach (var q in FindVisibleTiles(a.World, p, v.range))
foggedCells[q.X, q.Y] = exploredCells[q.X, q.Y];
}
return;
}
foreach (var p in v.vis)
foreach (var q in FindVisibleTiles(a.World, p, v.range))
--visibleCells[q.X, q.Y];
vis.Remove(a);
if (!Disabled)
Dirty();
}
@@ -185,8 +234,10 @@ namespace OpenRA.Traits
public void Explore(World world, CPos center, int range)
{
foreach (var q in FindVisibleTiles(world, center, range))
foreach (var q in FindVisibleTiles(world, center, range)) {
exploredCells[q.X, q.Y] = true;
foggedCells[q.X, q.Y] = true;
}
var box = new Rectangle(center.X - range, center.Y - range, 2 * range + 1, 2 * range + 1);
exploredBounds = (exploredBounds.HasValue) ? Rectangle.Union(exploredBounds.Value, box) : box;
@@ -197,9 +248,12 @@ namespace OpenRA.Traits
public void ExploreAll(World world)
{
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++)
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++)
for (int i = map.Bounds.Left; i < map.Bounds.Right; i++) {
for (int j = map.Bounds.Top; j < map.Bounds.Bottom; j++) {
exploredCells[i, j] = true;
foggedCells[i, j] = true;
}
}
exploredBounds = world.Map.Bounds;
if (!Disabled)
@@ -212,6 +266,10 @@ namespace OpenRA.Traits
for (var i = 0; i <= exploredCells.GetUpperBound(0); i++)
exploredCells[i, j] = visibleCells[i, j] > 0;
for (var j = 0; j <= foggedCells.GetUpperBound(1); j++)
for (var i = 0; i <= foggedCells.GetUpperBound(0); i++)
foggedCells[i, j] = visibleCells[i, j] > 0;
if (!Disabled)
Dirty();
}
@@ -222,16 +280,16 @@ namespace OpenRA.Traits
if (!map.IsInMap(x, y))
return false;
if (Disabled)
if (Disabled || Observing)
return true;
return exploredCells[x,y];
return foggedCells[x,y];
}
public bool IsVisible(CPos xy) { return IsVisible(xy.X, xy.Y); }
public bool IsVisible(int x, int y)
{
if (Disabled)
if (Disabled || Observing)
return true;
// Visibility is allowed to extend beyond the map cordon so that
@@ -245,10 +303,20 @@ namespace OpenRA.Traits
// Actors are hidden under shroud, but not under fog by default
public bool IsVisible(Actor a)
{
if (a.TraitsImplementing<IVisibilityModifier>().Any(t => !t.IsVisible(a)))
// I need to pass in the current shroud, otherwise we're just checking that true==true
if (a.TraitsImplementing<IVisibilityModifier>().Any(t => !t.IsVisible(this, a)))
return false;
return Disabled || a.Owner == a.World.LocalPlayer || GetVisOrigins(a).Any(o => IsExplored(o));
if(Owner == null) return true;
return Disabled || Observing || a.Owner.Stances[Owner] == Stance.Ally || GetVisOrigins(a).Any(o => IsExplored(o));
}
public bool IsTargetable(Actor a) {
if (a.TraitsImplementing<IVisibilityModifier>().Any(t => !t.IsVisible(this, a)))
return false;
return GetVisOrigins(a).Any(o => IsVisible(o));
}
}
}

View File

@@ -23,8 +23,10 @@ namespace OpenRA.Widgets
public int VisualHeight = ChromeMetrics.Get<int>("ButtonDepth");
public string Font = ChromeMetrics.Get<string>("ButtonFont");
public bool Disabled = false;
public bool Highlighted = false;
public Func<string> GetText;
public Func<bool> IsDisabled;
public Func<bool> IsHighlighted;
public Action<MouseInput> OnMouseDown = _ => {};
public Action<MouseInput> OnMouseUp = _ => {};
@@ -39,6 +41,7 @@ namespace OpenRA.Widgets
OnMouseUp = _ => OnClick();
OnKeyPress = _ => OnClick();
IsDisabled = () => Disabled;
IsHighlighted = () => Highlighted;
}
protected ButtonWidget(ButtonWidget widget)
@@ -52,6 +55,8 @@ namespace OpenRA.Widgets
OnMouseDown = widget.OnMouseDown;
Disabled = widget.Disabled;
IsDisabled = widget.IsDisabled;
Highlighted = widget.Highlighted;
IsHighlighted = widget.IsHighlighted;
OnMouseUp = mi => OnClick();
OnKeyPress = _ => OnClick();
@@ -124,13 +129,14 @@ namespace OpenRA.Widgets
{
var rb = RenderBounds;
var disabled = IsDisabled();
var highlighted = IsHighlighted();
var font = Game.Renderer.Fonts[Font];
var text = GetText();
var s = font.Measure(text);
var stateOffset = (Depressed) ? new int2(VisualHeight, VisualHeight) : new int2(0, 0);
DrawBackground(rb, disabled, Depressed, Ui.MouseOverWidget == this);
DrawBackground(rb, disabled, Depressed, Ui.MouseOverWidget == this, highlighted);
font.DrawText(text, new int2(rb.X + (UsableWidth - s.X)/ 2, rb.Y + (Bounds.Height - s.Y) / 2) + stateOffset,
disabled ? Color.Gray : Color.White);
}
@@ -138,17 +144,19 @@ namespace OpenRA.Widgets
public override Widget Clone() { return new ButtonWidget(this); }
public virtual int UsableWidth { get { return Bounds.Width; } }
public virtual void DrawBackground(Rectangle rect, bool disabled, bool pressed, bool hover)
public virtual void DrawBackground(Rectangle rect, bool disabled, bool pressed, bool hover, bool highlighted)
{
ButtonWidget.DrawBackground("button", rect, disabled, pressed, hover);
ButtonWidget.DrawBackground("button", rect, disabled, pressed, hover, highlighted);
}
public static void DrawBackground(string baseName, Rectangle rect, bool disabled, bool pressed, bool hover)
public static void DrawBackground(string baseName, Rectangle rect, bool disabled, bool pressed, bool hover, bool highlighted)
{
var state = disabled ? "-disabled" :
pressed ? "-pressed" :
hover ? "-hover" :
"";
if (highlighted)
state += "-highlighted";
WidgetUtils.DrawPanel(baseName + state, rect);
}

View File

@@ -46,19 +46,26 @@ namespace OpenRA.Widgets
foreach (var line in recentLines.AsEnumerable().Reverse())
{
chatpos.Y -= 20;
var inset = 0;
string owner = null;
if (!string.IsNullOrEmpty(line.Owner))
{
var owner = line.Owner + ":";
owner = line.Owner + ":";
inset = font.Measure(owner).X + 10;
}
var text = WidgetUtils.WrapText(line.Text, chatLogArea.Width - inset, font);
var textLines = text.Split(new[] { '\n' }).Count();
chatpos.Y -= 20 * textLines;
if (owner != null)
{
font.DrawTextWithContrast(owner, chatpos,
line.Color, Color.Black, UseContrast ? 1 : 0);
}
font.DrawTextWithContrast(line.Text, chatpos + new int2(inset, 0),
font.DrawTextWithContrast(text, chatpos + new int2(inset, 0),
Color.White, Color.Black, UseContrast ? 1 : 0);
}

View File

@@ -45,11 +45,6 @@ namespace OpenRA.Widgets
public override Rectangle EventBounds { get { return Rectangle.Empty; } }
public override bool LoseFocus(MouseInput mi)
{
return composing ? false : base.LoseFocus(mi);
}
public override bool HandleKeyPress(KeyInput e)
{
if (e.Event == KeyInputEvent.Up) return false;

View File

@@ -0,0 +1,187 @@
#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.Drawing;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Widgets
{
public class LineGraphWidget : Widget
{
public Func<IEnumerable<LineGraphSeries>> GetSeries;
public Func<string> GetValueFormat;
public Func<string> GetXAxisValueFormat;
public Func<string> GetYAxisValueFormat;
public Func<int> GetXAxisSize;
public Func<int> GetYAxisSize;
public Func<string> GetXAxisLabel;
public Func<string> GetYAxisLabel;
public Func<bool> GetDisplayFirstYAxisValue;
public Func<string> GetLabelFont;
public Func<string> GetAxisFont;
public string ValueFormat = "{0}";
public string XAxisValueFormat = "{0}";
public string YAxisValueFormat = "{0}";
public int XAxisSize = 10;
public int YAxisSize = 10;
public string XAxisLabel = "";
public string YAxisLabel = "";
public bool DisplayFirstYAxisValue = false;
public string LabelFont;
public string AxisFont;
public LineGraphWidget()
: base()
{
GetValueFormat = () => ValueFormat;
GetXAxisValueFormat = () => XAxisValueFormat;
GetYAxisValueFormat = () => YAxisValueFormat;
GetXAxisSize = () => XAxisSize;
GetYAxisSize = () => YAxisSize;
GetXAxisLabel = () => XAxisLabel;
GetYAxisLabel = () => YAxisLabel;
GetDisplayFirstYAxisValue = () => DisplayFirstYAxisValue;
GetLabelFont = () => LabelFont;
GetAxisFont = () => AxisFont;
}
protected LineGraphWidget(LineGraphWidget other)
: base(other)
{
GetSeries = other.GetSeries;
GetValueFormat = other.GetValueFormat;
GetXAxisValueFormat = other.GetXAxisValueFormat;
GetYAxisValueFormat = other.GetYAxisValueFormat;
GetXAxisSize = other.GetXAxisSize;
GetYAxisSize = other.GetYAxisSize;
GetXAxisLabel = other.GetXAxisLabel;
GetYAxisLabel = other.GetYAxisLabel;
GetDisplayFirstYAxisValue = other.GetDisplayFirstYAxisValue;
GetLabelFont = other.GetLabelFont;
GetAxisFont = other.GetAxisFont;
ValueFormat = other.ValueFormat;
XAxisValueFormat = other.XAxisValueFormat;
YAxisValueFormat = other.YAxisValueFormat;
XAxisSize = other.XAxisSize;
YAxisSize = other.YAxisSize;
XAxisLabel = other.XAxisLabel;
YAxisLabel = other.YAxisLabel;
DisplayFirstYAxisValue = other.DisplayFirstYAxisValue;
LabelFont = other.LabelFont;
AxisFont = other.AxisFont;
}
public override void Draw()
{
if (GetSeries == null || !GetSeries().Any()
|| GetLabelFont == null || GetLabelFont() == null
|| GetAxisFont == null || GetAxisFont() == null)
{
return;
}
var rect = RenderBounds;
var origin = new float2(rect.Left, rect.Bottom);
var width = rect.Width;
var height = rect.Height;
var tiny = Game.Renderer.Fonts[GetLabelFont()];
var bold = Game.Renderer.Fonts[GetAxisFont()];
var xAxisSize = GetXAxisSize();
var yAxisSize = GetYAxisSize();
var maxValue = GetSeries().Select(p => p.Points).SelectMany(d => d).Concat(new[] { 0f }).Max();
var scale = 200 / Math.Max(5000, (float)Math.Ceiling(maxValue / 1000) * 1000);
var xStep = width / xAxisSize;
var yStep = height / yAxisSize;
var pointCount = GetSeries().First().Points.Count();
var pointStart = Math.Max(0, pointCount - xAxisSize);
var pointEnd = Math.Max(pointCount, xAxisSize);
var keyOffset = 0;
foreach (var series in GetSeries())
{
var key = series.Key;
var color = series.Color;
var points = series.Points;
if (points.Any())
{
points = points.Reverse().Take(xAxisSize).Reverse();
var scaledData = points.Select(d => d * scale);
var x = 0;
scaledData.Aggregate((a, b) =>
{
Game.Renderer.LineRenderer.DrawLine(
origin + new float2(x, -a),
origin + new float2(x + xStep, -b),
color, color);
x += xStep;
return b;
});
var value = points.Last();
if (value != 0)
{
tiny.DrawText(GetValueFormat().F(value), origin + new float2(x, -value * scale - 2), color);
}
}
tiny.DrawText(key, new float2(rect.Left, rect.Top) + new float2(5, 10 * keyOffset + 3), color);
keyOffset++;
}
//todo: make this stuff not draw outside of the RenderBounds
for (int n = pointStart, x = 0; n <= pointEnd; n++, x += xStep)
{
Game.Renderer.LineRenderer.DrawLine(origin + new float2(x, 0), origin + new float2(x, -5), Color.White, Color.White);
tiny.DrawText(GetXAxisValueFormat().F(n), origin + new float2(x, 2), Color.White);
}
bold.DrawText(GetXAxisLabel(), origin + new float2(width / 2, 20), Color.White);
for (var y = (GetDisplayFirstYAxisValue() ? 0 : yStep); y <= height; y += yStep)
{
var yValue = y / scale;
Game.Renderer.LineRenderer.DrawLine(origin + new float2(width - 5, -y), origin + new float2(width, -y), Color.White, Color.White);
tiny.DrawText(GetYAxisValueFormat().F(yValue), origin + new float2(width + 2, -y), Color.White);
}
bold.DrawText(GetYAxisLabel(), origin + new float2(width + 40, -(height / 2)), Color.White);
Game.Renderer.LineRenderer.DrawLine(origin, origin + new float2(width, 0), Color.White, Color.White);
Game.Renderer.LineRenderer.DrawLine(origin, origin + new float2(0, -height), Color.White, Color.White);
Game.Renderer.LineRenderer.DrawLine(origin + new float2(width, 0), origin + new float2(width, -height), Color.White, Color.White);
Game.Renderer.LineRenderer.DrawLine(origin + new float2(0, -height), origin + new float2(width, -height), Color.White, Color.White);
}
public override Widget Clone()
{
return new LineGraphWidget(this);
}
}
public class LineGraphSeries
{
public string Key;
public Color Color;
public IEnumerable<float> Points;
public LineGraphSeries(string key, Color color, IEnumerable<float> points)
{
Key = key;
Color = color;
Points = points;
}
}
}

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
@@ -21,10 +22,11 @@ namespace OpenRA.Widgets
public Func<Map> Map = () => null;
public Func<Dictionary<int2, Color>> SpawnColors = () => new Dictionary<int2, Color>();
public Action<MouseInput> OnMouseDown = _ => {};
public Action<int, int2> OnTooltip = (_, __) => { };
public bool IgnoreMouseInput = false;
public bool ShowSpawnPoints = true;
static Cache<Map,Bitmap> PreviewCache = new Cache<Map, Bitmap>(stub => Minimap.RenderMapPreview( new Map( stub.Path )));
static readonly Cache<Map,Bitmap> PreviewCache = new Cache<Map, Bitmap>(stub => Minimap.RenderMapPreview( new Map( stub.Path )));
public MapPreviewWidget() : base() { }
@@ -96,7 +98,8 @@ namespace OpenRA.Widgets
{
var colors = SpawnColors();
foreach (var p in map.GetSpawnPoints())
var spawnPoints = map.GetSpawnPoints().ToList();
foreach (var p in spawnPoints)
{
var owned = colors.ContainsKey(p);
var pos = ConvertToPreview(p);
@@ -107,8 +110,24 @@ namespace OpenRA.Widgets
WidgetUtils.FillRectWithColor(new Rectangle(pos.X + offset.X + 2, pos.Y + offset.Y + 2, 12, 12), colors[p]);
Game.Renderer.RgbaSpriteRenderer.DrawSprite(sprite, pos + offset);
if ((pos - Viewport.LastMousePos).LengthSquared < 64)
{
OnTooltip(spawnPoints.IndexOf(p) + 1, pos);
}
}
}
}
/// <summary>
/// Forces loading the preview into the map cache.
/// </summary>
public Bitmap LoadMapPreview()
{
var map = Map();
if( map == null ) return null;
return PreviewCache[map];
}
}
}

View File

@@ -79,11 +79,11 @@ namespace OpenRA.Widgets
var thumbHover = Ui.MouseOverWidget == this && thumbRect.Contains(Viewport.LastMousePos);
WidgetUtils.DrawPanel(Background, backgroundRect);
WidgetUtils.DrawPanel("scrollpanel-bg", scrollbarRect);
ButtonWidget.DrawBackground("button", upButtonRect, upDisabled, UpPressed, upHover);
ButtonWidget.DrawBackground("button", downButtonRect, downDisabled, DownPressed, downHover);
ButtonWidget.DrawBackground("button", upButtonRect, upDisabled, UpPressed, upHover, false);
ButtonWidget.DrawBackground("button", downButtonRect, downDisabled, DownPressed, downHover, false);
if (thumbHeight > 0)
ButtonWidget.DrawBackground("scrollthumb", thumbRect, false, Focused && thumbHover, thumbHover);
ButtonWidget.DrawBackground("scrollthumb", thumbRect, false, Focused && thumbHover, thumbHover, false);
var upOffset = !UpPressed || upDisabled ? 4 : 4 + ButtonDepth;
var downOffset = !DownPressed || downDisabled ? 4 : 4 + ButtonDepth;

View File

@@ -118,7 +118,7 @@ namespace OpenRA.Widgets
// Thumb
var thumbHover = Ui.MouseOverWidget == this && tr.Contains(Viewport.LastMousePos);
ButtonWidget.DrawBackground("scrollthumb", tr, IsDisabled(), isMoving, thumbHover);
ButtonWidget.DrawBackground("scrollthumb", tr, IsDisabled(), isMoving, thumbHover, false);
}
}
}

View File

@@ -34,6 +34,11 @@ namespace OpenRA.Widgets
Game.Renderer.SpriteRenderer.DrawSprite(s,pos, wr, "chrome");
}
public static void DrawSHP(Sprite s, float2 pos, WorldRenderer wr, float2 size)
{
Game.Renderer.SpriteRenderer.DrawSprite(s, pos, wr, "chrome", size);
}
public static void DrawPanel(string collection, Rectangle Bounds)
{
DrawPanelPartial(collection, Bounds, PanelSides.All);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2013 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,
@@ -52,33 +52,53 @@ namespace OpenRA.Widgets
public override bool HandleMouseInput(MouseInput mi)
{
var xy = Game.viewport.ViewToWorldPx(mi);
var UseClassicMouseStyle = Game.Settings.Game.UseClassicMouseStyle;
var HasBox = (SelectionBox != null) ? true : false;
var MultiClick = (mi.MultiTapCount >= 2) ? true : false;
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
{
if (!TakeFocus(mi))
return false;
dragStart = dragEnd = xy;
ApplyOrders(world, xy, mi);
}
//place buildings
if (!UseClassicMouseStyle || (UseClassicMouseStyle && !world.Selection.Actors.Any()) )
ApplyOrders(world, xy, mi);
}
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Move)
dragEnd = xy;
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up)
{
if (UseClassicMouseStyle && Focused)
{
//order units around
if (!HasBox && world.Selection.Actors.Any() && !MultiClick)
{
ApplyOrders(world, xy, mi);
LoseFocus(mi);
return true;
}
}
if (world.OrderGenerator is UnitOrderGenerator)
{
if (mi.MultiTapCount == 2)
if (MultiClick)
{
var unit = SelectActorsInBox(world, xy, xy, _ => true).FirstOrDefault();
var visibleWorld = Game.viewport.ViewBounds(world);
var topLeft = Game.viewport.ViewToWorldPx(new int2(visibleWorld.Left, visibleWorld.Top));
var bottomRight = Game.viewport.ViewToWorldPx(new int2(visibleWorld.Right, visibleWorld.Bottom));
var newSelection = SelectActorsInBox(world, topLeft, bottomRight,
a => unit != null && a.Info.Name == unit.Info.Name && a.Owner == unit.Owner);
world.Selection.Combine(world, newSelection, true, false);
var newSelection2= SelectActorsInBox(world, topLeft, bottomRight,
a => unit != null && a.Info.Name == unit.Info.Name && a.Owner == unit.Owner);
world.Selection.Combine(world, newSelection2, true, false);
}
else
{
@@ -86,21 +106,27 @@ namespace OpenRA.Widgets
world.Selection.Combine(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
}
}
dragStart = dragEnd = xy;
LoseFocus(mi);
}
if (mi.Button == MouseButton.None && mi.Event == MouseInputEvent.Move)
dragStart = dragEnd = xy;
if (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Down)
if (SelectionBox == null) /* don't issue orders while selecting */
ApplyOrders(world, xy, mi);
{
if (UseClassicMouseStyle)
world.Selection.Clear();
if (!HasBox) // don't issue orders while selecting
ApplyOrders(world, xy, mi);
}
return true;
}
public Pair<PPos, PPos>? SelectionBox
{
get
@@ -115,14 +141,14 @@ namespace OpenRA.Widgets
if (world.OrderGenerator == null) return;
var orders = world.OrderGenerator.Order(world, xy.ToCPos(), mi).ToArray();
orders.Do( o => world.IssueOrder( o ) );
orders.Do(o => world.IssueOrder(o));
world.PlayVoiceForOrders(orders);
}
public override string GetCursor(int2 pos)
{
return Sync.CheckSyncUnchanged( world, () =>
return Sync.CheckSyncUnchanged(world, () =>
{
if (SelectionBox != null)
return null; /* always show an arrow while selecting */
@@ -130,12 +156,12 @@ namespace OpenRA.Widgets
var mi = new MouseInput
{
Location = pos,
Button = MouseButton.Right,
Button = Game.mouseButtonPreference.Action,
Modifiers = Game.GetModifierKeys()
};
// TODO: fix this up.
return world.OrderGenerator.GetCursor( world, Game.viewport.ViewToWorld(mi), mi );
return world.OrderGenerator.GetCursor(world, Game.viewport.ViewToWorld(mi), mi);
} );
}
@@ -145,10 +171,10 @@ namespace OpenRA.Widgets
{
if (e.KeyName.Length == 1 && char.IsDigit(e.KeyName[0]))
{
world.Selection.DoControlGroup(world, e.KeyName[0] - '0', e.Modifiers);
world.Selection.DoControlGroup(world, e.KeyName[0] - '0', e.Modifiers, e.MultiTapCount);
return true;
}
else if(e.KeyName == "pause" || e.KeyName == "f3")
else if (e.KeyName == Game.Settings.Keys.PauseKey)
{
world.IssueOrder(Order.PauseRequest());
}
@@ -164,11 +190,11 @@ namespace OpenRA.Widgets
IEnumerable<Actor> SelectActorsInBox(World world, PPos a, PPos b, Func<Actor, bool> cond)
{
return world.FindUnits(a, b)
.Where( x => x.HasTrait<Selectable>() && world.LocalShroud.IsVisible(x) && cond(x) )
.Where(x => x.HasTrait<Selectable>() && world.RenderedShroud.IsVisible(x) && cond(x))
.GroupBy(x => x.GetSelectionPriority())
.OrderByDescending(g => g.Key)
.Select( g => g.AsEnumerable() )
.DefaultIfEmpty( NoActors )
.Select(g => g.AsEnumerable())
.DefaultIfEmpty(NoActors)
.FirstOrDefault();
}
}

View File

@@ -41,10 +41,29 @@ namespace OpenRA
public Player LocalPlayer { get; private set; }
public readonly Shroud LocalShroud;
public Player RenderedPlayer;
public Shroud RenderedShroud {
get {
if(RenderedPlayer == null)
{
return LocalShroud;
}else{
return RenderedPlayer.Shroud;
}
}
}
public void SetLocalPlayer(string pr)
{
if (!(orderManager.Connection is ReplayConnection))
LocalPlayer = Players.FirstOrDefault(p => p.InternalName == pr);
{
LocalPlayer = Players.FirstOrDefault(p => p.InternalName == pr);
RenderedPlayer = LocalPlayer;
}else{
}
}
public readonly Actor WorldActor;
@@ -138,6 +157,7 @@ namespace OpenRA
a.IsInWorld = false;
actors.Remove(a);
ActorRemoved(a);
}
public void Add(IEffect b) { effects.Add(b); }

View File

@@ -24,7 +24,7 @@ namespace OpenRA
public static IEnumerable<Actor> FindUnitsAtMouse(this World world, int2 mouseLocation)
{
var loc = Game.viewport.ViewToWorldPx(mouseLocation);
return FindUnits(world, loc, loc).Where(a => world.LocalShroud.IsVisible(a));
return FindUnits(world, loc, loc).Where(a => world.RenderedShroud.IsVisible(a));
}
public static IEnumerable<Actor> FindUnits(this World world, PPos a, PPos b)
@@ -58,14 +58,37 @@ namespace OpenRA
public static IEnumerable<CPos> FindTilesInCircle(this World world, CPos a, int r)
{
var min = world.ClampToWorld(a - new CVec(r, r));
var max = world.ClampToWorld(a + new CVec(r, r));
for (var j = min.Y; j <= max.Y; j++)
for (var i = min.X; i <= max.X; i++)
if (r * r >= (new CPos(i, j) - a).LengthSquared)
yield return new CPos(i, j);
if (r >= TilesByDistance.Length)
throw new InvalidOperationException("FindTilesInCircle supports queries for only <= {0}".F(MaxRange));
for(var i = 0; i <= r; i++)
{
foreach(var offset in TilesByDistance[i])
{
var t = offset + a;
if (world.Map.Bounds.Contains(t.X, t.Y))
yield return t;
}
}
}
static List<CVec>[] InitTilesByDistance(int max)
{
var ts = new List<CVec>[max+1];
for (var i = 0; i < max+1; i++)
ts[i] = new List<CVec>();
for (var j = -max; j <= max; j++)
for (var i = -max; i <= max; i++)
if (max * max >= i * i + j * j)
ts[(int)Math.Ceiling(Math.Sqrt(i*i + j*j))].Add(new CVec(i,j));
return ts;
}
const int MaxRange = 50;
static List<CVec>[] TilesByDistance = InitTilesByDistance(MaxRange);
public static string GetTerrainType(this World world, CPos cell)
{
var custom = world.Map.CustomTerrain[cell.X, cell.Y];
@@ -104,7 +127,7 @@ namespace OpenRA
public static float Gauss1D(this Thirdparty.Random r, int samples)
{
return Exts.MakeArray(samples, _ => (float)r.NextDouble() * 2 - 1f)
return Exts.MakeArray(samples, _ => r.NextFloat() * 2 - 1f)
.Sum() / samples;
}

View File

@@ -61,8 +61,6 @@ namespace OpenRA.Mods.Cnc
}
}
static Set<string> excludePalettes = new Set<string>("cursor", "chrome", "colorpicker", "shroud", "fog");
public void AdjustPalette(Dictionary<string,Palette> palettes)
{
if (to == EffectType.None && remainingFrames == 0)
@@ -70,9 +68,6 @@ namespace OpenRA.Mods.Cnc
foreach (var pal in palettes)
{
if (excludePalettes.Contains(pal.Key))
continue;
for (var x = 0; x < 256; x++)
{
var orig = pal.Value.GetColor(x);

View File

@@ -32,11 +32,11 @@ namespace OpenRA.Mods.Cnc.Effects
public void Tick(World world) { anim.Tick(); }
public IEnumerable<Renderable> Render()
public IEnumerable<Renderable> Render(WorldRenderer wr)
{
yield return new Renderable(anim.Image,
target.CenterLocation.ToFloat2() - new float2(.5f * anim.Image.size.X, anim.Image.size.Y - Game.CellSize),
"effect", (int)target.CenterLocation.Y);
wr.Palette("effect"), (int)target.CenterLocation.Y);
}
void Finish( World world )

View File

@@ -107,15 +107,14 @@
<Compile Include="Widgets\Logic\SimpleTooltipLogic.cs" />
<Compile Include="Widgets\Logic\SupportPowerTooltipLogic.cs" />
<Compile Include="Widgets\Logic\WorldTooltipLogic.cs" />
<Compile Include="Widgets\PowerBarWidget.cs" />
<Compile Include="Widgets\ProductionPaletteWidget.cs" />
<Compile Include="Widgets\ProductionTabsWidget.cs" />
<Compile Include="Widgets\SiloBarWidget.cs" />
<Compile Include="Widgets\SupportPowersWidget.cs" />
<Compile Include="Widgets\ToggleButtonWidget.cs" />
<Compile Include="Widgets\TooltipContainerWidget.cs" />
<Compile Include="WithFire.cs" />
<Compile Include="WithRoof.cs" />
<Compile Include="Widgets\ResourceBarWidget.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">

View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.RA;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Mods.Cnc
@@ -39,7 +40,7 @@ namespace OpenRA.Mods.Cnc
Info = info;
}
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
public IEnumerable<Renderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<Renderable> r)
{
foreach (var c in cargo.Passengers)
{
@@ -55,7 +56,7 @@ namespace OpenRA.Mods.Cnc
Info.PassengerTypes.Contains(p.Trait<Passenger>().info.CargoType))
: cargo.Passengers;
return r.Concat(visiblePassengers.SelectMany(a => a.Render())
return r.Concat(visiblePassengers.SelectMany(a => a.Render(wr))
.Select(a => a.WithPos(a.Pos - new float2(0, Info.RelativeAltitude))
.WithZOffset(a.ZOffset + Info.RelativeAltitude)));
}

View File

@@ -11,6 +11,7 @@
using System;
using System.Drawing;
using OpenRA.Mods.RA.Orders;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
using OpenRA.Widgets;
@@ -114,6 +115,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
BindOrderButton<SellOrderGenerator>(world, sidebarRoot, "SELL_BUTTON", "sell");
BindOrderButton<RepairOrderGenerator>(world, sidebarRoot, "REPAIR_BUTTON", "repair");
var powerManager = world.LocalPlayer.PlayerActor.Trait<PowerManager>();
var playerResources = world.LocalPlayer.PlayerActor.Trait<PlayerResources>();
sidebarRoot.Get<LabelWidget>("CASH").GetText = () =>
"${0}".F(playerResources.DisplayCash + playerResources.DisplayOre);
@@ -152,6 +154,30 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
InitObserverWidgets(world, playerRoot);
});
};
var siloBar = playerWidgets.Get<ResourceBarWidget>("SILOBAR");
siloBar.GetProvided = () => playerResources.OreCapacity;
siloBar.GetUsed = () => playerResources.Ore;
siloBar.TooltipFormat = "Silo Usage: {0}/{1}";
siloBar.RightIndicator = true;
siloBar.GetBarColor = () =>
{
if (playerResources.Ore == playerResources.OreCapacity) return Color.Red;
if (playerResources.Ore >= 0.8 * playerResources.OreCapacity) return Color.Orange;
return Color.LimeGreen;
};
var powerBar = playerWidgets.Get<ResourceBarWidget>("POWERBAR");
powerBar.GetProvided = () => powerManager.PowerProvided;
powerBar.GetUsed = () => powerManager.PowerDrained;
powerBar.TooltipFormat = "Power Usage: {0}/{1}";
powerBar.RightIndicator = false;
powerBar.GetBarColor = () =>
{
if (powerManager.PowerState == PowerState.Critical) return Color.Red;
if (powerManager.PowerState == PowerState.Low) return Color.Orange;
return Color.LimeGreen;
};
}
static void BindOrderButton<T>(World world, Widget parent, string button, string icon)

View File

@@ -10,6 +10,7 @@
using System;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
using OpenRA.Widgets;
@@ -20,7 +21,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
Widget menu;
[ObjectCreator.UseCtor]
public CncIngameMenuLogic(Widget widget, World world, Action onExit)
public CncIngameMenuLogic(Widget widget, World world, Action onExit, WorldRenderer worldRenderer)
{
var resumeDisabled = false;
menu = widget.Get("INGAME_MENU");
@@ -72,6 +73,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs()
{
{ "world", world },
{ "worldRenderer", worldRenderer },
{ "onExit", () => hideButtons = false },
});
};

View File

@@ -85,9 +85,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
settingsMenu.Get<ButtonWidget>("SETTINGS_BUTTON").OnClick = () =>
{
Menu = MenuType.None;
Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs()
Game.OpenWindow("SETTINGS_PANEL", new WidgetArgs()
{
{ "world", world },
{ "onExit", () => Menu = MenuType.Settings },
});
};

View File

@@ -1,11 +1,12 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2013 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;
@@ -17,6 +18,7 @@ using OpenRA.GameRules;
using OpenRA.Mods.RA;
using OpenRA.Mods.RA.Widgets.Logic;
using OpenRA.Widgets;
using OpenRA.Mods.RA.Widgets;
namespace OpenRA.Mods.Cnc.Widgets.Logic
{
@@ -25,7 +27,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
enum PanelType { General, Input }
PanelType Settings = PanelType.General;
ColorPickerPaletteModifier playerPalettePreview;
ColorPreviewManagerWidget colorPreview;
World world;
[ObjectCreator.UseCtor]
@@ -52,8 +54,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
var nameTextfield = generalPane.Get<TextFieldWidget>("NAME_TEXTFIELD");
nameTextfield.Text = playerSettings.Name;
playerPalettePreview = world.WorldActor.Trait<ColorPickerPaletteModifier>();
playerPalettePreview.Ramp = playerSettings.ColorRamp;
colorPreview = panel.Get<ColorPreviewManagerWidget>("COLOR_MANAGER");
colorPreview.Ramp = playerSettings.ColorRamp;
var colorDropdown = generalPane.Get<DropDownButtonWidget>("COLOR");
colorDropdown.OnMouseDown = _ => ShowColorPicker(colorDropdown, playerSettings);
@@ -118,7 +120,9 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
inputButton.OnClick = () => Settings = PanelType.Input;
inputButton.IsDisabled = () => Settings == PanelType.Input;
inputPane.Get<CheckboxWidget>("CLASSICORDERS_CHECKBOX").IsDisabled = () => true;
var classicMouseCheckbox = inputPane.Get<CheckboxWidget>("CLASSICORDERS_CHECKBOX");
classicMouseCheckbox.IsChecked = () => gameSettings.UseClassicMouseStyle;
classicMouseCheckbox.OnClick = () => gameSettings.UseClassicMouseStyle ^= true;
var scrollSlider = inputPane.Get<SliderWidget>("SCROLLSPEED_SLIDER");
scrollSlider.Value = gameSettings.ViewportEdgeScrollStep;
@@ -151,8 +155,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
bool ShowColorPicker(DropDownButtonWidget color, PlayerSettings s)
{
Action<ColorRamp> onSelect = c => { s.ColorRamp = c; color.RemovePanel(); };
Action<ColorRamp> onChange = c => { playerPalettePreview.Ramp = c; };
Action<ColorRamp> onSelect = c => {s.ColorRamp = c; color.RemovePanel();};
Action<ColorRamp> onChange = c => {colorPreview.Ramp = c;};
var colorChooser = Game.LoadWidget(world, "COLOR_CHOOSER", null, new WidgetArgs()
{

View File

@@ -90,16 +90,6 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
static string ActorName( string a )
{
// hack hack hack - going to die soon anyway
if (a == "barracks")
return "Infantry Production";
if (a == "vehicleproduction")
return "Vehicle Production";
if (a == "techcenter")
return "Tech Center";
if (a == "anypower")
return "Power Plant";
ActorInfo ai;
Rules.Info.TryGetValue(a.ToLowerInvariant(), out ai);
if (ai != null && ai.Traits.Contains<TooltipInfo>())

View File

@@ -1,85 +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.Drawing;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Widgets;
namespace OpenRA.Mods.Cnc.Widgets
{
public class PowerBarWidget : Widget
{
public readonly string TooltipTemplate = "SIMPLE_TOOLTIP";
public readonly string TooltipContainer;
Lazy<TooltipContainerWidget> tooltipContainer;
float? lastProvidedFrac;
float? lastDrainedFrac;
readonly PowerManager pm;
[ObjectCreator.UseCtor]
public PowerBarWidget(World world)
{
pm = world.LocalPlayer.PlayerActor.Trait<PowerManager>();
tooltipContainer = Lazy.New(() =>
Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
}
public override void MouseEntered()
{
if (TooltipContainer == null) return;
Func<string> getText = () => "Power Usage: {0}/{1}".F(pm.PowerDrained, pm.PowerProvided);
tooltipContainer.Value.SetTooltip(TooltipTemplate, new WidgetArgs() {{ "getText", getText }});
}
public override void MouseExited()
{
if (TooltipContainer == null) return;
tooltipContainer.Value.RemoveTooltip();
}
public override void Draw()
{
float powerScaleBy = 100;
var maxPower = Math.Max(pm.PowerProvided, pm.PowerDrained);
while (maxPower >= powerScaleBy) powerScaleBy *= 2;
// Current power supply
var providedFrac = pm.PowerProvided / powerScaleBy;
lastProvidedFrac = providedFrac = float2.Lerp(lastProvidedFrac.GetValueOrDefault(providedFrac), providedFrac, .3f);
var color = Color.LimeGreen;
if (pm.PowerState == PowerState.Low)
color = Color.Orange;
if (pm.PowerState == PowerState.Critical)
color = Color.Red;
var b = RenderBounds;
var rect = new RectangleF(b.X,
b.Y + (1-providedFrac)*b.Height,
(float)b.Width,
providedFrac*b.Height);
Game.Renderer.LineRenderer.FillRect(rect, color);
var indicator = ChromeProvider.GetImage("sidebar-bits", "left-indicator");
var drainedFrac = pm.PowerDrained / powerScaleBy;
lastDrainedFrac = drainedFrac = float2.Lerp(lastDrainedFrac.GetValueOrDefault(drainedFrac), drainedFrac, .3f);
float2 pos = new float2(b.X + b.Width - indicator.size.X,
b.Y + (1-drainedFrac)*b.Height - indicator.size.Y / 2);
Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, pos);
}
}
}

View File

@@ -36,6 +36,9 @@ namespace OpenRA.Mods.Cnc.Widgets
public readonly string TooltipContainer;
public readonly string TooltipTemplate = "PRODUCTION_TOOLTIP";
public readonly string ReadyText = "";
public readonly string HoldText = "";
public string TooltipActor { get; private set; }
public readonly World world;
@@ -54,8 +57,8 @@ namespace OpenRA.Mods.Cnc.Widgets
Animation cantBuild, clock;
Rectangle eventBounds = Rectangle.Empty;
readonly WorldRenderer worldRenderer;
readonly SpriteFont overlayFont;
readonly float2 holdOffset, readyOffset, timeOffset, queuedOffset;
SpriteFont overlayFont;
float2 holdOffset, readyOffset, timeOffset, queuedOffset;
[ObjectCreator.UseCtor]
public ProductionPaletteWidget(World world, WorldRenderer worldRenderer)
@@ -75,12 +78,6 @@ namespace OpenRA.Mods.Cnc.Widgets
u => u.Name,
u => Game.modData.SpriteLoader.LoadAllSprites(
u.Traits.Get<TooltipInfo>().Icon ?? (u.Name + "icon"))[0]);
overlayFont = Game.Renderer.Fonts["TinyBold"];
holdOffset = new float2(32,24) - overlayFont.Measure("On Hold") / 2;
readyOffset = new float2(32,24) - overlayFont.Measure("Ready") / 2;
timeOffset = new float2(32,24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
queuedOffset = new float2(4,2);
}
public override void Tick()
@@ -210,10 +207,15 @@ namespace OpenRA.Mods.Cnc.Widgets
public override void Draw()
{
overlayFont = Game.Renderer.Fonts["TinyBold"];
timeOffset = new float2(32,24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
queuedOffset = new float2(4,2);
holdOffset = new float2(32,24) - overlayFont.Measure(HoldText) / 2;
readyOffset = new float2(32,24) - overlayFont.Measure(ReadyText) / 2;
if (CurrentQueue == null)
return;
var isBuildingSomething = CurrentQueue.CurrentItem() != null;
var buildableItems = CurrentQueue.BuildableItems().OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder);
// Background
@@ -235,7 +237,7 @@ namespace OpenRA.Mods.Cnc.Widgets
clock.Tick();
WidgetUtils.DrawSHP(clock.Image, icon.Pos, worldRenderer);
}
else if (isBuildingSomething || !buildableItems.Any(a => a.Name == icon.Name))
else if (!buildableItems.Any(a => a.Name == icon.Name))
WidgetUtils.DrawSHP(cantBuild.Image, icon.Pos, worldRenderer);
}
@@ -248,11 +250,11 @@ namespace OpenRA.Mods.Cnc.Widgets
var first = icon.Queued[0];
var waiting = first != CurrentQueue.CurrentItem() && !first.Done;
if (first.Done)
overlayFont.DrawTextWithContrast("Ready",
overlayFont.DrawTextWithContrast(ReadyText,
icon.Pos + readyOffset,
Color.White, Color.Black, 1);
else if (first.Paused)
overlayFont.DrawTextWithContrast("On Hold",
overlayFont.DrawTextWithContrast(HoldText,
icon.Pos + holdOffset,
Color.White, Color.Black, 1);
else if (!waiting)

View File

@@ -138,8 +138,8 @@ namespace OpenRA.Mods.Cnc.Widgets
var rightHover = Ui.MouseOverWidget == this && rightButtonRect.Contains(Viewport.LastMousePos);
WidgetUtils.DrawPanel("panel-black", rb);
ButtonWidget.DrawBackground("button", leftButtonRect, leftDisabled, leftPressed, leftHover);
ButtonWidget.DrawBackground("button", rightButtonRect, rightDisabled, rightPressed, rightHover);
ButtonWidget.DrawBackground("button", leftButtonRect, leftDisabled, leftPressed, leftHover, false);
ButtonWidget.DrawBackground("button", rightButtonRect, rightDisabled, rightPressed, rightHover, false);
WidgetUtils.DrawRGBA(ChromeProvider.GetImage("scrollbar", leftPressed || leftDisabled ? "left_pressed" : "left_arrow"),
new float2(leftButtonRect.Left + 2, leftButtonRect.Top + 2));
@@ -157,7 +157,7 @@ namespace OpenRA.Mods.Cnc.Widgets
var rect = new Rectangle(origin.X + ContentWidth, origin.Y, TabWidth, rb.Height);
var hover = !leftHover && !rightHover && Ui.MouseOverWidget == this && rect.Contains(Viewport.LastMousePos);
var baseName = tab.Queue == CurrentQueue ? "button-toggled" : "button";
ButtonWidget.DrawBackground(baseName, rect, false, false, hover);
ButtonWidget.DrawBackground(baseName, rect, false, false, hover, false);
ContentWidth += TabWidth - 1;
int2 textSize = font.Measure(tab.Name);
@@ -266,7 +266,7 @@ namespace OpenRA.Mods.Cnc.Widgets
public override bool HandleKeyPress(KeyInput e)
{
if (e.Event != KeyInputEvent.Down) return false;
if (e.KeyName == "tab")
if (e.KeyName == Game.Settings.Keys.CycleTabsKey)
{
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
SelectNextTab(e.Modifiers.HasModifier(Modifiers.Shift));

View File

@@ -17,22 +17,25 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Cnc.Widgets
{
public class SiloBarWidget : Widget
public class ResourceBarWidget : Widget
{
public readonly string TooltipTemplate = "SIMPLE_TOOLTIP";
public readonly string TooltipContainer;
Lazy<TooltipContainerWidget> tooltipContainer;
public float LowStorageThreshold = 0.8f;
float? lastCapacityFrac;
float? lastStoredFrac;
EWMA providedLerp = new EWMA(0.3f);
EWMA usedLerp = new EWMA(0.3f);
readonly PlayerResources pr;
public Func<float> GetProvided = () => 0;
public Func<float> GetUsed = () => 0;
public string TooltipFormat = "";
public bool RightIndicator = false;
public Func<Color> GetBarColor = () => Color.White;
[ObjectCreator.UseCtor]
public SiloBarWidget(World world)
public ResourceBarWidget(World world)
{
pr = world.LocalPlayer.PlayerActor.Trait<PlayerResources>();
tooltipContainer = Lazy.New(() =>
Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
}
@@ -40,7 +43,7 @@ namespace OpenRA.Mods.Cnc.Widgets
public override void MouseEntered()
{
if (TooltipContainer == null) return;
Func<string> getText = () => "Silo Usage: {0}/{1}".F(pr.Ore, pr.OreCapacity);
Func<string> getText = () => TooltipFormat.F(GetUsed(), GetProvided());
tooltipContainer.Value.SetTooltip(TooltipTemplate, new WidgetArgs() {{ "getText", getText }});
}
@@ -52,36 +55,30 @@ namespace OpenRA.Mods.Cnc.Widgets
public override void Draw()
{
float scaleBy = 100;
var max = Math.Max(pr.OreCapacity, pr.Ore);
var scaleBy = 100.0f;
var provided = GetProvided();
var used = GetUsed();
var max = Math.Max(provided, used);
while (max >= scaleBy) scaleBy *= 2;
// Current capacity
var capacityFrac = pr.OreCapacity / scaleBy;
lastCapacityFrac = capacityFrac = float2.Lerp(lastCapacityFrac.GetValueOrDefault(capacityFrac), capacityFrac, .3f);
var providedFrac = providedLerp.Update(provided/scaleBy);
var usedFrac = usedLerp.Update(used/scaleBy);
var color = GetBarColor();
var b = RenderBounds;
var rect = new RectangleF(b.X, float2.Lerp( b.Bottom, b.Top, capacityFrac ),
(float)b.Width, capacityFrac*b.Height);
var rect = new RectangleF(b.X, float2.Lerp( b.Bottom, b.Top, providedFrac ),
b.Width, providedFrac*b.Height);
Game.Renderer.LineRenderer.FillRect(rect, color);
var indicator = ChromeProvider.GetImage("sidebar-bits", "right-indicator");
var indicator = ChromeProvider.GetImage("sidebar-bits",
RightIndicator ? "right-indicator" : "left-indicator");
var storedFrac = pr.Ore / scaleBy;
lastStoredFrac = storedFrac = float2.Lerp(lastStoredFrac.GetValueOrDefault(storedFrac), storedFrac, .3f);
var indicatorX = RightIndicator ? (b.Right - indicator.size.X) : b.Left;
float2 pos = new float2(b.X, float2.Lerp( b.Bottom, b.Top, storedFrac ) - indicator.size.Y / 2);
var pos = new float2(indicatorX, float2.Lerp( b.Bottom, b.Top, usedFrac ) - indicator.size.Y / 2);
Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, pos);
}
Color GetBarColor()
{
if (pr.Ore == pr.OreCapacity) return Color.Red;
if (pr.Ore >= LowStorageThreshold * pr.OreCapacity) return Color.Orange;
return Color.LimeGreen;
}
}
}

View File

@@ -23,6 +23,9 @@ namespace OpenRA.Mods.Cnc.Widgets
{
public int Spacing = 10;
public readonly string ReadyText = "";
public readonly string HoldText = "";
Dictionary<string, Sprite> iconSprites;
Animation clock;
Dictionary<Rectangle, SupportPowerIcon> Icons = new Dictionary<Rectangle, SupportPowerIcon>();
@@ -36,8 +39,8 @@ namespace OpenRA.Mods.Cnc.Widgets
public override Rectangle EventBounds { get { return eventBounds; } }
readonly WorldRenderer worldRenderer;
readonly SupportPowerManager spm;
readonly SpriteFont overlayFont;
readonly float2 holdOffset, readyOffset, timeOffset;
SpriteFont overlayFont;
float2 holdOffset, readyOffset, timeOffset;
[ObjectCreator.UseCtor]
public SupportPowersWidget(World world, WorldRenderer worldRenderer)
@@ -54,11 +57,6 @@ namespace OpenRA.Mods.Cnc.Widgets
u => Game.modData.SpriteLoader.LoadAllSprites(u)[0]);
clock = new Animation("clock");
overlayFont = Game.Renderer.Fonts["TinyBold"];
holdOffset = new float2(32,24) - overlayFont.Measure("On Hold") / 2;
readyOffset = new float2(32,24) - overlayFont.Measure("Ready") / 2;
timeOffset = new float2(32,24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
}
public class SupportPowerIcon
@@ -94,6 +92,11 @@ namespace OpenRA.Mods.Cnc.Widgets
public override void Draw()
{
overlayFont = Game.Renderer.Fonts["TinyBold"];
holdOffset = new float2(32,24) - overlayFont.Measure(HoldText) / 2;
readyOffset = new float2(32,24) - overlayFont.Measure(ReadyText) / 2;
timeOffset = new float2(32,24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
// Background
foreach (var rect in Icons.Keys)
WidgetUtils.DrawPanel("panel-black", rect.InflateBy(1,1,1,1));
@@ -115,11 +118,11 @@ namespace OpenRA.Mods.Cnc.Widgets
foreach (var p in Icons.Values)
{
if (p.Power.Ready)
overlayFont.DrawTextWithContrast("Ready",
overlayFont.DrawTextWithContrast(ReadyText,
p.Pos + readyOffset,
Color.White, Color.Black, 1);
else if (!p.Power.Active)
overlayFont.DrawTextWithContrast("On Hold",
overlayFont.DrawTextWithContrast(HoldText,
p.Pos + holdOffset,
Color.White, Color.Black, 1);
else

View File

@@ -53,10 +53,10 @@ namespace OpenRA.Mods.Cnc.Widgets
tooltipContainer.Value.RemoveTooltip();
}
public override void DrawBackground(Rectangle rect, bool disabled, bool pressed, bool hover)
public override void DrawBackground(Rectangle rect, bool disabled, bool pressed, bool hover, bool highlighted)
{
var baseName = IsToggled() ? "button-toggled" : "button";
ButtonWidget.DrawBackground(baseName, rect, disabled, pressed, hover);
ButtonWidget.DrawBackground(baseName, rect, disabled, pressed, hover, highlighted);
}
}
}
}

View File

@@ -165,13 +165,12 @@ namespace OpenRA.Mods.RA.AI
{
var bi = Rules.Info[actorType].Traits.Get<BuildingInfo>();
for (var k = 0; k < MaxBaseDistance; k++)
foreach (var t in world.FindTilesInCircle(baseCenter, k))
if (world.CanPlaceBuilding(actorType, bi, t, null))
if (bi.IsCloseEnoughToBase(world, p, actorType, t))
if (NoBuildingsUnder(Util.ExpandFootprint(
FootprintUtils.Tiles(actorType, bi, t), false)))
return t;
foreach (var t in world.FindTilesInCircle(baseCenter, MaxBaseDistance))
if (world.CanPlaceBuilding(actorType, bi, t, null))
if (bi.IsCloseEnoughToBase(world, p, actorType, t))
if (NoBuildingsUnder(Util.ExpandFootprint(
FootprintUtils.Tiles(actorType, bi, t), false)))
return t;
return null; // i don't know where to put it.
}
@@ -224,7 +223,7 @@ namespace OpenRA.Mods.RA.AI
/* pick something worth attacking owned by that player */
var targets = world.Actors
.Where(a => a.Owner == enemy && a.HasTrait<IOccupySpace>());
.Where(a => a.Owner == enemy && a.HasTrait<IOccupySpace>() && !a.HasTrait<Husk>());
Actor target = null;
if (targets.Any())
@@ -270,8 +269,8 @@ namespace OpenRA.Mods.RA.AI
{
Activity act = a.GetCurrentActivity();
// A Wait activity is technically idle:
if ((act.GetType() != typeof(OpenRA.Mods.RA.Activities.Wait)) &&
(act.NextActivity == null || act.NextActivity.GetType() != typeof(OpenRA.Mods.RA.Activities.FindResources)))
if (!(act is Activities.Wait) &&
(act.NextActivity == null || !(act.NextActivity is Activities.FindResources)))
continue;
}
if (!harv.IsEmpty) continue;
@@ -282,7 +281,7 @@ namespace OpenRA.Mods.RA.AI
var newUnits = self.World.ActorsWithTrait<IMove>()
.Where(a => a.Actor.Owner == p && !a.Actor.HasTrait<BaseBuilding>()
&& !activeUnits.Contains(a.Actor))
&& !activeUnits.Contains(a.Actor) && a.Actor.IsInWorld)
.Select(a => a.Actor).ToArray();
foreach (var a in newUnits)
@@ -326,7 +325,7 @@ namespace OpenRA.Mods.RA.AI
foreach (var a1 in attackForce)
{
var enemyUnits = world.FindUnitsInCircle(a1.CenterLocation, Game.CellSize * 10)
.Where(unit => p.Stances[unit.Owner] == Stance.Enemy).ToList();
.Where(unit => p.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait<Husk>()).ToList();
if (enemyUnits.Count > 0)
{
@@ -490,4 +489,4 @@ namespace OpenRA.Mods.RA.AI
aggro[e.Attacker.Owner].Aggro += e.Damage;
}
}
}
}

View File

@@ -54,6 +54,9 @@ namespace OpenRA.Mods.RA.Activities
if (!Target.IsValid)
return NextActivity;
if (!self.Owner.HasFogVisibility() && Target.Actor != null && Target.Actor.HasTrait<Mobile>() && !self.Owner.Shroud.IsTargetable(Target.Actor))
return NextActivity;
if (targetable != null && !targetable.TargetableBy(Target.Actor, self))
return NextActivity;

View File

@@ -32,16 +32,9 @@ namespace OpenRA.Mods.RA.Activities
if ((nearest - mobile.toCell).LengthSquared > 2)
return Util.SequenceActivities(new MoveAdjacentTo(Target.FromActor(target)), this);
var capturable = target.TraitOrDefault<Capturable>();
if (capturable != null && capturable.CaptureInProgress && capturable.Captor.Owner.Stances[self.Owner] == Stance.Ally)
if (!target.Trait<Capturable>().BeginCapture(target, self))
return NextActivity;
var sellable = target.TraitOrDefault<Sellable>();
if (sellable != null && sellable.Selling)
return NextActivity;
target.Trait<Capturable>().BeginCapture(target, self);
var capturesInfo = self.Info.Traits.Get<CapturesInfo>();
if (capturesInfo != null && capturesInfo.WastedAfterwards)
self.World.AddFrameEndTask(w => self.Destroy());

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
@@ -9,6 +9,7 @@
#endregion
using System.Linq;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
@@ -30,9 +31,17 @@ namespace OpenRA.Mods.RA.Activities
foreach (var t in target.TraitsImplementing<IAcceptSpy>())
t.OnInfiltrate(target, self);
self.Destroy();
if (self.HasTrait<DontDestroyWhenInfiltrating>())
self.World.AddFrameEndTask(w =>
{
if (self.Destroyed) return;
w.Remove(self);
});
else
self.Destroy();
Sound.PlayToPlayer(self.Owner, "bldginf1.aud");
if (target.HasTrait<Building>())
Sound.PlayToPlayer(self.Owner, "bldginf1.aud");
return this;
}

View File

@@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA.Activities
var repairsUnits = host.Info.Traits.Get<RepairsUnitsInfo>();
var unitCost = self.Info.Traits.Get<ValuedInfo>().Cost;
var hpToRepair = repairsUnits.HpPerStep;
var cost = (hpToRepair * unitCost * repairsUnits.ValuePercentage) / (health.MaxHP * 100);
var cost = Math.Max(1, (hpToRepair * unitCost * repairsUnits.ValuePercentage) / (health.MaxHP * 100));
if (!self.Owner.PlayerActor.Trait<PlayerResources>().TakeCash(cost))
{

View File

@@ -19,9 +19,6 @@ namespace OpenRA.Mods.RA.Activities
{
public override Activity Tick(Actor self)
{
var capturing = self.TraitOrDefault<Capturable>();
if (capturing != null && capturing.CaptureInProgress) return NextActivity;
var h = self.TraitOrDefault<Health>();
var si = self.Info.Traits.Get<SellableInfo>();
var pr = self.Owner.PlayerActor.Trait<PlayerResources>();

View File

@@ -34,6 +34,9 @@ namespace OpenRA.Mods.RA.Activities
self.World.AddFrameEndTask(w =>
{
foreach (var nt in self.TraitsImplementing<INotifyTransform>())
nt.OnTransform(self);
var selected = w.Selection.Contains(self);
self.Destroy();
@@ -65,6 +68,9 @@ namespace OpenRA.Mods.RA.Activities
var a = w.CreateActor( ToActor, init );
foreach (var nt in self.TraitsImplementing<INotifyTransformed>())
nt.OnTransformed(a);
if (selected)
w.Selection.Add(w, a);
});

View File

@@ -35,10 +35,8 @@ namespace OpenRA.Mods.RA
if (IsSuitableCell(pilot, self.Location) && r > 100 - info.SuccessRate && aircraft.Altitude > 10
&& self.Owner.WinState != WinState.Lost)
{
self.World.AddFrameEndTask(w => w.Add(
new Parachute(pilot.Owner,
Util.CenterOfCell(self.CenterLocation.ToCPos()),
aircraft.Altitude, pilot)));
self.World.AddFrameEndTask(w => w.Add(new Parachute(pilot,
Util.CenterOfCell(self.CenterLocation.ToCPos()), aircraft.Altitude)));
Sound.Play(info.ChuteSound, self.CenterLocation);
}

View File

@@ -38,13 +38,12 @@ namespace OpenRA.Mods.RA.Air
}
var attack = self.Trait<AttackHeli>();
var range = attack.GetMaximumRange() * 0.625f;
var dist = target.CenterLocation - self.CenterLocation;
var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
if( !float2.WithinEpsilon( float2.Zero, dist.ToFloat2(), range * Game.CellSize ) )
if (!Combat.IsInRange(self.CenterLocation, attack.GetMaximumRange(), target))
aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, desiredFacing);
attack.DoAttack( self, target );

View File

@@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Air
}
var dist = Dest - aircraft.PxPosition;
if (float2.WithinEpsilon(float2.Zero, dist.ToFloat2(), 2))
if (Math.Abs(dist.X) < 2 && Math.Abs(dist.Y) < 2)
{
aircraft.SubPxPosition = Dest.ToPSubPos();
return NextActivity;

View File

@@ -68,7 +68,7 @@ namespace OpenRA.Mods.RA.Air
}
else if (order.OrderString == "ReturnToBase")
{
var airfield = ReturnToBase.ChooseAirfield(self);
var airfield = ReturnToBase.ChooseAirfield(self, true);
if (airfield == null) return;
UnReserve();

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Air
var altitude = self.Trait<Aircraft>().Altitude;
if (altitude == 0) return; // we're on the ground, let's stay there.
var airfield = ReturnToBase.ChooseAirfield(self);
var airfield = ReturnToBase.ChooseAirfield(self, true);
if (airfield != null)
{
self.QueueActivity(new ReturnToBase(self, airfield));

View File

@@ -22,20 +22,20 @@ namespace OpenRA.Mods.RA.Air
PPos w1, w2, w3; /* tangent points to turn circles */
public static Actor ChooseAirfield(Actor self)
public static Actor ChooseAirfield(Actor self, bool unreservedOnly)
{
var rearmBuildings = self.Info.Traits.Get<PlaneInfo>().RearmBuildings;
return self.World.ActorsWithTrait<Reservable>()
.Where(a => a.Actor.Owner == self.Owner)
.Where(a => rearmBuildings.Contains(a.Actor.Info.Name)
&& !Reservable.IsReserved(a.Actor))
&& (!unreservedOnly || !Reservable.IsReserved(a.Actor)))
.Select(a => a.Actor)
.ClosestTo( self.CenterLocation );
}
void Calculate(Actor self)
{
if (dest == null || Reservable.IsReserved(dest)) dest = ChooseAirfield(self);
if (dest == null || Reservable.IsReserved(dest)) dest = ChooseAirfield(self, true);
if (dest == null) return;
@@ -52,17 +52,21 @@ namespace OpenRA.Mods.RA.Air
var speed = .2f * aircraft.MovementSpeed;
var approachStart = landPos.ToFloat2() - new float2(aircraft.Altitude * speed, 0);
/* if the aircraft is on the ground, it will take off to the cruise altitude first before approaching */
var altitude = aircraft.Altitude;
if (altitude == 0) altitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
var approachStart = landPos.ToInt2() - new float2(altitude * speed, 0);
var turnRadius = (128f / self.Info.Traits.Get<AircraftInfo>().ROT) * speed / (float)Math.PI;
/* work out the center points */
var fwd = -float2.FromAngle(aircraft.Facing / 128f * (float)Math.PI);
var side = new float2(-fwd.Y, fwd.X); /* rotate */
var sideTowardBase = new[] { side, -side }
.OrderBy(a => float2.Dot(a, self.CenterLocation.ToFloat2() - approachStart))
.OrderBy(a => float2.Dot(a, self.CenterLocation.ToInt2() - approachStart))
.First();
var c1 = self.CenterLocation.ToFloat2() + turnRadius * sideTowardBase;
var c1 = self.CenterLocation.ToInt2() + turnRadius * sideTowardBase;
var c2 = approachStart + new float2(0, turnRadius * Math.Sign(self.CenterLocation.Y - approachStart.Y)); // above or below start point
/* work out tangent points */
@@ -94,14 +98,13 @@ namespace OpenRA.Mods.RA.Air
Calculate(self);
if (dest == null)
{
var rearmBuildings = self.Info.Traits.Get<PlaneInfo>().RearmBuildings;
var nearestAfld = self.World.ActorsWithTrait<Reservable>()
.Where(a => a.Actor.Owner == self.Owner && rearmBuildings.Contains(a.Actor.Info.Name))
.Select(a => a.Actor)
.ClosestTo(self.CenterLocation);
var nearestAfld = ChooseAirfield(self, false);
self.CancelActivity();
return Util.SequenceActivities(Fly.ToCell(nearestAfld.Location), new FlyCircle());
if (nearestAfld != null)
return Util.SequenceActivities(Fly.ToCell(nearestAfld.Location), new FlyCircle());
else
return new FlyCircle();
}
return Util.SequenceActivities(

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