Compare commits

...

1249 Commits

Author SHA1 Message Date
abcdefg30
4d368c1ec1 Merge pull request #10213 from obrakmann/fix9851_prep-edition
[prep] Fix AttackMove not working properly under certain conditions
2015-12-13 20:30:24 +01:00
RoosterDragon
c504b2a9ae Ensure LaysTerrain doesn't access cells outside the map. 2015-12-13 20:07:48 +01:00
RoosterDragon
b9f08b4607 Fix GPS refreshing for incorrect player.
GpsWatcher.RefreshGps was wrongly using the render player in simulation code.
2015-12-13 18:30:57 +01:00
RoosterDragon
5897230226 Fix GPS dot relying on frozen actor render state.
The GPS dot was not displayed if a frozen actor for it was already visible. However, this was mistakenly affecting visibility checks in the world. Now, we only avoid rendering it when the frozen actor is present, but the indicator is still regarded as visible for visilbity checks in the world.
2015-12-13 18:30:51 +01:00
RoosterDragon
f26b0f1251 Ensure frozen actors are rendered on the first tick they become visible.
The previous lazy rendering means the snapshot of the render state might be more up to date then when the frozen actor actually did become visible. Now, we take this snapshot as soon as needed. We still retain the performance of only doing this rendering when needed by avoiding extra rendering until the visibility cycles again.
2015-12-13 18:30:43 +01:00
RoosterDragon
7bc4d205fe Merge dictionaries in GpsDot.
This speeds up GpsDot.Tick as it requires only one dictionary lookup per player rather than two.
2015-12-13 18:30:35 +01:00
Oliver Brakmann
71d4e29483 Fix AttackMove not working properly under certain conditions
This fixes the issue where AttackMove (and possibly other order modes) would not work properly when people were clicking their mouse buttons at the same time. A move order (the default order mode) would be issued instead.
2015-12-13 14:17:39 +01:00
abcdefg30
0e082183e3 Let spawned soviet vehicles attack move on Survival02 2015-12-12 23:50:50 +02:00
RoosterDragon
00bce1266f When hardware cursors fail, retry next session. 2015-12-12 12:56:42 +00:00
RoosterDragon
09f0242059 When the SDL hardware cursor fails, ensure more of the error message is logged.
Capture the useful details from the inner exception into the message, as this will be logged.
2015-12-12 12:56:35 +00:00
Oliver Brakmann
aa14f1b0a2 Fix showing unread messages count on active lobby chat button
The lobby chat button text would change to include the unread messages count for a split second, even when the lobby chat was the current panel, leading to the button text sort of 'blinking' in an ugly way.
2015-12-08 20:51:32 +00:00
abcdefg30
3cf6148c03 Fix a crash when producing an actor without OccupiesSpace in combination with UpgradeActorsNear 2015-12-03 21:57:38 +01:00
Oliver Brakmann
eddda3ecca Set enemies of 'Creeps' player when adding a new player in the editor 2015-11-29 20:49:09 +02:00
abcdefg30
ec001a608e Misc (style) improvements in the upgrade rule code 2015-11-29 20:48:14 +02:00
abcdefg30
07ca72127f Try to avoid adding duplicate values through upgrade rules 2015-11-29 20:48:07 +02:00
abcdefg30
246b25f008 Let upgrade rules also account for negated traits
(this commit affects only "-SpawnViceroid:", "-LeavesHusk:", "-Plane:" and "-Helicopter:")
2015-11-29 20:47:55 +02:00
abcdefg30
0bca700bff Let the utility fix cosmetics in the chrome yamls 2015-11-29 20:47:46 +02:00
abcdefg30
0d286e12b2 Fix potential crashes in the upgrade rules 2015-11-29 20:47:38 +02:00
Oliver Brakmann
811acc5a58 Merge pull request #10144 from cjshmyr/missile-prepfix
Set missile default acceleration to 0 (prep only)
2015-11-29 13:10:05 +01:00
Curtis Shmyr
265faa3452 Set missile default acceleration to 0 2015-11-28 21:59:05 -07:00
Paul Chote
bc51d6638d Add a server log line for player joins. 2015-11-28 15:45:30 +01:00
Oliver Brakmann
60a27f9f83 Merge pull request #10130 from pchote/revert-bridge-fix
Revert "add custom selection sizes to aid the renderer" on prep-1512
2015-11-28 15:25:25 +01:00
Paul Chote
a7cfaff96c Revert "add custom selection sizes to aid the renderer"
This reverts commit c3dce785a5.
2015-11-28 09:58:44 +00:00
Paul Chote
d957a5a15e Implement suicide saboteur. 2015-11-27 14:31:20 +01:00
Paul Chote
026a27296c Fix C4Demolition trait doc punctuation. 2015-11-27 14:31:13 +01:00
Paul Chote
f7c2043e06 Add enter behaviour customisation to C4Demolition. 2015-11-27 14:31:02 +01:00
OmegaBolt
4efe8d091c D2k Deviator balance 2015-11-25 22:54:38 +02:00
Matthias Mailänder
97e810d753 simplify the hierarchy section hierarchy 2015-11-25 22:35:22 +02:00
Matthias Mailänder
7ed82fa4c7 make the "Game" component read-only 2015-11-25 22:35:15 +02:00
reaperrr
32b4402ba0 Give Missile Tank weapon a range limit and reduce Quad rocket range limit 2015-11-25 22:30:36 +02:00
DArcy Rush
897c0f01f0 Add second exit to kennel 2015-11-25 22:16:55 +02:00
Paul Chote
b21b9c9762 Fix the ConvertSpriteToPngCommand. 2015-11-25 22:08:30 +02:00
Paul Chote
5bcc83bc0c Add upgraded tag to D2K production structures. 2015-11-25 22:02:28 +02:00
Paul Chote
509662d8a6 Add SelectionDecoration flag to WithDecoration. 2015-11-25 22:02:14 +02:00
Paul Chote
fd171d842e Add new primary building tag artwork. 2015-11-25 22:02:07 +02:00
Paul Chote
9258face3c Fix D2K outpost artwork offsets and selection box. 2015-11-25 22:01:41 +02:00
Oliver Brakmann
41e5032d48 Fix worms not attacking anything anymore 2015-11-22 21:56:49 +01:00
OmegaBolt
6006dbd235 D2k, fix #10037 terrain regressions 2015-11-22 21:56:35 +01:00
OmegaBolt
b7e7ff7fc0 D2k spice no longer erases map details & terrain fixes 2015-11-22 18:22:11 +01:00
reaperrr
6d98635e94 Add invisible spice bloom spawn
When real spiceblooms explode, they spawn an invisible
spicebloom.spawnpoint actor, which only 'grows' when the cell is of
GrowthTerrainType. When 'exploding', it then displays the animation of
blowing spice up into the air, and spawns a real spicebloom.

This replicates the original behavior where spice blooms would only grow
on sand cells that had been harvested and free of spice.
2015-11-22 17:24:03 +01:00
reaperrr
46762140a5 Improve spice bloom seeding mechanism
Improve seeding target cell determination.
Draw out spice seedable cells before loop.
Default to null for SpiceBloom.Weapon.
Pull spice seeding into its own method.
Skip it completely if no seed weapon is defined.
2015-11-22 17:19:28 +01:00
reaperrr
09cdf3b257 Only allow spice blooms to grow on certain terrain types 2015-11-22 17:19:28 +01:00
RoosterDragon
033e469bea Prevent invalid cells checks in SeedsResource. 2015-11-22 08:05:10 +01:00
Paul Chote
7e680b9c02 Fix width of the MP filter checkboxes. 2015-11-22 01:36:32 +00:00
abcdefg30
a56d367f60 Add an upgrade rule for the Upgrades -> DeployedUpgrades change 2015-11-22 01:06:16 +01:00
Pavel Penev
bd2629196a Update thumpers and Mobile Sensor Arrays to the new DeployToUpgrade
Currently those are the only two usages of the trait.
2015-11-22 01:01:56 +01:00
Pavel Penev
011f566c6f Add support for deploy animations using a specific upgrade
Also ignore orders while playing a deploy/undeploy animation. Fixes 9242.

We grant a level 1 Undeployed upgrade(s) when the actor is created which enables the default behavior of the actor. When the actor receives a deploy order, the Undeployed upgrade(s) is(are) revoked, which may or may not be used to enable a trait to play a deploy animation. Once the deployment is complete, the Deployed upgrade(s) is(are) granted.
Then do the reverse when undeploying, disabling weapons and other systems first by revoking the Deployed upgrade(s), and granting the Undeployed upgrade(s) when the undeploy animation is done.
2015-11-22 01:01:40 +01:00
abcdefg30
161907b852 Fix 'oldlst's letting units enter it (after delivering them) 2015-11-21 23:23:36 +01:00
abcdefg30
1576101a2c Add IsDead checks to gdi06 2015-11-21 23:15:43 +01:00
abcdefg30
67ba3e53f2 Fix the harvester stopping when you reach the base in gdi05 2015-11-21 23:07:16 +01:00
DArcy Rush
52b061a8a8 Hide ammobox healthbar. 2015-11-21 22:49:06 +01:00
abcdefg30
5755f4048d Merge pull request #10057 from atlimit8/FinishRevertingMultilineSupportForSimpleTooltipLogic
Finish reverting multiline support for SimpleTooltipLogic
2015-11-21 22:37:36 +01:00
atlimit8
b1b210ea6d Finish reverting #9925 & #9715 2015-11-21 14:28:33 -06:00
abcdefg30
fc8f1d40c5 Fix the rushAI building spens/syrds without being able to build naval units 2015-11-21 21:02:22 +01:00
Paul Chote
5d83a5a7d6 Restore earlier spy targeting behaviour. 2015-11-21 20:58:17 +01:00
Paul Chote
8c24e87de2 Make CanTarget modifiers a ref parameter. 2015-11-21 20:58:17 +01:00
reaperrr
13c4f16272 Increase the default range of angles that missiles can launch at 2015-11-21 21:12:23 +02:00
Pavel Penev
20a33b8411 Make GPS respect shroud 2015-11-21 18:59:41 +01:00
Pavel Penev
51fcb55b22 Remove byPlayer parameter from IFogVisibilityModifier.HasFogVisibility() 2015-11-21 18:59:41 +01:00
Pavel Penev
8e7469e194 Add IFogVisibilityModifier.IsVisible(Actor) 2015-11-21 18:59:41 +01:00
Pavel Penev
7e0617075f Track GpsDot state per player
Should let us fix the issue mentioned in https://github.com/OpenRA/OpenRA/pull/10007#issuecomment-157409237
2015-11-21 18:59:41 +01:00
Pavel Penev
4ff6ba8c37 Don't attack actors that you can't see 2015-11-21 18:59:35 +01:00
atlimit8
958a72aaf8 Revert Multi-line tooltips due to lack of multi-line support.
This reverts #9925 & #9715.
2015-11-21 11:08:11 -06:00
Oliver Brakmann
e7df117892 Merge pull request #10019 from r34ch/ra-map-pool
Add a couple community maps to the pool.
2015-11-21 14:55:31 +01:00
reaperrr
57d49d0aeb Fix D2k wormspawner editor art 2015-11-19 19:36:54 +01:00
reaperrr
ee86b5f45f Fix D2k effect palette shadow index 2015-11-19 19:36:54 +01:00
reaperrr
ba0e3130af Fix mpspawn, waypoint and camera art
All mpspawn, waypoint and camera editor art uses the correct shadow and remap colors.
Additionally added camera art to CnC, D2k and TS.
2015-11-19 19:36:54 +01:00
Pavel Penev
64427dd1a6 Fix UpgradeActorsNear revoking upgrades after the actor dies
Very hard bug to reproduce: if you can power down a stealth generator just as it is dieing you can hit a race condition that leads to ActorExited() being called to revoke the upgrades after they have already been revoked once.
2015-11-19 19:00:12 +01:00
abcdefg30
7412669d03 Add production acceleration to d2k
except for starports
2015-11-17 19:33:26 +01:00
Curtis Shmyr
ec8e9f537d Increase TRUK and DTRK vision from 3 to 4 cells 2015-11-17 19:25:39 +01:00
DArcy Rush
9c71d555c1 Add a couple community maps to the pool. 2015-11-17 08:39:43 +00:00
abcdefg30
0f191484d7 Fix a crash when using the chronoshift power
if the "chronosphere-actor" doesn't have an "active" sequence
2015-11-16 22:00:30 +00:00
Pavel Penev
4be5979b90 Add a null check to CachedTransform.Update() 2015-11-16 21:52:19 +00:00
Pavel Penev
6bd092f192 Check if WithSpriteBody is available in GrantUpgradePower 2015-11-16 13:58:24 +01:00
Oliver Brakmann
bd6bcda6d0 Merge pull request #9993 from pchote/nsprocess-fix
Switch to a (hopefully) working NSProcess url.
2015-11-14 22:52:56 +01:00
Paul Chote
f12deca9ca Switch to a (hopefully) working NSProcess url. 2015-11-14 21:47:21 +00:00
Oliver Brakmann
5ea82b4e5e Increase range of flak truck against air targets
From 6 cells to 8 cells
2015-11-14 22:10:40 +01:00
DArcy Rush
2d210a97df Rebalance Tesla Tank.
Allow attacking of target regardless of facing.
2015-11-14 22:10:40 +01:00
DArcy Rush
f03a100115 Rebalance phase transport.
Passengers increased to 4, speed and LoS increased.
2015-11-14 22:10:40 +01:00
DArcy Rush
1e30684782 Reduce chronotank charge time.
Chronotank charge decreased from 20s to 12s.
2015-11-14 22:10:40 +01:00
Curtis Shmyr
abb45197b1 lower InfiltrateForPowerOutage time from 30->20sec 2015-11-14 19:34:37 +00:00
Paul Chote
a7935f6166 Check deploy location at the time of transform. 2015-11-14 16:46:18 +01:00
Oliver Brakmann
7b75a9c2f7 Fix reinforcements appearing in soviet04a/b despite killed radar dome 2015-11-14 15:01:51 +02:00
reaperrr
9b694f6044 Fix spice bloom editor visibility 2015-11-14 12:09:07 +00:00
Biofreak1987
0a75019aa0 Fix ai building in soviet04/06 missions despite killed construction yard 2015-11-13 20:53:26 +01:00
Biofreak1987
d3e41b6d50 Fix nod05 airstrike Lua crash and update map rules
- Fix airstrike Lua crash when there are no targets
- Increased harvester search range
- Hide owner row from husks and walls

Changes to make it closer to the original:
- Added e3 and sandbag production
- Made airstrikes gdi only
- Limited airstrike squadsize to 1
- Allow to attack civilian buildings
2015-11-12 22:52:38 +01:00
Oliver Brakmann
18f3e1f57b Merge pull request #9971 from pchote/tooltip-fix
Fix map editor crash
2015-11-12 19:32:02 +01:00
Paul Chote
1760f8acd6 Fix tooltip colour definition. 2015-11-11 23:15:33 +00:00
Pavel Penev
4154553318 Validate player color when changing slots in the lobby 2015-11-11 22:59:48 +00:00
Oliver Brakmann
e5e8e64ace Fix bogus owner check in Lua API production code 2015-11-11 22:24:05 +00:00
OmegaBolt
0ae58c10ad D2k thumper worm attraction balance 2015-11-11 23:01:53 +02:00
Paul Chote
89ea810cbe Truncate player name in replay browser. 2015-11-11 22:40:00 +02:00
Paul Chote
f6cf35c99c Truncate player name in observer stats and diplomacy panels. 2015-11-11 22:39:52 +02:00
Paul Chote
5fbaeabb6d Truncate player name in ingame menu stats. 2015-11-11 22:39:37 +02:00
Paul Chote
581907f53a Prevent frozen actors leaking through shroud. 2015-11-11 22:33:16 +02:00
Paul Chote
7cf4be9d78 Add copy/paste to the map editor. 2015-11-11 01:02:16 +02:00
Paul Chote
bdf9f5e201 Make editor brushes disposable. 2015-11-11 01:02:09 +02:00
Pavel Penev
b26b1f410f Enable AutoTarget to aquire targets under fog if GPS is present 2015-11-10 22:27:40 +01:00
OmegaBolt
ce69abe1f2 D2k fixed armour & AI typos 2015-11-10 22:04:09 +01:00
atlimit8
b3d2b36875 Make ActorSelector tooltips better match actor tooltips in map editor 2015-11-10 21:08:53 +01:00
atlimit8
f28b37323f Made editor actor preview tooltip easier to read 2015-11-10 21:08:53 +01:00
atlimit8
7c82ab60e8 Multiline support for SimpleTooltipLogic 2015-11-10 21:08:53 +01:00
Zimmermann Gyula
d14fbd0f84 Fix observer GUI showing disabled support powers. 2015-11-09 21:07:19 +01:00
OmegaBolt
c567f5cbdd D2k super weapon timers 2015-11-09 21:51:02 +02:00
OmegaBolt
51a9831fc2 D2k Ornithopter bomb damage increase 2015-11-09 19:58:36 +01:00
OmegaBolt
4d5777cbc9 D2k, fixed infantry moving slow on dunes and rough 2015-11-08 21:59:07 +02:00
Paul Chote
a6a835d95f Truncate long player names in lobby. 2015-11-08 17:24:24 +02:00
Paul Chote
e16be14ec7 Truncate long server names in MP browser. 2015-11-08 17:24:19 +02:00
Paul Chote
11939d3af1 Truncate long map name in replay browser. 2015-11-08 17:24:13 +02:00
Paul Chote
feb133c2eb Truncate long map name / mod version in MP panel. 2015-11-08 17:24:02 +02:00
Paul Chote
f6361b031b Truncate long map name / author in map chooser. 2015-11-08 17:23:56 +02:00
Paul Chote
36967951e6 Truncate long map name / author in lobby. 2015-11-08 17:23:39 +02:00
Paul Chote
012a9d71ba Add helpers for truncating long labels. 2015-11-08 17:23:31 +02:00
Paul Chote
cff369850c Set the default map location to the support dir. 2015-11-08 14:49:38 +02:00
DArcy Rush
136b4c0fa9 Add self to AUTHORS. 2015-11-08 11:40:37 +00:00
DArcy Rush
aae2459d0b Move blossom trees south one cell in cnc64gdi01. 2015-11-08 11:40:27 +00:00
teees
d47ba1d135 only change editor brushes on mouseup
let other uses of the right mouse button bubble up
2015-11-08 11:30:25 +00:00
teees
133cffff24 Handle mouse up event in default editor brush 2015-11-08 11:30:08 +00:00
Oliver Brakmann
52f6c993d5 Fix lint warning in gdi06 2015-11-08 11:17:22 +00:00
Biofreak1987
21eecb048d Fix soviet06 prerequisites 2015-11-08 09:48:47 +01:00
Oliver Brakmann
b97398a671 Fix typo in WeatherOverlayInfo 2015-11-08 09:14:22 +01:00
Curtis Shmyr
a285c908db Added 3 Lua player API properties 2015-11-08 08:53:15 +01:00
reaperrr
35b39162ff Fix spice debris target cell randomization 2015-11-07 18:32:21 +01:00
reaperrr
0b5b6adc7c Improve SpiceExplosion and add BloomExplosion
Fixes angle and loudness of spice debris, adds BloomExplosion to add proper animation and damage crushing actors.
2015-11-07 18:32:14 +01:00
reaperrr
5357eb6f29 Increase variation and average of spice bloom growth 2015-11-07 18:32:04 +01:00
reaperrr
e274ac5ff8 Make sure that a spice bloom spawns at least the minimum of pieces 2015-11-07 18:31:59 +01:00
reaperrr
f8e39bd142 Reduce spawned spice per piece 2015-11-07 18:31:56 +01:00
Pavel Penev
48881f4e73 Fix repair pad reference in units' Repairable trait 2015-11-07 18:31:52 +01:00
Pavel Penev
d2eb56183d Buff D2k repair pads 2015-11-07 18:10:40 +01:00
reaperrr
afd75c7f55 Fix WithSpriteRotorOverlay upgrade rule to account for @ separator 2015-11-07 16:18:29 +02:00
reaperrr
6d1551c9fd Change engineVersion for upgrade rules of changes made between 20150808 and 20150919
Those changes were merged after the feature-freeze, but predate the stable release. Changing the engine version to the day after release makes it easier for modders to upgrade without using bogus engine dates.
2015-11-07 16:18:18 +02:00
Paul Chote
a015b0990b Fetch battlefield news once per game launch. 2015-11-07 14:13:31 +02:00
Paul Chote
6dd08bbc98 Fix global chat line margins. 2015-11-07 12:43:14 +01:00
Paul Chote
343616e924 Add unread message count to lobby chat tabs. 2015-11-07 12:43:03 +01:00
Paul Chote
91242a832f Add Tick method to ChromeLogic. 2015-11-07 12:43:03 +01:00
OmegaBolt
1c53bfed11 D2k crate balance
- Fixed prerequisites.
- Added more infantry crates.
- Upped the create explosion damage, though it is still very little. Takes about a third health off a Trike.
2015-11-06 19:47:34 +01:00
RoosterDragon
e5e7d037a3 Remove event handler when disposed in MainMenuLogic.
Removes a static event handler to Game.OnRemoteDirectConnect which allow the GC to reclaim the MainMenuLogic class after it has been disposed.
2015-11-05 22:49:25 +01:00
RoosterDragon
2a301392c6 Remove event handlers to CellEntryChanged when done.
Several classes would attach event handlers to the Map which would live longer then they did. Detaching them when no longer needed allows the GC to reclaim them.
2015-11-05 22:49:25 +01:00
RoosterDragon
e35bb8ea95 Detach event handlers on dispose in TerrainSpriteLayer.
The WorldRenderer outlives the TerrainSpriteLayer and thus keeps it alive longer than expected via the event handler. We detach it to allow the GC to reclaim it.
2015-11-05 22:49:25 +01:00
Pavel Penev
7a4002ff08 Fix the C17 delivery plane doing a steep dive when trying to land 2015-11-05 19:49:04 +00:00
RoosterDragon
523fe20255 Work around a hang on shutdown caused by IRC.
Our IRC client doesn't shut down properly - but we only need to shut it down when we're about to close the game anyway, so we just don't bother since it won't hurt anybody.
2015-11-05 20:42:15 +01:00
Zimmermann Gyula
31e0c8b2e3 Fix (HealthPercentage)DamageWarheads ignoring stances/TargetTypes.
Moves the IsValidAgainst check from SpreadDamage level to Damage level
and adds a duplication to HealthPercentageDamageWarhead.
2015-11-04 22:34:48 +00:00
Pavel Penev
7c37d1cfcc Fix server filter width 2015-11-04 22:31:27 +01:00
Oliver Brakmann
8e76a109bd Fix viceroids being spawned by crushed infantry 2015-11-03 10:33:40 +00:00
Michael Rätzel
ba9b18ccb7 reset RallyPoint Location after capture. resolves #9163. 2015-10-31 21:59:03 +01:00
Oliver Brakmann
c61d028069 Merge pull request #9829 from pchote/fixup-install
Add IRC library to the install rules.
2015-10-31 20:44:47 +01:00
Paul Chote
bcebba3a2f Add IRC library to the install rules. 2015-10-31 19:39:59 +00:00
Pavel Penev
ef1e217a2a Merge pull request #9825 from reaperrr/d2k-stealth-det
Add infantry stealth detection to D2k
2015-10-31 20:18:15 +02:00
reaperrr
82d00c22b2 Merge pull request #9821 from abcdefg30/hijackerspeed
Increase the speed of HIJACKER
2015-10-31 18:09:16 +01:00
Pavel Penev
499eba944a Merge pull request #9822 from reaperrr/fix-ts-sensor
Fix TS sensor array DetectCloaked range
2015-10-31 18:52:51 +02:00
reaperrr
124989c6c6 Add stealth detection to D2k infantry 2015-10-31 17:39:10 +01:00
reaperrr
283e864f73 Fix TS sensor array DetectCloaked range 2015-10-31 16:29:05 +01:00
abcdefg30
16dbdebb72 Increase the speed of HIJACKER 2015-10-31 16:08:16 +01:00
Pavel Penev
9ae4114d26 Merge pull request #9771 from reaperrr/d2k-thumper
Implement D2k thumper
2015-10-31 15:47:33 +02:00
Pavel Penev
0ca370e2ae Merge pull request #9813 from atlimit8/FixRallyPointColor
RallyPoint palette tracks owner
2015-10-31 15:12:45 +02:00
Pavel Penev
a263f18824 Merge pull request #9812 from obrakmann/fix9811_missing-production-bar-after-capture
Fix missing production bar on captured factories
2015-10-31 15:04:48 +02:00
reaperrr
2e0a8ef9c4 Make sandworms not eat infantry 2015-10-31 13:44:00 +01:00
reaperrr
f220a18fef Align thumper-sand overlay with thump anim 2015-10-31 13:43:59 +01:00
reaperrr
dbaf7e9d12 Add D2k thumper sound 2015-10-31 13:43:58 +01:00
reaperrr
bbf5a4a06d Make AmbientSound upgradable and add customisable interval 2015-10-31 13:43:57 +01:00
reaperrr
85de71514d Merge pull request #9818 from pchote/fix-latency
Fix singleplayer game latency.
2015-10-31 12:44:33 +01:00
Paul Chote
64498b1ea7 Fix singleplayer game latency. 2015-10-31 11:36:32 +00:00
atlimit8
faa1a49604 RallyPoint palette tracks owner 2015-10-30 20:09:39 -05:00
Oliver Brakmann
b1e6916838 Add missing Requires<> to ProductionBar 2015-10-31 00:24:41 +01:00
Oliver Brakmann
9843d10dbd Fix production bars not being visible on captured factories 2015-10-31 00:00:08 +01:00
reaperrr
b6229fd456 Implement D2k thumper 2015-10-30 14:23:37 +01:00
atlimit8
168dab9707 Merge pull request #9706 from reaperrr/block-height
Add Height property to BlocksProjectiles
2015-10-29 23:51:14 -05:00
abcdefg30
a1f27c6133 Merge pull request #9796 from obrakmann/fix9784_missing-base-range-circle
Fix base range circle not being shown during building placement
2015-10-29 21:58:48 +01:00
Oliver Brakmann
e7e4f2f825 Fix base range circle not being shown during building placement 2015-10-29 11:00:59 +01:00
Oliver Brakmann
0997f5b52f Merge pull request #9773 from Mailaender/musictab-dereference
Fixed musicTab = null return value from GetOrNull<ButtonWidget>
2015-10-28 21:53:59 +01:00
Oliver Brakmann
bdf71eabf3 Merge pull request #9777 from teees/repulsion-fix
calculate correct altitude with terrain elevation offset (aircraft repulsion)
2015-10-28 20:56:53 +01:00
Oliver Brakmann
c89bced9f0 Merge pull request #9782 from atlimit8/AircraftIsMovingAboveGround
Fix Aircaft.IsMoving Check
2015-10-28 20:45:15 +01:00
Oliver Brakmann
f69ab464af Merge pull request #9785 from abcdefg30/upgradeExit
Fix upgrades in d2k not being producible
2015-10-27 21:36:24 +01:00
abcdefg30
687f459fbc Merge pull request #9611 from obrakmann/fix3285_default-stance-defend
Change the default stance to Defend for human players
2015-10-27 21:21:43 +01:00
abcdefg30
f72dd97844 Fix upgrades in d2k not being producible 2015-10-27 21:17:53 +01:00
Oliver Brakmann
a0fdfc3f79 Add testcase for StanceInit 2015-10-27 19:41:49 +01:00
Oliver Brakmann
b096671acb Add an ActorInit for unit stances 2015-10-27 19:41:49 +01:00
Oliver Brakmann
1a879009f1 Change InitialStance to Defend for human players 2015-10-27 19:41:49 +01:00
atlimit8
2772ddbab4 Fix Aircaft.IsMoving Check 2015-10-27 10:45:45 -05:00
teees
3f718ae7d5 calculate correct altitude with terrain elevation offset 2015-10-27 11:19:56 +01:00
atlimit8
549f8a9e7c Merge pull request #9760 from pchote/fix-teleporting-harvesters
Fix harvesters teleporting through doors
2015-10-26 23:42:51 -05:00
Matthias Mailänder
d2ce79e580 avoid a possible null return value musicTab 2015-10-26 21:45:40 +01:00
Oliver Brakmann
8b2245ad4e Merge pull request #9772 from Mailaender/multiplayer-dereference
Fixed filtersButton = null return value from GetOrNull<DropDownButtonWidget>
2015-10-26 21:30:45 +01:00
Matthias Mailänder
e435864531 don't dereference null return value 2015-10-26 21:21:47 +01:00
Oliver Brakmann
bfdac57138 Merge pull request #9676 from reaperrr/d2k-falloff
Tweaked D2k warhead falloffs
2015-10-26 21:12:45 +01:00
Oliver Brakmann
2723ca1a1f Merge pull request #9615 from reaperrr/d2k-rest1
Remaining D2k changes to restore original balancing/gameplay
2015-10-26 21:03:12 +01:00
Oliver Brakmann
d07ac08dff Merge pull request #9458 from reaperrr/d2k-sight
Change D2k shroud revealing ranges to match original
2015-10-26 20:49:52 +01:00
reaperrr
f166fd9525 Merge pull request #9526 from penev92/tileShapes
Rename TileShape to fit its role better
2015-10-26 15:41:09 +01:00
reaperrr
ce43d02dbc Reduce range and number of D2k building debris
Fix debris warhead falloff
2015-10-26 15:14:11 +01:00
reaperrr
0d990d2818 Calculate D2k building visibility around center instead of footprint 2015-10-26 15:14:10 +01:00
reaperrr
3ce1ee24ae Make only light infantry come out of destroyed D2k buildings 2015-10-26 15:14:09 +01:00
reaperrr
0d2c9725ea Tweak D2k infantry bounds 2015-10-26 15:14:08 +01:00
reaperrr
793b72b3ba Tone down D2k veterancy stat gains 2015-10-26 15:14:07 +01:00
reaperrr
d469e073bc Disable D2k capturing of husks, make husks explode 2015-10-26 15:14:06 +01:00
reaperrr
e37729f634 Tweak D2k worm disappear chance, spawn interval and minimum 2015-10-26 15:14:05 +01:00
reaperrr
7fdc8f9ad9 Make D2k constr. yard explicit prerequisite
In preparation for moving Upgrades to the player actor in the future.

Additionally remove unnecessary Exit trait from construction yard.
2015-10-26 15:12:16 +01:00
abcdefg30
91fda29f84 Merge pull request #9769 from RoosterDragon/fix-replay-2-the-fixining
Fix replay freeze 2
2015-10-26 12:19:38 +01:00
abcdefg30
86df9f66e8 Merge pull request #9718 from penev92/hvaException
Check HVA files validity at load time
2015-10-26 12:14:28 +01:00
Pavel Penev
905d46bd99 Merge pull request #9723 from evgeniysergeev/fix_sprite
flip or mirror sprites with negative width and height
2015-10-26 01:31:15 +02:00
Pavel Penev
5f7ecbe0af Merge pull request #9767 from obrakmann/fix-cnc-plane-max-pitch
Change aircraft's maximum pitch in TD to match the increased cruise altitude
2015-10-26 01:21:19 +02:00
Pavel Penev
b16ebd480b Rename MapGridType.Diamond to MapGridType.RectangularIsometric 2015-10-26 00:42:30 +02:00
Pavel Penev
0e417a3cf3 Rename MapGridType.Rectangle to MapGridType.Rectangular 2015-10-26 00:41:26 +02:00
Pavel Penev
bb3aea338a Rename enum TileShape to MapGridType 2015-10-26 00:41:21 +02:00
Pavel Penev
84db36d3e8 Check HVA files validity at load time 2015-10-26 00:25:28 +02:00
RoosterDragon
36a1715e5c Ensure replays end when the recorder disconnects.
When ReplayConnection fixes up disconnection packets, this allows the game to continue past the point of a player disconnecting. Unfortunately this also applies to the player who actually disconnected which means the replay continues in an invalid manner. To fix this - we now explicitly don't replace their packet in order to ensure such replays end at the correct time.
2015-10-25 21:22:44 +00:00
RoosterDragon
0ca1805ea7 Merge pull request #9389 from Herve-M/fix-replay
Fix replay freeze
2015-10-25 21:20:11 +00:00
Oliver Brakmann
744d66955a Merge pull request #9749 from RoosterDragon/delay-toctou-fixes
Fix TOCTOU issues when calling Game.RunAfterDelay
2015-10-25 21:16:15 +01:00
RoosterDragon
7c889c5ef0 Fix TOCTOU issues when calling Game.RunAfterDelay.
Since the action runs after a delay, the state of the game may no longer be the same and it may no longer be valid to run the action. Anything that references the world now calls IsCurrentWorld to ensure the world hasn't changed or been disposed.
2015-10-25 19:44:21 +00:00
Oliver Brakmann
8eb2a380f7 Change aircraft's maximum pitch in TD to match the increased cruise altitude 2015-10-25 20:01:55 +01:00
abcdefg30
d10dd5c9d9 Merge pull request #9758 from reaperrr/fix-barrel-seldeco
Fix #9751 - Replace Selectable with CustomSelectionSize on RA barrels
2015-10-25 18:51:02 +01:00
abcdefg30
f5ab218c4f Merge pull request #9766 from obrakmann/fix-d2k-missing-replaybrowser
Add replaybrowser yaml file back to d2k manifest.
2015-10-25 18:43:58 +01:00
atlimit8
10aca92bef Merge pull request #9720 from penev92/fixUtility
Fix a crash in CheckPlayers when an actor doesn't define an Owner
2015-10-25 12:41:50 -05:00
Matthias Mailänder
e0dffe773c Merge pull request #9550 from clemty/gdi06
Add gdi06
2015-10-25 18:27:33 +01:00
Matthias Mailänder
d4016ae6f0 Merge pull request #9716 from teees/hover-fix
Disable hovering for landed aircraft
2015-10-25 18:01:29 +01:00
Oliver Brakmann
356b50fb18 Add replaybrowser yaml file back to d2k manifest. 2015-10-25 18:00:02 +01:00
reaperrr
bdfbbb540b Misc D2k visibility changes
- Make structure reveal range centered around CenterPosition.
- Change camera range
2015-10-25 17:38:00 +01:00
reaperrr
2c88015bb3 Change D2k vehicle shroud reveal ranges to original values 2015-10-25 17:37:59 +01:00
reaperrr
3ce670998a Change D2k shroud reveal ranges to original values 2015-10-25 17:37:57 +01:00
reaperrr
63aeb6b2d5 Change D2k infantry shroud reveal ranges to match original 2015-10-25 17:37:55 +01:00
Matthias Mailänder
86ddcf05a1 Merge pull request #9764 from Biofreak1987/fix_soviet06
Fix unit production in soviet06
2015-10-25 17:37:31 +01:00
Pavel Penev
0487ec0d08 Fix a crash in CheckPlayers when an actor doesn't define an Owner 2015-10-25 17:11:51 +02:00
Pavel Penev
06ba175fde Merge pull request #9762 from obrakmann/fix7926_fix_td_sams_not_closing
Fix TD SAM sites not closing after killing a target.
2015-10-25 16:12:37 +02:00
atlimit8
7c1e93a880 Merge pull request #9730 from r34ch/fake-structures-detonate
Fake structures detonate to mask health difference.
2015-10-25 09:12:02 -05:00
Biofreak1987
454ac1edaf Fix soviet06 unit production 2015-10-25 14:55:56 +01:00
reaperrr
02fcdb80d6 Re-increase siege tank and grenadier area of effect
Siege Tank:
- 'Stretches' each Spread step by 1 pixel (from 12 to 13), increasing total area of effect from 48 pixels (1.5 cells) to 52 pixels (1.625 cells)
- increases falloff damage by 5 percentage points

Grenadier:
- same Falloff as Siege Tank
2015-10-25 14:05:23 +01:00
DArcy Rush
60ad19b625 Fake structures use 'DamageThreshold' under 'Explodes'.
This change means that fake structures take damage at the same
rate as their real counterparts, but explode at 90% of their
max health.

MSLF and PDOF have been given a health buff as only one fake
version of each can be built.

Also fixed mission Monster Tank Madness. Actor v19.Husk required
HealthInfo.
2015-10-25 11:51:27 +00:00
Pavel Penev
82144ce975 Merge pull request #9738 from abcdefg30/loadimport
Fix the legacy map importer not working
2015-10-25 13:41:29 +02:00
Oliver Brakmann
3d4500a86e Fix TD SAM sites not closing after killing a target.
This fix will not make the SAM close if the target is still alive and got out of range.
2015-10-25 12:40:09 +01:00
abcdefg30
7210883e71 Merge pull request #9754 from atlimit8/LuaArraysToTables
Convert Lua array-like structures to use named entries.
2015-10-25 11:43:13 +01:00
Paul Chote
68bdedb9ba Make the production exit wait uncancellable. 2015-10-25 10:41:17 +00:00
reaperrr
80e6e024d8 Replace Selectable with CustomSelectionSize on RA barrels
This still allows targeting them, but you neither see their health bar on mouse-over, nor can you select them (effectively making their health bar and selection box invisible).
2015-10-25 10:01:14 +01:00
Matthias Mailänder
8e6c5cef74 Merge pull request #9757 from Biofreak1987/add_to_authors
Add myself to AUTHORS
2015-10-25 09:22:00 +01:00
reaperrr
1c98dc9a62 Remove SpiceExplosion impact sound
Way too annoying, and the original didn't have this either.
2015-10-25 09:16:20 +01:00
reaperrr
fe85458dde Fix animations and sounds of explosions
Animation for small and medium explosion was reversed, sounds were wrong compared to original.
2015-10-25 09:15:36 +01:00
reaperrr
943e43a738 Remove unnecessary D2k ValidTargets entries 2015-10-25 09:15:35 +01:00
reaperrr
2a6a46f120 Remove redundant 100% versus values from D2k warheads 2015-10-25 09:15:34 +01:00
reaperrr
064a008f3e Make D2k bazooka and quad rocket more inaccurate 2015-10-25 09:15:33 +01:00
reaperrr
64b4e92ab2 Tweaked D2k warhead falloffs 2015-10-25 09:15:32 +01:00
Biofreak1987
f02d87fa35 Add myself to AUTHORS 2015-10-25 09:15:15 +01:00
atlimit8
128574723a Merge pull request #9753 from RoosterDragon/better-actor-lookups
Improve some actor queries
2015-10-25 02:38:21 -05:00
Matthias Mailänder
40a7ab5a6a Merge pull request #9628 from abcdefg30/luatime
Fix Utils.FormatTime not working properly on different game speeds
2015-10-25 07:49:01 +01:00
Matthias Mailänder
3dc765f7c1 Merge pull request #9744 from pchote/serverbrowser
Redesign the MP server browser.
2015-10-25 07:32:04 +01:00
Matthias Mailänder
83399277b5 Merge pull request #9717 from teees/emp-disable-extensions
Let emp effect buildings and cyborgs too
2015-10-25 07:20:26 +01:00
atlimit8
f79ac636f2 Convert Lua array-like structures to use named entries 2015-10-25 00:36:04 -05:00
RoosterDragon
30aee56d78 Improve some actor queries.
Use ActorsWithTrait if possible to avoid querying all actors in the world.
2015-10-25 01:19:29 +01:00
DArcy Rush
c0850e44f4 Explodes trait has new 'DamageThreshold' property.
An actor will explode when its health is below the
defined percentage of its max health.
2015-10-24 23:02:42 +01:00
abcdefg30
e65465c539 Fix Utils.FormatTime not working properly on different game speeds 2015-10-24 23:42:32 +02:00
Paul Chote
e0177d7798 Merge pull request #9494 from abcdefg30/luabackground
Add lua support for playing background music
2015-10-24 22:25:35 +01:00
Paul Chote
be37717e6d Account for cross-mod tile shapes in map previews. 2015-10-24 22:02:46 +01:00
Paul Chote
c0f42904f0 Overhaul the server browser. 2015-10-24 21:58:31 +01:00
Paul Chote
2a210a7314 Fix some lobby yaml nits. 2015-10-24 21:38:09 +01:00
Paul Chote
c87c2270ca Merge pull request #9668 from abcdefg30/balanceRA
RA-Balance changes for the next playtest
2015-10-24 21:16:52 +01:00
Oliver Brakmann
c62d1a395b Merge pull request #9748 from pchote/map-metadata-lint
Add a lint pass for map format/author/title.
2015-10-24 22:13:49 +02:00
Paul Chote
347eb6410c Add a lint pass for map metadata. 2015-10-24 20:36:38 +01:00
Paul Chote
f425323965 Merge pull request #9702 from reaperrr/d2k-airspeed
Increase D2k aircraft speed
2015-10-24 20:35:19 +01:00
abcdefg30
90968022cb Merge pull request #9703 from reaperrr/fix-tanya9673
Fix Tanya's Colt targeting buildings
2015-10-24 21:21:03 +02:00
abcdefg30
caaa779da4 Merge pull request #9736 from obrakmann/fix9693_lua-attack-broken
Fix broken scripted attacks in some missions
2015-10-24 21:18:45 +02:00
Oliver Brakmann
63c687cdce Merge pull request #9746 from matija-hustic/missile_submarine
Revert missile explosion condition to strictly less than zero
2015-10-24 20:11:50 +02:00
Matija Hustić
8f4543c1e1 Changed TD Advanced Guard Tower's firing height 2015-10-24 19:54:36 +02:00
RoosterDragon
bf7aace592 Merge pull request #9714 from Phrohdoh/fix_9713
Fix misleading Utility message.
2015-10-24 18:22:55 +01:00
Matija Hustić
7ca8d85771 Revert explosion condition to strictly less than zero 2015-10-24 18:20:18 +02:00
reaperrr
663de1a6ea Merge pull request #9731 from obrakmann/fix9647_9727_remove_tesla_boost_from_ra
Remove tesla boost from RA
2015-10-24 12:33:57 +02:00
reaperrr
b5cdde6c5d Fix RA building TargetTypes 2015-10-24 08:45:30 +02:00
Taryn Hill
9ab5eacdee Cache the command entered in a variable in Utility.Program.cs for easier reading. 2015-10-23 20:55:18 -05:00
Taryn Hill
780f905959 Fix misleading Utility message
We were reporting that the entered command did not exist
by assuming that any ArgumentException indicated this.

Now we will throw and catch a NoSuchCommandException.
2015-10-23 20:55:13 -05:00
abcdefg30
69496c2f16 Fix the legacy map importer not working 2015-10-24 00:59:14 +02:00
Oliver Brakmann
42d2e016ed Fix broken scripted attacks in some missions
In all three cases, the failure came down to the targets not being declared as enemies to the attackers.

Recent changes to the attack code made it impossible to attack friendly or neutral things with the Lua API's Attack() method. Changing the allegiance of affected parties fixed it, or, in the case of Soviet 02a, using force-attack.
2015-10-24 00:36:09 +02:00
Oliver Brakmann
6420a6ec8a Allow force-attacking things with the Lua API's Attack() method 2015-10-24 00:27:23 +02:00
abcdefg30
f6d1e51050 Merge pull request #9708 from r34ch/chronotank-extra-bar
Charge now using ticks and fixed extra bar time formula.
2015-10-23 23:29:20 +02:00
DArcy Rush
1e2101fab9 Add an upgrade rule. 2015-10-23 22:22:55 +01:00
Oliver Brakmann
206f644949 Merge pull request #9672 from penev92/fixAutoTarget
Fix a series of visibility/targeting bugs
2015-10-23 20:53:03 +02:00
Oliver Brakmann
9c75079b2e Remove tesla boost from RA 2015-10-23 19:51:39 +02:00
abcdefg30
fcd27707d7 Merge pull request #9705 from reaperrr/misc-cleanup
Misc yaml formatting cleanup
2015-10-23 14:38:44 +02:00
abcdefg30
60d7880b77 Merge pull request #9719 from penev92/d2kTimer
Bring back the observer clock for D2k
2015-10-23 14:29:57 +02:00
abcdefg30
ff02644ea1 Merge pull request #9725 from atlimit8/InvalidOperationException-to-YamlException-in-Warhead-RulesetLoaded
Replace InvalidOperationException with YamlException in SpreadDamageWarhead
2015-10-23 14:11:21 +02:00
atlimit8
6992decad0 InvalidOperationException => YamlException in SpreadDamageWarhead 2015-10-23 02:37:39 -05:00
reaperrr
d0c9d743cf Merge pull request #9722 from teees/cursor-fix
use right cursor for ion and nuke
2015-10-23 09:04:52 +02:00
teees
43eda007d6 disable buildings and cyborgs with emp 2015-10-23 08:52:41 +02:00
teees
dfb1c7a357 shutdown power when buildings get emp disabled 2015-10-23 08:52:40 +02:00
atlimit8
173f85319a Merge pull request #9715 from teees/mouseovereditor
Show owner and faction of units in map editor tooltips
2015-10-22 20:10:33 -05:00
atlimit8
7de98ad6d8 Merge pull request #9635 from RoosterDragon/occupy-space-perf
Speed up checks for IOccupySpace trait
2015-10-22 18:28:57 -05:00
Pavel Penev
35b926705c Bring back the observer clock for D2k 2015-10-23 01:04:49 +03:00
Pavel Penev
a69f26b705 Fix players being able to manually attack invisible structures 2015-10-23 00:27:46 +03:00
Pavel Penev
000c701414 Fix actors ignoring Disguise 2015-10-23 00:27:43 +03:00
Pavel Penev
8c7bdae617 Fix AutoTarget acquiring targets under fog/shroud 2015-10-23 00:27:42 +03:00
RoosterDragon
b30fc2c725 Merge pull request #9696 from RoosterDragon/vs-sln
Allow VS2015 to format solution file
2015-10-22 21:04:01 +01:00
Oliver Brakmann
b739151eaf Merge pull request #9711 from penev92/fixMapEditor
Fix D2kEditorResourceLayer starting NetWorth
2015-10-22 19:56:57 +02:00
evgeniysergeev
907df4800a flip or/and mirror sprites with negative width and heigth 2015-10-22 20:53:15 +03:00
abcdefg30
ac95dc65dd Clean SONAR up 2015-10-22 17:21:44 +02:00
abcdefg30
64931db796 Add camera.spyplane and let camera.paradrop inherit CAMERA 2015-10-22 17:21:43 +02:00
abcdefg30
234796ef6f Remove ProximityCaptor from CAMERA and camera.paradrop 2015-10-22 16:46:22 +02:00
abcdefg30
6eb5dcb6cf Remove DetectCloaked from CAMERA 2015-10-22 16:43:12 +02:00
abcdefg30
7c2d3682b0 Reduce the range of FLAK-23 from 8c0 to 6c0 2015-10-22 16:43:11 +02:00
abcdefg30
f675c17640 Remove junk values (5c0 is the default) 2015-10-22 16:43:11 +02:00
abcdefg30
1a7a184730 Add cloak to HIJACKER 2015-10-22 16:43:10 +02:00
abcdefg30
065386f134 Increase Crushable: WarnProbability: to 95 for HIJACKERs 2015-10-22 16:43:09 +02:00
abcdefg30
3f7a65e1bc Reduce chinook sight range 2015-10-22 16:43:08 +02:00
teees
326f82242d use right cursor for ion and nuke 2015-10-22 14:40:00 +02:00
reaperrr
f7b8eaf1ac Add height visualization to CombatDebugOverlay 2015-10-22 13:21:57 +02:00
reaperrr
c1b805ce42 Lower TS wall blocking height
Allows Tick Tanks to shoot over them from certain angles/distances, like in the original.
2015-10-22 12:19:43 +02:00
reaperrr
9b2cdd4457 Add Height property to BlocksProjectiles 2015-10-22 12:19:42 +02:00
teees
9292219d3b hover only when airborne 2015-10-22 10:30:33 +02:00
teees
36753b5d99 change hovers trait to be upgradeable 2015-10-22 10:29:26 +02:00
teees
f9c3446849 Added owner name and faction to map editor tooltips 2015-10-22 09:43:06 +02:00
teees
7f96ee4589 Multi line simple tooltips 2015-10-22 09:42:50 +02:00
Pavel Penev
f7a63ab2f8 Fix D2kEditorResourceLayer starting NetWorth 2015-10-22 01:10:16 +03:00
Pavel Penev
ccddc37c08 Merge pull request #9701 from pchote/widget-baseclass
Add a common ChromeLogic base class and lint verification.
2015-10-22 00:39:43 +03:00
Oliver Brakmann
a0816b7dea Merge pull request #9692 from pchote/lobby-irc
Integrate global chat with the lobby.
2015-10-21 21:04:54 +02:00
Paul Chote
8e59c4a106 Make the lobby buttons consistent across mods. 2015-10-21 19:38:28 +01:00
Paul Chote
fa2b10b269 Integrate global chat with the server lobby. 2015-10-21 19:38:28 +01:00
Paul Chote
3d7d7ff2a5 Allow chrome yaml to define disabled text fields. 2015-10-21 19:38:28 +01:00
Paul Chote
d6c75844bf Add a lint pass to check chrome logic validity. 2015-10-21 19:35:35 +01:00
Paul Chote
b6f463729b Add a ChromeLogic base class for chrome logic. 2015-10-21 19:35:35 +01:00
Pavel Penev
f68da6ada7 Small refactoring to AutoTarget
- Move a check for AutoTargetIgnore up the chain
 - Simplify some LINQs to a single .FirstOrDefault()
 - Rename local variable
2015-10-21 21:09:26 +03:00
atlimit8
1e890a921f Merge pull request #9709 from reaperrr/unitsat-actorsat
Rename ActorMap *UnitsAt* occurences to *ActorsAt*
2015-10-21 09:56:41 -05:00
DArcy Rush
0111f0d750 Charge now using ticks and fixed extra bar time formula.
ChargeTime has been changed to ChargeDelay and is
measured in ticks rather than seconds.

The formula for working out the extra bar time has
been fixed to work properly at different charge delays.
2015-10-21 12:08:44 +01:00
atlimit8
5f3d735864 Merge pull request #9700 from r34ch/chronotank-extra-bar
Use support power like charge bar for Chronotank instead of pips.
2015-10-21 03:32:59 -05:00
reaperrr
78def7330e Make TS laser weapon names more descriptive and remove comments 2015-10-21 10:07:50 +02:00
reaperrr
5615719d28 Fix WithMuzzleOverlay upgrade rule to properly cover cases with @ separator 2015-10-21 10:07:49 +02:00
reaperrr
8e6d5bd603 Misc yaml formatting/style fixes 2015-10-21 10:07:48 +02:00
reaperrr
1a08e6de77 Add Music trait to maps (applied upgrade rule) 2015-10-21 08:20:48 +02:00
Pavel Penev
8c32f7ff9f Merge pull request #9697 from RoosterDragon/irc-no-force-copy
Don't force SmarIrc4net to be copied to output
2015-10-21 07:58:57 +03:00
reaperrr
6f2292d14b Increase D2k aircraft speed 2015-10-21 06:55:31 +02:00
DArcy Rush
ecccc8bc68 Chronotank uses extra bar when charging.
The two blue pips have been replaced by
a magenta charge bar.
2015-10-20 23:14:08 +01:00
RoosterDragon
983032205f Merge pull request #9593 from huwpascoe/HealthTrait
Moved Health to OpenRA.Mods.Common
2015-10-20 20:59:04 +01:00
RoosterDragon
557731bc6b Don't force SmarIrc4net to be copied to output.
Instead, it will be implicitly included since it is a reference. This avoids pulling in the documentary .xml file.
2015-10-20 20:06:44 +01:00
Oliver Brakmann
03e47a9cb7 Merge pull request #9682 from pchote/polish-mapchooser
Polish mapchoosers
2015-10-20 20:38:07 +02:00
RoosterDragon
9049ae7bfc Allow VS2015 to format solution file. 2015-10-20 19:17:24 +01:00
Oliver Brakmann
a547f55c6f Merge pull request #9646 from matija-hustic/missile_fixup
Temporary fix for missiles launched from zero height
2015-10-20 20:16:59 +02:00
Pavel Penev
dc47288ce2 Merge pull request #9695 from RoosterDragon/fix-sln
Fix solution file
2015-10-20 21:14:35 +03:00
RoosterDragon
7448093b12 Fix solution file. 2015-10-20 19:08:05 +01:00
Oliver Brakmann
72a0f7e69c Merge pull request #9633 from Mailaender/movement-class-logs
Added the movement classes of the domain index to the debug logs
2015-10-20 20:01:10 +02:00
Pavel Penev
11210109f4 Merge pull request #9675 from abcdefg30/missionprefixes
Remove the prefixes of all red alert missions
2015-10-20 17:05:32 +03:00
abcdefg30
7d97f22f11 Merge pull request #9681 from pchote/fix-d2k-refinery
Fix D2K refinery flames.
2015-10-19 21:49:14 +02:00
abcdefg30
30e03b5d0b Align the titles of all ra missions 2015-10-19 21:40:13 +02:00
Paul Chote
f53cdbfb35 Polish RA map chooser. 2015-10-19 18:36:37 +01:00
Paul Chote
9c3d278853 Polish TD map chooser. 2015-10-19 18:02:14 +01:00
Paul Chote
8c50f444ec Fix refinery flame animation. 2015-10-19 17:54:05 +01:00
Paul Chote
a9424d0fa7 Hide the docking animation when it is not active. 2015-10-19 17:43:27 +01:00
abcdefg30
b64e4886a7 Remove the prefixes of all red alert missions 2015-10-18 21:59:07 +02:00
Matthias Mailänder
ec56d2ec88 Merge pull request #9674 from OpenRA/fixFremen
Fix a typo on the Fremen Select voices
2015-10-18 21:47:16 +02:00
Pavel Penev
fd577f4b7c Fix a typo on the Fremen Select voices 2015-10-18 22:24:14 +03:00
abcdefg30
919ba7762c Merge pull request #9657 from Biofreak1987/soviet-06b
Add soviet-06b
2015-10-18 21:19:45 +02:00
Biofreak1987
4b7f5f2c1f Add soviet-06b 2015-10-18 21:12:57 +02:00
clemty
2dfa39bdfb Add gdi06 2015-10-18 21:01:11 +02:00
abcdefg30
ce95ff074a Add checks for missing music tracks 2015-10-18 20:43:47 +02:00
abcdefg30
0c373cc8c4 Remove an unused using 2015-10-18 20:43:46 +02:00
abcdefg30
4afef8868e Add lua support for playing background music 2015-10-18 20:43:45 +02:00
abcdefg30
76ada5176f Merge pull request #9656 from Biofreak1987/soviet-06a
Add soviet-06a
2015-10-18 20:26:25 +02:00
Biofreak1987
7fcde4a7c9 Add soviet-06a 2015-10-18 20:17:44 +02:00
Oliver Brakmann
27e898f4ee Merge pull request #9512 from abcdefg30/atreides02b
Add atreides02b
2015-10-18 20:07:18 +02:00
abcdefg30
8caa5511c3 Fix the Enemies: entries in all d2k missions 2015-10-18 19:53:41 +02:00
abcdefg30
6eb4ba2a7c Add bricks to the harkonnen base in atreides02a 2015-10-18 19:53:40 +02:00
abcdefg30
7347278d79 Add atreides02b.lua to OpenRA.sln 2015-10-18 19:53:40 +02:00
abcdefg30
2467c3a76f Fix the description of atreides02a 2015-10-18 19:53:39 +02:00
abcdefg30
08ee4fe02d Adjust the descriptions of the atreides01 missions 2015-10-18 19:53:38 +02:00
abcdefg30
4cc73ab9a7 Add atreides02b 2015-10-18 19:53:37 +02:00
Matthias Mailänder
742aa01284 Merge pull request #9666 from pchote/fix-startingmusic-clash
Fix map StartingMusic overriding BackgroundMusic initialization.
2015-10-18 19:36:39 +02:00
Oliver Brakmann
c1dda97836 Merge pull request #9586 from pchote/irc-common
Overhaul IRC in preparation for the global chat UI
2015-10-18 19:31:07 +02:00
abcdefg30
674b1672f5 Merge pull request #9488 from atlimit8/MapMusic
Map Music
2015-10-18 17:47:26 +02:00
atlimit8
63513af027 Load music after mounting map 2015-10-18 09:53:39 -05:00
atlimit8
90bdeb1e92 Move external Fort Lonestar assets into map directory 2015-10-18 09:53:39 -05:00
Oliver Brakmann
d216362a56 Merge pull request #9655 from Biofreak1987/soviet-02b
Add soviet-02b
2015-10-18 14:47:36 +02:00
Biofreak1987
dc90a35aa0 Add soviet-02b 2015-10-18 14:41:07 +02:00
abcdefg30
f4d937094d Merge pull request #9664 from reaperrr/td-aggreg-seq
Use aggregate sequences for all TD flame/chem muzzles
2015-10-18 12:37:45 +02:00
Pavel Penev
9d76c61b8b Merge pull request #9660 from abcdefg30/factionalign
Fix the faction in the lobby being misaligned
2015-10-18 12:57:40 +03:00
Paul Chote
fb631367ea Fix map StartingMusic overriding BackgroundMusic. 2015-10-18 09:56:12 +01:00
Matthias Mailänder
b14f5ca608 Merge pull request #9661 from pchote/editor-preview-fix
Update the UID stored in the map file after saving.
2015-10-18 08:27:22 +02:00
reaperrr
48babec519 Use aggregate sequences for all TD flame/chem muzzles 2015-10-18 03:23:05 +02:00
reaperrr
380f30ed13 Merge pull request #9547 from pchote/aggregate-sequences
Add support for aggregate sequences
2015-10-18 02:23:23 +02:00
Pavel Penev
6c94eef763 Merge pull request #9662 from reaperrr/color_remap2
Fix hardcoded player color ramp Lerp
2015-10-18 02:29:56 +03:00
reaperrr
51aca8de9a Fix hardcoded player color ramp Lerp 2015-10-18 01:21:59 +02:00
reaperrr
d2f656737b Merge pull request #9654 from evgeniysergeev/color_remap
fix player color remap to handle RemapIndex: with any number of entri…
2015-10-18 01:05:11 +02:00
Paul Chote
cf875c3db6 Update the UID stored in the map file after saving. 2015-10-17 23:25:52 +01:00
Pavel Penev
3db724e6dd Merge pull request #9640 from abcdefg30/luaSLN
Add the missing lua files to OpenRA.sln
2015-10-18 01:11:31 +03:00
abcdefg30
e76bb593a2 Fix the faction in the lobby being misaligned 2015-10-18 00:01:00 +02:00
abcdefg30
4daf22e759 Merge pull request #9634 from pchote/fix-bridge-huts
Fix bridge destruction and repair.
2015-10-17 23:51:14 +02:00
Paul Chote
940bc310c3 Use aggregate sequences for TD flame muzzle. 2015-10-17 22:50:22 +01:00
Paul Chote
9ce8544e34 Add support for aggregate sequences. 2015-10-17 22:50:22 +01:00
abcdefg30
bc9abdb3db Merge pull request #9476 from pchote/depthbuffer
Make the TS terrain depth data available for use by shaders.
2015-10-17 23:45:31 +02:00
abcdefg30
501a965c63 Add the missing lua files to OpenRA.sln 2015-10-17 23:38:49 +02:00
abcdefg30
5cc69d7877 Rename some lua files 2015-10-17 23:38:47 +02:00
Paul Chote
83949b250a Add a visualisation mode for depth sprites.
For now this displays the raw sprites.  It will
eventually be repurposed for rendering the proper
depth data.
2015-10-17 22:35:47 +01:00
Paul Chote
b08adbeb61 Add support for boolean uniforms. 2015-10-17 22:35:47 +01:00
Paul Chote
3665d8f19b Send TS terrain depth data to the GPU. 2015-10-17 22:35:07 +01:00
Paul Chote
9a5483fea7 Send TS terrain depth data to the GPU. 2015-10-17 22:34:46 +01:00
Paul Chote
d5fd8e5828 Use varyings for masks instead of overloading gl_TexCoord. 2015-10-17 22:28:19 +01:00
Paul Chote
e819ff832b Record the SheetType in each Sheet. 2015-10-17 22:28:19 +01:00
Matthias Mailänder
8d0d789e40 fix bridge hut selection priority 2015-10-17 22:23:44 +01:00
Paul Chote
4226370495 Fix bridge destruction and repair. 2015-10-17 22:23:44 +01:00
Paul Chote
a3fe2b3d35 Overhaul the IRC implementation.
* Simplified UI plumbing.
* Improves handling of errors and kicks.
* Persists chat history between session.
* Fixes leaks of the old widget tree when exiting.
* A few small UI polish improvements.
2015-10-17 22:13:22 +01:00
Paul Chote
386f252736 Implement ObservableList collection. 2015-10-17 22:13:22 +01:00
Paul Chote
4ba78f65b9 Add Dispose support to widget logic objects. 2015-10-17 22:13:22 +01:00
evgeniysergeev
0830e4a2c0 fix player color remap to handle RemapIndex: with any number of entries, not only 16 colors 2015-10-17 22:47:03 +03:00
Matthias Mailänder
426e187a4c Merge pull request #9515 from Biofreak1987/soviet03
Add soviet03
2015-10-17 17:05:20 +02:00
Matthias Mailänder
eab5e474cb Merge pull request #9637 from abcdefg30/newTDdelay
Reduce InitialSpawnDelay for crates in TD
2015-10-17 15:15:54 +02:00
Biofreak1987
628e75d484 Add Soviet03 2015-10-17 12:46:25 +02:00
Matthias Mailänder
66a2512c21 Merge pull request #9638 from JoppyFurr/bleed
Change mouse cursors while joystick scrolling
2015-10-17 09:07:56 +02:00
reaperrr
5778d1621a Merge pull request #8987 from Mailaender/spiceblooms
Added spice blooms
2015-10-16 19:38:21 +02:00
Pavel Penev
3abf2af9ff Merge pull request #9649 from r34ch/balance-mcv-crate
Balance mcv crate
2015-10-16 18:41:56 +03:00
DArcy Rush
2cc3cafdd2 Rebalance MCV crate in TS mod
Completely removes the chance of getting an MCV from a crate
in the TS mod unless the player has no base remaining.
2015-10-16 16:23:17 +01:00
DArcy Rush
e6417abb51 Rebalance MCV crate in RA mod
Completely removes the chance of getting an MCV from a crate
in the RA mod unless the player has no base remaining.
2015-10-16 16:22:37 +01:00
abcdefg30
d5a6d9949c Remove the now unnecessary InitialSpawnDelay: 0 from the dropzone maps 2015-10-16 14:44:48 +02:00
abcdefg30
7624256001 Set InitialSpawnDelay to 0
and set the value to 1500 in the default mods.
2015-10-16 14:42:11 +02:00
Matija Hustić
5fe7c4af4d Temporary fix for missiles launched from zero height 2015-10-16 10:22:58 +02:00
Pavel Penev
8cbb132764 Merge pull request #9644 from hypercube33/patch-1
Update gdi-vehicles.yaml
2015-10-16 10:32:42 +03:00
hypercube33
093aea81c4 Update gdi-vehicles.yaml 2015-10-15 20:40:33 -05:00
Joppy Furr
6ded247d0c Change mouse cursors while joystick scrolling
This patch adds mouse cursors to the joystick scrolling feature.

On Tiberian Sun, which itself had joystick scrolling, the same cursors are
used as in the original game.

As the older games did not have joystick scrolling, I've had to make a
best-effort guess as to what were suitable cursors.
  -> When scrolling in all directions is available, the default arrow
     cursor is used.
  -> When a direction is blocked, the edge-scrolling blocked direction
     cursor is used.
2015-10-16 11:53:53 +13:00
reaperrr
2f69711341 Rename ActorMap *UnitsAt* occurences to *ActorsAt*
These enumerate actors in general, not just mobile actors (which the term 'unit' usually refers to).
2015-10-16 00:07:06 +02:00
abcdefg30
fd37869a88 Merge pull request #9636 from RoosterDragon/ai-mcv-perf
Remove a redundant check
2015-10-15 12:21:49 +02:00
RoosterDragon
a4338d9350 Remove a redundant check in FindAndDeployBackupMcv.
This avoids enumerating the mcvs twice.
2015-10-14 21:06:37 +01:00
RoosterDragon
262ab408b5 Speed up checks for IOccupySpace trait.
Eagerly load the trait (if it exists) in Actor, and use this reference to avoid having to perform self.Info.HasTraitInfo<IOccupySpaceInfo>() checks.
2015-10-14 20:46:15 +01:00
Matthias Mailänder
e0fa63ae19 also mention the movement class of the domain index in logs 2015-10-14 20:34:20 +02:00
Oliver Brakmann
410f121a1e Merge pull request #8717 from matija-hustic/missile
Some work on the missile projectile
2015-10-13 19:02:25 +02:00
Pavel Penev
b161c58bbc Merge pull request #9622 from DSUK/test_fix
Fixed TFD Installation.
2015-10-13 10:48:42 +03:00
Pavel Penev
d070971272 Merge pull request #9618 from abcdefg30/cncplanes
Increase planes' CruiseAltitude in cnc
2015-10-13 09:52:52 +03:00
James
5000369463 Fixed TFD Not Creating Install Directory 2015-10-12 19:52:49 +01:00
James
b071bcf28c Added myself to AUTHORS 2015-10-12 19:52:49 +01:00
abcdefg30
5242bc88f7 Increase planes' CruiseAltitude in cnc 2015-10-12 17:26:28 +02:00
Huw Pascoe
c95fc793e4 Moved Health trait to OpenRA.Mods.Common
In preparation for custom hitboxes.
2015-10-12 01:56:00 +01:00
Huw Pascoe
5a81d5dfa7 Created IHealth interface and cleanup.
To decouple the Health trait from OpenRA.Traits.
DisplayHp renamed to DisplayHP and HealthExts moved
moved next to Actor.Kill() for consistency.
2015-10-12 01:55:59 +01:00
Matija Hustić
cd8a15271c Downward lookahead.
Added downward lookahead capability.
2015-10-11 22:15:30 +02:00
Matija Hustić
12b4f8ccf4 Programatic YAML upgrade 2015-10-11 22:03:06 +02:00
Matija Hustić
b9e57d33c3 Added lookahead, launch speed & angle computation.
The missiles should be more intelligent, avoiding cliffs,
surmounting inclines and flexibly selecting appropriate
launch speed and angle to avoid a close incline or miss
a close target.
2015-10-11 22:02:02 +02:00
Matija Hustić
41f57f2a15 Missile projectile refactor.
Introduces:

Vertical rate of turn
Customizable vertical launch angle
Delayed activation of the homing mechanism / propulsion
Freefall while propulsion deactivated
Customizable explosion altitude (for airburst)
Customizable cruise altitude (when target out of range)
Height checks for terrain impact and shadow rendering
Acceleration (instead of constant speed from launch to impact)
2015-10-11 22:02:01 +02:00
Matthias Mailänder
a79b71c608 Merge pull request #9581 from matija-hustic/attackmove_defendstance
Gets AttackMove to work with 'Defend' stance
2015-10-11 21:28:35 +02:00
Matthias Mailänder
40eb7fa074 Merge pull request #9588 from pchote/fix-recoil
Fix sprite turret recoil.
2015-10-11 21:21:48 +02:00
abcdefg30
9e24d4ec79 Merge pull request #9590 from pchote/fix-debug-case
Fix debug menu terminology.
2015-10-11 20:45:13 +02:00
Herve-M
4366593b33 2 pass replay loader (fix freeze) close #6241 2015-10-11 20:21:19 +02:00
Matthias Mailänder
4437bce132 Merge pull request #9459 from reaperrr/d2k-power-misc
Change D2k power draw and various other aspects to match original
2015-10-11 19:48:41 +02:00
Matthias Mailänder
770afd520b let the crusher take damage on spice explosions 2015-10-11 19:30:28 +02:00
Matthias Mailänder
1887875413 make Devastators crush walls 2015-10-11 19:30:28 +02:00
Matthias Mailänder
c6eff7023a add spice blooms 2015-10-11 19:30:28 +02:00
Matthias Mailänder
f2663c18a3 add an empty sprite 2015-10-11 19:30:28 +02:00
Christopher Grant
246f85413f document ThrowsShrapnel 2015-10-11 19:30:24 +02:00
Matthias Mailänder
6107eb389b Merge pull request #9600 from abcdefg30/tanyadamage
Fix tanya not being able to damage barrels
2015-10-11 19:26:27 +02:00
Matija Hustić
1ba81d7c97 Fixes bad comment in UpgradeRules
https://github.com/OpenRA/OpenRA/pull/8768/files#r41694572
2015-10-11 19:23:10 +02:00
Matija Hustić
2a0a7541ba Gets AttackMove to work with 'Defend' stance 2015-10-11 19:23:08 +02:00
Christopher Grant
a378abe7c1 Moved RandomWalk to OpenRA.Traits.Util 2015-10-11 18:59:11 +02:00
reaperrr
5646f4118f Make D2k infantry no longer attract worms 2015-10-11 16:28:41 +02:00
reaperrr
0629cde10f D2k implement classic engineer capturing, reduce Fremen cloak delay, add cloak to Saboteur 2015-10-11 16:27:39 +02:00
reaperrr
efde2ab8ff Enable Carryall self-healing 2015-10-11 16:27:36 +02:00
reaperrr
a94b8f5f0c Enable self-healing on D2k MCV, Harvester and Devastator to match original
Additionally change harvester PipCount and Capacity to match original.
2015-10-11 16:27:35 +02:00
reaperrr
5d20a9e4f2 Tweak emitted infantry types of D2k construction yard 2015-10-11 16:27:34 +02:00
reaperrr
4292a05470 Tweak D2k barracks RallyPoint offset 2015-10-11 16:27:33 +02:00
reaperrr
6dd5e3b77a Reduce D2k wall line build range 2015-10-11 16:27:32 +02:00
reaperrr
e8defccd95 Remove stealth detection from D2k buildings 2015-10-11 16:27:30 +02:00
reaperrr
70163e9c86 Change D2k building power draw/output to original values 2015-10-11 16:27:29 +02:00
Oliver Brakmann
421b15cad1 Merge pull request #9562 from Biofreak1987/soviet07-fix
Fix early game over in soviet07
2015-10-11 15:43:26 +02:00
Oliver Brakmann
42b04b8a6f Merge pull request #9450 from atlimit8/SpreadDamageWarheadRangeOnRulesetLoaded
SpreadDamageWarhead Range on ruleset loaded
2015-10-11 15:28:19 +02:00
Oliver Brakmann
244093834c Merge pull request #9447 from atlimit8/CacheFireportsForAttackGarrisoned
Cache AttackGarrisoned fire ports using IRulesetLoaded
2015-10-11 15:26:38 +02:00
Oliver Brakmann
63d1158f94 Merge pull request #8563 from matija-hustic/tesla_boost
Tesla boost for RA2 mod
2015-10-11 14:33:13 +02:00
Biofreak1987
4e36ce2050 Soviet07 fix game over and add healthcrate
-Fix game over
-Add healthcrate
2015-10-11 14:32:51 +02:00
abcdefg30
6aa8f9772a Fix tanya not being able to damage barrels 2015-10-11 14:24:03 +02:00
abcdefg30
b0c1f95ef2 Merge pull request #9486 from reaperrr/fix-9403
Fix AI queueing structure build orders twice at higher game speeds due to lag
2015-10-11 13:51:02 +02:00
reaperrr
3711ef8eb5 Fix AI queueing build orders twice at higher game speeds due to lag
Fixes #9403.
2015-10-11 01:53:25 +02:00
Paul Chote
08df5b9d7d Fix the server reporting for Debug Menu. 2015-10-10 21:41:27 +01:00
Paul Chote
f40dea41d6 Fix capitalisation in Debug menu. 2015-10-10 21:38:53 +01:00
Paul Chote
7e1dfa96be Merge pull request #9584 from obrakmann/fix-d2k-sequence-crash
Fix case sensitivity issue in d2k sequence definitions
2015-10-10 20:46:11 +01:00
Paul Chote
6c0a4e0722 Merge pull request #9453 from reaperrr/d2k-cost
Change D2k Cost and CustomBuildValues to match original
2015-10-10 20:44:33 +01:00
Paul Chote
ad3714e9ec Merge pull request #9406 from reaperrr/d2k-weapon-offsets
Fixed D2k armament offsets and some cleanup
2015-10-10 20:34:02 +01:00
Paul Chote
8954ac585c Merge pull request #9442 from Mailaender/ai-world-check
Fixed AI bots trying to assign orders to units not in the world
2015-10-10 20:21:10 +01:00
Paul Chote
d70fbdf6ce Fix sprite turret recoil. 2015-10-10 19:31:28 +01:00
Matthias Mailänder
4579e8af06 don't let the AI assign orders to units not in the world 2015-10-10 19:06:20 +02:00
Matthias Mailänder
f1b1df1428 Merge pull request #9537 from penev92/fixLaunch
Fix crash when launching the game directly into a mod with missing assets
2015-10-10 18:59:19 +02:00
Matthias Mailänder
dd90d6929f Merge pull request #9567 from abcdefg30/soviet02ownerrow
Hide the owner row of FCOM
2015-10-10 18:50:57 +02:00
Matthias Mailänder
d677192bea Merge pull request #9578 from penev92/deployOnRamps
Add a CanDeployOnRamps property to DeployToUpgrade
2015-10-10 18:44:42 +02:00
Oliver Brakmann
a26e1a1d52 Fix case sensitivity issue in d2k sequence definitions
Game would crash on systems with case-sensitive filesystems when a support-power beacon appeared.
2015-10-10 14:19:02 +02:00
Matija Hustić
c55141c91c Enabled multiple timed upgrades from single source.
This makes the UpgradeManager support requests to grant a timed
upgrade multiple times from a single source.
GrantUpgradeWarhead modified to take advantage of this.
2015-10-09 22:41:23 +02:00
Matija Hustić
03c80fb9c6 Added tesla boost capabilities.
Shock troopers and tesla tanks standing near a tesla coil
will charge it up, enhancing its range, modifying the zap
animation and allowing it to work even when player's power
is down.
The sound for charger weapons edited from
https://www.freesound.org/people/JoelAudio/sounds/136542/
2015-10-09 22:41:21 +02:00
Pavel Penev
db609b12a0 Add a CanDeployOnRamps property to DeployToUpgrade 2015-10-09 17:15:54 +03:00
Pavel Penev
6e1f461e9b Move mod asset validation from BlankLoadScreen.StartGame() to Game.InitializeMod()
This fixes a crash that happens when you try to launch a mod directly while its assets aren't installed.
Additionally should reduce the overhead for dedicated servers (in theory).
2015-10-09 12:34:58 +03:00
Pavel Penev
50679cd6c4 Merge pull request #9576 from obrakmann/fix-broken-infiltration
Fix inverted TargetTypes test in Infiltrates order resolution logic
2015-10-09 01:37:32 +03:00
Oliver Brakmann
6274f2a47e Merge pull request #8768 from matija-hustic/attackbase_refactor
Some work on Attack*
2015-10-08 21:56:22 +02:00
Oliver Brakmann
d741c86ed8 Merge pull request #9549 from pchote/lobby-music
Add a music player to the game lobby.
2015-10-08 21:40:04 +02:00
Oliver Brakmann
784f2425bf Fix inverted TargetTypes test in Infiltrates order resolution logic 2015-10-08 21:21:15 +02:00
Matthias Mailänder
d199ba5048 Merge pull request #9520 from obrakmann/make-scroll-keys-remappable
Add hotkey configuration for scroll keys
2015-10-08 20:15:55 +02:00
Matthias Mailänder
1318a11ed2 Merge pull request #9551 from clemty/editorwindow
Editor: Increase size of editor tile/actor list widget
2015-10-08 20:05:23 +02:00
abcdefg30
4db2704f45 Merge pull request #9568 from reaperrr/fix-chinook-box
Fix RA Chinook selection box size
2015-10-08 16:08:31 +02:00
reaperrr
247bbeb869 Fix RA Chinook selection box size 2015-10-07 22:26:11 +02:00
abcdefg30
ae805726b0 Merge pull request #9563 from HenrytheSlav/polish
Map polish
2015-10-07 22:05:30 +02:00
HenrytheSlav
f120c65b0f Polish for maps Monster tank madness and Arctic triangle affair 2015-10-07 22:02:14 +02:00
Oliver Brakmann
92d8c358b1 Merge pull request #9521 from pchote/produce-support
Implement actor-producing support powers
2015-10-07 21:41:36 +02:00
abcdefg30
c339df6b72 Merge pull request #9564 from pchote/more-maps
Add more TD maps.
2015-10-07 21:31:48 +02:00
abcdefg30
17225c732b Hide the owner row of FCOM 2015-10-07 21:23:15 +02:00
Oliver Brakmann
de5e37539b Merge pull request #9506 from AoAGeneral/upstream/myfeature
TD Additional Balance Changes Revamped
2015-10-07 20:11:00 +02:00
clemty
a4eafa9a15 Increase size of editor tile/actor list widget 2015-10-07 19:38:27 +02:00
Oliver Brakmann
783928f20e Merge pull request #9545 from abcdefg30/selectcrash
Fix a possible crash in WorldInteractionControllerWidget
2015-10-07 19:32:14 +02:00
Paul Chote
f35ea28dfc Add new 2v2 and 3v3 maps. 2015-10-06 23:28:43 +01:00
Paul Chote
51fd1fac75 Restore Deterring Democracy map. 2015-10-06 23:19:43 +01:00
Oliver Brakmann
7eb2c48a1e Merge pull request #9471 from abcdefg30/luaprereq
Add a lua function to check for prerequisites
2015-10-06 22:20:19 +02:00
abcdefg30
be50adbed3 Add a lua function to check for prerequisites 2015-10-06 22:14:23 +02:00
Oliver Brakmann
cd62044a3a Merge pull request #9462 from abcdefg30/sovietfix
Fix a crash in the soviet04 missions
2015-10-06 20:27:16 +02:00
Oliver Brakmann
d4863badb6 Merge pull request #9397 from Herve-M/feat-utility-polish
Add basic arguments validation
2015-10-06 19:23:23 +02:00
Matija Hustić
69696fc154 UpgradeRules YAMLs 2015-10-06 02:00:39 +02:00
Matija Hustić
d94c645046 First step in the attack mechanism's refactor.
Enabled firing multiple armaments at a target simultaneously.
Each armament defines own cursor for targeting.
The force attack modifier influences armament choice for target.
Autotargeting modified to handle firing multiple armaments simultaneously.
As a consequence, healers (medics) no longer require separate Heal
activity and AttackMedic and AutoHeal traits.
2015-10-06 01:46:55 +02:00
Paul Chote
73adfe0bfc Add music player to lobby. 2015-10-05 22:43:19 +01:00
Chris Forbes
72ea009042 Merge pull request #9546 from pchote/lobby-panels
Add panel-transparent to TD
2015-10-06 10:27:25 +13:00
Paul Chote
6dce8a1385 Implement Hunter-seeker support power. 2015-10-05 22:05:02 +01:00
Paul Chote
213ac2d554 Fix Hunter-seeker rules. 2015-10-05 22:05:02 +01:00
Paul Chote
8ae01cf73b Move fremen and saboteur to palace powers. 2015-10-05 22:05:02 +01:00
Paul Chote
b43f9bc524 Add ProduceActorsPower trait. 2015-10-05 22:05:01 +01:00
Paul Chote
9b6dba02a8 Improve customisation of support power targeting. 2015-10-05 22:05:01 +01:00
Paul Chote
cade56084a Don’t render transparent overlays. 2015-10-05 19:15:03 +01:00
Paul Chote
ca5b08968d Add panel-transparent background to TD. 2015-10-05 19:15:02 +01:00
abcdefg30
d7c0d4197c Fix a possible crash in WorldInteractionControllerWidget 2015-10-05 17:23:42 +02:00
abcdefg30
36b7524d37 Merge pull request #9491 from cjshmyr/gameinprogress
Fix incorrect "In progress" time shown in server browser
2015-10-05 16:34:13 +02:00
Curtis Shmyr
2b3432e68e Fix incorrect gametime in progress shown in server browser 2015-10-04 17:08:10 -06:00
abcdefg30
efa8f3f59e Merge pull request #9534 from pchote/refresh-cnc-1v1-maps
Refresh TD 1v1 map choices
2015-10-04 22:08:19 +02:00
gitTerebi
86c57a270b Add hotkey configuration for scroll keys 2015-10-04 22:04:44 +02:00
abcdefg30
c1e1a32010 Merge pull request #9532 from atlimit8/CacheWeaponInfoLookups
Cache WeaponInfo Look-ups
2015-10-04 21:46:27 +02:00
Matthias Mailänder
93dc472020 Merge pull request #9528 from abcdefg30/seedsoutofbounds
Fix a possible crash in ResourceLayer
2015-10-04 21:40:39 +02:00
Matthias Mailänder
243bbe1981 Merge pull request #9527 from abcdefg30/halfsietch
Fix the sietch being DamagedWithoutFoundation
2015-10-04 21:02:24 +02:00
abcdefg30
dcd1638455 Merge pull request #9523 from penev92/fixWalls
Fix TS component towers
2015-10-04 21:01:47 +02:00
Matthias Mailänder
01fc961bd3 Merge pull request #9539 from pchote/lobby-prep
Prepare for lobby layout overhaul.
2015-10-04 20:58:30 +02:00
abcdefg30
e5dca60f5c Merge pull request #9542 from reaperrr/WithRotorOverlay
Rename WithRotor to WithSpriteRotorOverlay
2015-10-04 20:50:59 +02:00
Matthias Mailänder
1a8ec3745b Merge pull request #9540 from obrakmann/fix9530
Fix H and Home keys not working when the shroud debug option is enabled
2015-10-04 20:49:53 +02:00
reaperrr
b722aa6721 Rename WithRotor to WithSpriteRotorOverlay 2015-10-04 20:22:46 +02:00
Oliver Brakmann
f98a55c72f Fix H and Home keys not working when the shroud debug option is enabled 2015-10-04 18:46:05 +02:00
Paul Chote
fba879b954 Add four new 1v1 TD maps, and remove two older ones. 2015-10-04 17:31:13 +01:00
Paul Chote
d5721af91e Inherit map bin size from the root. 2015-10-04 17:26:44 +01:00
Paul Chote
c6740b1bcb Inherit lobby bin size from the root. 2015-10-04 17:26:38 +01:00
Paul Chote
b73f775ef2 Move the player bin header to lobby-players.yaml. 2015-10-04 17:26:32 +01:00
Paul Chote
fb5a6d8ec0 Reorganise the lobby chrome files. 2015-10-04 17:26:25 +01:00
Pavel Penev
044e562457 Merge pull request #9533 from pchote/fix-d2k-assets
Copy palette.bin from disk and check it exists.
2015-10-04 15:20:22 +03:00
Pavel Penev
828c53cd26 Merge pull request #9518 from JoppyFurr/bleed
Tiberian Sun style right-click-and-drag scrolling implementation
2015-10-04 14:45:21 +03:00
Paul Chote
020cce5414 Copy palette.bin from disk and check it exists. 2015-10-04 09:50:06 +01:00
atlimit8
49d7604bd9 Cache WeaponInfo look-ups 2015-10-03 22:29:40 -05:00
Joppy Furr
447049c495 Update AUTHORS 2015-10-04 16:23:07 +13:00
Joppy Furr
07273fa666 Add support for Tiberian Sun style right-click-and-drag scrolling
This patch introduces support for the right-click-and-drag scrolling that
is available in Tiberian Sun and Red Alert 2. It can be enabled by
selecting "Joystick" scrolling in the Input settings.

The speed of the scroll is proportional to the product of the distance of
the drag, and the Scroll Speed selected in the Input settings menu.

A side-effect of this is that events previously tied to right clicks on
the world are now based on the release of the click rather than the press.

The "Middle-Mouse Scrolling:" option is renamed
to "Mouse Scrolling Method:"
2015-10-04 16:22:55 +13:00
Pavel Penev
8b83fac306 Fix WithWallSpriteBody hijacking WithSpriteBody's DefaultAnimation before/during the "make" animation 2015-10-04 04:02:40 +03:00
abcdefg30
e291606dad Fix a possible crash in ResourceLayer 2015-10-04 00:18:38 +02:00
abcdefg30
3ad4aafcef Fix the sietch being DamagedWithoutFoundation 2015-10-03 23:15:33 +02:00
Herve-M
1485dd1675 Add basic arguments validation 2015-10-03 17:21:21 +02:00
Pavel Penev
f2f2fd8871 Merge pull request #9514 from abcdefg30/02aPreview
Fix the preview of atreides02a
2015-10-03 16:38:05 +03:00
Oliver Brakmann
9940efd3cb Merge pull request #9483 from reaperrr/cleanup-assets
Clean up assets
2015-10-03 12:37:55 +02:00
abcdefg30
acdb9a67f6 Fix the preview of atreides02a 2015-10-03 12:31:24 +02:00
atlimit8
a000bf7805 Merge pull request #9400 from reaperrr/fix-airefplaceperf
Fixed massive AI base builder performance issue
2015-10-02 23:18:10 -05:00
reaperrr
2ae0694385 Merge pull request #9054 from penev92/bleed_aircraft
Merge Plane and Helicopter traits
2015-10-03 01:52:30 +02:00
atlimit8
e86eea383a SpreadDamageWarhead.Range loading 2015-10-02 13:42:26 -05:00
atlimit8
dc54841bad cache AttackGarrisoned fire ports using IRulesetLoaded 2015-10-02 13:40:21 -05:00
atlimit8
079cff0a7a IRulesetLoaded Warhead support and better error messages. 2015-10-02 13:40:21 -05:00
reaperrr
87d6b3c7f2 Remove d2k.pal from D2k bits
And use palette.bin instead.
2015-10-02 18:13:49 +02:00
AoAGeneral
f2ca1d272b TD Additional Balance Changes Revamped
Infantry stealth detection: Increase sight range of stealth detection to
2 from 1.

MLRS: Reduce price to 1000 from 1200

Repair pad: Power remains at 30. Repair speed increased. (Interval 15
from 0)

Blue Tiberium: Reduce the value income to 75-90% from 110% (60 from 75)

Infantry evade chance: 75 from 67

Samsites: cost reduced to 700 from 750. Reduced build time (2000 from
2160)

Airstrikes: Increase cool down timer to 3:30 from 3:00.
2015-10-02 03:22:30 -07:00
atlimit8
22183fd5c7 Merge pull request #9465 from huwpascoe/CombatOverlay
Added warhead visualization to combat debug overlay.
2015-10-01 22:14:18 -05:00
Huw Pascoe
cfd179b0c6 Added warhead visualization to combat debug overlay. 2015-10-02 02:48:21 +01:00
Pavel Penev
c33371226c Merge pull request #9435 from ABrandau/bleed
Create disable movement trait
2015-10-02 04:30:22 +03:00
atlimit8
dc1e48556d Merge pull request #9464 from clemty/playername
TD: Lua replace GDI/Nod player reference variables with player/enemy variables
2015-10-01 17:57:27 -05:00
Oliver Brakmann
07d7df0345 Merge pull request #9485 from clemty/n64gdi01fix
Fix crash in cnc64gdi01
2015-10-01 23:38:01 +02:00
clemty
6a3b558227 Fix crash in cnc64gdi01
apparently helicopters can't .Hunt()
I introduced the bug late in testing, so it didn't trigger in review
on the plus side, AI will now attack you from a random direction
2015-10-01 23:00:01 +02:00
Oliver Brakmann
77ed5454dd Merge pull request #9402 from abcdefg30/atreides02a
Add atreides02a
2015-10-01 22:43:48 +02:00
abcdefg30
e9c8ab8d6b Add atreides02a 2015-10-01 21:46:57 +02:00
Oliver Brakmann
3f32730143 Merge pull request #9478 from clemty/pngcrush
PNG file size reduction
2015-10-01 20:18:21 +02:00
Pavel Penev
0ee38de4bb Rename HeliReturn
Rename HeliReturn to HeliReturnToBase to keep somewhat with the convention established for Plane- against Heli- oriented traits.
2015-10-01 20:15:50 +03:00
Pavel Penev
15a5bde7e7 Don't stop rearming if ordered to "Stop" while rearming
This one actually fixes a bug.
2015-10-01 20:15:47 +03:00
Pavel Penev
1ab2a781f1 Add an upgrade rule for Helicopter removal 2015-10-01 20:15:45 +03:00
Pavel Penev
d55541c5f8 Add an upgrade rule for Plane removal 2015-10-01 20:15:43 +03:00
Pavel Penev
8a44366667 Merge Plane and Helicopter into Aircraft 2015-10-01 20:15:41 +03:00
Pavel Penev
0ee1ad3fa4 Add a default value to ReturnToBase's constructor for non-Lua usages 2015-10-01 20:09:16 +03:00
Pavel Penev
4e3d6bde4f Split AircraftMoveOrderTargeter to its own file 2015-10-01 20:09:12 +03:00
Pavel Penev
ce52c62639 Merge pull request #9270 from reaperrr/upgradable-blockproj
Made BlocksProjectiles upgradable
2015-10-01 01:52:00 +03:00
reaperrr
4cf27fc207 Replace duplicate BlockedByActor with BlocksProjectiles.AnyBlockingActorAt 2015-09-30 23:54:21 +02:00
reaperrr
7e1f29d4c5 Made BlocksProjectiles upgradable 2015-09-30 21:54:35 +02:00
RoosterDragon
1b1e4f1dd2 Merge pull request #9174 from reaperrr/radius-explode
Customizable impact victim scan radius
2015-09-30 20:28:17 +01:00
atlimit8
f6180d7fa4 Include add/replace playlist entries support using map.yaml 2015-09-30 10:31:49 -05:00
Pavel Penev
0ed3ef0eb8 Merge pull request #9219 from deniz1a/hide-map-crate
Adds IncludeAllies option to hide-map crate.
2015-09-30 16:15:26 +03:00
Pavel Penev
a31302116c Merge pull request #9475 from clemty/yaml-cleanup
TD mission yaml fixes
2015-09-30 16:09:44 +03:00
Pavel Penev
356fa9d847 Merge pull request #9457 from Phrohdoh/fix#ai
Fix NullReferenceException in HackyAI.BuildUnit
2015-09-30 16:07:57 +03:00
reaperrr
85eba9da1c Remove mouse.shp and mousepal.pal from TS bits 2015-09-30 01:56:13 +02:00
reaperrr
4fd95ee2b2 Remove cursor.pal and mouse.shp from RA bits 2015-09-30 01:56:12 +02:00
reaperrr
3049fa07e0 Remove cursor.pal from TD bits 2015-09-30 01:56:11 +02:00
reaperrr
95709f1157 Remove obsolete mount hack 2015-09-30 01:56:10 +02:00
reaperrr
74308c245c Add AI MinBaseRadius to give more control over and slightly increase performance of AI building placement checks 2015-09-29 22:19:21 +02:00
reaperrr
2b0920398f Add AI MaxResourceCellsToCheck for refinery placement decision 2015-09-29 22:19:20 +02:00
clemty
76de14b6f5 PNG file size reduction
run pngcrush -brute on *.png

before:
 70 File(s)      3.455.140 bytes

after:
 70 File(s)      2.616.088 bytes
2015-09-29 20:47:36 +02:00
reaperrr
17ff3864e8 Merge pull request #9441 from Mailaender/d2k-mouse
Removed the included MOUSE.R8
2015-09-29 20:22:14 +02:00
reaperrr
258d2e2222 Merge pull request #9469 from obrakmann/fix-aircraft-husk-crash-velocity
Fix aircraft husk crash velocity
2015-09-29 20:05:29 +02:00
Nolt
7994d08702 Create #9435 DisableMovementOnUpgrade, rename DisableUpgrade to DisableOnUpgrade and Fixed not showing the blocked move cursor when movement is disabled. 2015-09-28 21:32:00 -03:00
Oliver Brakmann
8c6872fff0 Merge pull request #9387 from pchote/mission-gamespeed
Add game speed dropdown to the mission browser.
2015-09-28 21:05:30 +02:00
clemty
43590e5a67 TD yaml fixes 2015-09-28 20:18:06 +02:00
Taryn Hill
3d7e49655d Fix NullReferenceException in HackyAI.BuildUnit
HackyAIInfo grew a UnitLimits Dictionary that was not null-checked.
Also null-check UnitsToBuild.
2015-09-28 13:17:19 -05:00
Oliver Brakmann
ebfe5a3fd7 Merge pull request #9474 from obrakmann/pr9217
Ensure that we have a working OpenGL context.
2015-09-28 18:26:51 +02:00
Guido L
d0447fd97e Ensure that we have a working OpenGL context. 2015-09-28 18:20:35 +02:00
abcdefg30
7a0a618169 Merge pull request #9309 from reaperrr/missile-airfix
Add margin to CreateEffectWarhead air check
2015-09-28 17:33:46 +02:00
Oliver Brakmann
2f66fc98b9 Merge pull request #9118 from clemty/n64-01
N64 Special Ops - GDI 1
2015-09-27 23:12:57 +02:00
Oliver Brakmann
05e18fe682 Fix aircraft husk crash velocity
This fixes the long glide time aircraft husks had when they were shot down. They are falling down to earth much faster now and the distance covered matches that from release-20150614
2015-09-27 22:53:01 +02:00
clemty
62bad226e5 N64 Special Ops - GDI 1 2015-09-27 22:41:15 +02:00
Oliver Brakmann
8f0ce91f63 Merge pull request #9090 from Mailaender/cloak-reveal
Fixed cloaked units getting revealed by tooltips
2015-09-27 21:26:09 +02:00
clemty
6e315a815c replace GDI/Nod player reference variables with player/enemy
fixes unit production in nod02a and nod02b (killed infantry wouldn't get rebuilt)
2015-09-27 21:18:10 +02:00
abcdefg30
3a68364bc5 Fix a crash in the soviet04 missions 2015-09-27 19:04:38 +02:00
Pavel Penev
7fa7ebe657 Merge pull request #9384 from Mailaender/lint-player-palettes
Added a lint check for player palette references.
2015-09-27 18:44:55 +03:00
atlimit8
8495c1e2a4 Merge pull request #9448 from abcdefg30/oiltip
Don't show "Oil Pump" owner in campaign mission tooltips.
2015-09-27 09:39:17 -05:00
atlimit8
30985ff9c9 Merge pull request #9342 from penev92/mapGrid
Organize map data in Manifest
2015-09-27 09:18:39 -05:00
Matthias Mailänder
f4bb55113c fix cloak getting revealed by frozen actor tooltips 2015-09-27 15:05:07 +02:00
Paul Chote
d1f437e944 Adjust the d2k mission browser layout. 2015-09-27 13:58:57 +01:00
Matthias Mailänder
defba7aece lint check player palette reference
and tell which actor is affected when a problem is found
2015-09-27 14:57:58 +02:00
Paul Chote
36b5eb651e Rename Default game speed to Normal. 2015-09-27 10:28:34 +01:00
Paul Chote
3322f34e7b Add game speed option for missions. 2015-09-27 10:28:34 +01:00
reaperrr
74bcbcc9a8 D2k original starport prerequisites 2015-09-27 04:57:27 +02:00
reaperrr
bccfc33859 D2k original queue build speeds 2015-09-27 04:56:39 +02:00
reaperrr
9cdaf6114d D2k original cost and build speed 2015-09-27 04:56:38 +02:00
Pavel Penev
642468ce0c Add MapGrid class
MapGrid is a mod Manifest field which includes (and thus makes redundant) TileSize, TileShape, SubCells info and MaximumTerrainHeight.
2015-09-27 04:14:43 +03:00
atlimit8
699a7f8227 Merge pull request #9302 from RoosterDragon/alloc-tweaks
Reduce allocations for shroud checks and lost actors.
2015-09-26 15:31:57 -05:00
RoosterDragon
108f2e9b6e Tweak some AI methods to avoid allocations. 2015-09-26 21:12:07 +01:00
RoosterDragon
d70eea5adc Refactor occupied cells visibility checks.
Provide some common extension methods to reduce code duplication, and also use loops instead of LINQ to reduce allocations and provide a minor speedup.
2015-09-26 21:12:05 +01:00
atlimit8
49d351bf22 Merge pull request #9417 from clemty/topleft
Reduce use of Map.Topleft and Map.Bottomright
2015-09-26 14:36:22 -05:00
atlimit8
5e4e085a85 Merge pull request #9445 from RoosterDragon/activity-early-bail
Provide an early exit in RunActivity when there is no activity
2015-09-26 14:02:14 -05:00
RoosterDragon
e016227ddf Merge pull request #9327 from Mailaender/bridge-render-sizes
Fixed bridge rendering glitches
2015-09-26 19:54:43 +01:00
Oliver Brakmann
d667271ab7 Merge pull request #9262 from RoosterDragon/frozen-unify-dict
Speed up FrozenUnderFog.Tick
2015-09-26 20:45:58 +02:00
reaperrr
4c41f8f656 Lint check for SpreadDamageWarhead victim scan radius bonus 2015-09-26 17:46:28 +02:00
reaperrr
33dc50d29c Fix Bullet to consider DistanceAboveTerrain 2015-09-26 17:46:27 +02:00
abcdefg30
512faddb3e Hide the OwnerRow of the "Oil Pump"s tooltip in campaign missions 2015-09-26 17:45:02 +02:00
RoosterDragon
285a3eab2e Merge pull request #8760 from atlimit8/RangeMultiplier
Added [I]RangeMultiplier & made UpgradeMultiplierTraitInfo implement ITraitInfo
2015-09-26 16:24:17 +01:00
abcdefg30
fb97dd9481 Merge pull request #9407 from reaperrr/d2k-nsfremen
Added no stealth map creep fremen to d2k
2015-09-26 17:04:14 +02:00
reaperrr
5ad9eb852c Fix massive AI base builder performance issue
Previously, the Refinery placement check would first collect all cells
with resources inside the MaxBaseRadius, then perform a full findPos check
for each cell until one of them would not return null. The problem was
that if all of the cells returned null (for example if there wasn't enough
space between base center and resource, or if all suitable space was
otherwise occupied), it would basically check all tiles with resources
only to fail finding a suitable position and fall back to the normal
findPos check.

Since nearbyResources already performs a shuffle, I simply made the check
use the first cell from the list and use the basic findPos fallback if
that cell is null.

Closes #4717.
2015-09-26 16:48:03 +02:00
RoosterDragon
faaf1ea1e1 Provide an early exit in RunActivity when there is no activity. 2015-09-26 15:32:26 +01:00
reaperrr
e913fbcb3f Enable no-stealth fremen in map importer 2015-09-26 15:17:19 +02:00
reaperrr
73a07a5e19 Add no stealth map creep fremen to d2k 2015-09-26 15:17:18 +02:00
Matthias Mailänder
64dbaf8e76 Merge pull request #9444 from atlimit8/ModChooserMetricsExtraLine
Remove overridden ButtonBaseLine line in mods/modchooser/metrics.yaml
2015-09-26 14:54:23 +02:00
Matthias Mailänder
3e0330ab8b fix a crash when cloaking trains 2015-09-26 14:48:59 +02:00
atlimit8
361501c40c Remove overridden ButtonBaseLine line in mods/modchooser/metrics.yaml 2015-09-26 07:31:54 -05:00
Matthias Mailänder
9088a58756 Merge pull request #9408 from reaperrr/d2k-debris
Added original D2k debris
2015-09-26 13:56:51 +02:00
Matthias Mailänder
76b53ce9d7 Merge pull request #9288 from RoosterDragon/action-queue-order
Fix ActionQueue ordering
2015-09-26 13:42:56 +02:00
Matthias Mailänder
3884a31550 Merge pull request #9313 from RoosterDragon/actor-eager
Eagerly cache traits in Actor
2015-09-26 13:18:05 +02:00
Matthias Mailänder
83a17710a1 Merge pull request #9418 from reaperrr/d2k-speed
Apply original D2k actor speed
2015-09-26 13:07:49 +02:00
Matthias Mailänder
7063a4a8bb use the supplied MOUSE.R8 2015-09-26 12:42:39 +02:00
Paul Chote
9aa5828155 Merge pull request #9307 from obrakmann/fix6174_beacon-key-in-replays
Make some navigation keys available to spectators
2015-09-26 11:30:50 +01:00
Paul Chote
7ceb283034 Merge pull request #9263 from penev92/assetInstallation
Move asset installation to the ModChooser
2015-09-26 10:40:04 +01:00
Oliver Brakmann
c7cfd40f65 Merge pull request #9060 from abcdefg30/cratespawndelay
Add a InitialSpawnDelay to CrateSpawner
2015-09-26 01:26:41 +02:00
Oliver Brakmann
3e2102192e Merge pull request #9437 from pchote/fix-bogus-memory-copy
Rewrite BlowfishKeyProvider.ProcessPredata using safe code.
2015-09-26 00:47:22 +02:00
Paul Chote
7dcb896f3d Rewrite BlowfishKeyProvider.ProcessPredata using safe code.
Fixes #2441.  This error would occur when the memory
regions were allocated at particular addresses when
running a mono-compiled binary on a .net runtime.

The data would be copied to the pointer returned
from a fixed() statement, but the managed array
would *not* be updated with the new data.  This
caused DecryptKey to silently return a bogus key
full of zeros, and the mix file header decryption
would subsequently fail.
2015-09-25 22:13:55 +01:00
abcdefg30
4c52d10aaf Fix an oversight in ConvertFloatToIntPercentage 2015-09-25 17:00:08 +02:00
abcdefg30
ccf184413e Add an upgrade rule for the float to int percentage change 2015-09-25 17:00:07 +02:00
abcdefg30
589e673aa9 Replace the float WaterChance by an integer percentage 2015-09-25 17:00:06 +02:00
abcdefg30
e7c62b070b Add an upgrade rule for the seconds -> ticks change
and update the default mods
2015-09-25 17:00:06 +02:00
abcdefg30
277f9acb89 Replace seconds by ticks 2015-09-25 16:53:45 +02:00
abcdefg30
7fd3ae7db9 Adjust the dropzone maps 2015-09-25 16:53:44 +02:00
abcdefg30
10c2a897f4 Small code cleanup 2015-09-25 16:53:44 +02:00
abcdefg30
a2af88da21 Add a InitialSpawnDelay to CrateSpawner 2015-09-25 16:53:43 +02:00
Oliver Brakmann
0e9257abcf Merge pull request #9239 from penev92/clearFootprint
Move actors outside of the desired footprint when placing a building
2015-09-25 15:34:38 +02:00
Pavel Penev
059769de76 Merge pull request #9346 from reaperrr/fix-silo-preview
Fixed silo placement preview
2015-09-25 16:26:21 +03:00
Pavel Penev
b26e622bee Merge pull request #9284 from clemty/newtiles
TD: Add additional desert tiles (work originally by psydev)
2015-09-25 16:20:05 +03:00
reaperrr
74da2a2c72 Add TargetExtraSearchRadius to SpreadDamageWarhead
Allows to customize the victim scan radius. Necessary to ensure that actors where health radius is close enough, but CenterPosition isn't, properly receive damage.
2015-09-25 15:11:06 +02:00
abcdefg30
8a0023b40a Merge pull request #9248 from r34ch/ra-balance-changes
Lower shocktrooper health
2015-09-25 14:50:39 +02:00
reaperrr
010d8e8147 Upgrade rule 2015-09-25 14:30:15 +02:00
reaperrr
59a96ab0ef Make sure silo animation is properly updated on owner change 2015-09-25 14:26:22 +02:00
reaperrr
522e7d5d04 Add custom sequence support to WithSiloAnimation
Additionally add description to Stages property, and remove unnecessary var (information is only needed once anyway).
2015-09-25 14:26:21 +02:00
Pavel Penev
e67bd7cffe Merge pull request #9425 from abcdefg30/chosecrash
Fix possible crashes in the MapChooserLogic
2015-09-25 12:38:57 +03:00
atlimit8
558eea0bd5 Merge pull request #9390 from reaperrr/rename-flashoverlay
Renamed WithMuzzleFlash to WithMuzzleOverlay
2015-09-24 20:04:13 -05:00
atlimit8
74a9dc6793 Added IRangeMultiplier 2015-09-24 16:37:43 -05:00
atlimit8
65c1d2f5c1 Add IRulesetLoaded for late binding in trait info getting all rules 2015-09-24 16:26:42 -05:00
atlimit8
a8106a9999 Made UpgradeMultiplierTraitInfo implement ITraitInfo 2015-09-24 16:17:06 -05:00
atlimit8
527675db8d Attack activities use armaments directly through constructor 2015-09-24 16:17:06 -05:00
clemty
d4e1b1ba48 reduce use of Map.Topleft and Map.Bottomright as requested in #8549 2015-09-24 21:03:36 +02:00
reaperrr
5b5164211e Rename WithMuzzleFlash to WithMuzzleOverlay 2015-09-24 20:23:31 +02:00
abcdefg30
e989ce2ef2 Fix possible crashes in the MapChooserLogic 2015-09-24 16:57:03 +02:00
reaperrr
e8f18d2c3f Remove incorrect anti-air capability from quad rocket 2015-09-24 14:43:03 +02:00
reaperrr
3ce18834ed Fix siege tank weapon explosion sound 2015-09-24 14:43:02 +02:00
reaperrr
1b39936e80 Use both firing offsets for missile tank and missile tower
Remove missile tank FireDelay. Fix Report of missile tank weapon. Fix and explosion animation of both missile weapons and use less audible explosion sound (had no sound at all in the original).
2015-09-24 14:43:01 +02:00
reaperrr
63344aafcb Remove duplicate d2k explosion sequences, increase explosion tick, fix deviator explosion offset 2015-09-24 14:43:00 +02:00
reaperrr
03508c7bda Fix d2k bazooka explosion
to match original.
2015-09-24 14:42:59 +02:00
reaperrr
3fb1ec91b8 Tweak d2k armament offsets of some actors 2015-09-24 14:42:58 +02:00
Pavel Penev
cdd4590ece Merge pull request #8839 from RoosterDragon/test-sync-implementations
Test sync implementations
2015-09-24 15:17:33 +03:00
Pavel Penev
c41446e022 Merge pull request #9139 from Mailaender/editor-cash-counter
Added a total resource cash counter to the map editor
2015-09-24 15:07:15 +03:00
reaperrr
2b867c99b4 Original d2k terrain speeds 2015-09-24 13:46:07 +02:00
reaperrr
f762bcb252 Fix D2k aircraft HP and armor
This seems to have been overlooked or lost during rebase.
2015-09-24 13:46:06 +02:00
Pavel Penev
2c27452a44 Merge pull request #9386 from atlimit8/FinishWrappingActorInfoTraits
Finish wrapping ActorInfo.Traits
2015-09-24 14:40:07 +03:00
Pavel Penev
32ed7ca416 Merge pull request #9257 from reaperrr/incr-harv-radius
Increased harvester search radii
2015-09-24 12:32:53 +03:00
Pavel Penev
a5f1293c69 Merge pull request #9413 from abcdefg30/new_d2k_flags
Add new flags for d2k
2015-09-24 12:27:23 +03:00
atlimit8
1f247a0a51 Merge pull request #9220 from GraionDilach/observer-clocks
Add customizable properties to observer clocks.
2015-09-23 21:07:01 -05:00
atlimit8
8e0f5bb943 Merge pull request #9361 from visav/player-count-map-filter
Extends MapChooserLogic.mapFilter to match against PlayerCount
2015-09-23 18:46:45 -05:00
reaperrr
f955e83797 Apply original D2k base speeds
10.666667 in OpenRA with 32x32px tiles equals 1 in original RA1 and 64 in original D2k (ground actors).
For aircraft, I applied original D2k speed / 64 * 7, which should be correct for 32x32px.
2015-09-23 20:51:49 +02:00
reaperrr
685be50168 Added original D2k debris 2015-09-23 19:07:07 +02:00
Pavel Penev
f942ab1389 Move any mobile actors that block the building's desired footprint when placing a building 2015-09-23 19:41:21 +03:00
Pavel Penev
02be188d14 Add ActorExts.ClosestCell() 2015-09-23 19:13:34 +03:00
abcdefg30
d47ebc4dd6 Add definitions for the new flags 2015-09-23 16:14:47 +02:00
x-a-n-a-x
b257d4001a Add new flags for factions in d2k 2015-09-23 15:17:21 +02:00
Pavel Penev
60fee57f75 Remove obsolete installation UI YAML files from the official mods 2015-09-23 15:33:08 +03:00
Pavel Penev
50ea12723c Streamline mod changing after installation
- Don't return to the ModChooser after a successful installation.
 - Don't reload the ModChooser after a cancelled installation.
2015-09-23 15:33:06 +03:00
Pavel Penev
4401e1aa0c Pipe mod music installation through the ModChooser 2015-09-23 15:33:03 +03:00
Pavel Penev
0e7122acad Enable mod asset installation from CD from the modchooser 2015-09-23 15:33:00 +03:00
Pavel Penev
bdcb0fee58 Enable mod asset package downloading from the modchooser 2015-09-23 15:32:57 +03:00
Pavel Penev
f0a2e58ccd Add content installation dialogs to modchooser 2015-09-23 15:32:51 +03:00
Pavel Penev
cb0ccbac50 Add paths to TestFiles
File checks for existing files don't work otherwise.
2015-09-23 15:32:41 +03:00
Pavel Penev
fbfb2cfda1 Remove asset handling from BlankLoadScreen 2015-09-23 15:32:40 +03:00
Pavel Penev
d472805fc6 Add mod asset checks to ModBrowserLogic 2015-09-23 15:32:37 +03:00
Pavel Penev
4314fae77a Move ContentInstaller to OpenRA.Game from Mods.Common 2015-09-23 15:32:35 +03:00
Pavel Penev
82bf66a9be Generalise progress bars 2015-09-23 15:32:33 +03:00
Pavel Penev
19388fd773 Add ButtonBaseLine metric 2015-09-23 15:32:29 +03:00
Pavel Penev
1e57f13ecd Fix ModChooser UI 2015-09-23 15:32:26 +03:00
Pavel Penev
863814105b Move D2k tilesets to the root asset directory 2015-09-23 15:32:24 +03:00
abcdefg30
95d2f7c461 Merge pull request #9412 from simon-v/patch-1
Allies-02: Fix mission timer on medium difficulty
2015-09-23 14:10:57 +02:00
Simon Volpert
c1b8ded79b Allies-02: Fix mission timer on medium difficulty 2015-09-23 13:21:15 +03:00
Zimmermann Gyula
1358024b38 Add customizable properties to observer clocks. 2015-09-22 23:30:48 +02:00
Pavel Penev
0ac0fed15c Merge pull request #9340 from reaperrr/d2k-bal-weapons
Changed D2k health, armor types and weapon stats to match original
2015-09-22 23:55:25 +03:00
RoosterDragon
3a63a427e6 Improved sync lint pass.
Now also checks for classes with Sync members lacking the ISync interface.
2015-09-21 22:17:09 +01:00
RoosterDragon
6b62aa1ad5 Add missing sync interfaces. 2015-09-21 22:17:06 +01:00
RoosterDragon
593d913f55 Remove sync on actor - as it doesn't currently work. 2015-09-21 22:16:03 +01:00
atlimit8
9cef739dd5 Make ActorInfo.{Traits => traits} private 2015-09-21 15:50:57 -05:00
atlimit8
b889675c83 ActorInfoTest fixup with new ActorInfo ctor 2015-09-21 15:50:57 -05:00
atlimit8
9acf121eb1 Replace ActorInfo.Traits.WithInterface with ActorInfo.TraitInfos<T>() 2015-09-21 15:50:57 -05:00
atlimit8
6e39a5e264 Replace .WithInterface<T>().Any() => .HasTraitInfo<T>() 2015-09-21 15:50:57 -05:00
atlimit8
b38b6eadd0 Add IEnumerable<ITraitInfo> ActorInfo.TraitInfos() replacing actorInfo.traits enumeration 2015-09-21 15:50:57 -05:00
RoosterDragon
7decfc83ea Fix ActionQueue ordering.
This enforces a well defined ordering for ActionQueue to ensure it runs actions in the the order one would expect.
2015-09-20 23:20:51 +01:00
RoosterDragon
bbdd597917 Merge pull request #9394 from pchote/unstatic-sound
Unstatic the Sound class.
2015-09-20 22:58:00 +01:00
Paul Chote
7f4663f606 Pull out a temporary variable in ProductionQueue. 2015-09-20 22:46:07 +01:00
Paul Chote
d112083c44 Clean up sound devices on game exit. 2015-09-20 22:46:07 +01:00
RoosterDragon
6b9bd1cbbc Eagerly cache traits in Actor.
In this case, removing the lazy generation buys us more performance in removing the overhead of accessing these values than we lose from avoided computation when these values are never accessed.
2015-09-20 22:36:21 +01:00
Oliver Brakmann
28c78f6085 Make a number of navigation keys available to spectators
This will make the following keys available to spectators and in replays:

* Center screen on last event/beacon [Space]
* Center screen on current selection [Home]
* Cycle construction yards [H]
* Cycle production buildings [Tab]

The latter two need a player view to work, the former two work in all
views.
2015-09-20 22:39:06 +02:00
Oliver Brakmann
379b5a181f Make (Harvester|Base)AttackNotifiers visible to team mates and spectators 2015-09-20 22:37:34 +02:00
Visa Varjus
b9f7fb4ebc adds map filtering by PlayerCount 2015-09-20 22:06:46 +03:00
Paul Chote
ef55d646f7 Unstatic the Sound class. 2015-09-20 14:11:06 +01:00
Matthias Mailänder
c3dce785a5 add custom selection sizes to aid the renderer 2015-09-20 14:58:39 +02:00
Matthias Mailänder
7845577553 Add descriptions to the SelectionSize traits. 2015-09-20 14:58:23 +02:00
Paul Chote
ff10fe3e07 Merge pull request #9377 from reaperrr/fix-bldplace-overlay
Fixed TS crane overlay's last frame hiding idle overlay
2015-09-20 12:13:52 +01:00
Paul Chote
141575fc45 Merge pull request #9339 from reaperrr/sbag-fence
Makes only concrete walls block fire
2015-09-20 11:57:04 +01:00
Pavel Penev
db11b81c13 Merge pull request #9371 from reaperrr/maketest-order
Changed make.ps1 test order
2015-09-20 03:15:53 +03:00
Matthias Mailänder
c79f5a20a5 Merge pull request #9369 from RoosterDragon/cross-thread-checks
Added thread-affinity checks to SDL2 renderer
2015-09-19 21:09:08 +02:00
reaperrr
5ec1f8f8a0 Merge pull request #9379 from atlimit8/DanglingActorInfoTraitsContains
Changed missed ActorInfo.Traits.Contains => ActorInfo.HasTraitInfo
2015-09-19 20:55:16 +02:00
reaperrr
e36e4f97bb Fix Grenadier projectile 2015-09-19 20:47:27 +02:00
reaperrr
4aaa62845d Fix TS repair depot idle overlay
This was an idle animation in the original, and this and "platform" cannot be displayed at the same time anyway.
Also increased Tick rate to match idle light.
2015-09-19 20:37:59 +02:00
reaperrr
58e474ec80 Make repair overlay invisible when not repairing 2015-09-19 20:37:58 +02:00
reaperrr
e99c951a0c Hide WithBuildingPlacedOverlay after it has been played
Fixes #9319.
2015-09-19 20:37:57 +02:00
Paul Chote
7dfd5ade3a Merge pull request #9301 from atlimit8/WDistTraitRangeFields
Make Range WDist for all traits with circular ranges.
2015-09-19 19:10:34 +01:00
Paul Chote
3fec4c2032 Merge pull request #9298 from atlimit8/AffectsShroud
Create abstract class AffectsShroud[Info] with RevealsShroud core logic also used by CreatesShroud
2015-09-19 18:46:23 +01:00
atlimit8
131084d129 Changed missed ActorInfo.Traits.Contains => ActorInfo.HasTraitInfo 2015-09-19 12:06:37 -05:00
Matthias Mailänder
fea59346a5 add a total resource cash counter to the map editor 2015-09-19 18:21:07 +02:00
atlimit8
de7f5a4288 Make Range WDist for all traits with circular ranges. 2015-09-19 11:02:28 -05:00
reaperrr
654c66ddd0 Split Trike and Raider muzzle flash to its own weapon
Allows to show 3 muzzle flashes while only playing report, explosion effect and applying damage once
2015-09-19 17:40:02 +02:00
reaperrr
8e737d09c1 Temporary work-around for D2k deviator missile
The lint check doesn't handle player palettes properly yet.
2015-09-19 17:40:01 +02:00
reaperrr
ec277be9b6 Missile tank weapon renamed 2015-09-19 17:40:00 +02:00
reaperrr
ad9bc30c7e D2k added Grenadier and Sardaukar explosions 2015-09-19 17:39:59 +02:00
reaperrr
ab5a07fa5c D2k weapon targeting validity changes 2015-09-19 17:39:58 +02:00
reaperrr
03413b9875 D2k weapon warhead changes 2015-09-19 17:39:57 +02:00
abcdefg30
97346e1833 Merge pull request #9355 from ChaoticMind/socket_crash
Catch exception when hosting server on busy port
2015-09-19 17:27:11 +02:00
abcdefg30
6cbcd66b87 Merge pull request #9215 from LipkeGu/upnp_externalip_fix
Move NAT Logic from ClientTooltipLogic into its own Function at LobbyUtils.
2015-09-19 17:22:02 +02:00
reaperrr
d77839bb3d Merge pull request #9332 from atlimit8/TraitInfoAccess_1
TraitInfo through ActorInfo and HasTrait Removal
2015-09-19 17:06:10 +02:00
atlimit8
09984683a7 Add ActorInfo.TraitInfo[OrDefault]<T>() requiring ITraitIfo types 2015-09-19 09:56:14 -05:00
reaperrr
0ce36b6648 D2k weapon projectile changes
speed, trails, rate of turn, projectile type etc.
2015-09-19 16:55:20 +02:00
atlimit8
6970959ef1 .Trait[OrDefault]<Trait> => .Info.Traits.Get[OrDefault]<TraitInfo> where applicable 2015-09-19 09:49:24 -05:00
atlimit8
8162fa27ab Add ActorInfo.HasTraitInfo<T>() requiring ITraitInfo types 2015-09-19 09:49:24 -05:00
atlimit8
85fab45451 Remove Actor.HasTrait<T>() 2015-09-19 09:49:23 -05:00
reaperrr
d62460cfa1 Reorder yaml testing in make.ps1 to match makefile 2015-09-19 14:28:20 +02:00
reaperrr
959914779f Merge pull request #9376 from pchote/fix-news-panel-width
Make the news panel dropdown consistent across mods.
2015-09-19 14:20:38 +02:00
Paul Chote
55dee63b55 Make the news panel dropdown consistent across mods. 2015-09-19 12:46:07 +01:00
Matthias Mailänder
c0dd9c4566 Merge pull request #9359 from RoosterDragon/fix-pathfinder-layer-pooling
Fixed pooling of layers used for pathfinding
2015-09-19 13:07:33 +02:00
Matthias Mailänder
b5a5dfdb54 Merge pull request #9365 from atlimit8/HealUnitsCrateAction_use_ActorsWithTrait
HealUnitsCrateAction.Activate() use ActorsWithTrait<Health>()
2015-09-19 12:53:25 +02:00
Matthias Mailänder
6c26251b41 Merge pull request #9368 from atlimit8/Harvester_linq_syntax
Replace only use of Linq syntax
2015-09-19 12:03:19 +02:00
RoosterDragon
fc436f1aab Added thread-affinity checks to SDL2 renderer.
If a call is made into a graphics resource that has thread-affinity, from a thread other than the one that created the graphics device, an exception will now be thrown to make debugging easier.
2015-09-18 21:04:21 +01:00
atlimit8
be010249d7 Replace only use of Linq syntax 2015-09-18 10:31:41 -05:00
atlimit8
1d9d28b540 HealUnitsCrateAction.Activate() use ActorsWithTrait<Health>() 2015-09-17 23:55:38 -05:00
reaperrr
4fa20e78fa Merge pull request #9304 from atlimit8/Fix_AttackBase_GetMinimumRange
Make AttackBase.GetMinimumRange() return WDist.Zero if there are no available armaments
2015-09-18 01:26:35 +02:00
reaperrr
ef451ad4a7 Merge pull request #9356 from atlimit8/RemoveIBodyOrientation
Remove redundant IBodyOrientation[Info] & replace with BodyOrientation[Info]
2015-09-18 01:11:54 +02:00
reaperrr
1c759427b5 Merge pull request #9358 from abcdefg30/ts_stnk
Fix a crash when the stnk of TS is cloaking
2015-09-18 01:05:18 +02:00
reaperrr
4d85081577 D2k weapon changes to reload, burst and range 2015-09-17 22:08:40 +02:00
Kevin Azzam
f4461b292e Generalize error message when creating a server fails 2015-09-17 20:03:05 +02:00
RoosterDragon
519be4374c Fixed pooling of layers used for pathfinding.
The previous implementation:
- Was failing to dispose of pooled layers.
- Was using a finalizer to allow undisposed layers to be reused.

This means all pooled layers are kept alive indefinitely until the map changes. If the finalizer is slow for any reason then the pathfiinder will allocate new layers when the pool runs out. Since these new layers are eventually stuffed back into the pool when the finalizer does run, this can theoretically leak unbounded memory until the pool goes out of scope. In practice it would leak tens of megabytes.

The new implementation ensures layers are disposed and pooled correctly to allow proper memory reuse. It also introduces some safeguards against memory leaks:
- A cap is set on the number of pooled layers. If more concurrent layers are needed than this, then the excess layers will not be pooled but instead be allowed to be garbage collected.
- No finalizer. An implementation that fails to call dispose simply allows the layer to be garbage collected instead.
2015-09-16 21:25:46 +01:00
abcdefg30
a5b9442170 Fix a crash when the stnk of TS is cloaking 2015-09-16 17:54:06 +02:00
reaperrr
6b0816d68f Increase default harvester resource search radius
While this slightly decreases performance per search, it reduces the
chance of search-fail-repeat loops on human-controlled and singleplayer AI
harvesters as well as the chance of the more expensive fallback search on skirmish bot harvesters.
2015-09-16 17:37:24 +02:00
Kevin Azzam
89f2a479bf Catch exception when hosting server on busy port
Closes #9354
2015-09-16 13:08:23 +02:00
atlimit8
45112cfa76 Remove redundant IBodyOrientation[Info] & replace with BodyOrientation[Info] 2015-09-15 22:57:08 -05:00
reaperrr
886f366926 Clean up TS wall default
- don't give experience
- don't update player statistics
- don't count it as structure that must be destroyed
2015-09-16 00:51:44 +02:00
reaperrr
b5bf9ec605 Make TS sandbags not block fire anymore 2015-09-16 00:51:43 +02:00
reaperrr
81b8754ffa Make only concrete walls block fire in RA 2015-09-16 00:51:42 +02:00
reaperrr
42a4722ebc Make only concrete walls block fire in TD 2015-09-16 00:51:40 +02:00
Matthias Mailänder
59edf85513 Merge pull request #9344 from reaperrr/fix-ra-water
Fixed RotationPaletteEffect tileset validity check
2015-09-15 21:10:37 +02:00
Guido L
8a1a6945f1 Fix and move Logic into its own Function in LobbyUtils 2015-09-14 23:19:50 +02:00
reaperrr
6613db7a15 Fix RotationPaletteEffect tileset validity check
If Tilesets was empty but ExcludeTilesets was not, it would always return false even though that combination is supposed to mean only the excluded tileset(s) is/are not valid for this effect.
2015-09-14 16:36:56 +02:00
reaperrr
605ec81c55 Merge pull request #9203 from Mailaender/tunnel-rendering
Added tunnel top rendering
2015-09-14 15:42:14 +02:00
reaperrr
642497a5b7 Merge pull request #9323 from abcdefg30/d2k_rock
Fixed a wrong tileset definition in d2k
2015-09-14 15:17:09 +02:00
Pavel Penev
3fc41238d8 Merge pull request #9333 from atlimit8/DuplicateUnitCrateAction_EnabledTargetting
Make DuplicateUnitCrateAction only check enabled targetability
2015-09-14 02:45:19 +03:00
reaperrr
472191c634 Changed d2k vehicle HP and armor types to their original values 2015-09-14 00:03:36 +02:00
reaperrr
98137c514e Changed d2k structure HP and armor types to their original values 2015-09-14 00:03:35 +02:00
reaperrr
6d24006a7f Changed d2k infantry HP to their original values 2015-09-14 00:03:34 +02:00
Pavel Penev
4fad418db5 Merge pull request #9341 from reaperrr/d2k-cleanup1
Some D2k cleanup
2015-09-14 00:27:33 +03:00
reaperrr
ce8554b94a Make ornithopters targetable by anti-air weapons 2015-09-13 22:46:07 +02:00
reaperrr
6c828f90ad Remove unused airborne upgrade from unlandable d2k aircraft 2015-09-13 22:46:06 +02:00
reaperrr
ac9db803e0 Make Carryalls targetable as in original D2k 2015-09-13 22:35:12 +02:00
reaperrr
82b57165e7 Remove Parachutable from d2k infantry default 2015-09-13 22:33:06 +02:00
Pavel Penev
3e542d1039 Merge pull request #9338 from reaperrr/d2k-paradrop
Removes paradrop and carryall.infantry from D2k
2015-09-13 22:56:30 +03:00
reaperrr
ab603827ca Remove paradrop remnants from D2k 2015-09-13 21:49:24 +02:00
reaperrr
3fc11c4555 Remove carryall.infantry
No longer used since paradrops were removed.
2015-09-13 21:49:23 +02:00
reaperrr
be28da2a64 Remove paradrop power from Ix Lab 2015-09-13 21:49:22 +02:00
Pavel Penev
c41e3025c1 Merge pull request #9337 from reaperrr/d2k-orni
Removes unused ornithopter definition and renames ornithopter.bomber
2015-09-13 22:37:43 +03:00
reaperrr
7aaa31774d Rename ornithopter.bomber to just ornithopter 2015-09-13 19:41:41 +02:00
reaperrr
1d197da5ac Remove unused ornithopter definition 2015-09-13 19:39:38 +02:00
reaperrr
a580e6846e Merge pull request #9328 from Mailaender/ai-common-names
Fixed BuildingCommonNames magic
2015-09-13 18:53:37 +02:00
abcdefg30
48ecc717b2 Merge pull request #8996 from Mailaender/alpha-cloak
Added pre-multiplied alpha palettes for cloak effects
2015-09-13 18:53:17 +02:00
abcdefg30
47f07a47bd Merge pull request #9330 from clemty/buildtool
make: don't assume luac is installed
2015-09-13 17:47:29 +02:00
Matthias Mailänder
9df86f031b Merge pull request #9278 from pchote/rename-d2k-actors
Rename d2k actors to match original game rules.
2015-09-13 17:44:15 +02:00
abcdefg30
f78aea4f90 Merge pull request #8636 from Mailaender/irc
Added the in-game IRC client again
2015-09-13 17:14:36 +02:00
abcdefg30
4fc07c55b9 Merge pull request #9260 from Mailaender/tileset-import-fixes
Fixed the legacy isometric tileset importer
2015-09-13 17:07:24 +02:00
Matthias Mailänder
59142d7782 terrain sprite definition MiniYaml changed to plural form, too 2015-09-13 15:01:15 +02:00
Matthias Mailänder
d65600352b Merge pull request #9325 from Mailaender/ai-editor
Fixed HackyAI crashing the map editor
2015-09-13 13:48:36 +02:00
Matthias Mailänder
a7235d84e9 document the hidden keys 2015-09-13 08:30:17 +02:00
atlimit8
578a92370b Make DuplicateUnitCrateAction only check enabled targetability 2015-09-12 21:30:35 -05:00
clemty
378fff75bf don't assume luac is installed 2015-09-12 20:27:51 +02:00
Matthias Mailänder
f903cfea96 don't throw as we are checking for null later 2015-09-12 10:27:22 +02:00
Matthias Mailänder
39b79f5347 don't load the AI routines in the map editor 2015-09-12 08:40:40 +02:00
Matthias Mailänder
b4d22c2eb0 setup tunnel top rendering 2015-09-12 08:24:02 +02:00
abcdefg30
c79f416461 Fix a wrong tileset definition 2015-09-12 02:18:50 +02:00
reaperrr
4108b6da46 Merge pull request #9256 from Mailaender/ai-harv-search
Added AI search for new resource patches avoiding enemies
2015-09-11 23:25:59 +02:00
abcdefg30
0af5b45cb9 Merge pull request #9211 from Mailaender/railroad
Added Tiberian Sun railroad track rendering
2015-09-11 21:25:36 +02:00
abcdefg30
5660b45690 Merge pull request #9267 from clemty/luadocs
Lua API documentation cleanup
2015-09-11 20:32:48 +02:00
reaperrr
0b9fb4420b Add margin to CreateEffectWarhead isAir check 2015-09-11 16:20:25 +02:00
reaperrr
f0129838d7 Merge pull request #9016 from OmegaBolt/hmlrs-orca-wep-expl
TS vanilla rocket explosions
2015-09-11 16:06:42 +02:00
reaperrr
8cae4ee982 Merge pull request #9280 from clemty/nod05build
Nod05: fix unit production
2015-09-11 15:06:07 +02:00
abcdefg30
7573b53c7f Merge pull request #9300 from Mailaender/bot-debug-production
Removed a redundant bot production debug message
2015-09-11 14:40:34 +02:00
Matthias Mailänder
958f305520 Merge pull request #9314 from baxxxster/patch-1
Update soviet01.lua
2015-09-11 07:35:55 +02:00
Pavel Penev
0494ffa120 Update the D2k map importer 2015-09-10 19:26:56 +01:00
Pavel Penev
d74d50df52 Add an upgrade rule for D2k actor renaming 2015-09-10 19:26:52 +01:00
Pavel Penev
a23ea17c2d Update mission Lua scipts 2015-09-10 19:23:06 +01:00
Paul Chote
96b8b8c1ce Rename actors to match original game rules. 2015-09-10 19:23:05 +01:00
reaperrr
181e934ee8 Merge pull request #9311 from atlimit8/Fix9310
DeathType Count check in Explodes
2015-09-10 17:57:26 +02:00
Glenn Martin Jensen
e201e390ff Update soviet01.lua 2015-09-10 15:49:12 +02:00
atlimit8
33915fb271 DeathType Count check in Explodes 2015-09-09 18:35:55 -05:00
Matthias Mailänder
4b1bedd7dd use pre-multiplied alpha for cloak effects 2015-09-09 23:07:24 +02:00
Matthias Mailänder
dae3b62d2a add a simple in-game IRC client 2015-09-09 20:56:05 +02:00
Matthias Mailänder
e06970d942 add railroad tracks 2015-09-09 20:52:26 +02:00
Pavel Penev
4bc8a60fb9 Merge pull request #9231 from reaperrr/bye-rendersimple4
Remove RenderSimple
2015-09-09 18:51:08 +03:00
Pavel Penev
20fe9a9ff2 Merge pull request #9255 from pchote/gamespeed
Add a game speed dropdown to the lobby options.
2015-09-09 18:14:05 +03:00
Pavel Penev
14defdea6c Merge pull request #9258 from Mailaender/editor-mousewheel
Added stepless mouse wheel actor rotation to the editor
2015-09-09 17:33:52 +03:00
Pavel Penev
9e6c664f30 Merge pull request #9290 from RoosterDragon/fix-tileset-dispose
Dispose earlier in FixClassicTilesets.
2015-09-09 17:23:50 +03:00
Pavel Penev
7d7e3a8e0e Merge pull request #9294 from RoosterDragon/remove-shroud-tests
Remove Shroud.IsVisibleTest and IsExploredTest
2015-09-09 17:22:00 +03:00
Pavel Penev
f65a049e61 Merge pull request #9296 from RoosterDragon/can-view-actor-perf
Speed up Player.CanViewActor
2015-09-09 14:14:06 +03:00
atlimit8
6ab32d75bf Make AttackBase.GetMinimumRange() return WDist.Zero if there are no available armaments 2015-09-08 23:36:05 -05:00
atlimit8
b6ffcb8279 Add WDist.MaxValue 2015-09-08 23:25:48 -05:00
atlimit8
3e211232a3 Create abstract class AffectsShroud[Info] with RevealsShroud core logic also used by CreatesShroud 2015-09-08 17:24:49 -05:00
reaperrr
c2a0ca49a6 Cut yaml duplication between anti-actor mines 2015-09-09 00:16:23 +02:00
reaperrr
c272e790e5 Remove RenderSimple
All traits inheriting from it have been removed, and WithSpriteBody can
now take its place.
2015-09-09 00:16:21 +02:00
deniz1a
07c0f489e3 Adds IncludeAllies option to hide-map crate. 2015-09-08 04:06:15 +03:00
reaperrr
7c7506fafb Merge pull request #9096 from deniz1a/hide-crate
Hides crates under fog.
2015-09-07 22:35:46 +02:00
Matthias Mailänder
088f56d181 remove redundant bot debug message 2015-09-07 20:58:52 +02:00
Matthias Mailänder
c53126513e Merge pull request #9295 from reaperrr/hashhash
Use HashSets for AI
2015-09-07 20:55:17 +02:00
RoosterDragon
d1960258db Speed up Player.CanViewActor.
Create Actor.CanBeViewedByPlayer and simply call this instead. The actor can cache all trait lookups on construction to avoid them being repeated for every visibility check.
2015-09-06 23:29:09 +01:00
reaperrr
60359cc6f5 Use HashSets for AI 2015-09-06 22:59:49 +02:00
RoosterDragon
ebf113dfb7 Remove Shroud.IsVisibleTest and IsExploredTest.
These are no longer any faster than the regular checks, so there's no need to keep them.
2015-09-06 21:13:32 +01:00
Pavel Penev
aae3c8ef7d Merge pull request #9293 from RoosterDragon/repair-render-perf
Speed up RepairIndicator.Render.
2015-09-06 23:13:28 +03:00
RoosterDragon
a1f6b83653 Speed up RepairIndicator.Render.
Check repairer count first, as this is quicker than checking fog visibility.
2015-09-06 21:06:02 +01:00
Matthias Mailänder
a8d4bc2cef Merge pull request #9292 from obrakmann/fix-silo-infinite-loop
Fix an infinite loop that occurs when a silo is captured
2015-09-06 21:54:14 +02:00
Oliver Brakmann
caa0e1678e Fix an infinite loop that occurs when a silo is captured 2015-09-06 21:46:20 +02:00
RoosterDragon
662077a47e Merge pull request #9103 from reaperrr/water-rot
Refactored WaterPaletteRotation into RotationPaletteEffect
2015-09-06 20:19:09 +01:00
reaperrr
fabdefeaf1 Use HashSets for tileset checks, check in constructor for better performance 2015-09-06 20:58:24 +02:00
RoosterDragon
286372fedf Dispose earlier in FixClassicTilesets.
Ensure we dispose the stream we opened right away to avoid leaving it open when an exception occurs.
2015-09-06 19:55:00 +01:00
OmegaBolt
55d55b3723 removed ImpactTypes changes 2015-09-06 19:47:16 +01:00
RoosterDragon
1e22762a16 Merge pull request #8766 from TheRaffy/WeatherOverlay
Added a WeatherOverlay
2015-09-06 19:35:00 +01:00
TheRaffy
1fc2158f2e Added a WeatherOverlay 2015-09-06 20:25:29 +02:00
reaperrr
ea7811a076 Rename temp to rotationBuffer and remove comment 2015-09-06 19:28:16 +02:00
reaperrr
cd9effaa35 Added positive palette/tileset properties to RotationPaletteEffect 2015-09-06 19:28:15 +02:00
reaperrr
96c7d4345e Renamed WaterPaletteRotation to RotationPaletteEffect 2015-09-06 19:25:12 +02:00
reaperrr
ca055eb7bb Refactored WaterPaletteRotation
Moved RotationBase from tileset definition to WaterPaletteRotation effect.
Unhardcoded rotation range and rotation rate.
Added possibility to exclude Tilesets from effect.

Fixed RA water palette rotation for actors on desert maps (#8872).
2015-09-06 19:25:10 +02:00
Paul Chote
1109ec53d1 Update UI timers for variable game speed. 2015-09-06 17:48:42 +01:00
Paul Chote
301b698c81 Add game speed dropdown to the lobby. 2015-09-06 17:48:41 +01:00
Paul Chote
257c043e58 Add Timestep property to GlobalSettings. 2015-09-06 17:48:26 +01:00
Matthias Mailänder
0df8b3ba39 bring back AI search for new resource patches avoiding enemies 2015-09-06 12:56:23 +02:00
clemty
bc13ae7ff0 Add missing desert tiles (work originally by psydev) 2015-09-06 12:39:19 +02:00
Pavel Penev
7912e3c7ff Merge pull request #9283 from reaperrr/d2k-weapon-names
Changed D2k weapon names to match original
2015-09-06 13:29:14 +03:00
Pavel Penev
5b93146279 Merge pull request #9273 from clemty/tileset
TD: make cliffs unbuildable
2015-09-06 12:54:39 +03:00
Pavel Penev
8262591cc4 Merge pull request #9282 from reaperrr/d2k-nobounty
Removed bounties from D2k
2015-09-06 12:37:27 +03:00
Matthias Mailänder
c206bebb7f Merge pull request #9274 from pchote/fix-sound-engine
Don’t create multiple sound contexts.
2015-09-06 11:35:50 +02:00
Matthias Mailänder
0e5fcc1756 Merge pull request #9279 from atlimit8/SemanticallySets
More HashSet trait fields & Lint support
2015-09-06 10:23:20 +02:00
Matthias Mailänder
154225d9ee rotate actors freely with mouse wheel and remove the facing hack 2015-09-06 08:54:14 +02:00
Matthias Mailänder
d20e93495e Merge pull request #9272 from pchote/remove-dps-table
Remove the broken actor stats export command.
2015-09-06 08:24:55 +02:00
reaperrr
5e6d30c3f5 D2k - switch stats of UnitExplodeSmall and UnitExplodeMed to match name 2015-09-06 05:08:45 +02:00
reaperrr
a321b41c72 D2k - remove unused UnitExplode 2015-09-06 05:08:44 +02:00
reaperrr
3b2d69df18 D2k - change position and name of ChainGun
To reduce conflicts with stats changes
2015-09-06 05:08:43 +02:00
reaperrr
b9377c49a9 D2k - remove unused ParaBomb 2015-09-06 05:08:40 +02:00
reaperrr
fe2491dd50 Add 80mm_O cannon for Ordos tank
To reduce conflicts with upcoming stats changes.
2015-09-06 05:08:39 +02:00
reaperrr
d3e8ffceb2 D2k weapon renamings 2015-09-06 05:08:38 +02:00
reaperrr
f857f49c10 Remove bounties from d2k 2015-09-06 02:37:28 +02:00
clemty
3bf31c99da Nod05: fix unit production
closes #9277
2015-09-06 00:24:30 +02:00
RoosterDragon
6b14d400ce Merge pull request #9259 from atlimit8/AI_countsAllAircraftRearmBuildings
AI counts all aircraft rearm buildings
2015-09-05 23:17:28 +01:00
atlimit8
8250f223c4 More HashSet trait fields & Lint support 2015-09-05 16:59:30 -05:00
clemty
23c6baa57d TD: make cliffs unbuildable
fixes #9265
2015-09-05 22:41:37 +02:00
Paul Chote
886d489766 Don’t create multiple sound contexts. 2015-09-05 18:29:14 +01:00
Paul Chote
a11ffa5135 Remove the bitrotted actor stats command. 2015-09-05 18:01:32 +01:00
RoosterDragon
592004e738 Unify the player dictionaries in FrozenUnderFog.
This improves the performance of FrozenUnderFog.Tick as only one lookup needs to be done rather than two.
2015-09-05 16:10:00 +01:00
reaperrr
e74c0d6c13 Merge pull request #9141 from RoosterDragon/pathfinder-perf
Improve pathfinder performance (paths may change)
2015-09-05 16:49:51 +02:00
clemty
ea71620f47 Lua API documentation cleanup
also reduces amount of headings with only a single entry

SendAirStrike() - now listed under "Support Powers"
Guard() - now listed under "Combat"
FindResources() - now listed under "Movement"
Deploy() - now listed under "General"
SendParaTroopers() - now listed under "Support Powers"
Paradrop() - no listed under "Transports"

Teleport() should probably be listd under "Movement", but I don't know how to change that (currently listed under "General").

note that I changed "ScriptGlobal" to "ScriptPropertyGroup" for SendAirStrike() - I hope that does not screw up anything
2015-09-05 15:01:14 +02:00
reaperrr
e0e31d89b1 Merge pull request #9264 from penev92/appearsOnRadar
Make AppearsOnRadar implement INotifyCreated
2015-09-05 00:39:33 +02:00
Pavel Penev
c323046ed0 Make AppearsOnRadar implement INotifyCreated
Cache the IRadarColorModifier so we don't look for it on every render tick.
2015-09-05 01:18:45 +03:00
RoosterDragon
e44342daa0 Merge pull request #9250 from reaperrr/fix-deco-visibility
Make rocks and trees HiddenUnderShroud instead of FrozenUnderFog
2015-09-04 18:15:34 +01:00
atlimit8
dbae16b7a0 AI counts all aircraft rearm buildings 2015-09-04 10:45:58 -05:00
reaperrr
543dc8e5d0 Make rocks and trees HiddenUnderShroud instead of FrozenUnderFog
This improves performance significantly when many trees and rocks are on the map and shroud/fog are enabled.
2015-09-04 17:15:16 +02:00
deniz1a
fb87bf0b90 Hides crates under fog of war. 2015-09-04 13:01:01 +03:00
Matthias Mailänder
91c7d7893e Merge pull request #9238 from deniz1a/asymmetric
Red Alert: Corrects spelling in "Asymetric Battle" map.
2015-09-04 10:50:25 +02:00
Matthias Mailänder
f785c5d03f Merge pull request #9246 from RoosterDragon/array-to-set
Change some arrays to sets
2015-09-04 08:56:44 +02:00
Matthias Mailänder
02460a16b4 Merge pull request #9240 from penev92/fixAnims
Fix crash when aircraft is rearming at a helipad in TS
2015-09-04 08:46:23 +02:00
Matthias Mailänder
266a1eac8d Merge pull request #9241 from reaperrr/streamline-bo-yaml
Added ^SpriteActor and fixed remaining BodyOrientation regressions
2015-09-04 08:25:14 +02:00
reaperrr
31bcbeb789 Added ^SpriteActor and streamlined TS defaults
To avoid BodyOrientation issues.
2015-09-03 22:40:02 +02:00
reaperrr
89a115466c Added ^SpriteActor and streamlined D2k defaults
To reduce risk of BodyOrientation issues.
2015-09-03 22:40:01 +02:00
reaperrr
ec48c411f0 Added ^SpriteActor and streamlined TD defaults
To fix BodyOrientation regressions and reduce risk of future regressions.
2015-09-03 22:40:00 +02:00
reaperrr
0fc9507930 Clean and fix RA maps to avoid BodyOrientation-related crashes 2015-09-03 22:39:59 +02:00
reaperrr
6b9a511bd5 Added ^SpriteActor and streamlined RA defaults
To fix potential BodyOrientation issues and reduce risk of future
regressions.
2015-09-03 22:39:57 +02:00
reaperrr
fc4fadbd8d Merge pull request #9237 from Mailaender/allies-03-prison-orientation
Fixed BodyOrientation in 3rd Allies mission
2015-09-03 22:33:08 +02:00
DArcy Rush
f9a011d657 lower shocktrooper health 2015-09-03 20:51:54 +01:00
RoosterDragon
901e604cf3 Replace arrays with sets.
In places where arrays were being treated as a set, just create a set directly. This reveals the intention of such collections better, and also improves performance by allowing set based methods to be used.
2015-09-03 20:09:24 +01:00
Pavel Penev
4f4bab2cdf Merge pull request #9245 from atlimit8/WarheadTargetHashSets
Load HashSets in OpenRA.Mods.Common/Warheads/Warhead.cs directly from MiniYaml
2015-09-03 21:35:59 +03:00
atlimit8
7e31a249ab Load HashSets in OpenRA.Mods.Common/Warheads/Warhead.cs directly from MiniYaml 2015-09-03 13:27:58 -05:00
Pavel Penev
27e16d0730 Don't try to play a rearming animation if it doesn't exist 2015-09-03 15:55:20 +03:00
deniz1a
650cc8fb51 Red Alert: Corrects spelling in "Asymetric Battle" map.
Changes map name to "Asymmetric Battle".
2015-09-03 12:29:59 +03:00
Matthias Mailänder
4f0f5cdee7 remove BodyOrientation for invisible actor 2015-09-03 07:42:21 +02:00
Matthias Mailänder
119023c485 Merge pull request #8727 from atlimit8/MultipleTargetableTraits
TargetTypes by Upgrade and Replacement of Targetable* by Targetable and ITargetablePositions
2015-09-03 07:41:34 +02:00
atlimit8
5f079f2463 Add MinAirborneAltitude to Aircraft trait to set airborne threshold 2015-09-02 23:19:00 -05:00
atlimit8
b789739352 Allies 03 - kill prisoners with barrels 2015-09-02 23:19:00 -05:00
atlimit8
fadfd179cb Cache FrozenActor ITargetable.TargetTypes union 2015-09-02 23:19:00 -05:00
atlimit8
6986cd9f0e Remove TargetableAircraft 2015-09-02 23:19:00 -05:00
atlimit8
97ce4766f3 Grant upgrades while aircraft is airborne 2015-09-02 23:19:00 -05:00
atlimit8
a6cd770dcf Remove TargetableSubmarine 2015-09-02 23:14:41 -05:00
atlimit8
ecc15d9ae6 Grant upgrades while cloaked 2015-09-02 23:14:40 -05:00
atlimit8
23d0424437 Add ITargetablePositions seperating it from ITargetable 2015-09-02 23:14:40 -05:00
atlimit8
f5c3575c5a Support multiple ITargetable traits 2015-09-02 23:14:40 -05:00
Taryn Hill
4bd34e3ed3 Merge pull request #9236 from atlimit8/FixAircraftTraitIndent
Fix indentation in OpenRA.Mods.Common/Traits/Air/Aircraft.cs
2015-09-02 23:07:57 -05:00
atlimit8
5bfa3afd88 Fix indentation in OpenRA.Mods.Common/Traits/Air/Aircraft.cs 2015-09-02 22:54:05 -05:00
Paul Chote
2f759abddc Merge pull request #9159 from penev92/bleed_plugInit
Add PlugInit
2015-09-03 04:18:29 +01:00
Matthias Mailänder
8114a53760 Merge pull request #9222 from GraionDilach/hackyai-unitlimits
Implement HackyAI->UnitLimits.
2015-09-02 21:14:13 +02:00
Matthias Mailänder
8e382cf598 Merge pull request #9218 from deniz1a/badger-satellite
Red Alert: Adds satellite icons to badger planes.
2015-09-02 21:00:46 +02:00
Matthias Mailänder
735bb06c48 Merge pull request #9229 from pchote/fix-building-offsets
Fix TS building artwork offsets.
2015-09-02 20:45:15 +02:00
Pavel Penev
2042fccefd Merge pull request #9189 from reaperrr/bye-rendersimple3
Remove RenderBuilding
2015-09-02 19:21:01 +03:00
reaperrr
032bef7d71 Merge pull request #9124 from penev92/bleed_deployToUpgrade
Make use of DeployToUpgrade
2015-09-02 18:15:14 +02:00
reaperrr
0785bdbcf1 Move WithSpriteBody pause check to constructor 2015-09-02 17:55:03 +02:00
reaperrr
2031df965c Clarify TODO on TS missile silo sequences 2015-09-02 17:51:43 +02:00
reaperrr
45e6c62ec9 Cache WithSpriteBody in Refinery constructor 2015-09-02 17:51:19 +02:00
Paul Chote
7063d785a3 Fix Nod stealth generator offsets. 2015-09-02 16:22:24 +01:00
Paul Chote
291ba0e664 Fix GDI upgrade center offset. 2015-09-02 16:18:37 +01:00
Paul Chote
abce4678ca Fix Nod advanced power plant offset. 2015-09-02 16:18:27 +01:00
Paul Chote
04c61727f7 Don’t sample map height when calculating building centers. 2015-09-02 16:06:05 +01:00
Pavel Penev
495a99991c Add turret plugs to the TS shellmap 2015-09-02 16:13:27 +03:00
Pavel Penev
8f42cff550 Introduce PlugsInit 2015-09-02 16:13:23 +03:00
Pavel Penev
c4bf92870b Merge pull request #9083 from Mailaender/lint-cleanup
Cleaned up the ILint boiler plate code
2015-09-02 15:49:43 +03:00
Pavel Penev
59aded844f Merge pull request #9204 from reaperrr/bleed-rendertweaks1
Fix TD tower selection boxes and improve TS sequence offsets
2015-09-02 15:45:31 +03:00
Pavel Penev
8fbe35d156 Merge pull request #9228 from penev92/buildFix
Fix the build after a bad merge
2015-09-02 15:29:03 +03:00
Pavel Penev
a3633671a9 Fix the build after a bad merge
Merging #9187 without rebasing it on post-#9182 bleed was a bad idea.
2015-09-02 15:22:14 +03:00
Pavel Penev
ba9abc9e0a Merge pull request #9187 from RoosterDragon/field-saver-culture
Fix culture in FieldSaver for collections
2015-09-02 15:14:42 +03:00
Pavel Penev
b7192ffa14 Merge pull request #9207 from Mailaender/ctdam-animations
Added damaged, light and water animations to the Tiberian Sun hydroelectric dam
2015-09-02 15:08:49 +03:00
Pavel Penev
1679ac5a91 Merge pull request #9208 from Mailaender/kodiak-lights
Added Tiberian Sun Kodiak positional lights
2015-09-02 15:04:57 +03:00
Pavel Penev
325e974a94 Merge pull request #9209 from Mailaender/nod-lights
Added lights to the Nod Montauk and Pyramid
2015-09-02 14:58:19 +03:00
Pavel Penev
acd11d4521 Merge pull request #9212 from OpenRA/trucka
Added the unloaded truck to Tiberian Sun
2015-09-02 14:53:10 +03:00
Pavel Penev
995926b572 Merge pull request #9226 from GraionDilach/d2k-bo
Fix misc D2k BodyOrientation-regressions.
2015-09-02 14:42:44 +03:00
Pavel Penev
800b77e137 Merge pull request #9007 from reaperrr/armor-upgradable
Made Armor upgradable
2015-09-02 14:19:30 +03:00
Pavel Penev
8e2fca6f46 Merge pull request #9225 from LipkeGu/Namespace_Is_Wrong
Fix Namespace definition
2015-09-02 13:42:01 +03:00
Zimmermann Gyula
7ce1b89ba9 Fix misc D2k BodyOrientation-regressions. 2015-09-02 10:39:12 +02:00
Guido L
7181519fe4 Fix Namespace definition 2015-09-02 08:11:27 +02:00
Zimmermann Gyula
11c5144cb4 Restore AI kennel usage, limit AI harvesters and dogs. 2015-09-01 23:32:22 +02:00
Zimmermann Gyula
0a79109d01 Implement HackyAI->UnitLimits. 2015-09-01 23:32:13 +02:00
RoosterDragon
509a0e54a2 Merge pull request #9182 from penev92/bleed_dicts
Add support for Dictionary to FieldLoader and FieldSaver
2015-09-01 21:28:24 +01:00
Pavel Penev
256929073c Clean up some trait info loading code
Remove some methods that traits define to load their YAML values on their own.
2015-09-01 22:52:22 +03:00
Pavel Penev
8ddbabbfde Add Dictionary<,> support to FieldSaver 2015-09-01 22:52:20 +03:00
Pavel Penev
341b3395c8 Add Dictionary<,> support to FieldLoader 2015-09-01 22:52:18 +03:00
Pavel Penev
821e09877d Remove an assumption from FieldLoader.TryGetValueFromYaml() about the current value not having subnodes.
FieldLoader assumed the YAML that is being loaded is a simple value with no subnodes and threw an exception otherwise. This explicitly excluded the possibility of trying to load a Dictionary or another more complex object.
2015-09-01 22:52:04 +03:00
Matthias Mailänder
2df76ad962 add an overload that doesn't use string.Format 2015-09-01 20:59:14 +02:00
Matthias Mailänder
d17d68f894 Merge pull request #9221 from GraionDilach/fix-veinhole
Fix veinholes.
2015-09-01 20:38:46 +02:00
Pavel Penev
606a8c1639 Convert the Mobile Sensor Array to use DeployToUpgrade
Stop using Transforms.
2015-09-01 20:24:45 +03:00
Pavel Penev
899ea7e16d Add a description to DisableUpgrade 2015-09-01 20:19:31 +03:00
Pavel Penev
cdedfe6931 Don't get stuck in deployed mode because of an impossible move order 2015-09-01 20:19:29 +03:00
Pavel Penev
7668e0a30c Add deploy and undeploy sounds to DeployToUpgrade 2015-09-01 20:19:27 +03:00
Pavel Penev
21f9547fed Add facing to DeployToUpgrade
Make the actor turn to a desired facing before starting to deploy (and before granting the upgrade).
2015-09-01 20:19:25 +03:00
Pavel Penev
7d59aaa00c Add a deploy animation to DeployToUpgrade
Play a "deploy"/"undeploy" animation
2015-09-01 20:19:23 +03:00
Pavel Penev
3678e146cf Make WithVoxelBody upgradable 2015-09-01 20:19:21 +03:00
RoosterDragon
ac55c5bf09 Fix pathfinding using PriorityQueue incorrectly.
By providing a comparer that could change over time (as estimated costs on the graph were updated), this meant the priority queue could have its heap property invalidated and thus not maintain a correct ordering. Instead we store elements into the queue with their estimations at the time. This preserves the heap property and thus ensures the queue returns properly ordered results, although it may contain out of date estimations.

This also improves performance. The fixed comparer need not perform expensive lookups into the graph, but can instead use the readily available value. This speeds up adds and removes on the queue significantly.
2015-09-01 17:29:36 +01:00
RoosterDragon
77923a27c1 Tweak IPathSearch to avoid exposing the OpenQueue directly. 2015-09-01 17:29:36 +01:00
RoosterDragon
774992c246 Cache only unit paths in the pathfinder.
The path caching works on the assumption that the time saved from reusing a cached path outweights the cost of caching it in the first place.

For unit paths, this assumption holds. For path searchs, we spend more time caching them then we save when we get to reuse these cached paths. This is because they are reused less often, and calculating their key is more expensive in comparison.
2015-09-01 17:29:35 +01:00
Zimmermann Gyula
1410a3d405 Fix veinholes. 2015-09-01 17:14:41 +02:00
reaperrr
7f7031d5c8 Update outdated description 2015-09-01 13:52:09 +02:00
Zimmermann Gyula
4aba64cc0f Fix armors. 2015-09-01 13:52:08 +02:00
reaperrr
0f9ef4036e Merge pull request #9140 from RoosterDragon/safe-pathfinder-perf
Improve pathfinder performance
2015-09-01 13:02:29 +02:00
reaperrr
a154410307 Merge pull request #9214 from Mailaender/ts-trains
Fixed the TS mod crashing on startup and oh trains!
2015-09-01 13:00:14 +02:00
deniz1a
d065c9f202 Red Alert: Adds satellite icons to badger planes.
They drop crates, paratroopers and parabombs.
2015-09-01 10:15:37 +03:00
Matthias Mailänder
2ed240527e add train locomotive and waggons 2015-08-31 22:22:49 +02:00
Matthias Mailänder
b3bed529d2 fix 'nawall' does not define a quantized body orientation 2015-08-31 22:14:17 +02:00
RoosterDragon
0739fc80a3 Cache the speed modifiers enumerable, not just the traits, in Mobile. 2015-08-31 20:45:34 +01:00
RoosterDragon
d9dd96ca35 Speed up Map.ContainsAllProjectedCellsCovering on flat maps.
This method gets called often via Contains calls. We can significantly speed up the method for flat maps since we know the projection and it is trivial to perform. This avoids an expensive projection lookup.
2015-08-31 20:45:32 +01:00
RoosterDragon
76303e9699 In PathGraph.GetConnections, return a List of neighbors directly, rather than a LinkedList typed an IEnumerable.
The caller can enumerate the list more efficiently without the IEnumerable indirection, and the reduced memory allocation is marginally faster than allocating a linked list and several nodes.
2015-08-31 20:45:31 +01:00
RoosterDragon
7d44eb953e Reduce size of GraphConnection for allocation efficiency. 2015-08-31 20:45:29 +01:00
RoosterDragon
be59d045ce Only enumerate crushable traits once in MobileInfo.IsBlockedBy. 2015-08-31 20:45:25 +01:00
RoosterDragon
dab53f403d Provide a hand-written enumerator for ActorMap.GetUnitsAt(CPos). 2015-08-31 20:43:19 +01:00
RoosterDragon
18478646d4 Avoid multiple ToMPos calls in ActorMap. 2015-08-31 20:43:18 +01:00
RoosterDragon
ac1658c9ce Refactor movement cost method to avoid repeated terrain information lookups.
As the world tileset is fixed, the pathfinder can look up the terrain information for that tileset on creation. This is implemented by the WorldMovementInfo struct. When calculating node costs, this allows the pathfinder to avoid having to repeat this expensive dictionary lookup on every node.
2015-08-31 20:43:18 +01:00
RoosterDragon
4eacb6e5c9 Transparently cache results of GetTerrainIndex in Map.
This method performs an expensive calculation and is called often during pathfinding. We create a cache of the terrain indicies for the map to vastly reduce the cost.
2015-08-31 20:43:17 +01:00
RoosterDragon
fa87befeff Add missing CellEntryChanged checks. 2015-08-31 20:43:16 +01:00
Matthias Mailänder
f65c356399 add Kodiak positional lights 2015-08-31 20:20:47 +02:00
Matthias Mailänder
ee8cac25d0 add lights to the Nod pyramid 2015-08-31 20:18:14 +02:00
reaperrr
3175ef4d67 Merge pull request #9193 from Mailaender/quanbo-fixup
Fixed BodyOrientation refactor regressions
2015-08-31 20:12:53 +02:00
Matthias Mailänder
252b102886 add the unloaded truck 2015-08-31 18:30:22 +02:00
Matthias Mailänder
6137a44123 add lights to the Montauk 2015-08-30 18:51:00 +02:00
Matthias Mailänder
f60080e0ac Merge pull request #9186 from LavenderMoon/bleed
Combine Shrapnel into Bullet
2015-08-30 18:40:26 +02:00
Matthias Mailänder
47b581d8c0 be more concise 2015-08-30 17:42:56 +02:00
Matthias Mailänder
19801b6cc3 add damaged, light and water animations 2015-08-30 17:40:54 +02:00
reaperrr
10ab4cbe61 Fixed production overlay ZOffsets 2015-08-30 15:45:01 +02:00
reaperrr
c39c7cdc4e Fix d2k NukePower sequence requirement 2015-08-30 15:45:00 +02:00
reaperrr
9da56f51e2 Remove RenderBuilding 2015-08-30 15:44:59 +02:00
reaperrr
df29ee1e19 Improved TS sequence offsets for gaplug and naapwr
Fixes #9003.
2015-08-30 15:38:03 +02:00
reaperrr
6c2eb1b0a8 Fixed TD obelisk and adv. guard tower visual selection boxes 2015-08-30 15:38:02 +02:00
Pavel Penev
5e55cef02c Merge pull request #8699 from deniz1a/disguise-owner
Shows real owner of disguised units to allies.
2015-08-30 14:32:34 +03:00
Matthias Mailänder
0b8d7708ef add more lint interfaces to reduce boiler plate 2015-08-30 13:12:25 +02:00
Lavender Moon
81e5b7866b Combine Shrapnel into Bullet 2015-08-30 06:37:38 -04:00
Matthias Mailänder
838faa4ae3 Merge pull request #9200 from penev92/bleed_upgradableResources
Make SeedsResource upgradable
2015-08-30 11:41:12 +02:00
Matthias Mailänder
24a5c37d5b Merge pull request #9199 from reaperrr/fix-td-shell-mamm
Fixed TD shellmap mammoth turrets drawn below body
2015-08-30 11:11:37 +02:00
Pavel Penev
55045d691a Make SeedsResource upgradable 2015-08-30 02:13:56 +03:00
Pavel Penev
43809b7fc5 Merge pull request #9194 from Mailaender/emitError-sequences
Fixed undefined sequence lint checks not emitting errors
2015-08-30 01:29:20 +03:00
reaperrr
bf51e0600d RenderBuildingWall -> WithWallSpriteBody 2015-08-30 00:22:53 +02:00
reaperrr
21186c10b6 RenderBuildingTurreted -> WithTurretedSpriteBody 2015-08-30 00:22:52 +02:00
reaperrr
dddb49e095 Fix TD shellmap mammoth turrets 2015-08-29 23:59:16 +02:00
reaperrr
69d062495c RenderBuildingSilo -> WithSiloAnimation 2015-08-29 23:33:18 +02:00
reaperrr
2df318cd3e RenderBuildingCharge -> WithChargeAnimation 2015-08-29 23:33:17 +02:00
reaperrr
bc2b60be05 Extend WithSpriteBody funtionality
Move building placement range circle to PlaceBuilding, add
PauseAnimationWhenDisabled.
2015-08-29 23:10:22 +02:00
Matthias Mailänder
539e25920c add missing spaces 2015-08-29 21:24:58 +02:00
Pavel Penev
8d1e46dc54 Merge pull request #9195 from Mailaender/map-preview-leak
Fixed a resource leak in MapPreview
2015-08-29 20:36:48 +03:00
Matthias Mailänder
25a0143b46 avoid unnecessary trait lookups 2015-08-29 18:58:30 +02:00
Matthias Mailänder
1dfb982d6f fix paradrop camera not defining a body orientation 2015-08-29 18:49:51 +02:00
Matthias Mailänder
72dffe3391 dispose res properly 2015-08-29 18:47:10 +02:00
Matthias Mailänder
5fc8a413e6 emitError for undefined sequences 2015-08-29 08:18:52 +02:00
Matthias Mailänder
da0c80dc3d fix bridges not defining body orientation 2015-08-29 08:15:17 +02:00
Matthias Mailänder
45f7526967 fix dereference after null check 2015-08-29 08:05:00 +02:00
Matthias Mailänder
fda39f7136 add missing ISync 2015-08-29 08:04:37 +02:00
Matthias Mailänder
589cb4cd0a Merge pull request #9191 from reaperrr/fix-qffs
Fix TS regression from #9004
2015-08-29 07:12:21 +02:00
reaperrr
c3ff298572 Fix TS regression from #9004 2015-08-29 02:41:26 +02:00
Matthias Mailänder
9c1eeafa08 Merge pull request #9004 from reaperrr/quanbo
Introduce QuantizeFacingsFromSequence
2015-08-28 22:46:29 +02:00
Pavel Penev
c793ac565e Merge pull request #9188 from RoosterDragon/friendly-name-hashset
Friendly name for HashSet in docs
2015-08-28 23:03:15 +03:00
Matthias Mailänder
a0bdce9ad8 Merge pull request #9185 from reaperrr/d2k-fixes
D2k fix for cliff passability
2015-08-28 21:51:03 +02:00
Matthias Mailänder
88df5057b6 Merge pull request #9175 from penev92/bleed_maxMind
Update MaxMind.GeoIP2 version to 2.3.1
2015-08-28 21:48:19 +02:00
RoosterDragon
637a87c33b Use a better name for HashSet in ExtractTraitDocsCommand.FriendlyTypeName. 2015-08-28 19:55:25 +01:00
RoosterDragon
d11e60474a Ensure the elements of arrays and sets are formatted correctly in FormatValue.
We call FormatValue on each element to ensure correct culture and other formatting that would otherwise not be applied.
2015-08-28 19:39:25 +01:00
RoosterDragon
243763f570 Remove redundant invariant culture handling for float, decimal, double.
This is already handled by the type converter portion of the code.
2015-08-28 19:33:59 +01:00
reaperrr
a4bac0ab29 Fix ground type of some D2k cliffs 2015-08-28 17:37:14 +02:00
reaperrr
f62bc3c226 Merge pull request #9172 from Mailaender/fix-withcargo-desync
Fixed a desync involving WithCargo
2015-08-28 15:05:55 +02:00
Pavel Penev
d1a3bf97a6 Merge pull request #9105 from RoosterDragon/cmfi-refactor-perf
Mobile Blocking Refactor
2015-08-28 15:35:49 +03:00
Pavel Penev
3d76f76c26 Merge pull request #9181 from RoosterDragon/field-loader-hashsets
Support HashSet in FieldLoader/FieldSaver
2015-08-28 01:13:33 +03:00
RoosterDragon
2f9ca36506 Update WeaponInfo to use HashSets for some fields directly. 2015-08-27 21:48:12 +01:00
RoosterDragon
5a177a889c Add ability to load and save HashSets. 2015-08-27 21:48:09 +01:00
RoosterDragon
6d183b6d63 Merge pull request #9178 from LavenderMoon/bleed
Move duplicate Tick() code from Plane and Helicopter to Aircraft.
2015-08-27 21:42:18 +01:00
RoosterDragon
410b97823a Ensure our array handling only accepts single dimensional arrays. 2015-08-27 21:31:24 +01:00
RoosterDragon
42123d5653 Merge pull request #9143 from LipkeGu/mod_loadscreen_crash
LoadScreen: Do not crash when Image or Text is not defined.
2015-08-27 21:25:26 +01:00
Lavender Moon
4649c03260 Move duplicate Tick() code from Plane and Helicopter to Aircraft. 2015-08-27 16:21:51 -04:00
Pavel Penev
353d9215c6 Update MaxMind.GeoIP2 version to 2.3.1
Fixes an "Operation did not complete successfully because the file contains a virus." message when making dependencies.
2015-08-27 21:43:47 +03:00
Paul Chote
8730a7f223 Fix WithCargo desync. 2015-08-26 19:35:18 +02:00
Guido L
bc39fcda98 LoadScreen: Add fallback message when no Text or Image is specified. 2015-08-25 20:44:38 +02:00
reaperrr
508c99655c Made Armor upgradable 2015-08-25 20:12:37 +02:00
Pavel Penev
d5e0bf2169 Merge pull request #9006 from reaperrr/remove-cantarget
Remove legacy 0% = not targetable assumption
2015-08-25 20:03:31 +03:00
reaperrr
aff1e5afe7 Upgrade notice 2015-08-25 18:54:01 +02:00
reaperrr
050a9076ed Fix TS medic heal target validation 2015-08-25 18:54:00 +02:00
reaperrr
cb95eeb914 Fix RA target validation
0% versus no longer means cannot target
2015-08-25 18:53:59 +02:00
reaperrr
6161b72f3e TD target validation
This mod already implements ValidTargets as intended, but grounded helicopters should count as vehicles for target validation.
2015-08-25 18:53:58 +02:00
reaperrr
468b0b4223 Fix D2k target validation
0% versus no longer means not targetable.
2015-08-25 18:53:57 +02:00
abcdefg30
1ddab69025 Merge pull request #9131 from Mailaender/ts-logo
Added a Tiberian Sun loadscreen and shellmap logo
2015-08-25 11:53:59 +02:00
Pavel Penev
d48cf695f3 Merge pull request #9144 from Mailaender/opt-find-resource
Optimized FindResources worse case scenario path finding
2015-08-25 04:24:05 +03:00
abcdefg30
d5680f0ee0 Merge pull request #8952 from Mailaender/ts-debris-variation
Added more variation to Tiberian Sun debris
2015-08-24 22:02:13 +02:00
abcdefg30
67966ad704 Merge pull request #8731 from deniz1a/simplify-lobby-logic
Simplifies Start button logic in lobby
2015-08-24 21:27:05 +02:00
reaperrr
18b8eb30a3 Merge pull request #9134 from clemty/docs
minor LUA and trait documentation fixes, whitespace fixes
2015-08-24 21:26:20 +02:00
abcdefg30
b9f4431ed0 Merge pull request #9151 from penev92/bleed_summaries
Add a bit of code documentation
2015-08-24 21:18:11 +02:00
Pavel Penev
ae43d813ad Merge pull request #9024 from atlimit8/consolidateDefenseDeployedVehicle
Consolidate rules into ^Defense (all) & ^DeployedVehicle (ts)
2015-08-24 22:08:38 +03:00
Matthias Mailänder
5c2849a08f add a simple projectile with random sequences for debris effects 2015-08-24 21:05:37 +02:00
Matthias Mailänder
2a21c7d1f2 don't let bots do 2x the amount of path searches 2015-08-24 21:03:46 +02:00
Matthias Mailänder
7108344501 bail out early before trying impossible paths 2015-08-24 21:03:46 +02:00
clemty
2bbc1fcda4 LUA and trait documentation fixes
- Typo in documentation ("proximitry").
- Add spaces between sentences.
- Remove most occurrences of "  " (two spaces) unless clearly used as indendation
- Punctuation (although no fullstop after filenames like "notifications.yaml").
2015-08-24 19:41:15 +02:00
reaperrr
64bbfe4121 Merge pull request #9129 from Mailaender/ts-build-palette
Fixed black dots on Tiberian Sun build palette icons
2015-08-24 17:46:02 +02:00
reaperrr
7f928477f9 Merge pull request #9130 from Mailaender/gdi4-shellmap
Replaced the blank shellmap with something more interesting
2015-08-24 17:29:22 +02:00
Matthias Mailänder
6132ec6558 Merge pull request #9150 from penev92/bleed_dedicatedSound
Make lower-level Sound not require the server state directly
2015-08-24 06:44:51 +02:00
atlimit8
f45358c36d Consolidate defense rules into ^Defense & ^DeployedVehicle for ts mod 2015-08-23 22:42:10 -05:00
atlimit8
a83806d90c Consolidate defense structure rules into ^Defense for d2k mod 2015-08-23 22:39:13 -05:00
atlimit8
68ee859666 Consolidate defense structure rules into ^Defense for cnc mod 2015-08-23 22:39:13 -05:00
atlimit8
59cd477e3e Consolidate defense structure rules into ^Defense for ra mod 2015-08-23 22:39:13 -05:00
Pavel Penev
02dd5afbd9 Merge pull request #9058 from RoosterDragon/reduce-alloc
Reduce allocations in the main game loop
2015-08-24 02:11:08 +03:00
reaperrr
3821729744 Upgrade rule 2015-08-24 00:49:01 +02:00
reaperrr
ed81eaaac2 TS yaml changes 2015-08-24 00:49:00 +02:00
reaperrr
542d88245d D2k yaml changes 2015-08-24 00:48:59 +02:00
reaperrr
9780bb26c2 RA yaml changes 2015-08-24 00:48:58 +02:00
reaperrr
2293494c56 TD yaml changes 2015-08-24 00:48:57 +02:00
reaperrr
006e66a3c3 Refactored IQuantizeBodyOrientation implementation
Moved BodyOrientation and related interfaces from Game to Mods.Common.
Introduced QuantizeFacingsFromSequence trait.
With*Body render traits no longer implement IQuantizeBodyOrientation
themselves.
2015-08-24 00:48:56 +02:00
Pavel Penev
09a41d8bde Add a bit of code documentation 2015-08-24 01:47:35 +03:00
Pavel Penev
49e9ad2c7c Make lower-level Sound not require the server state directly 2015-08-24 01:36:56 +03:00
Pavel Penev
1d3cfcf378 Merge pull request #8632 from Mailaender/openra-platform
Removed the OpenAL/OpenGL/SDL2 dependency from the game engine
2015-08-24 00:45:27 +03:00
Pavel Penev
535863ea83 Merge pull request #9147 from Mailaender/exception-log-map
Added the current map to the exception.log
2015-08-24 00:29:52 +03:00
Matthias Mailänder
0fba872b73 replace blank shellmap with something more interesting 2015-08-23 22:49:17 +02:00
Matthias Mailänder
001d2cde30 add the map to the exception.log 2015-08-23 22:27:00 +02:00
Pavel Penev
d64f5f29a4 Merge pull request #9075 from deniz1a/fix-crate
Removes LocalPlayer check from HideMapCrateAction and RevealMapCrateAction.
2015-08-23 23:17:28 +03:00
Matthias Mailänder
bec209085b Merge pull request #7873 from penev92/bleed_raceToFaction
Replace old "country" and "race" name in the code with the generic "faction"
2015-08-23 17:49:40 +02:00
Matthias Mailänder
f7b0454b9e avoid an unnecessary overload 2015-08-23 07:58:07 +02:00
Matthias Mailänder
4059f83b7e remove redundant namespace repetition 2015-08-23 07:58:06 +02:00
Matthias Mailänder
bfc7013ba4 avoid magic numbers 2015-08-23 07:58:06 +02:00
Matthias Mailänder
6abd21e71d explicitly set the OpenTK GL context 2015-08-23 07:58:06 +02:00
Matthias Mailänder
17f3466451 untie the engine from SDL2 and MiniTK 2015-08-23 07:58:03 +02:00
Pavel Penev
60eea5a507 Merge pull request #8840 from deniz1a/dropdown-gap
Removes spacing between dropdown menu items.
2015-08-23 01:32:53 +03:00
Pavel Penev
dec2696e76 Change "Change faction" lobby command 2015-08-22 23:34:40 +03:00
Pavel Penev
05e081043b Rename last usages of "race" in UI YAML files 2015-08-22 23:34:38 +03:00
Pavel Penev
09f67d18bb Some internal "race" to "faction" renaming 2015-08-22 23:34:36 +03:00
Pavel Penev
a83fc81571 Merge pull request #9126 from LipkeGu/RadarWidget_crash
Add Cell check to RadarWidget
2015-08-22 22:58:19 +03:00
Pavel Penev
b1b576c41b Merge pull request #8797 from abcdefg30/gpsvanish
Add a GpsRemoveFrozenActor trait
2015-08-22 22:47:57 +03:00
abcdefg30
87580d0aab Add a GpsRemoveFrozenActor trait 2015-08-22 21:36:30 +02:00
abcdefg30
429e6145cb Merge pull request #9073 from pchote/remove-production-duplication
Minor Production trait cleanups.
2015-08-22 20:39:10 +02:00
Pavel Penev
6d0d5b52fe Merge pull request #9133 from abcdefg30/interiorsmudge
Fix smudges/scorches being displayed on interior clear ground
2015-08-22 21:27:24 +03:00
abcdefg30
0f599bfc10 Fix smudges/scorches being displayed on interior clear ground 2015-08-22 18:26:10 +02:00
Matthias Mailänder
79f38802be replace Tiberian Dawn artwork for consistency 2015-08-22 17:37:13 +02:00
Matthias Mailänder
2917d28545 set up original build click palette to fix dark pixel errors 2015-08-22 16:18:19 +02:00
reaperrr
8e9da7f897 unhardcode palettes and sequences 2015-08-22 16:09:07 +02:00
Matthias Mailänder
1c45ca75a7 Merge pull request #9034 from Biofreak1987/soviet07
Add Soviet07
2015-08-22 14:12:56 +02:00
deniz1a
3b36ddfc54 Removes LocalPlayer check from HideMapCrateAction and RevealMapCrateAction.
Fixes #9063.
Fixes #9127.
2015-08-22 14:37:39 +03:00
Matthias Mailänder
f325463204 Merge pull request #9117 from GraionDilach/infiltrate-fix
Prevent infiltrating allied targets.
2015-08-22 12:54:42 +02:00
Guido L
9bad84e117 Add Cell check to RadarWidget. 2015-08-22 09:31:09 +02:00
deniz1a
347143ba87 Adds TopBottomSpacing to GridLayout. 2015-08-22 04:04:05 +03:00
deniz1a
90897481f9 Adds TopBottomSpacing values to yaml files. 2015-08-22 03:51:07 +03:00
deniz1a
a534290dc5 Removes spacing between dropdown menu items. 2015-08-22 03:51:07 +03:00
Zimmermann Gyula
3670c003a4 Prevent infiltrating allied targets unless explicitly set. 2015-08-22 00:35:41 +02:00
Pavel Penev
b7af5f5291 Merge pull request #9018 from Mailaender/cnc-maps
Added high quality Tiberian Dawn community maps
2015-08-22 01:13:01 +03:00
abcdefg30
8783905c51 Merge pull request #8773 from dan9550/ts-yaml
Alter install logic to convert case of file names
2015-08-21 21:53:48 +02:00
Dan9550
a559f6d4ac Modified mod.yaml to respect case sensitive file names
Modified mod.yaml to respect case sensitive file names

Modified install logic to convert case of files on install

Revert initial changes
2015-08-21 23:42:10 +10:00
Pavel Penev
174bde57f1 Merge pull request #9123 from clemty/authors
add myself to AUTHORS
2015-08-21 13:38:28 +03:00
clemty
447326c328 add myself to AUTHORS 2015-08-21 12:06:32 +02:00
Pavel Penev
d803a06a1e Merge pull request #8995 from reaperrr/vxl-upgrades1
Made WithVoxelTurret and WithVoxelBarrel upgradable
2015-08-21 00:33:42 +03:00
Biofreak1987
2242ae8937 Add Soviet07 2015-08-20 22:41:52 +02:00
Matthias Mailänder
9a861bdfba Merge pull request #8700 from deniz1a/rename-disable-shroud
Renames "Disable Shroud & Fog" debug option to "Observer view".
2015-08-20 20:41:01 +02:00
Matthias Mailänder
913871f171 Merge pull request #9097 from LipkeGu/rules_terrainType_fixes
Fix TerrainTypes for walls and crates
2015-08-20 20:37:12 +02:00
Pavel Penev
20193f086f Merge pull request #8942 from reaperrr/explodes2
Add specific exception message when Explodes cannot find a weapon
2015-08-20 13:03:37 +03:00
Matthias Mailänder
59a7d743cb Merge pull request #9047 from clemty/tooltips
TD tooltip fixes
2015-08-19 22:08:53 +02:00
Matthias Mailänder
cafad9f843 Merge pull request #9092 from penev92/bleed_rename
Some more renaming from "race" to "faction"
2015-08-19 22:03:01 +02:00
abcdefg30
7612f60b22 Merge pull request #8939 from Mailaender/lint-map-scripts
Added checks for syntax errors in Lua scripts
2015-08-19 21:36:34 +02:00
abcdefg30
7e7e3723dc Add "check-scripts" to make.ps1 2015-08-19 21:21:01 +02:00
Matthias Mailänder
5a3e61a902 check the .lua scripts for syntax error 2015-08-19 21:21:01 +02:00
clemty
4351094bd7 TD tooltip fixes
- mention Apache being strong vs aircraft
- mention engineers will damage buildings, not just capture them

reverted:
- Sentences are now (mostly) lowercase, end with full-stop
- Changed "defence" tab tooltip to "defense"
2015-08-19 12:53:08 +02:00
RoosterDragon
3d94c4b216 Minor formatting fix in Mobile.cs. 2015-08-18 22:03:14 +01:00
RoosterDragon
7eab7220ff In CanMoveFreelyInto, check if transient actor checks are needed at the start.
When transient actors checks are not needed, all control flows in the method return true. Therefore, we can return true directly in this case. Checking this condition is cheaper than checking for a free sub-cell, so this allows us a faster exit when we don't need to check for transient actors.
2015-08-18 22:03:13 +01:00
RoosterDragon
ca75b5af30 Factor logic for determining if an actor blocks movement into IsBlockedBy. 2015-08-18 22:03:11 +01:00
RoosterDragon
6414743f8e Introduce HasCellCondition to avoid HasFlag overhead. 2015-08-18 22:03:09 +01:00
RoosterDragon
d415d3ba4e Reduce allocations in the main game loop.
- Cache the shroud projection even for flat maps to avoid allocating single element arrays.
- Avoid LINQ in shroud and map projection queries to avoid enumerator allocations.
- Avoid LINQ in calculation of sync values.
- Cache enumerables in ProductionQueue.
- Cache delegate in HackyAI.
2015-08-18 21:17:28 +01:00
abcdefg30
83b310713d Merge pull request #8905 from atlimit8/WithProductionOverlay_accept_OnOwnerChanged
WithProductionOverlay: replace ITick => INotifyCreated & add INotifyOwnerChanged
2015-08-18 21:17:00 +02:00
abcdefg30
ee09dd41bc Merge pull request #8957 from Mailaender/ts-decorations
Added Tiberian Sun decorational actors
2015-08-18 21:15:28 +02:00
reaperrr
e057a97217 Remove bogus ShadowIndex from TS cameo palette 2015-08-18 18:33:46 +02:00
Pavel Penev
663c9239df Mop up remaining "race" private variables 2015-08-18 00:26:11 +03:00
Pavel Penev
2b359b54c7 Add an upgrade rule for renaming crates' ValidRaces 2015-08-18 00:26:09 +03:00
Pavel Penev
1a95e7a9f1 Rename crates' ValidRaces 2015-08-18 00:26:07 +03:00
Pavel Penev
b6b107de46 Rename RenderSpritesInfo.RaceImages 2015-08-18 00:26:05 +03:00
Pavel Penev
1e817fad76 Merge pull request #9089 from Mailaender/editor-coordinate
Added a coordinate display to the map editor
2015-08-18 00:12:10 +03:00
Pavel Penev
3d292d8200 Merge pull request #8749 from Mailaender/lint-palettes
Added a lint rule for palette references
2015-08-17 23:09:53 +03:00
Matthias Mailänder
4f05681707 Merge pull request #8912 from reaperrr/ts-icons1
Added the Nod repair bay icon
2015-08-17 21:46:20 +02:00
Matthias Mailänder
322358ff3d also check shroud sequences 2015-08-17 21:36:55 +02:00
Matthias Mailänder
118782a85e check palette references 2015-08-17 21:36:45 +02:00
Matthias Mailänder
41698ab8bb show the current coordinate at the top 2015-08-17 21:21:52 +02:00
Matthias Mailänder
ba8e292b71 Merge pull request #9022 from RoosterDragon/less-sync
Sync only once per tick
2015-08-17 21:13:55 +02:00
abcdefg30
0c021770f0 Merge pull request #9076 from Mailaender/resource-sequences
Added missing check yaml references
2015-08-17 21:13:32 +02:00
Paul Chote
eae41b1750 Fix LST queue type. 2015-08-17 19:37:24 +01:00
reaperrr
4e633b21f6 Fixed D2k grenadier to not explode violently when reloading
Removed redundant Chance (default is 100 anyway).
2015-08-17 20:11:57 +02:00
reaperrr
3ae75f870c Add Explodes safeguards
Accept both null and empty string to disable explosion weapons.

Throw specific exception if weapon was not found.
Require Weapon (EmptyWeapon stays optional).
2015-08-17 20:11:38 +02:00
Pavel Penev
17b2a37e97 Merge pull request #9051 from abcdefg30/creepssetting
Fix the creeps setting being ignored
2015-08-17 18:57:06 +03:00
abcdefg30
0c4e691008 Rename HuskActor to Actor 2015-08-17 17:38:07 +02:00
abcdefg30
3dc5515d16 Remove references to 'husk' in the descriptions 2015-08-17 17:38:06 +02:00
abcdefg30
5967b06189 Remove the 'workaround' in gdi05 2015-08-17 17:38:05 +02:00
abcdefg30
b24c1845fb Adjust the upgrade rule for SpawnActorOnDeath 2015-08-17 17:38:04 +02:00
abcdefg30
9f5a8a6d1f Fix the creeps setting being ignored 2015-08-17 17:38:03 +02:00
Guido L
ce9bbd2a52 Fix TerrainTypes for walls and crates 2015-08-17 16:44:20 +02:00
Pavel Penev
71c5d69dc5 Merge pull request #8938 from abcdefg30/heliheigth
Have flying actors account for terrain height
2015-08-17 13:53:39 +03:00
Pavel Penev
ac46a356f4 Merge pull request #9057 from Mailaender/map-tilset-sequence-nre
Fixed a likely null reference exception when checking mod sequence definitions
2015-08-17 13:44:06 +03:00
abcdefg30
e05ba2454c Merge pull request #9084 from Mailaender/sonar-shroud
Fixed sonar pulse revealing shroud
2015-08-16 23:58:09 +02:00
Matthias Mailänder
51fabae106 change editor tooltip to actor: description (type) 2015-08-16 21:58:17 +02:00
Pavel Penev
4600d1c62b Merge pull request #9071 from pchote/fix-shroud-healthbars
Fix visibility queries when fog is disabled.
2015-08-16 19:19:16 +03:00
Matthias Mailänder
61cba78d62 rebalance sonar to not reveal any shroud 2015-08-16 13:32:26 +02:00
Matthias Mailänder
e3194ed35a Merge pull request #9080 from pchote/fix-spy-overlay
Replace icon veterancy overlay with new artwork.
2015-08-16 09:33:47 +02:00
Paul Chote
78391e7c65 Replace icon veterancy overlay with new artwork.
New shp includes frames for higher level veterancy
for potential future use.
2015-08-15 20:59:52 +01:00
Paul Chote
0b13a173ae Merge pull request #9053 from abcdefg30/dropzone-w-shroudrange
Fix a crash in dropzone-w
2015-08-15 10:25:45 +01:00
Paul Chote
a4c4cec4ee Merge pull request #9050 from GraionDilach/fix-td-shippedost
Increase ShippedSoundtracks of the TD mod.
2015-08-15 10:15:04 +01:00
Paul Chote
b7d549e2d2 Merge pull request #9062 from clemty/renamedefencetab
TD: renames tooltip on "Defence" tab to "Support"
2015-08-15 10:04:35 +01:00
Matthias Mailänder
37b6dc1603 add maps from the resource site 2015-08-15 11:03:45 +02:00
Matthias Mailänder
dc477c3ced add missing sequence reference 2015-08-15 09:59:53 +02:00
Matthias Mailänder
d0634d9bb7 add missing weapon reference 2015-08-15 09:57:42 +02:00
Matthias Mailänder
299e5881b3 Merge pull request #9072 from pchote/fix-shroud-option-case
Fix capitalisation of the "Explored Map" option.
2015-08-14 23:26:14 +02:00
Paul Chote
30d0ce2dee Remove bogus property from d2k conyard. 2015-08-14 19:44:24 +01:00
Paul Chote
8dfd42b30e Make Production.Info readonly. 2015-08-14 19:44:24 +01:00
Paul Chote
086467020e Simplify IOccupySpace check. 2015-08-14 19:44:24 +01:00
Paul Chote
d730b4ee50 Remove duplicated DoProduction from Production. 2015-08-14 19:35:48 +01:00
Paul Chote
1d5644476a Fix capitalisation of the "Explored Map" option. 2015-08-14 19:29:04 +01:00
Paul Chote
738a500876 Fix visibility queries when fog is disabled. 2015-08-14 19:26:01 +01:00
clemty
31fe6b7e9d TD: renames tooltip on "Defence" tab to "Support" as suggested in #9047#issuecomment-130350382 2015-08-14 00:04:26 +02:00
Matthias Mailänder
9dabf9019f Merge pull request #9026 from baxxxster/bleed
Changed TimestampFormat for server logs
2015-08-13 21:16:23 +02:00
Matthias Mailänder
e13f983946 Merge pull request #9038 from penev92/bleed_rename
Some more renaming from "race" to "faction"
2015-08-13 21:13:31 +02:00
Matthias Mailänder
c5b1e6be5f fix a null reference exception at map (tileset) 2015-08-13 20:28:52 +02:00
abcdefg30
92c41aedb6 Fix a crash in dropzone-w
We don't need RevealsShroud here anyway,
as the map disabled Shroud and Fog.
2015-08-12 23:34:39 +02:00
abcdefg30
dae70321c2 Merge pull request #8792 from deniz1a/reveal-shroud
Changes shroud lobby setting from disabling shroud to revealing it.
2015-08-12 22:04:15 +02:00
abcdefg30
032ea2a377 Merge pull request #9032 from deniz1a/fix-8935
Fixes observer widgets being loaded multiple times at game end.
2015-08-12 20:47:39 +02:00
Zimmermann Gyula
e29a103e32 Increase ShippedSoundtracks of the TD mod. 2015-08-12 17:45:01 +02:00
abcdefg30
15f22c32b3 Merge pull request #8886 from atimoschenkow/fly-queue
Fix queue commands for Plane/Heli
2015-08-12 00:50:43 +02:00
abcdefg30
7e5b4f61eb Merge pull request #9036 from reaperrr/heli-reserve
Improve aircraft unreserving of structures
2015-08-11 23:36:32 +02:00
reaperrr
d97d4c82a3 Plane style fixes 2015-08-11 15:49:06 +02:00
reaperrr
9cbc16b6a3 If aircraft has FallsToEarth, return instead of just skipping reservation. 2015-08-11 15:47:45 +02:00
reaperrr
6fc8de69ac Unreserve aircraft when removed from world 2015-08-11 15:02:31 +02:00
deniz1a
e59cd78322 Fixes observer widgets being loaded multiple times at game end. 2015-08-11 12:31:23 +03:00
Pavel Penev
4d11195989 Rename MPStartUnitsInfo.Races to Factions
Also add an upgrade rule.
2015-08-11 04:00:08 +03:00
Pavel Penev
fd01e95d6c Rename EmitInfantryOnSellInfo.Races to Factions
Also rename the rest of "race" in that file.
2015-08-11 03:46:12 +03:00
Pavel Penev
8b58f3a1d8 Rename ProductionQueue.Race to Faction 2015-08-11 03:29:49 +03:00
Pavel Penev
6e9b5ed2c9 Rename ProductionQueueInfo.Race to Factions
Also add an upgrade rule.
2015-08-11 03:27:12 +03:00
Pavel Penev
a6dae8e854 Merge pull request #9017 from reaperrr/lower-rank1
Rebalanced stat gains from rank-up
2015-08-11 02:36:01 +03:00
Pavel Penev
c99dcb3f24 Merge pull request #9023 from RoosterDragon/actor-lookup
Add a method to look up actors by ID.
2015-08-11 02:28:36 +03:00
abcdefg30
923c5405d2 Merge pull request #8965 from Mailaender/rallypoint-polish
Fixed the RallyPoint trait for Tiberian Sun polish
2015-08-10 22:03:13 +02:00
Matthias Mailänder
27016367c7 use more appropriate waypoint art for rally points 2015-08-10 21:35:21 +02:00
Matthias Mailänder
df206ddb18 unhardcode rallypoint sprites 2015-08-10 21:35:21 +02:00
Matthias Mailänder
b536e677fb rename RallyPoint.RallyPoint to RallyPoint.Offset 2015-08-10 21:35:21 +02:00
reaperrr
f11331a7cd Merge pull request #8989 from Mailaender/ts-light-cloak
Removed cloak effect from light posts
2015-08-10 19:14:21 +02:00
Glenn Martin Jensen
441f23d1e6 Changed TimestampFormat for server logs
Changed TimestampFormat for server logs
2015-08-10 16:53:51 +02:00
abcdefg30
22184a6791 Merge pull request #8934 from Mailaender/travis-mono4
Updated Travis to use Mono 4.0
2015-08-09 22:16:25 +02:00
abcdefg30
797b9d18c8 Merge pull request #8915 from Mailaender/cpos-mpos-test
Added a unit test for MPos conversions
2015-08-09 22:01:33 +02:00
RoosterDragon
89f5a23077 When dumping the sync report, log all the orders issued in the frame that desynced. 2015-08-09 20:59:59 +01:00
RoosterDragon
709befda08 Sync only once per tick, rather than once per tick and once per order.
This greatly improves performance by not syncing the world state for every single order processed as this becomes very expensive, at the cost of being unable to directly pinpoint the order that causes a desync. Instead the granularity of detecting desyncs is reduced to the tick level.
2015-08-09 20:58:20 +01:00
Matthias Mailänder
4d360a66ed Merge pull request #8979 from penev92/bleed_production
Remove producer-is-in-world assumptions from Production
2015-08-09 21:29:29 +02:00
RoosterDragon
a0117a3890 Add a method to look up actors by ID.
This can be used to speed up some methods.
2015-08-09 20:25:34 +01:00
Matthias Mailänder
021b344532 Merge pull request #8988 from reaperrr/fix-moveanim
Fix for WithAttackAnimation breaking WithMoveAnimation
2015-08-09 21:21:33 +02:00
Matthias Mailänder
84fdd97f94 Merge pull request #8744 from abcdefg30/viceroidhusk
Merge SpawnViceroid into LeavesHusk
2015-08-09 21:07:32 +02:00
Matthias Mailänder
9efc3b377b Merge pull request #9020 from abcdefg30/clearscreenshot
Fix shroud outside map bounds being transparent
2015-08-09 20:55:23 +02:00
abcdefg30
e8477b1b5a Rename LeavesHusk to SpawnActorOnDeath 2015-08-09 19:24:14 +02:00
abcdefg30
1a1e1e08d7 Fix shroud outside map bounds being transparent 2015-08-09 18:55:13 +02:00
reaperrr
d8ca66bec5 Merge pull request #9014 from Mailaender/immobile-groundcheck
Fixed ground level checks for immobile actors
2015-08-09 15:48:50 +02:00
Pavel Penev
03cc69538e Merge pull request #9015 from Mailaender/publishcoverity-0.11
Fixed automatic Coverity build submissions
2015-08-09 13:52:34 +03:00
reaperrr
fdeb901da6 Rebalance TS rankups 2015-08-09 12:47:26 +02:00
reaperrr
05b82dbc02 Rebalance D2k rankups 2015-08-09 12:47:11 +02:00
reaperrr
cd41ecaa78 Rebalance TD rankups 2015-08-09 12:46:55 +02:00
reaperrr
b5352c24a0 Rebalance RA rankups 2015-08-09 12:46:41 +02:00
Matthias Mailänder
bf53f981d4 fix path for PublishCoverity 0.11.0 2015-08-09 11:50:15 +02:00
Matthias Mailänder
208cfa9542 fix IsAtGroundLevel always being false for immobile actors 2015-08-09 11:45:25 +02:00
reaperrr
277ac04f85 Remove legacy 0% = not targetable assumption 2015-08-09 01:11:10 +02:00
abcdefg30
abf5047072 Add an upgrade rule and update the default mods 2015-08-08 23:23:32 +02:00
abcdefg30
538723f8fb Merge SpawnViceroid into LeavesHusk 2015-08-08 23:23:31 +02:00
abcdefg30
1bc84275fd Merge pull request #9000 from reaperrr/fix-misl-shadow
Fixed missile shadow on elevated terrain
2015-08-08 23:20:23 +02:00
reaperrr
433eac34b5 Fixes missile shadow on elevated terrain 2015-08-08 20:14:05 +02:00
reaperrr
e527513cbd Made voxel turret and barrel traits upgradable. 2015-08-08 18:13:27 +02:00
Matthias Mailänder
7f42664b23 don't cloak light posts 2015-08-08 17:32:58 +02:00
reaperrr
281a87acbc Fix WithAttackAnimation breaking WithMoveAnimation 2015-08-08 17:00:38 +02:00
Matthias Mailänder
4e101afb6d Merge pull request #8838 from reaperrr/withbarrel2
Fixed WithBarrel and made it upgradable
2015-08-08 16:50:42 +02:00
Matthias Mailänder
88b98fa8ef Merge pull request #8975 from penev92/bleed_rename
Some more renaming from "country" and "race" to "faction"
2015-08-08 16:13:16 +02:00
Pavel Penev
3cb707ad3c Remove producer-is-in-world assumptions from Production
D2k upgrades need to be actors that never actor the world, produced by the PlayerActor, who is also not in the world, but the Production trait expects the producer to be in the world even if it has Exit.MoveIntoWorld = False, allowing the producees to not enter the world.
2015-08-08 16:36:24 +03:00
atimoschenkow
b1c51cc910 Fix for #6161 queue commands for Plane/Heli (do not ignore Order.Queued in ResolveOrder()) 2015-08-07 23:41:03 +02:00
Matthias Mailänder
d358c495c5 test the coordinate system conversions 2015-08-07 00:31:58 +02:00
Matthias Mailänder
ddb01b6ae5 fix warnings about unused local variables 2015-08-07 00:31:24 +02:00
Matthias Mailänder
8aac12ffb4 add palettes (decorational sprites) 2015-08-05 18:27:13 +02:00
Matthias Mailänder
1685dce28f add drums 2015-08-05 18:22:00 +02:00
Matthias Mailänder
6c3b668a86 add boxes (decorational crates) 2015-08-05 18:18:47 +02:00
Pavel Penev
10aee9ffa9 Rid Transforms and Transform of "race" 2015-08-05 18:15:11 +03:00
Pavel Penev
faf0da6994 Rename Session.Slot.LockRace 2015-08-05 18:11:10 +03:00
Pavel Penev
2f38239f32 Clean up LobbyUtils from "race" a bit 2015-08-05 18:07:26 +03:00
Pavel Penev
5eaf5b5b51 Rename Session.Client.Race 2015-08-05 17:45:56 +03:00
Pavel Penev
50f4508123 Rid SpawnSelectorTooltipLogic from "Country" 2015-08-05 17:35:07 +03:00
Pavel Penev
957af9ac5e Rename SpawnOccupant.Country 2015-08-05 17:31:00 +03:00
deniz1a
2ca949dbd2 Renames Shroud lobby option to Explored map. 2015-08-04 17:31:07 +03:00
deniz1a
7efbf0633e Changes shroud lobby setting from disabling shroud to revealing it. 2015-08-04 17:31:06 +03:00
abcdefg30
a94e35163a Have flying actors account for terrain height 2015-08-04 15:48:03 +02:00
Matthias Mailänder
9170db9642 update Travis to use Mono 4 2015-08-04 12:00:45 +02:00
reaperrr
dff3201eca Use Nod variant of repair bay icon 2015-08-03 22:12:27 +02:00
atlimit8
d785c50c3e WithProductionOverlay: replace ITick => INotifyCreated & add INotifyOwnerChanged 2015-08-03 10:00:33 -05:00
deniz1a
2abd1b5350 Renames "Disable Shroud & Fog" debug option to "Disable visibility checks". 2015-08-02 00:30:42 +03:00
reaperrr
72d67de414 Fixed WithBarrel and made it upgradable.
Fixed missing Requires<ArmamentInfo>.
Removed now-redundant Barrel property (has been unused since RenderSprites animation keys were removed).
Made trait classes public.
Made ctor-cached trait lookups readonly.
2015-08-01 19:31:59 +02:00
deniz1a
f2ac6c9980 Some yaml cleanups. 2015-07-25 23:03:15 +03:00
deniz1a
ac6e915839 Simplifies Start button logic in lobby. 2015-07-25 23:03:14 +03:00
deniz1a
1a968588b6 Shows real owner of disguised units to allies. 2015-07-10 23:00:04 +03:00
1164 changed files with 34219 additions and 14082 deletions

View File

@@ -2,7 +2,7 @@
# see travis-ci.org for details
language: csharp
mono: 3.12.0
mono: 4.0.0
# http://docs.travis-ci.com/user/migrating-from-legacy
sudo: false
@@ -14,6 +14,7 @@ cache:
addons:
apt:
packages:
- lua5.1
- nsis
- nsis-common
- dpkg
@@ -31,6 +32,7 @@ script:
- travis_retry make all-dependencies
- make all
- make check
- make check-scripts
- make test
# Automatically update the trait documentation and Lua API

10
AUTHORS
View File

@@ -35,13 +35,16 @@ Also thanks to:
* Arik Lirette (Angusm3)
* Barnaby Smith (mvi)
* Bellator
* Biofreak
* Braxton Williams (Buddytex)
* Bryan Wilbur
* Bugra Cuhadaroglu (BugraC)
* Christer Ulfsparre (Holloweye)
* Chris Grant (Unit158)
* clem
* Cody Brittain (Generalcamo)
* D2k Sardaukar
* D'Arcy Rush (r34ch)
* Daniel Derejvanik (Harisson)
* Danny Keary (Dan9550)
* David Jiménez (Rydra)
@@ -50,6 +53,7 @@ Also thanks to:
* Dmitri Suvorov (suvjunmd)
* Erasmus Schroder (rasco)
* Eric Bajumpaa (SteelPhase)
* Evgeniy Sergeev (evgeniysergeev)
* Fahrradkette
* Frank Razenberg (zzattack)
* Gareth Needham (Ripley`)
@@ -58,17 +62,20 @@ Also thanks to:
* Gordon Martin (Happy0)
* Guido Lipke (LipkeGu)
* Gyula Zimmermann (Graion Dilach)
* Hervé Matysiak (Herve-M)
* Huw Pascoe
* Ian T. Jacobsen (Smilex)
* Imago
* Iran
* Jacob Dufault (jacobdufault)
* James Dunne (jsd)
* James Gilbert (DSUK)
* Jan-Willem Buurlage (jwbuurlage)
* Jason (atlimit8)
* Jeff Harris (jeff_1amstudios)
* Jes
* Joakim Lindberg (booom3)
* Joppy Furr
* Kanar
* Kenny Hoxworth (hoxworth)
* Krishnakanth Mallik
@@ -150,6 +157,9 @@ Motmans and distributed under the MIT license.
Using ICSharpCode.SharpZipLib initially by Mike
Krueger and distributed under the GNU GPL terms.
Using SmartIrc4Net developed by Mirco Bauer
distributed under the LGPL version 2.1 or later.
Finally, special thanks goes to the original teams
at Westwood Studios and EA for creating the classic

View File

@@ -40,7 +40,7 @@
CSC = dmcs
CSFLAGS = -nologo -warn:4 -codepage:utf8 -unsafe -warnaserror
DEFINE = TRACE
COMMON_LIBS = System.dll System.Core.dll System.Data.dll System.Data.DataSetExtensions.dll System.Drawing.dll System.Xml.dll thirdparty/download/ICSharpCode.SharpZipLib.dll thirdparty/download/FuzzyLogicLibrary.dll thirdparty/download/Mono.Nat.dll thirdparty/download/MaxMind.Db.dll thirdparty/download/MaxMind.GeoIP2.dll thirdparty/download/Eluant.dll
COMMON_LIBS = System.dll System.Core.dll System.Data.dll System.Data.DataSetExtensions.dll System.Drawing.dll System.Xml.dll thirdparty/download/ICSharpCode.SharpZipLib.dll thirdparty/download/FuzzyLogicLibrary.dll thirdparty/download/Mono.Nat.dll thirdparty/download/MaxMind.Db.dll thirdparty/download/MaxMind.GeoIP2.dll thirdparty/download/Eluant.dll thirdparty/download/SmarIrc4net.dll
DEBUG = true
ifeq ($(DEBUG), $(filter $(DEBUG),false no n off 0))
@@ -79,7 +79,7 @@ INSTALL_PROGRAM = $(INSTALL) -m755
INSTALL_DATA = $(INSTALL) -m644
# program targets
CORE = rsdl2 rnull game utility
CORE = pdefault pnull game utility
TOOLS = gamemonitor
VERSION = $(shell git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || echo git-`git rev-parse --short HEAD`)
@@ -100,25 +100,25 @@ endif
game_SRCS := $(shell find OpenRA.Game/ -iname '*.cs')
game_TARGET = OpenRA.Game.exe
game_KIND = winexe
game_LIBS = $(COMMON_LIBS) $(game_DEPS) thirdparty/download/SDL2-CS.dll thirdparty/download/SharpFont.dll
game_LIBS = $(COMMON_LIBS) $(game_DEPS) thirdparty/download/SharpFont.dll
game_FLAGS = -win32icon:OpenRA.Game/OpenRA.ico
PROGRAMS += game
game: $(game_TARGET)
# Renderer dlls
rsdl2_SRCS := $(shell find OpenRA.Renderer.Sdl2/ -iname '*.cs')
rsdl2_TARGET = OpenRA.Renderer.Sdl2.dll
rsdl2_KIND = library
rsdl2_DEPS = $(game_TARGET)
rsdl2_LIBS = $(COMMON_LIBS) thirdparty/download/SDL2-CS.dll $(rsdl2_DEPS)
# Platform dlls
pdefault_SRCS := $(shell find OpenRA.Platforms.Default/ -iname '*.cs')
pdefault_TARGET = OpenRA.Platforms.Default.dll
pdefault_KIND = library
pdefault_DEPS = $(game_TARGET)
pdefault_LIBS = $(COMMON_LIBS) thirdparty/download/SDL2-CS.dll $(pdefault_DEPS)
rnull_SRCS := $(shell find OpenRA.Renderer.Null/ -iname '*.cs')
rnull_TARGET = OpenRA.Renderer.Null.dll
rnull_KIND = library
rnull_DEPS = $(game_TARGET)
rnull_LIBS = $(COMMON_LIBS) $(rnull_DEPS)
PROGRAMS += rsdl2 rnull
renderers: $(rsdl2_TARGET) $(rnull_TARGET)
pnull_SRCS := $(shell find OpenRA.Platforms.Null/ -iname '*.cs')
pnull_TARGET = OpenRA.Platforms.Null.dll
pnull_KIND = library
pnull_DEPS = $(game_TARGET)
pnull_LIBS = $(COMMON_LIBS) $(pnull_DEPS)
PROGRAMS += pdefault pnull
platforms: $(pdefault_TARGET) $(pnull_TARGET)
# Mods Common
mod_common_SRCS := $(shell find OpenRA.Mods.Common/ -iname '*.cs')
@@ -170,13 +170,22 @@ mod_ts_LIBS = $(COMMON_LIBS) $(STD_MOD_LIBS) $(mod_common_TARGET)
PROGRAMS += mod_ts
mod_ts: $(mod_ts_TARGET)
check-scripts:
@echo
@echo "Checking for Lua syntax errors..."
@luac -p $(shell find mods/*/maps/* -iname '*.lua')
@luac -p $(shell find lua/* -iname '*.lua')
check: utility mods
@echo
@echo "Checking for code style violations in OpenRA.Game..."
@mono --debug OpenRA.Utility.exe ra --check-code-style OpenRA.Game
@echo
@echo "Checking for code style violations in OpenRA.Renderer.Null..."
@mono --debug OpenRA.Utility.exe ra --check-code-style OpenRA.Renderer.Null
@echo "Checking for code style violations in OpenRA.Platforms.Default..."
@mono --debug OpenRA.Utility.exe ra --check-code-style OpenRA.Platforms.Default
@echo
@echo "Checking for code style violations in OpenRA.Platforms.Null..."
@mono --debug OpenRA.Utility.exe ra --check-code-style OpenRA.Platforms.Null
@echo
@echo "Checking for code style violations in OpenRA.GameMonitor..."
@mono --debug OpenRA.Utility.exe ra --check-code-style OpenRA.GameMonitor
@@ -196,9 +205,6 @@ check: utility mods
@echo "Checking for code style violations in OpenRA.Mods.TS..."
@mono --debug OpenRA.Utility.exe ra --check-code-style OpenRA.Mods.TS
@echo
@echo "Checking for code style violations in OpenRA.Renderer.Sdl2..."
@mono --debug OpenRA.Utility.exe ra --check-code-style OpenRA.Renderer.Sdl2
@echo
@echo "Checking for code style violations in OpenRA.Utility..."
@mono --debug OpenRA.Utility.exe ra --check-code-style OpenRA.Utility
@echo
@@ -269,7 +275,7 @@ $(foreach prog,$(PROGRAMS),$(eval $(call BUILD_ASSEMBLY,$(prog))))
#
default: core
core: game renderers mods utility
core: game platforms mods utility
tools: gamemonitor
@@ -363,6 +369,7 @@ install-core: default
@$(INSTALL_PROGRAM) MaxMind.GeoIP2.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) Newtonsoft.Json.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) RestSharp.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) SmarIrc4net.dll "$(DATA_INSTALL_DIR)"
ifneq ($(UNAME_S),Darwin)
@$(CP) *.sh "$(DATA_INSTALL_DIR)"

View File

@@ -30,7 +30,7 @@ namespace OpenRA
public readonly uint ActorID;
[Sync] public Player Owner { get; set; }
public Player Owner { get; set; }
public bool IsInWorld { get; internal set; }
public bool Disposed { get; private set; }
@@ -40,37 +40,34 @@ namespace OpenRA
public Group Group;
public int Generation;
Lazy<Rectangle> bounds;
Lazy<Rectangle> visualBounds;
Lazy<IFacing> facing;
Lazy<Health> health;
Lazy<IOccupySpace> occupySpace;
Lazy<IEffectiveOwner> effectiveOwner;
public Rectangle Bounds { get { return bounds.Value; } }
public Rectangle VisualBounds { get { return visualBounds.Value; } }
public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } }
public IEffectiveOwner EffectiveOwner { get { return effectiveOwner.Value; } }
public Rectangle Bounds { get; private set; }
public Rectangle VisualBounds { get; private set; }
public IEffectiveOwner EffectiveOwner { get; private set; }
public IOccupySpace OccupiesSpace { get; private set; }
public bool IsIdle { get { return currentActivity == null; } }
public bool IsDead { get { return Disposed || (health.Value == null ? false : health.Value.IsDead); } }
public bool IsDead { get { return Disposed || (health != null && health.IsDead); } }
public CPos Location { get { return occupySpace.Value.TopLeft; } }
public WPos CenterPosition { get { return occupySpace.Value.CenterPosition; } }
public CPos Location { get { return OccupiesSpace.TopLeft; } }
public WPos CenterPosition { get { return OccupiesSpace.CenterPosition; } }
public WRot Orientation
{
get
{
// TODO: Support non-zero pitch/roll in IFacing (IOrientation?)
var facingValue = facing.Value != null ? facing.Value.Facing : 0;
var facingValue = facing != null ? facing.Facing : 0;
return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facingValue));
}
}
readonly IFacing facing;
readonly IHealth health;
readonly IRenderModifier[] renderModifiers;
readonly IRender[] renders;
readonly IDisable[] disables;
readonly IVisibilityModifier[] visibilityModifiers;
readonly IDefaultVisibility defaultVisibility;
internal Actor(World world, string name, TypeDictionary initDict)
{
@@ -81,8 +78,6 @@ namespace OpenRA
if (initDict.Contains<OwnerInit>())
Owner = init.Get<OwnerInit, Player>();
occupySpace = Exts.Lazy(() => TraitOrDefault<IOccupySpace>());
if (name != null)
{
name = name.ToLowerInvariant();
@@ -92,44 +87,54 @@ namespace OpenRA
Info = world.Map.Rules.Actors[name];
foreach (var trait in Info.TraitsInConstructOrder())
{
AddTrait(trait.Create(init));
// Some traits rely on properties provided by IOccupySpace in their initialization,
// so we must ready it now, we cannot wait until all traits have finished construction.
if (trait is IOccupySpaceInfo)
OccupiesSpace = Trait<IOccupySpace>();
}
}
facing = Exts.Lazy(() => TraitOrDefault<IFacing>());
health = Exts.Lazy(() => TraitOrDefault<Health>());
effectiveOwner = Exts.Lazy(() => TraitOrDefault<IEffectiveOwner>());
bounds = Exts.Lazy(() =>
{
var si = Info.Traits.GetOrDefault<SelectableInfo>();
var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) :
TraitsImplementing<IAutoSelectionSize>().Select(x => x.SelectionSize(this)).FirstOrDefault();
var offset = -size / 2;
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
offset += new int2(si.Bounds[2], si.Bounds[3]);
return new Rectangle(offset.X, offset.Y, size.X, size.Y);
});
visualBounds = Exts.Lazy(() =>
{
var sd = Info.Traits.GetOrDefault<ISelectionDecorationsInfo>();
if (sd == null || sd.SelectionBoxBounds == null)
return bounds.Value;
var size = new int2(sd.SelectionBoxBounds[0], sd.SelectionBoxBounds[1]);
var offset = -size / 2;
if (sd.SelectionBoxBounds.Length > 2)
offset += new int2(sd.SelectionBoxBounds[2], sd.SelectionBoxBounds[3]);
return new Rectangle(offset.X, offset.Y, size.X, size.Y);
});
Bounds = DetermineBounds();
VisualBounds = DetermineVisualBounds();
EffectiveOwner = TraitOrDefault<IEffectiveOwner>();
facing = TraitOrDefault<IFacing>();
health = TraitOrDefault<IHealth>();
renderModifiers = TraitsImplementing<IRenderModifier>().ToArray();
renders = TraitsImplementing<IRender>().ToArray();
disables = TraitsImplementing<IDisable>().ToArray();
visibilityModifiers = TraitsImplementing<IVisibilityModifier>().ToArray();
defaultVisibility = Trait<IDefaultVisibility>();
}
Rectangle DetermineBounds()
{
var si = Info.TraitInfoOrDefault<SelectableInfo>();
var size = (si != null && si.Bounds != null) ? new int2(si.Bounds[0], si.Bounds[1]) :
TraitsImplementing<IAutoSelectionSize>().Select(x => x.SelectionSize(this)).FirstOrDefault();
var offset = -size / 2;
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
offset += new int2(si.Bounds[2], si.Bounds[3]);
return new Rectangle(offset.X, offset.Y, size.X, size.Y);
}
Rectangle DetermineVisualBounds()
{
var sd = Info.TraitInfoOrDefault<ISelectionDecorationsInfo>();
if (sd == null || sd.SelectionBoxBounds == null)
return Bounds;
var size = new int2(sd.SelectionBoxBounds[0], sd.SelectionBoxBounds[1]);
var offset = -size / 2;
if (sd.SelectionBoxBounds.Length > 2)
offset += new int2(sd.SelectionBoxBounds[2], sd.SelectionBoxBounds[3]);
return new Rectangle(offset.X, offset.Y, size.X, size.Y);
}
public void Tick()
@@ -222,11 +227,6 @@ namespace OpenRA
return World.TraitDict.WithInterface<T>(this);
}
public bool HasTrait<T>()
{
return World.TraitDict.Contains<T>(this);
}
public void AddTrait(object trait)
{
World.TraitDict.AddTrait(this, trait);
@@ -279,12 +279,28 @@ namespace OpenRA
});
}
public void Kill(Actor attacker)
public DamageState GetDamageState()
{
if (health.Value == null)
if (Disposed)
return DamageState.Dead;
return (health == null) ? DamageState.Undamaged : health.DamageState;
}
public void InflictDamage(Actor attacker, int damage, IWarhead warhead)
{
if (Disposed || health == null)
return;
health.Value.InflictDamage(this, attacker, health.Value.MaxHP, null, true);
health.InflictDamage(this, attacker, damage, warhead, false);
}
public void Kill(Actor attacker)
{
if (Disposed || health == null)
return;
health.Kill(this, attacker);
}
public bool IsDisabled()
@@ -295,6 +311,15 @@ namespace OpenRA
return false;
}
public bool CanBeViewedByPlayer(Player player)
{
foreach (var visibilityModifier in visibilityModifiers)
if (!visibilityModifier.IsVisible(this, player))
return false;
return defaultVisibility.IsVisible(this, player);
}
#region Scripting interface
Lazy<ScriptActorInterface> luaInterface;

View File

@@ -44,15 +44,15 @@ namespace OpenRA
public MPos ToMPos(Map map)
{
return ToMPos(map.TileShape);
return ToMPos(map.Grid.Type);
}
public MPos ToMPos(TileShape shape)
public MPos ToMPos(MapGridType gridType)
{
if (shape == TileShape.Rectangle)
if (gridType == MapGridType.Rectangular)
return new MPos(X, Y);
// Convert from diamond cell (x, y) position to rectangular map position (u, v)
// Convert from RectangularIsometric cell (x, y) position to rectangular map position (u, v)
// - The staggered rows make this fiddly (hint: draw a diagram!)
// (a) Consider the relationships:
// - +1x (even -> odd) adds (0, 1) to (u, v)

View File

@@ -0,0 +1,37 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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.Collections.Generic;
namespace OpenRA
{
// Referenced from ModMetadata, so needs to be in OpenRA.Game :(
public class ContentInstaller : IGlobalModData
{
public readonly string[] TestFiles = { };
public readonly string[] DiskTestFiles = { };
public readonly string PackageToExtractFromCD = null;
public readonly bool OverwriteFiles = true;
public readonly Dictionary<string, string[]> CopyFilesFromCD = new Dictionary<string, string[]>();
public readonly Dictionary<string, string[]> ExtractFilesFromCD = new Dictionary<string, string[]>();
public readonly string PackageMirrorList = null;
public readonly string MusicPackageMirrorList = null;
public readonly int ShippedSoundtracks = 0;
/// <summary> InstallShield .CAB file IDs, used to extract Mod-specific files. </summary>
public readonly HashSet<int> InstallShieldCABFileIds = new HashSet<int>();
/// <summary> InstallShield .CAB file IDs, used to extract Mod-specific archives and extract contents of ExtractFilesFromCD. </summary>
public readonly HashSet<string> InstallShieldCABFilePackageIds = new HashSet<string>();
}
}

View File

@@ -46,7 +46,7 @@ namespace OpenRA
public static Func<string, Type, string, object> InvalidValueAction = (s, t, f) =>
{
throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s, f, t));
throw new YamlException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s, f, t));
};
public static Action<string, Type> UnknownFieldAction = (s, f) =>
@@ -110,13 +110,8 @@ namespace OpenRA
if (!md.TryGetValue(yamlName, out yaml))
return false;
if (yaml.Nodes.Count == 0)
{
ret = GetValue(field.Name, field.FieldType, yaml.Value, field);
return true;
}
throw new InvalidOperationException("TryGetValueFromYaml: unable to load field {0} (of type {1})".F(yamlName, field.FieldType));
ret = GetValue(field.Name, field.FieldType, yaml, field);
return true;
}
public static T Load<T>(MiniYaml y) where T : new()
@@ -165,6 +160,12 @@ namespace OpenRA
public static object GetValue(string fieldName, Type fieldType, string value, MemberInfo field)
{
return GetValue(fieldName, fieldType, new MiniYaml(value), field);
}
public static object GetValue(string fieldName, Type fieldType, MiniYaml yaml, MemberInfo field)
{
var value = yaml.Value;
if (value != null) value = value.Trim();
if (fieldType == typeof(int))
@@ -417,7 +418,7 @@ namespace OpenRA
}
else if (fieldType == typeof(bool))
return ParseYesNo(value, fieldType, fieldName);
else if (fieldType.IsArray)
else if (fieldType.IsArray && fieldType.GetArrayRank() == 1)
{
if (value == null)
return Array.CreateInstance(fieldType.GetElementType(), 0);
@@ -429,6 +430,33 @@ namespace OpenRA
ret.SetValue(GetValue(fieldName, fieldType.GetElementType(), parts[i].Trim(), field), i);
return ret;
}
else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(HashSet<>))
{
var set = Activator.CreateInstance(fieldType);
if (value == null)
return set;
var parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var addMethod = fieldType.GetMethod("Add", fieldType.GetGenericArguments());
for (var i = 0; i < parts.Length; i++)
addMethod.Invoke(set, new[] { GetValue(fieldName, fieldType.GetGenericArguments()[0], parts[i].Trim(), field) });
return set;
}
else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
var dict = Activator.CreateInstance(fieldType);
var arguments = fieldType.GetGenericArguments();
var addMethod = fieldType.GetMethod("Add", arguments);
foreach (var node in yaml.Nodes)
{
var key = GetValue(fieldName, arguments[0], node.Key, field);
var val = GetValue(fieldName, arguments[1], node.Value, field);
addMethod.Invoke(dict, new[] { key, val });
}
return dict;
}
else if (fieldType == typeof(Size))
{
if (value != null)
@@ -576,7 +604,7 @@ namespace OpenRA
var loader = sa.GetLoader(type);
if (loader == null && sa.FromYamlKey)
loader = (yaml) => GetValue(yamlName, field.FieldType, yaml.Value, field);
loader = yaml => GetValue(yamlName, field.FieldType, yaml, field);
var fli = new FieldLoadInfo(field, sa, yamlName, loader);
ret.Add(fli);
@@ -620,6 +648,7 @@ namespace OpenRA
public string YamlName;
public string Loader;
public bool FromYamlKey;
public bool DictionaryFromYamlKey;
public bool Required;
public SerializeAttribute(bool serialize = true, bool required = false)
@@ -682,6 +711,17 @@ namespace OpenRA
}
}
// Special-cases FieldFromYamlKeyAttribute for use with Dictionary<K,V>.
[AttributeUsage(AttributeTargets.Field)]
public sealed class DictionaryFromYamlKeyAttribute : FieldLoader.SerializeAttribute
{
public DictionaryFromYamlKeyAttribute()
{
FromYamlKey = true;
DictionaryFromYamlKey = true;
}
}
// mirrors DescriptionAttribute from System.ComponentModel but we dont want to have to use that everywhere.
[AttributeUsage(AttributeTargets.All)]
public sealed class DescAttribute : Attribute

View File

@@ -28,7 +28,18 @@ namespace OpenRA
foreach (var info in FieldLoader.GetTypeLoadInfo(o.GetType(), includePrivateByDefault))
{
if (info.Attribute.FromYamlKey)
if (info.Attribute.DictionaryFromYamlKey)
{
var dict = (System.Collections.IDictionary)info.Field.GetValue(o);
foreach (var kvp in dict)
{
var key = ((System.Collections.DictionaryEntry)kvp).Key;
var value = ((System.Collections.DictionaryEntry)kvp).Value;
nodes.Add(new MiniYamlNode(FormatValue(key), FormatValue(value)));
}
}
else if (info.Attribute.FromYamlKey)
root = FormatValue(o, info.Field);
else
nodes.Add(new MiniYamlNode(info.YamlName, FormatValue(o, info.Field)));
@@ -55,11 +66,13 @@ namespace OpenRA
return new MiniYamlNode(field, FormatValue(o, o.GetType().GetField(field)));
}
public static string FormatValue(object v, Type t)
public static string FormatValue(object v)
{
if (v == null)
return "";
var t = v.GetType();
// Color.ToString() does the wrong thing; force it to format as an array
if (t == typeof(Color))
{
@@ -70,14 +83,6 @@ namespace OpenRA
((int)c.B).Clamp(0, 255));
}
// Don't save using country-specific decimal separators which can be misunderstood as group seperators.
if (t == typeof(float))
return ((float)v).ToString(CultureInfo.InvariantCulture);
if (t == typeof(decimal))
return ((decimal)v).ToString(CultureInfo.InvariantCulture);
if (t == typeof(double))
return ((double)v).ToString(CultureInfo.InvariantCulture);
if (t == typeof(ImageFormat))
{
return ((ImageFormat)v).ToString();
@@ -89,10 +94,33 @@ namespace OpenRA
return "{0},{1},{2},{3}".F(r.X, r.Y, r.Width, r.Height);
}
if (t.IsArray)
if (t.IsArray && t.GetArrayRank() == 1)
{
var elems = ((Array)v).OfType<object>();
return elems.JoinWith(", ");
return ((Array)v).Cast<object>().Select(FormatValue).JoinWith(", ");
}
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(HashSet<>))
{
return ((System.Collections.IEnumerable)v).Cast<object>().Select(FormatValue).JoinWith(", ");
}
// This is only for documentation generation
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
var result = "";
var dict = (System.Collections.IDictionary)v;
foreach (var kvp in dict)
{
var key = ((System.Collections.DictionaryEntry)kvp).Key;
var value = ((System.Collections.DictionaryEntry)kvp).Value;
var formattedKey = FormatValue(key);
var formattedValue = FormatValue(value);
result += "{0}: {1}{2}".F(formattedKey, formattedValue, Environment.NewLine);
}
return result;
}
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(OpenRA.Primitives.Cache<,>))
@@ -119,7 +147,7 @@ namespace OpenRA
public static string FormatValue(object o, FieldInfo f)
{
return FormatValue(f.GetValue(o), f.FieldType);
return FormatValue(f.GetValue(o));
}
}
}

View File

@@ -119,12 +119,6 @@ namespace OpenRA.FileFormats
pubkey.Len = BitLenBigNum(pubkey.KeyOne, 64) - 1;
}
uint LenPreData()
{
var a = (pubkey.Len - 1) / 8;
return (55 / a + 1) * (a + 1);
}
static int CompareBigNum(uint[] n1, uint[] n2, uint len)
{
while (len > 0)
@@ -462,46 +456,37 @@ namespace OpenRA.FileFormats
}
}
static unsafe void Memcopy(byte* dest, byte* src, int len)
{
while (len-- != 0) *dest++ = *src++;
}
unsafe void ProcessPredata(byte* pre, uint pre_len, byte* buf)
byte[] ProcessPredata(byte[] src)
{
var dest = new byte[256];
var n2 = new uint[64];
var n3 = new uint[64];
var a = (pubkey.Len - 1) / 8;
var a = (int)((pubkey.Len - 1) / 8);
var pre_len = (55 / a + 1) * (a + 1);
var srcOffset = 0;
var destOffset = 0;
while (a + 1 <= pre_len)
{
InitBigNum(n2, 0, 64);
fixed (uint* pn2 = &n2[0])
Memcopy((byte*)pn2, pre, (int)a + 1);
CalcKey(n3, n2, pubkey.KeyTwo, pubkey.KeyOne, 64);
fixed (uint* pn3 = &n3[0])
Memcopy(buf, (byte*)pn3, (int)a);
Buffer.BlockCopy(src, srcOffset, n2, 0, a + 1);
CalcKey(n3, n2, pubkey.KeyTwo, pubkey.KeyOne, 64);
Buffer.BlockCopy(n3, 0, dest, destOffset, a);
pre_len -= a + 1;
pre += a + 1;
buf += a;
srcOffset += a + 1;
destOffset += a;
}
return dest;
}
public byte[] DecryptKey(byte[] src)
{
InitPublicKey();
var dest = new byte[256];
unsafe
{
fixed (byte* pdest = &dest[0])
fixed (byte* psrc = &src[0])
ProcessPredata(psrc, LenPreData(), pdest);
}
return dest.Take(56).ToArray();
return ProcessPredata(src).Take(56).ToArray();
}
}
}

View File

@@ -9,7 +9,10 @@
#endregion
using System;
using System.IO;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA.FileFormats
{
@@ -19,7 +22,7 @@ namespace OpenRA.FileFormats
public readonly uint LimbCount;
public readonly float[] Transforms;
public HvaReader(Stream s)
public HvaReader(Stream s, string fileName)
{
// Index swaps for transposing a matrix
var ids = new byte[] { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14 };
@@ -31,6 +34,8 @@ namespace OpenRA.FileFormats
// Skip limb names
s.Seek(16 * LimbCount, SeekOrigin.Current);
Transforms = new float[16 * FrameCount * LimbCount];
var testMatrix = new float[16];
for (var j = 0; j < FrameCount; j++)
for (var i = 0; i < LimbCount; i++)
{
@@ -43,13 +48,19 @@ namespace OpenRA.FileFormats
for (var k = 0; k < 12; k++)
Transforms[c + ids[k]] = s.ReadFloat();
Array.Copy(Transforms, 16 * (LimbCount * j + i), testMatrix, 0, 16);
if (Util.MatrixInverse(testMatrix) == null)
throw new InvalidDataException(
"The transformation matrix for HVA file `{0}` section {1} frame {2} is invalid because it is not invertible!"
.F(fileName, i, j));
}
}
public static HvaReader Load(string filename)
{
using (var s = File.OpenRead(filename))
return new HvaReader(s);
return new HvaReader(s, Path.GetFileName(filename));
}
}
}

View File

@@ -102,6 +102,10 @@ namespace OpenRA.FileFormats
{
return new ReplayMetadata(fs, path);
}
catch (YamlException ex)
{
Log.Write("debug", ex.ToString());
}
catch (InvalidOperationException ex)
{
Log.Write("debug", ex.ToString());

View File

@@ -443,6 +443,7 @@ namespace OpenRA.FileSystem
public void ExtractFile(uint index, string fileName)
{
Directory.CreateDirectory(Path.GetDirectoryName(fileName));
using (var destfile = File.Open(fileName, FileMode.Create))
GetContentById(index, destfile);
}

View File

@@ -16,6 +16,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using OpenRA.Chat;
using OpenRA.FileSystem;
using OpenRA.Graphics;
using OpenRA.Network;
@@ -42,8 +43,11 @@ namespace OpenRA
public static MersenneTwister CosmeticRandom = new MersenneTwister(); // not synced
public static Renderer Renderer;
public static Sound Sound;
public static bool HasInputFocus = false;
public static GlobalChat GlobalChat;
public static OrderManager JoinServer(string host, int port, string password, bool recordReplay = true)
{
IConnection connection = new NetworkConnection(host, port);
@@ -147,7 +151,7 @@ namespace OpenRA
using (new PerfTimer("PrepareMap"))
map = ModData.PrepareMap(mapUID);
using (new PerfTimer("NewWorld"))
OrderManager.World = new World(map, OrderManager, type) { Timestep = Timestep };
OrderManager.World = new World(map, OrderManager, type);
worldRenderer = new WorldRenderer(OrderManager.World);
@@ -203,6 +207,7 @@ namespace OpenRA
Log.AddChannel("sound", "sound.log");
Log.AddChannel("graphics", "graphics.log");
Log.AddChannel("geoip", "geoip.log");
Log.AddChannel("irc", "irc.log");
if (Settings.Server.DiscoverNatDevices)
UPnP.TryNatDiscovery();
@@ -215,7 +220,7 @@ namespace OpenRA
GeoIP.Initialize();
GlobalFileSystem.Mount(Platform.GameDir); // Needed to access shaders
var renderers = new[] { Settings.Graphics.Renderer, "Sdl2", null };
var renderers = new[] { Settings.Graphics.Renderer, "Default", null };
foreach (var r in renderers)
{
if (r == null)
@@ -234,17 +239,9 @@ namespace OpenRA
}
}
try
{
Sound.Create(Settings.Sound.Engine);
}
catch (Exception e)
{
Log.Write("sound", "{0}", e);
Console.WriteLine("Creating the sound engine failed. Fallback in place. Check sound.log for details.");
Settings.Sound.Engine = "Null";
Sound.Create(Settings.Sound.Engine);
}
Sound = new Sound(Settings.Server.Dedicated ? "Null" : Settings.Sound.Engine);
GlobalChat = new GlobalChat();
Console.WriteLine("Available mods:");
foreach (var mod in ModMetadata.AllMods)
@@ -290,13 +287,30 @@ namespace OpenRA
Sound.Initialize();
ModData = new ModData(mod, !Settings.Server.Dedicated);
ModData.InitializeLoaders();
if (!Settings.Server.Dedicated)
Renderer.InitializeFonts(ModData.Manifest);
using (new PerfTimer("LoadMaps"))
ModData.MapCache.LoadMaps();
if (Settings.Server.Dedicated)
{
RunDedicatedServer();
Environment.Exit(0);
}
var installData = ModData.Manifest.Get<ContentInstaller>();
var isModContentInstalled = installData.TestFiles.All(f => File.Exists(Platform.ResolvePath(f)));
// Mod assets are missing!
if (!isModContentInstalled)
{
InitializeMod("modchooser", new Arguments());
return;
}
ModData.MountFiles();
ModData.InitializeLoaders();
Renderer.InitializeFonts(ModData.Manifest);
if (Cursor != null)
Cursor.Dispose();
@@ -315,7 +329,6 @@ namespace OpenRA
Console.WriteLine("Error was: " + e.Message);
Cursor = new SoftwareCursor(ModData.CursorProvider);
Settings.Graphics.HardwareCursors = false;
}
}
else
@@ -328,39 +341,38 @@ namespace OpenRA
JoinLocal();
if (Settings.Server.Dedicated)
ModData.LoadScreen.StartGame(args);
}
public static void RunDedicatedServer()
{
while (true)
{
Settings.Server.Map = WidgetUtils.ChooseInitialMap(Settings.Server.Map);
Settings.Save();
CreateServer(new ServerSettings(Settings.Server));
while (true)
{
Settings.Server.Map = WidgetUtils.ChooseInitialMap(Settings.Server.Map);
Settings.Save();
CreateServer(new ServerSettings(Settings.Server));
while (true)
Thread.Sleep(100);
if (server.State == Server.ServerState.GameStarted && server.Conns.Count < 1)
{
Thread.Sleep(100);
if (server.State == Server.ServerState.GameStarted && server.Conns.Count < 1)
{
Console.WriteLine("No one is playing, shutting down...");
server.Shutdown();
break;
}
Console.WriteLine("No one is playing, shutting down...");
server.Shutdown();
break;
}
if (Settings.Server.DedicatedLoop)
{
Console.WriteLine("Starting a new server instance...");
ModData.MapCache.LoadMaps();
continue;
}
break;
}
Environment.Exit(0);
if (Settings.Server.DedicatedLoop)
{
Console.WriteLine("Starting a new server instance...");
ModData.MapCache.LoadMaps();
continue;
}
break;
}
else
ModData.LoadScreen.StartGame(args);
}
public static void LoadEditor(string mapUid)
@@ -393,9 +405,9 @@ namespace OpenRA
// Note: These delayed actions should only be used by widgets or disposing objects
// - things that depend on a particular world should be queuing them on the worldactor.
static ActionQueue delayedActions = new ActionQueue();
public static void RunAfterTick(Action a) { delayedActions.Add(a); }
public static void RunAfterDelay(int delay, Action a) { delayedActions.Add(a, delay); }
static volatile ActionQueue delayedActions = new ActionQueue();
public static void RunAfterTick(Action a) { delayedActions.Add(a, Game.RunTime); }
public static void RunAfterDelay(int delayMilliseconds, Action a) { delayedActions.Add(a, Game.RunTime + delayMilliseconds); }
static void TakeScreenshotInner()
{
@@ -403,7 +415,7 @@ namespace OpenRA
Bitmap bitmap;
using (new PerfTimer("Renderer.TakeScreenshot"))
bitmap = Renderer.TakeScreenshot();
bitmap = Renderer.Device.TakeScreenshot();
ThreadPool.QueueUserWorkItem(_ =>
{
@@ -496,7 +508,7 @@ namespace OpenRA
static void LogicTick()
{
delayedActions.PerformActions();
delayedActions.PerformActions(Game.RunTime);
if (OrderManager.Connection.ConnectionState != lastConnectionState)
{
@@ -681,6 +693,9 @@ namespace OpenRA
worldRenderer.Dispose();
ModData.Dispose();
ChromeProvider.Deinitialize();
GlobalChat.Dispose();
Sound.Dispose();
Renderer.Dispose();
OnQuit();
@@ -751,7 +766,7 @@ namespace OpenRA
public static bool IsCurrentWorld(World world)
{
return OrderManager != null && OrderManager.World == world;
return OrderManager != null && OrderManager.World == world && !world.Disposing;
}
}
}

View File

@@ -24,20 +24,20 @@ namespace OpenRA
public string MapUid;
public string MapTitle;
/// <summary>Game start timestamp (when the recoding started).</summary>
public DateTime StartTimeUtc;
// Game end timestamp (when the recoding stopped).
/// <summary>Game end timestamp (when the recoding stopped).</summary>
public DateTime EndTimeUtc;
// Gets the game's duration, from the time the game started until the
// replay recording stopped.
/// <summary>Gets the game's duration, from the time the game started until the replay recording stopped.</summary>
public TimeSpan Duration { get { return EndTimeUtc > StartTimeUtc ? EndTimeUtc - StartTimeUtc : TimeSpan.Zero; } }
public IList<Player> Players { get; private set; }
public MapPreview MapPreview { get { return Game.ModData.MapCache[MapUid]; } }
public IEnumerable<Player> HumanPlayers { get { return Players.Where(p => p.IsHuman); } }
public bool IsSinglePlayer { get { return HumanPlayers.Count() == 1; } }
Dictionary<OpenRA.Player, Player> playersByRuntime;
readonly Dictionary<OpenRA.Player, Player> playersByRuntime;
public GameInformation()
{
@@ -70,7 +70,7 @@ namespace OpenRA
return info;
}
catch (InvalidOperationException)
catch (YamlException)
{
Log.Write("debug", "GameInformation deserialized invalid MiniYaml:\n{0}".F(data));
throw;
@@ -79,9 +79,10 @@ namespace OpenRA
public string Serialize()
{
var nodes = new List<MiniYamlNode>();
nodes.Add(new MiniYamlNode("Root", FieldSaver.Save(this)));
var nodes = new List<MiniYamlNode>
{
new MiniYamlNode("Root", FieldSaver.Save(this))
};
for (var i = 0; i < Players.Count; i++)
nodes.Add(new MiniYamlNode("Player@{0}".F(i), FieldSaver.Save(Players[i])));
@@ -89,7 +90,7 @@ namespace OpenRA
return nodes.WriteToString();
}
// Adds the player information at start-up.
/// <summary>Adds the player information at start-up.</summary>
public void AddPlayer(OpenRA.Player runtimePlayer, Session lobbyInfo)
{
if (runtimePlayer == null)
@@ -118,7 +119,7 @@ namespace OpenRA
Color = runtimePlayer.Color,
Team = client.Team,
SpawnPoint = runtimePlayer.SpawnPoint,
IsRandomFaction = runtimePlayer.Faction.InternalName != client.Race,
IsRandomFaction = runtimePlayer.Faction.InternalName != client.Faction,
IsRandomSpawnPoint = runtimePlayer.SpawnPoint != client.SpawnPoint
};
@@ -126,7 +127,7 @@ namespace OpenRA
Players.Add(player);
}
// Gets the player information for the specified runtime player instance.
/// <summary>Gets the player information for the specified runtime player instance.</summary>
public Player GetPlayer(OpenRA.Player runtimePlayer)
{
Player player;
@@ -138,38 +139,43 @@ namespace OpenRA
public class Player
{
// Start-up information
#region Start-up information
public int ClientIndex;
// The player name, not guaranteed to be unique.
/// <summary>The player name, not guaranteed to be unique.</summary>
public string Name;
public bool IsHuman;
public bool IsBot;
// The faction name (aka Country)
/// <summary>The faction's display name.</summary>
public string FactionName;
// The faction id (aka Country, aka Race)
/// <summary>The faction ID, a.k.a. the faction's internal name.</summary>
public string FactionId;
public HSLColor Color;
// The team id on start-up, or 0 if the player is not part of the team.
/// <summary>The team ID on start-up, or 0 if the player is not part of a team.</summary>
public int Team;
public int SpawnPoint;
// True if the faction was chosen at random; otherwise, false
/// <summary>True if the faction was chosen at random; otherwise, false.</summary>
public bool IsRandomFaction;
// True if the spawn point was chosen at random; otherwise, false.</summary>
/// <summary>True if the spawn point was chosen at random; otherwise, false.</summary>
public bool IsRandomSpawnPoint;
// Information gathered at a later stage
#endregion
// The game outcome for this player
#region
/// <summary>The game outcome for this player.</summary>
public WinState Outcome;
// The time when this player won or lost the game
/// <summary>The time when this player won or lost the game.</summary>
public DateTime OutcomeTimestampUtc;
#endregion
}
}
}

View File

@@ -28,7 +28,7 @@ namespace OpenRA
/// You can remove inherited traits by adding a - infront of them as in -TraitName: to inherit everything, but this trait.
/// </summary>
public readonly string Name;
public readonly TypeDictionary Traits = new TypeDictionary();
readonly TypeDictionary traits = new TypeDictionary();
List<ITraitInfo> constructOrderCache = null;
public ActorInfo(string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits)
@@ -52,7 +52,7 @@ namespace OpenRA
if (t.Key != "Inherits" && !t.Key.StartsWith("Inherits@"))
try
{
Traits.Add(LoadTraitInfo(t.Key.Split('@')[0], t.Value));
traits.Add(LoadTraitInfo(t.Key.Split('@')[0], t.Value));
}
catch (FieldLoader.MissingFieldsException e)
{
@@ -67,6 +67,13 @@ namespace OpenRA
}
}
public ActorInfo(string name, params ITraitInfo[] traitInfos)
{
Name = name;
foreach (var t in traitInfos)
traits.Add(t);
}
static Dictionary<string, MiniYaml> GetParents(MiniYaml node, Dictionary<string, MiniYaml> allUnits)
{
return node.Nodes.Where(n => n.Key == "Inherits" || n.Key.StartsWith("Inherits@"))
@@ -121,7 +128,7 @@ namespace OpenRA
if (constructOrderCache != null)
return constructOrderCache;
var source = Traits.WithInterface<ITraitInfo>().Select(i => new
var source = traits.WithInterface<ITraitInfo>().Select(i => new
{
Trait = i,
Type = i.GetType(),
@@ -172,7 +179,7 @@ namespace OpenRA
public IEnumerable<Pair<string, Type>> GetInitKeys()
{
var inits = Traits.WithInterface<ITraitInfo>().SelectMany(
var inits = traits.WithInterface<ITraitInfo>().SelectMany(
t => t.GetType().GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(UsesInit<>))
.Select(i => i.GetGenericArguments()[0])).ToList();
@@ -183,5 +190,10 @@ namespace OpenRA
i => Pair.New(
i.Name.Replace("Init", ""), i));
}
public bool HasTraitInfo<T>() where T : ITraitInfo { return traits.Contains<T>(); }
public T TraitInfo<T>() where T : ITraitInfo { return traits.Get<T>(); }
public T TraitInfoOrDefault<T>() where T : ITraitInfo { return traits.GetOrDefault<T>(); }
public IEnumerable<T> TraitInfos<T>() where T : ITraitInfo { return traits.WithInterface<T>(); }
}
}

View File

@@ -32,21 +32,9 @@ namespace OpenRA.GameRules
var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud";
Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext;
if (!GlobalFileSystem.Exists(Filename))
return;
Exists = true;
using (var s = GlobalFileSystem.Open(Filename))
{
if (Filename.ToLowerInvariant().EndsWith("wav"))
Length = (int)WavLoader.WaveLength(s);
else
Length = (int)AudLoader.SoundLength(s);
}
}
public void Reload()
public void Load()
{
if (!GlobalFileSystem.Exists(Filename))
return;

View File

@@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA
{
@@ -41,6 +42,40 @@ namespace OpenRA
Music = new ReadOnlyDictionary<string, MusicInfo>(music);
TileSets = new ReadOnlyDictionary<string, TileSet>(tileSets);
Sequences = new ReadOnlyDictionary<string, SequenceProvider>(sequences);
foreach (var a in Actors.Values)
{
foreach (var t in a.TraitInfos<IRulesetLoaded>())
{
try
{
t.RulesetLoaded(this, a);
}
catch (YamlException e)
{
throw new YamlException("Actor type {0}: {1}".F(a.Name, e.Message));
}
}
}
foreach (var weapon in Weapons)
{
foreach (var warhead in weapon.Value.Warheads)
{
var cacher = warhead as IRulesetLoaded<WeaponInfo>;
if (cacher != null)
{
try
{
cacher.RulesetLoaded(this, weapon.Value);
}
catch (YamlException e)
{
throw new YamlException("Weapon type {0}: {1}".F(weapon.Key, e.Message));
}
}
}
}
}
public IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }

View File

@@ -80,7 +80,7 @@ namespace OpenRA
using (new PerfTimer("Music"))
music = LoadYamlRules(musicCache, m.Music,
NoMapRules,
map != null ? map.MusicDefinitions : NoMapRules,
(k, _) => new MusicInfo(k.Key, k.Value));
using (new PerfTimer("TileSets"))

View File

@@ -16,22 +16,14 @@ namespace OpenRA.GameRules
{
public class SoundInfo
{
[FieldLoader.Ignore] public readonly Dictionary<string, string[]> Variants;
[FieldLoader.Ignore] public readonly Dictionary<string, string[]> Prefixes;
[FieldLoader.Ignore] public readonly Dictionary<string, string[]> Voices;
[FieldLoader.Ignore] public readonly Dictionary<string, string[]> Notifications;
public readonly Dictionary<string, string[]> Variants = new Dictionary<string, string[]>();
public readonly Dictionary<string, string[]> Prefixes = new Dictionary<string, string[]>();
public readonly Dictionary<string, string[]> Voices = new Dictionary<string, string[]>();
public readonly Dictionary<string, string[]> Notifications = new Dictionary<string, string[]>();
public readonly string DefaultVariant = ".aud";
public readonly string DefaultPrefix = "";
public readonly string[] DisableVariants = { };
public readonly string[] DisablePrefixes = { };
static Dictionary<string, string[]> Load(MiniYaml y, string name)
{
var nd = y.ToDictionary();
return nd.ContainsKey(name)
? nd[name].ToDictionary(my => FieldLoader.GetValue<string[]>("(value)", my.Value))
: new Dictionary<string, string[]>();
}
public readonly HashSet<string> DisableVariants = new HashSet<string>();
public readonly HashSet<string> DisablePrefixes = new HashSet<string>();
public readonly Lazy<Dictionary<string, SoundPool>> VoicePools;
public readonly Lazy<Dictionary<string, SoundPool>> NotificationsPools;
@@ -39,10 +31,6 @@ namespace OpenRA.GameRules
public SoundInfo(MiniYaml y)
{
FieldLoader.Load(this, y);
Variants = Load(y, "Variants");
Prefixes = Load(y, "Prefixes");
Voices = Load(y, "Voices");
Notifications = Load(y, "Notifications");
VoicePools = Exts.Lazy(() => Voices.ToDictionary(a => a.Key, a => new SoundPool(a.Value)));
NotificationsPools = Exts.Lazy(() => Notifications.ToDictionary(a => a.Key, a => new SoundPool(a.Value)));

View File

@@ -21,6 +21,7 @@ namespace OpenRA.GameRules
public WeaponInfo Weapon;
public int[] DamageModifiers;
public int[] InaccuracyModifiers;
public int[] RangeModifiers;
public int Facing;
public WPos Source;
public Actor SourceActor;
@@ -47,10 +48,10 @@ namespace OpenRA.GameRules
public readonly bool Charges = false;
[Desc("What types of targets are affected.")]
public readonly string[] ValidTargets = { "Ground", "Water" };
public readonly HashSet<string> ValidTargets = new HashSet<string> { "Ground", "Water" };
[Desc("What types of targets are unaffected.", "Overrules ValidTargets.")]
public readonly string[] InvalidTargets = { };
public readonly HashSet<string> InvalidTargets = new HashSet<string>();
[Desc("Delay in ticks between firing shots from the same ammo magazine.")]
public readonly int BurstDelay = 5;
@@ -64,14 +65,9 @@ namespace OpenRA.GameRules
[FieldLoader.LoadUsing("LoadWarheads")]
public readonly List<IWarhead> Warheads = new List<IWarhead>();
readonly HashSet<string> validTargetSet;
readonly HashSet<string> invalidTargetSet;
public WeaponInfo(string name, MiniYaml content)
{
FieldLoader.Load(this, content);
validTargetSet = new HashSet<string>(ValidTargets);
invalidTargetSet = new HashSet<string>(InvalidTargets);
}
static object LoadProjectile(MiniYaml yaml)
@@ -99,7 +95,7 @@ namespace OpenRA.GameRules
public bool IsValidTarget(IEnumerable<string> targetTypes)
{
return validTargetSet.Overlaps(targetTypes) && !invalidTargetSet.Overlaps(targetTypes);
return ValidTargets.Overlaps(targetTypes) && !InvalidTargets.Overlaps(targetTypes);
}
/// <summary>Checks if the weapon is valid against (can target) the target.</summary>
@@ -130,8 +126,8 @@ namespace OpenRA.GameRules
/// <summary>Checks if the weapon is valid against (can target) the actor.</summary>
public bool IsValidAgainst(Actor victim, Actor firedBy)
{
var targetable = victim.TraitOrDefault<ITargetable>();
if (targetable == null || !IsValidTarget(targetable.TargetTypes))
var targetable = victim.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled);
if (!IsValidTarget(targetable.SelectMany(t => t.TargetTypes)))
return false;
if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy)))
@@ -143,8 +139,7 @@ namespace OpenRA.GameRules
/// <summary>Checks if the weapon is valid against (can target) the frozen actor.</summary>
public bool IsValidAgainst(FrozenActor victim, Actor firedBy)
{
var targetable = victim.Info.Traits.GetOrDefault<ITargetableInfo>();
if (targetable == null || !IsValidTarget(targetable.GetTargetTypes()))
if (!IsValidTarget(victim.TargetTypes))
return false;
if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy)))

40
OpenRA.Game/GameSpeed.cs Normal file
View File

@@ -0,0 +1,40 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA
{
public class GameSpeed
{
[Translate]
public readonly string Name = "Default";
public readonly int Timestep = 40;
public readonly int OrderLatency = 3;
}
public class GameSpeeds : IGlobalModData
{
[FieldLoader.LoadUsing("LoadSpeeds")]
public readonly Dictionary<string, GameSpeed> Speeds;
static object LoadSpeeds(MiniYaml y)
{
var ret = new Dictionary<string, GameSpeed>();
foreach (var node in y.Nodes)
ret.Add(node.Key, FieldLoader.Load<GameSpeed>(node.Value));
return ret;
}
}
}

382
OpenRA.Game/GlobalChat.cs Normal file
View File

@@ -0,0 +1,382 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Meebey.SmartIrc4net;
using OpenRA;
using OpenRA.Primitives;
namespace OpenRA.Chat
{
public enum ChatConnectionStatus { Disconnected, Connecting, Connected, Disconnecting, Joined, Error }
public enum ChatMessageType { Message, Notification }
public sealed class ChatUser
{
public readonly string Name;
public bool IsOp;
public bool IsVoiced;
public ChatUser(string name, bool isOp, bool isVoice)
{
Name = name;
IsOp = isOp;
IsVoiced = isVoice;
}
}
public sealed class ChatMessage
{
static long nextUID;
public readonly DateTime Time;
public readonly ChatMessageType Type;
public readonly string Nick;
public readonly string Message;
public readonly string UID;
public ChatMessage(DateTime time, ChatMessageType type, string nick, string message)
{
Time = time;
Type = type;
Nick = nick;
Message = message;
UID = Interlocked.Increment(ref nextUID).ToString();
}
public override string ToString()
{
var time = Time.ToString(Game.Settings.Chat.TimestampFormat);
if (Type == ChatMessageType.Notification)
return "{0} {1}".F(time, Message);
return "{0} {1}: {2}".F(time, Nick, Message);
}
}
public class GlobalChat : IDisposable
{
readonly IrcClient client = new IrcClient();
volatile Channel channel;
public readonly ObservableSortedDictionary<string, ChatUser> Users = new ObservableSortedDictionary<string, ChatUser>(StringComparer.InvariantCultureIgnoreCase);
public readonly ObservableList<ChatMessage> History = new ObservableList<ChatMessage>();
volatile string topic;
public string Topic { get { return topic; } }
volatile ChatConnectionStatus connectionStatus = ChatConnectionStatus.Disconnected;
public ChatConnectionStatus ConnectionStatus { get { return connectionStatus; } }
public GlobalChat()
{
client.Encoding = System.Text.Encoding.UTF8;
client.SendDelay = 100;
client.ActiveChannelSyncing = true;
client.OnConnecting += OnConnecting;
client.OnConnected += OnConnected;
client.OnDisconnecting += OnDisconnecting;
client.OnDisconnected += OnDisconnected;
client.OnError += OnError;
client.OnKick += OnKick;
client.OnRawMessage += (_, e) => Game.RunAfterTick(() => Log.Write("irc", e.Data.RawMessage));
client.OnJoin += OnJoin;
client.OnChannelActiveSynced += OnChannelActiveSynced;
client.OnTopic += (_, e) => topic = e.Topic;
client.OnTopicChange += (_, e) => topic = e.NewTopic;
client.OnNickChange += OnNickChange;
client.OnChannelMessage += (_, e) => AddMessage(e.Data.Nick, e.Data.Message);
client.OnOp += (_, e) => SetUserOp(e.Whom, true);
client.OnDeop += (_, e) => SetUserOp(e.Whom, false);
client.OnVoice += (_, e) => SetUserVoiced(e.Whom, true);
client.OnDevoice += (_, e) => SetUserVoiced(e.Whom, false);
client.OnPart += OnPart;
client.OnQuit += OnQuit;
}
void SetUserOp(string whom, bool isOp)
{
Game.RunAfterTick(() =>
{
ChatUser user;
if (Users.TryGetValue(whom, out user))
user.IsOp = isOp;
});
}
void SetUserVoiced(string whom, bool isVoiced)
{
Game.RunAfterTick(() =>
{
ChatUser user;
if (Users.TryGetValue(whom, out user))
user.IsVoiced = isVoiced;
});
}
public void Connect()
{
if (client.IsConnected)
return;
new Thread(() =>
{
try
{
client.Connect(Game.Settings.Chat.Hostname, Game.Settings.Chat.Port);
}
catch (Exception e)
{
connectionStatus = ChatConnectionStatus.Error;
AddNotification(e.Message);
Game.RunAfterTick(() => Log.Write("irc", e.ToString()));
return;
}
client.Listen();
}) { Name = "IrcListenThread", IsBackground = true }.Start();
}
void AddNotification(string text)
{
var message = new ChatMessage(DateTime.Now, ChatMessageType.Notification, null, text);
Game.RunAfterTick(() =>
{
History.Add(message);
Log.Write("irc", text);
});
}
void AddMessage(string nick, string text)
{
var message = new ChatMessage(DateTime.Now, ChatMessageType.Message, nick, text);
Game.RunAfterTick(() =>
{
History.Add(message);
Log.Write("irc", text);
});
}
void OnConnecting(object sender, EventArgs e)
{
AddNotification("Connecting to {0}:{1}...".F(Game.Settings.Chat.Hostname, Game.Settings.Chat.Port));
connectionStatus = ChatConnectionStatus.Connecting;
}
void OnConnected(object sender, EventArgs e)
{
AddNotification("Connected.");
connectionStatus = ChatConnectionStatus.Connected;
// Guard against settings.yaml modification
var nick = SanitizedName(Game.Settings.Chat.Nickname);
if (nick != Game.Settings.Chat.Nickname)
Game.RunAfterTick(() => Game.Settings.Chat.Nickname = nick);
client.Login(nick, "in-game IRC client", 0, "OpenRA");
client.RfcJoin("#" + Game.Settings.Chat.Channel);
}
void OnDisconnecting(object sender, EventArgs e)
{
if (connectionStatus != ChatConnectionStatus.Error)
connectionStatus = ChatConnectionStatus.Disconnecting;
}
void OnDisconnected(object sender, EventArgs e)
{
Game.RunAfterTick(Users.Clear);
// Keep the chat window open if there is an error
// It will be cleared by the Disconnect button
if (connectionStatus != ChatConnectionStatus.Error)
{
Game.RunAfterTick(History.Clear);
topic = null;
connectionStatus = ChatConnectionStatus.Disconnected;
}
}
void OnError(object sender, ErrorEventArgs e)
{
// Ignore any errors that happen during disconnect
if (connectionStatus != ChatConnectionStatus.Disconnecting)
{
connectionStatus = ChatConnectionStatus.Error;
AddNotification("Error: " + e.ErrorMessage);
}
}
void OnKick(object sender, KickEventArgs e)
{
Disconnect();
connectionStatus = ChatConnectionStatus.Error;
AddNotification("Error: You were kicked from the chat by {0}".F(e.Who));
}
void OnJoin(object sender, JoinEventArgs e)
{
if (e.Who == client.Nickname || e.Channel != channel.Name)
return;
AddNotification("{0} joined the chat.".F(e.Who));
Game.RunAfterTick(() => Users.Add(e.Who, new ChatUser(e.Who, false, false)));
}
void OnChannelActiveSynced(object sender, IrcEventArgs e)
{
channel = client.GetChannel(e.Data.Channel);
AddNotification("{0} users online".F(channel.Users.Count));
connectionStatus = ChatConnectionStatus.Joined;
foreach (DictionaryEntry user in channel.Users)
{
var u = (ChannelUser)user.Value;
Game.RunAfterTick(() => Users.Add(u.Nick, new ChatUser(u.Nick, u.IsOp, u.IsVoice)));
}
}
void OnNickChange(object sender, NickChangeEventArgs e)
{
AddNotification("{0} is now known as {1}.".F(e.OldNickname, e.NewNickname));
Game.RunAfterTick(() =>
{
ChatUser user;
if (!Users.TryGetValue(e.OldNickname, out user))
return;
Users.Remove(e.OldNickname);
Users.Add(e.NewNickname, new ChatUser(e.NewNickname, user.IsOp, user.IsVoiced));
});
}
void OnQuit(object sender, QuitEventArgs e)
{
AddNotification("{0} left the chat.".F(e.Who));
Game.RunAfterTick(() => Users.Remove(e.Who));
}
void OnPart(object sender, PartEventArgs e)
{
if (e.Data.Channel != channel.Name)
return;
AddNotification("{0} left the chat.".F(e.Who));
Game.RunAfterTick(() => Users.Remove(e.Who));
}
public string SanitizedName(string dirty)
{
if (string.IsNullOrEmpty(dirty))
return null;
// There is no need to mangle the nick if it is already valid
if (Rfc2812.IsValidNickname(dirty))
return dirty;
// TODO: some special chars are allowed as well, but not at every position
var clean = new string(dirty.Where(c => char.IsLetterOrDigit(c)).ToArray());
if (string.IsNullOrEmpty(clean))
return null;
if (char.IsDigit(clean[0]))
return SanitizedName(clean.Substring(1));
// Source: https://tools.ietf.org/html/rfc2812#section-1.2.1
if (clean.Length > 9)
clean = clean.Substring(0, 9);
return clean;
}
public bool IsValidNickname(string name)
{
return Rfc2812.IsValidNickname(name);
}
public void SendMessage(string text)
{
if (connectionStatus != ChatConnectionStatus.Joined)
return;
// Guard against a last-moment disconnection
try
{
client.SendMessage(SendType.Message, channel.Name, text);
AddMessage(client.Nickname, text);
}
catch (NotConnectedException) { }
}
public bool TrySetNickname(string nick)
{
// TODO: This is inconsistent with the other check
if (Rfc2812.IsValidNickname(nick))
{
client.RfcNick(nick);
Game.Settings.Chat.Nickname = nick;
return true;
}
return false;
}
public void Disconnect()
{
// Error is an alias for disconnect, but keeps the panel open
// so that clients can see the error
if (connectionStatus == ChatConnectionStatus.Error)
{
Game.RunAfterTick(History.Clear);
topic = null;
connectionStatus = ChatConnectionStatus.Disconnected;
}
else
connectionStatus = ChatConnectionStatus.Disconnecting;
if (!client.IsConnected)
return;
client.RfcQuit(Game.Settings.Chat.QuitMessage);
AddNotification("Disconnecting from {0}...".F(client.Address));
Game.RunAfterTick(() => Game.Settings.Chat.ConnectAutomatically = false);
}
public void Dispose()
{
// HACK: The IRC library we are using has terrible thread-handling code that relies on Thread.Abort.
// There is a thread reading from the network socket which is aborted, however on Windows this is inside
// native code so this abort call hangs until the network socket reads something and returns to managed
// code where it can then be aborted.
//
// This means we may hang for several seconds during shutdown (until we receive something over IRC!) before
// closing.
//
// Since our IRC client currently lives forever, the only time we call this Dispose method is during the
// shutdown of our process. Therefore, we can work around the problem by just not bothering to disconnect
// properly. Since our process is about to die anyway, it's not like anyone will care.
////if (client.IsConnected)
//// client.Disconnect();
}
}
}

View File

@@ -106,7 +106,7 @@ namespace OpenRA.Graphics
sheet = cachedSheets[mi.Src];
else
{
sheet = new Sheet(mi.Src);
sheet = new Sheet(SheetType.BGRA, mi.Src);
cachedSheets.Add(mi.Src, sheet);
}

View File

@@ -15,11 +15,11 @@ using OpenRA.Graphics;
namespace OpenRA
{
[AttributeUsage(AttributeTargets.Assembly)]
public sealed class RendererAttribute : Attribute
public sealed class PlatformAttribute : Attribute
{
public readonly Type Type;
public RendererAttribute(Type graphicsDeviceType)
public PlatformAttribute(Type graphicsDeviceType)
{
if (!typeof(IDeviceFactory).IsAssignableFrom(graphicsDeviceType))
throw new InvalidOperationException("Incorrect type in RendererAttribute");
@@ -29,7 +29,8 @@ namespace OpenRA
public interface IDeviceFactory
{
IGraphicsDevice Create(Size size, WindowMode windowMode);
IGraphicsDevice CreateGraphics(Size size, WindowMode windowMode);
ISoundEngine CreateSound();
}
public interface IHardwareCursor : IDisposable { }
@@ -88,6 +89,7 @@ namespace OpenRA
public interface IShader
{
void SetBool(string name, bool value);
void SetVec(string name, float x);
void SetVec(string name, float x, float y);
void SetVec(string name, float[] vec, int length);

View File

@@ -20,17 +20,17 @@ namespace OpenRA.Graphics
{
public static Bitmap TerrainBitmap(TileSet tileset, Map map, bool actualSize = false)
{
var isDiamond = map.TileShape == TileShape.Diamond;
var isRectangularIsometric = map.Grid.Type == MapGridType.RectangularIsometric;
var b = map.Bounds;
// Fudge the heightmap offset by adding as much extra as we need / can.
// This tries to correct for our incorrect assumption that MPos == PPos
var heightOffset = Math.Min(map.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
var heightOffset = Math.Min(map.Grid.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
var width = b.Width;
var height = b.Height + heightOffset;
var bitmapWidth = width;
if (isDiamond)
if (isRectangularIsometric)
bitmapWidth = 2 * bitmapWidth - 1;
if (!actualSize)
@@ -55,7 +55,7 @@ namespace OpenRA.Graphics
var type = tileset.GetTileInfo(mapTiles[uv]);
var leftColor = type != null ? type.LeftColor : Color.Black;
if (isDiamond)
if (isRectangularIsometric)
{
// Odd rows are shifted right by 1px
var dx = uv.V & 1;
@@ -81,16 +81,16 @@ namespace OpenRA.Graphics
static Bitmap AddStaticResources(TileSet tileset, Map map, Ruleset resourceRules, Bitmap terrainBitmap)
{
var terrain = new Bitmap(terrainBitmap);
var isDiamond = map.TileShape == TileShape.Diamond;
var isRectangularIsometric = map.Grid.Type == MapGridType.RectangularIsometric;
var b = map.Bounds;
// Fudge the heightmap offset by adding as much extra as we need / can
// This tries to correct for our incorrect assumption that MPos == PPos
var heightOffset = Math.Min(map.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
var heightOffset = Math.Min(map.Grid.MaximumTerrainHeight, map.MapSize.Y - b.Bottom);
var width = b.Width;
var height = b.Height + heightOffset;
var resources = resourceRules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
var resources = resourceRules.Actors["world"].TraitInfos<ResourceTypeInfo>()
.ToDictionary(r => r.ResourceType, r => r.TerrainType);
var bitmapData = terrain.LockBits(terrain.Bounds(),
@@ -113,7 +113,7 @@ namespace OpenRA.Graphics
continue;
var color = tileset[tileset.GetTerrainIndex(res)].Color.ToArgb();
if (isDiamond)
if (isRectangularIsometric)
{
// Odd rows are shifted right by 1px
var dx = uv.V & 1;

View File

@@ -33,16 +33,17 @@ namespace OpenRA.Graphics
var c2 = new HSLColor(c.H, c.S, (byte)Math.Max(0, c.L - rampRange)).RGB;
var baseIndex = ramp[0];
var remapRamp = ramp.Select(r => r - ramp[0]);
var rampMaxIndex = ramp.Length - 1;
// reversed remapping
if (ramp[0] > ramp[15])
if (ramp[0] > ramp[rampMaxIndex])
{
baseIndex = ramp[15];
for (var i = 15; i > 0; i--)
remapRamp = ramp.Select(r => r - ramp[15]);
baseIndex = ramp[rampMaxIndex];
for (var i = rampMaxIndex; i > 0; i--)
remapRamp = ramp.Select(r => r - ramp[rampMaxIndex]);
}
remapColors = remapRamp.Select((x, i) => Pair.New(baseIndex + i, Exts.ColorLerp(x / 16f, c1, c2)))
remapColors = remapRamp.Select((x, i) => Pair.New(baseIndex + i, Exts.ColorLerp(x / (float)ramp.Length, c1, c2)))
.ToDictionary(u => u.First, u => u.Second);
}

View File

@@ -74,7 +74,7 @@ namespace OpenRA.Graphics
wlr.DrawLine(start + r, z + r, barColor2);
}
Color GetHealthColor(Health health)
Color GetHealthColor(IHealth health)
{
var player = actor.World.RenderPlayer ?? actor.World.LocalPlayer;
@@ -104,7 +104,7 @@ namespace OpenRA.Graphics
health.DamageState == DamageState.Heavy ? Color.Yellow : Color.LimeGreen;
}
void DrawHealthBar(WorldRenderer wr, Health health, float2 start, float2 end)
void DrawHealthBar(WorldRenderer wr, IHealth health, float2 start, float2 end)
{
if (health == null || health.IsDead)
return;
@@ -133,7 +133,7 @@ namespace OpenRA.Graphics
wlr.DrawLine(start + q, z + q, healthColor);
wlr.DrawLine(start + r, z + r, healthColor2);
if (health.DisplayHp != health.HP)
if (health.DisplayHP != health.HP)
{
var deltaColor = Color.OrangeRed;
var deltaColor2 = Color.FromArgb(
@@ -141,7 +141,7 @@ namespace OpenRA.Graphics
deltaColor.R / 2,
deltaColor.G / 2,
deltaColor.B / 2);
var zz = float2.Lerp(start, end, (float)health.DisplayHp / health.MaxHP);
var zz = float2.Lerp(start, end, (float)health.DisplayHP / health.MaxHP);
wlr.DrawLine(z + p, zz + p, deltaColor2);
wlr.DrawLine(z + q, zz + q, deltaColor);
@@ -155,7 +155,7 @@ namespace OpenRA.Graphics
if (!actor.IsInWorld || actor.IsDead)
return;
var health = actor.TraitOrDefault<Health>();
var health = actor.TraitOrDefault<IHealth>();
var screenPos = wr.ScreenPxPosition(pos);
var bounds = actor.VisualBounds;

View File

@@ -24,6 +24,8 @@ namespace OpenRA.Graphics
byte[] data;
public readonly Size Size;
public readonly SheetType Type;
public byte[] GetData()
{
CreateBuffer();
@@ -32,18 +34,20 @@ namespace OpenRA.Graphics
public bool Buffered { get { return data != null || texture == null; } }
public Sheet(Size size)
public Sheet(SheetType type, Size size)
{
Type = type;
Size = size;
}
public Sheet(ITexture texture)
public Sheet(SheetType type, ITexture texture)
{
Type = type;
this.texture = texture;
Size = texture.Size;
}
public Sheet(string filename)
public Sheet(SheetType type, string filename)
{
using (var stream = GlobalFileSystem.Open(filename))
using (var bitmap = (Bitmap)Image.FromStream(stream))
@@ -54,6 +58,7 @@ namespace OpenRA.Graphics
Util.FastCopyIntoSprite(new Sprite(this, bitmap.Bounds(), TextureChannel.Red), bitmap);
}
Type = type;
ReleaseBuffer();
}

View File

@@ -40,16 +40,16 @@ namespace OpenRA.Graphics
int rowHeight = 0;
Point p;
public static Sheet AllocateSheet(int sheetSize)
public static Sheet AllocateSheet(SheetType type, int sheetSize)
{
return new Sheet(new Size(sheetSize, sheetSize));
return new Sheet(type, new Size(sheetSize, sheetSize));
}
public SheetBuilder(SheetType t)
: this(t, Game.Settings.Graphics.SheetSize) { }
public SheetBuilder(SheetType t, int sheetSize)
: this(t, () => AllocateSheet(sheetSize)) { }
: this(t, () => AllocateSheet(t, sheetSize)) { }
public SheetBuilder(SheetType t, Func<Sheet> allocateSheet)
{

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System;
using System.Drawing;
namespace OpenRA.Graphics
@@ -37,10 +38,10 @@ namespace OpenRA.Graphics
FractionalOffset = offset / Size;
Left = (float)bounds.Left / sheet.Size.Width;
Top = (float)bounds.Top / sheet.Size.Height;
Right = (float)bounds.Right / sheet.Size.Width;
Bottom = (float)bounds.Bottom / sheet.Size.Height;
Left = (float)Math.Min(bounds.Left, bounds.Right) / sheet.Size.Width;
Top = (float)Math.Min(bounds.Top, bounds.Bottom) / sheet.Size.Height;
Right = (float)Math.Max(bounds.Left, bounds.Right) / sheet.Size.Width;
Bottom = (float)Math.Max(bounds.Top, bounds.Bottom) / sheet.Size.Height;
}
}

View File

@@ -119,5 +119,10 @@ namespace OpenRA.Graphics
shader.SetVec("r1", zoom * 2f / screen.Width, -zoom * 2f / screen.Height);
shader.SetVec("r2", -1, 1);
}
public void SetDepthPreviewEnabled(bool enabled)
{
shader.SetBool("EnableDepthPreview", enabled);
}
}
}

View File

@@ -18,11 +18,13 @@ namespace OpenRA.Graphics
readonly TerrainSpriteLayer terrain;
readonly Theater theater;
readonly CellLayer<TerrainTile> mapTiles;
readonly CellLayer<byte> mapHeight;
public TerrainRenderer(World world, WorldRenderer wr)
{
theater = wr.Theater;
mapTiles = world.Map.MapTiles.Value;
mapHeight = world.Map.MapHeight.Value;
terrain = new TerrainSpriteLayer(world, wr, theater.Sheet, BlendMode.Alpha,
wr.Palette("terrain"), wr.World.Type != WorldType.Editor);
@@ -30,8 +32,8 @@ namespace OpenRA.Graphics
foreach (var cell in world.Map.AllCells)
UpdateCell(cell);
world.Map.MapTiles.Value.CellEntryChanged += UpdateCell;
world.Map.MapHeight.Value.CellEntryChanged += UpdateCell;
mapTiles.CellEntryChanged += UpdateCell;
mapHeight.CellEntryChanged += UpdateCell;
}
public void UpdateCell(CPos cell)
@@ -48,6 +50,8 @@ namespace OpenRA.Graphics
public void Dispose()
{
mapTiles.CellEntryChanged -= UpdateCell;
mapHeight.CellEntryChanged -= UpdateCell;
terrain.Dispose();
}
}

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
readonly WorldRenderer worldRenderer;
readonly Map map;
float paletteIndex;
readonly PaletteReference palette;
public TerrainSpriteLayer(World world, WorldRenderer wr, Sheet sheet, BlendMode blendMode, PaletteReference palette, bool restrictToBounds)
{
@@ -41,7 +41,7 @@ namespace OpenRA.Graphics
this.restrictToBounds = restrictToBounds;
Sheet = sheet;
BlendMode = blendMode;
paletteIndex = palette.TextureIndex;
this.palette = palette;
map = world.Map;
rowStride = 4 * map.MapSize.X;
@@ -50,28 +50,28 @@ namespace OpenRA.Graphics
vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(vertices.Length);
emptySprite = new Sprite(sheet, Rectangle.Empty, TextureChannel.Alpha);
wr.PaletteInvalidated += () =>
wr.PaletteInvalidated += UpdatePaletteIndices;
}
void UpdatePaletteIndices()
{
// Everything in the layer uses the same palette,
// so we can fix the indices in one pass
for (var i = 0; i < vertices.Length; i++)
{
paletteIndex = palette.TextureIndex;
var v = vertices[i];
vertices[i] = new Vertex(v.X, v.Y, v.Z, v.U, v.V, palette.TextureIndex, v.C);
}
// Everything in the layer uses the same palette,
// so we can fix the indices in one pass
for (var i = 0; i < vertices.Length; i++)
{
var v = vertices[i];
vertices[i] = new Vertex(v.X, v.Y, v.Z, v.U, v.V, paletteIndex, v.C);
}
for (var row = 0; row < map.MapSize.Y; row++)
dirtyRows.Add(row);
};
for (var row = 0; row < map.MapSize.Y; row++)
dirtyRows.Add(row);
}
public void Update(CPos cell, Sprite sprite)
{
var pos = sprite == null ? float2.Zero :
worldRenderer.ScreenPosition(map.CenterOfCell(cell)) + sprite.Offset - 0.5f * sprite.Size;
Update(cell.ToMPos(map.TileShape), sprite, pos);
Update(cell.ToMPos(map.Grid.Type), sprite, pos);
}
public void Update(MPos uv, Sprite sprite, float2 pos)
@@ -88,7 +88,7 @@ namespace OpenRA.Graphics
sprite = emptySprite;
var offset = rowStride * uv.V + 4 * uv.U;
Util.FastCreateQuad(vertices, pos, sprite, paletteIndex, offset, sprite.Size);
Util.FastCreateQuad(vertices, pos, sprite, palette.TextureIndex, offset, sprite.Size);
dirtyRows.Add(uv.V);
}
@@ -130,6 +130,7 @@ namespace OpenRA.Graphics
public void Dispose()
{
worldRenderer.PaletteInvalidated -= UpdatePaletteIndices;
vertexBuffer.Dispose();
}
}

View File

@@ -43,16 +43,18 @@ namespace OpenRA.Graphics
{
this.tileset = tileset;
var allocated = false;
var type = tileset.EnableDepth ? SheetType.DualIndexed : SheetType.Indexed;
Func<Sheet> allocate = () =>
{
if (allocated)
throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
allocated = true;
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
return new Sheet(type, new Size(tileset.SheetSize, tileset.SheetSize));
};
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
sheetBuilder = new SheetBuilder(type, allocate);
random = new MersenneTwister();
var frameCache = new FrameCache(Game.ModData.SpriteLoaders);
@@ -63,8 +65,19 @@ namespace OpenRA.Graphics
foreach (var i in t.Value.Images)
{
var allFrames = frameCache[i];
var frames = t.Value.Frames != null ? t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames;
variants.Add(frames.Select(f => sheetBuilder.Add(f)).ToArray());
var frameCount = tileset.EnableDepth ? allFrames.Length / 2 : allFrames.Length;
var indices = t.Value.Frames != null ? t.Value.Frames : Enumerable.Range(0, frameCount);
variants.Add(indices.Select(j =>
{
var f = allFrames[j];
var s = sheetBuilder.Allocate(f.Size, f.Offset);
Util.FastCopyIntoChannel(s, 0, f.Data);
if (tileset.EnableDepth)
Util.FastCopyIntoChannel(s, 1, allFrames[j + frameCount].Data);
return s;
}).ToArray());
}
var allSprites = variants.SelectMany(s => s);
@@ -95,7 +108,7 @@ namespace OpenRA.Graphics
return template.Sprites[start * template.Stride + r.Index];
}
public Rectangle TemplateBounds(TerrainTemplateInfo template, Size tileSize, TileShape tileShape)
public Rectangle TemplateBounds(TerrainTemplateInfo template, Size tileSize, MapGridType mapGrid)
{
Rectangle? templateRect = null;
@@ -112,8 +125,8 @@ namespace OpenRA.Graphics
continue;
var sprite = TileSprite(tile);
var u = tileShape == TileShape.Rectangle ? x : (x - y) / 2f;
var v = tileShape == TileShape.Rectangle ? y : (x + y) / 2f;
var u = mapGrid == MapGridType.Rectangular ? x : (x - y) / 2f;
var v = mapGrid == MapGridType.Rectangular ? y : (x + y) / 2f;
var tl = new float2(u * tileSize.Width, (v - 0.5f * tileInfo.Height) * tileSize.Height) - 0.5f * sprite.Size;
var rect = new Rectangle((int)(tl.X + sprite.Offset.X), (int)(tl.Y + sprite.Offset.Y), (int)sprite.Size.X, (int)sprite.Size.Y);

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Graphics
{
// yes, our channel order is nuts.
static readonly int[] ChannelMasks = { 2, 1, 0, 3 };
static readonly float[] ChannelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
static readonly float[] ChannelSelect = { 0.2f, 0.4f, 0.6f, 0.8f };
public static void FastCreateQuad(Vertex[] vertices, float2 o, Sprite r, float paletteTextureIndex, int nv, float2 size)
{
@@ -32,6 +32,8 @@ namespace OpenRA.Graphics
public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, float paletteTextureIndex, int nv)
{
var attribC = ChannelSelect[(int)r.Channel];
if (r.Sheet.Type == SheetType.DualIndexed)
attribC *= -1;
vertices[nv] = new Vertex(a, r.Left, r.Top, paletteTextureIndex, attribC);
vertices[nv + 1] = new Vertex(b, r.Right, r.Top, paletteTextureIndex, attribC);

View File

@@ -9,7 +9,6 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
@@ -92,15 +91,15 @@ namespace OpenRA.Graphics
public Viewport(WorldRenderer wr, Map map)
{
worldRenderer = wr;
var grid = Game.ModData.Manifest.Get<MapGrid>();
// Calculate map bounds in world-px
if (wr.World.Type == WorldType.Editor)
{
// The full map is visible in the editor
var ts = Game.ModData.Manifest.TileSize;
var width = map.MapSize.X * ts.Width;
var height = map.MapSize.Y * ts.Height;
if (wr.World.Map.TileShape == TileShape.Diamond)
var width = map.MapSize.X * grid.TileSize.Width;
var height = map.MapSize.Y * grid.TileSize.Height;
if (wr.World.Map.Grid.Type == MapGridType.RectangularIsometric)
height /= 2;
mapBounds = new Rectangle(0, 0, width, height);
@@ -115,23 +114,22 @@ namespace OpenRA.Graphics
}
Zoom = Game.Settings.Graphics.PixelDouble ? 2 : 1;
tileSize = Game.ModData.Manifest.TileSize;
tileSize = grid.TileSize;
}
public CPos ViewToWorld(int2 view)
{
var world = worldRenderer.Viewport.ViewToWorldPx(view);
var map = worldRenderer.World.Map;
var ts = Game.ModData.Manifest.TileSize;
var candidates = CandidateMouseoverCells(world);
var candidates = CandidateMouseoverCells(world).ToList();
var tileSet = worldRenderer.World.TileSet;
foreach (var uv in candidates)
{
// Coarse filter to nearby cells
var p = map.CenterOfCell(uv.ToCPos(map.TileShape));
var p = map.CenterOfCell(uv.ToCPos(map.Grid.Type));
var s = worldRenderer.ScreenPxPosition(p);
if (Math.Abs(s.X - world.X) <= ts.Width && Math.Abs(s.Y - world.Y) <= ts.Height)
if (Math.Abs(s.X - world.X) <= tileSize.Width && Math.Abs(s.Y - world.Y) <= tileSize.Height)
{
var ramp = 0;
if (map.Contains(uv))
@@ -153,11 +151,11 @@ namespace OpenRA.Graphics
// Mouse is not directly over a cell (perhaps on a cliff)
// Try and find the closest cell
if (candidates.Any())
if (candidates.Count > 0)
{
return candidates.OrderBy(uv =>
{
var p = map.CenterOfCell(uv.ToCPos(map.TileShape));
var p = map.CenterOfCell(uv.ToCPos(map.Grid.Type));
var s = worldRenderer.ScreenPxPosition(p);
var dx = Math.Abs(s.X - world.X);
var dy = Math.Abs(s.Y - world.Y);
@@ -177,8 +175,8 @@ namespace OpenRA.Graphics
var minPos = worldRenderer.ProjectedPosition(world);
// Find all the cells that could potentially have been clicked
var a = map.CellContaining(minPos - new WVec(1024, 0, 0)).ToMPos(map.TileShape);
var b = map.CellContaining(minPos + new WVec(512, 512 * map.MaximumTerrainHeight, 0)).ToMPos(map.TileShape);
var a = map.CellContaining(minPos - new WVec(1024, 0, 0)).ToMPos(map.Grid.Type);
var b = map.CellContaining(minPos + new WVec(512, 512 * map.Grid.MaximumTerrainHeight, 0)).ToMPos(map.Grid.Type);
for (var v = b.V; v >= a.V; v--)
for (var u = b.U; u >= a.U; u--)
@@ -241,10 +239,9 @@ namespace OpenRA.Graphics
var tl = (PPos)map.CellContaining(worldRenderer.ProjectedPosition(TopLeft)).ToMPos(map);
var br = (PPos)map.CellContaining(worldRenderer.ProjectedPosition(BottomRight)).ToMPos(map);
// Diamond tile shapes don't have straight edges, and so we need
// an additional cell margin to include the cells that are half
// visible on each edge.
if (map.TileShape == TileShape.Diamond)
// RectangularIsometric maps don't have straight edges, and so we need an additional
// cell margin to include the cells that are half visible on each edge.
if (map.Grid.Type == MapGridType.RectangularIsometric)
{
tl = new PPos(tl.U - 1, tl.V - 1);
br = new PPos(br.U + 1, br.V + 1);

View File

@@ -52,7 +52,7 @@ namespace OpenRA.Graphics
if (allocated)
throw new SheetOverflowException("");
allocated = true;
return SheetBuilder.AllocateSheet(Game.Settings.Graphics.SheetSize);
return SheetBuilder.AllocateSheet(SheetType.DualIndexed, Game.Settings.Graphics.SheetSize);
};
return new SheetBuilder(SheetType.DualIndexed, allocate);
@@ -220,7 +220,7 @@ namespace OpenRA.Graphics
using (var s = GlobalFileSystem.Open(files.First + ".vxl"))
vxl = new VxlReader(s);
using (var s = GlobalFileSystem.Open(files.Second + ".hva"))
hva = new HvaReader(s);
hva = new HvaReader(s, files.Second + ".hva");
return new Voxel(this, vxl, hva);
}

View File

@@ -331,7 +331,7 @@ namespace OpenRA.Graphics
var size = new Size(renderer.SheetSize, renderer.SheetSize);
var framebuffer = renderer.Device.CreateFrameBuffer(size);
var sheet = new Sheet(framebuffer.Texture);
var sheet = new Sheet(SheetType.DualIndexed, framebuffer.Texture);
mappedBuffers.Add(sheet, framebuffer);
return sheet;

View File

@@ -25,6 +25,7 @@ namespace OpenRA.Graphics
static readonly int[][] RangeCircleStartRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i).AsMatrix());
static readonly int[][] RangeCircleEndRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i + 6).AsMatrix());
public readonly Size TileSize;
public readonly World World;
public readonly Theater Theater;
public Viewport Viewport { get; private set; }
@@ -40,6 +41,7 @@ namespace OpenRA.Graphics
internal WorldRenderer(World world)
{
World = world;
TileSize = World.Map.Grid.TileSize;
Viewport = new Viewport(this, world.Map);
createPaletteReference = CreatePaletteReference;
@@ -130,6 +132,9 @@ namespace OpenRA.Graphics
if (World.WorldActor.Disposed)
return;
if (devTrait.Value != null)
Game.Renderer.WorldSpriteRenderer.SetDepthPreviewEnabled(devTrait.Value.ShowDepthPreview);
RefreshPalette();
if (World.Type == WorldType.Shellmap && !Game.Settings.Game.ShowShellmap)
@@ -145,7 +150,6 @@ namespace OpenRA.Graphics
for (var i = 0; i < renderables.Count; i++)
renderables[i].Render(this);
// added for contrails
foreach (var a in World.ActorsWithTrait<IPostRender>())
if (a.Actor.IsInWorld && !a.Actor.Disposed)
a.Trait.RenderAfterWorld(this, a.Actor);
@@ -182,7 +186,7 @@ namespace OpenRA.Graphics
if (World.Type == WorldType.Regular && Game.Settings.Game.AlwaysShowStatusBars)
{
foreach (var g in World.Actors.Where(a => !a.Disposed
&& a.HasTrait<Selectable>()
&& a.Info.HasTraitInfo<SelectableInfo>()
&& !World.FogObscures(a)
&& !World.Selection.Actors.Contains(a)))
@@ -194,7 +198,7 @@ namespace OpenRA.Graphics
public void DrawRollover(Actor unit)
{
if (unit.HasTrait<Selectable>())
if (unit.Info.HasTraitInfo<SelectableInfo>())
new SelectionBarsRenderable(unit).Render(this);
}
@@ -232,8 +236,7 @@ namespace OpenRA.Graphics
// Conversion between world and screen coordinates
public float2 ScreenPosition(WPos pos)
{
var ts = Game.ModData.Manifest.TileSize;
return new float2(ts.Width * pos.X / 1024f, ts.Height * (pos.Y - pos.Z) / 1024f);
return new float2(TileSize.Width * pos.X / 1024f, TileSize.Height * (pos.Y - pos.Z) / 1024f);
}
public int2 ScreenPxPosition(WPos pos)
@@ -246,10 +249,9 @@ namespace OpenRA.Graphics
// For scaling vectors to pixel sizes in the voxel renderer
public void ScreenVectorComponents(WVec vec, out float x, out float y, out float z)
{
var ts = Game.ModData.Manifest.TileSize;
x = ts.Width * vec.X / 1024f;
y = ts.Height * vec.Y / 1024f;
z = ts.Height * vec.Z / 1024f;
x = TileSize.Width * vec.X / 1024f;
y = TileSize.Height * vec.Y / 1024f;
z = TileSize.Height * vec.Z / 1024f;
}
// For scaling vectors to pixel sizes in the voxel renderer
@@ -270,8 +272,7 @@ namespace OpenRA.Graphics
public float ScreenZPosition(WPos pos, int offset)
{
var ts = Game.ModData.Manifest.TileSize;
return ZPosition(pos, offset) * ts.Height / 1024f;
return ZPosition(pos, offset) * TileSize.Height / 1024f;
}
static int ZPosition(WPos pos, int offset)
@@ -285,8 +286,7 @@ namespace OpenRA.Graphics
/// </summary>
public WPos ProjectedPosition(int2 screenPx)
{
var ts = Game.ModData.Manifest.TileSize;
return new WPos(1024 * screenPx.X / ts.Width, 1024 * screenPx.Y / ts.Height, 0);
return new WPos(1024 * screenPx.X / TileSize.Width, 1024 * screenPx.Y / TileSize.Height, 0);
}
public void Dispose()

View File

@@ -17,6 +17,8 @@ namespace OpenRA
/// </summary>
string Name { get; }
bool ValidateArguments(string[] args);
void Run(ModData modData, string[] args);
}
}

View File

@@ -38,15 +38,15 @@ namespace OpenRA
public CPos ToCPos(Map map)
{
return ToCPos(map.TileShape);
return ToCPos(map.Grid.Type);
}
public CPos ToCPos(TileShape shape)
public CPos ToCPos(MapGridType gridType)
{
if (shape == TileShape.Rectangle)
if (gridType == MapGridType.Rectangular)
return new CPos(U, V);
// Convert from rectangular map position to diamond cell position
// Convert from rectangular map position to RectangularIsometric cell position
// - The staggered rows make this fiddly (hint: draw a diagram!)
// (a) Consider the relationships:
// - +1u (even -> odd) adds (1, -1) to (x, y)

View File

@@ -10,14 +10,12 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.Primitives;
namespace OpenRA
{
public enum TileShape { Rectangle, Diamond }
public interface IGlobalModData { }
public sealed class SpriteSequenceFormat : IGlobalModData
@@ -47,31 +45,13 @@ namespace OpenRA
public readonly MiniYaml LobbyDefaults;
public readonly Dictionary<string, Pair<string, int>> Fonts;
public readonly Size TileSize = new Size(24, 24);
public readonly TileShape TileShape = TileShape.Rectangle;
public readonly byte MaximumTerrainHeight = 0;
public readonly string[] SpriteFormats = { };
[Desc("(x,y,z) offset of the full cell and each sub-cell", "X & Y should be between -512 ... 512 and Z >= 0")]
public readonly WVec[] SubCellOffsets =
{
new WVec(0, 0, 0), // full cell - index 0
new WVec(-299, -256, 0), // top left - index 1
new WVec(256, -256, 0), // top right - index 2
new WVec(0, 0, 0), // center - index 3
new WVec(-299, 256, 0), // bottom left - index 4
new WVec(256, 256, 0), // bottom right - index 5
};
[Desc("Default subcell index used if SubCellInit is absent", "0 - full cell, 1 - first sub-cell")]
public readonly int SubCellDefaultIndex = 3;
readonly string[] reservedModuleNames = { "Metadata", "Folders", "MapFolders", "Packages", "Rules",
"Sequences", "VoxelSequences", "Cursors", "Chrome", "Assemblies", "ChromeLayout", "Weapons",
"Voices", "Notifications", "Music", "Translations", "TileSets", "ChromeMetrics", "Missions",
"ServerTraits", "LoadScreen", "LobbyDefaults", "Fonts", "TileSize", "MaximumTerrainHeight",
"TileShape", "SubCells", "SupportsMapsFrom", "SpriteFormats" };
"ServerTraits", "LoadScreen", "LobbyDefaults", "Fonts", "SupportsMapsFrom", "SpriteFormats" };
readonly TypeDictionary modules = new TypeDictionary();
readonly Dictionary<string, MiniYaml> yaml;
@@ -118,33 +98,6 @@ namespace OpenRA
return Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value));
});
if (yaml.ContainsKey("TileSize"))
TileSize = FieldLoader.GetValue<Size>("TileSize", yaml["TileSize"].Value);
if (yaml.ContainsKey("TileShape"))
TileShape = FieldLoader.GetValue<TileShape>("TileShape", yaml["TileShape"].Value);
if (yaml.ContainsKey("MaximumTerrainHeight"))
MaximumTerrainHeight = FieldLoader.GetValue<byte>("MaximumTerrainHeight", yaml["MaximumTerrainHeight"].Value);
if (yaml.ContainsKey("SubCells"))
{
var subcells = yaml["SubCells"].ToDictionary();
// Read (x,y,z) offset (relative to cell center) pairs for positioning subcells
if (subcells.ContainsKey("Offsets"))
SubCellOffsets = FieldLoader.GetValue<WVec[]>("Offsets", subcells["Offsets"].Value);
if (subcells.ContainsKey("DefaultIndex"))
SubCellDefaultIndex = FieldLoader.GetValue<int>("DefaultIndex", subcells["DefaultIndex"].Value);
else // Otherwise set the default subcell index to the middle subcell entry
SubCellDefaultIndex = SubCellOffsets.Length / 2;
}
// Validate default index - 0 for no subcells, otherwise > 1 & <= subcell count (offset triples count - 1)
if (SubCellDefaultIndex < (SubCellOffsets.Length > 1 ? 1 : 0) || SubCellDefaultIndex >= SubCellOffsets.Length)
throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells");
// Allow inherited mods to import parent maps.
var compat = new List<string>();
compat.Add(mod);

View File

@@ -20,36 +20,36 @@ namespace OpenRA
{
public readonly Size Size;
readonly Rectangle bounds;
public readonly TileShape Shape;
public readonly MapGridType GridType;
public event Action<CPos> CellEntryChanged = null;
readonly T[] entries;
public CellLayer(Map map)
: this(map.TileShape, new Size(map.MapSize.X, map.MapSize.Y)) { }
: this(map.Grid.Type, new Size(map.MapSize.X, map.MapSize.Y)) { }
public CellLayer(TileShape shape, Size size)
public CellLayer(MapGridType gridType, Size size)
{
Size = size;
bounds = new Rectangle(0, 0, Size.Width, Size.Height);
Shape = shape;
GridType = gridType;
entries = new T[size.Width * size.Height];
}
public void CopyValuesFrom(CellLayer<T> anotherLayer)
{
if (Size != anotherLayer.Size || Shape != anotherLayer.Shape)
if (Size != anotherLayer.Size || GridType != anotherLayer.GridType)
throw new ArgumentException(
"layers must have a matching size and shape.", "anotherLayer");
"layers must have a matching size and shape (grid type).", "anotherLayer");
if (CellEntryChanged != null)
throw new InvalidOperationException(
"Cannot copy values when there are listeners attached to the CellEntryChanged event.");
Array.Copy(anotherLayer.entries, entries, entries.Length);
}
public static CellLayer<T> CreateInstance(Func<MPos, T> initialCellValueFactory, Size size, TileShape tileShape)
public static CellLayer<T> CreateInstance(Func<MPos, T> initialCellValueFactory, Size size, MapGridType mapGridType)
{
var cellLayer = new CellLayer<T>(tileShape, size);
var cellLayer = new CellLayer<T>(mapGridType, size);
for (var v = 0; v < size.Height; v++)
{
for (var u = 0; u < size.Width; u++)
@@ -65,7 +65,7 @@ namespace OpenRA
// Resolve an array index from cell coordinates
int Index(CPos cell)
{
return Index(cell.ToMPos(Shape));
return Index(cell.ToMPos(GridType));
}
// Resolve an array index from map coordinates
@@ -104,7 +104,7 @@ namespace OpenRA
entries[Index(uv)] = value;
if (CellEntryChanged != null)
CellEntryChanged(uv.ToCPos(Shape));
CellEntryChanged(uv.ToCPos(GridType));
}
}
@@ -128,12 +128,12 @@ namespace OpenRA
public bool Contains(CPos cell)
{
// .ToMPos() returns the same result if the X and Y coordinates
// are switched. X < Y is invalid in the Diamond coordinate system,
// are switched. X < Y is invalid in the RectangularIsometric coordinate system,
// so we pre-filter these to avoid returning the wrong result
if (Shape == TileShape.Diamond && cell.X < cell.Y)
if (GridType == MapGridType.RectangularIsometric && cell.X < cell.Y)
return false;
return Contains(cell.ToMPos(Shape));
return Contains(cell.ToMPos(GridType));
}
public bool Contains(MPos uv)
@@ -143,7 +143,7 @@ namespace OpenRA
public CPos Clamp(CPos uv)
{
return Clamp(uv.ToMPos(Shape)).ToCPos(Shape);
return Clamp(uv.ToMPos(GridType)).ToCPos(GridType);
}
public MPos Clamp(MPos uv)
@@ -155,10 +155,10 @@ namespace OpenRA
// Helper functions
public static class CellLayer
{
/// <summary>Create a new layer by resizing another layer. New cells are filled with defaultValue.</summary>
/// <summary>Create a new layer by resizing another layer. New cells are filled with defaultValue.</summary>
public static CellLayer<T> Resize<T>(CellLayer<T> layer, Size newSize, T defaultValue)
{
var result = new CellLayer<T>(layer.Shape, newSize);
var result = new CellLayer<T>(layer.GridType, newSize);
var width = Math.Min(layer.Size.Width, newSize.Width);
var height = Math.Min(layer.Size.Height, newSize.Height);

View File

@@ -22,33 +22,33 @@ namespace OpenRA
// Corners of the region
public readonly CPos TopLeft;
public readonly CPos BottomRight;
readonly TileShape shape;
readonly MapGridType gridType;
// Corners in map coordinates
// These will only equal TopLeft and BottomRight for TileShape.Rectangular
// These will only equal TopLeft and BottomRight for MapGridType.Rectangular
readonly MPos mapTopLeft;
readonly MPos mapBottomRight;
public CellRegion(TileShape shape, CPos topLeft, CPos bottomRight)
public CellRegion(MapGridType gridType, CPos topLeft, CPos bottomRight)
{
this.shape = shape;
this.gridType = gridType;
TopLeft = topLeft;
BottomRight = bottomRight;
mapTopLeft = TopLeft.ToMPos(shape);
mapBottomRight = BottomRight.ToMPos(shape);
mapTopLeft = TopLeft.ToMPos(gridType);
mapBottomRight = BottomRight.ToMPos(gridType);
}
/// <summary>Expand the specified region with an additional cordon. This may expand the region outside the map borders.</summary>
public static CellRegion Expand(CellRegion region, int cordon)
{
var tl = new MPos(region.mapTopLeft.U - cordon, region.mapTopLeft.V - cordon).ToCPos(region.shape);
var br = new MPos(region.mapBottomRight.U + cordon, region.mapBottomRight.V + cordon).ToCPos(region.shape);
return new CellRegion(region.shape, tl, br);
var tl = new MPos(region.mapTopLeft.U - cordon, region.mapTopLeft.V - cordon).ToCPos(region.gridType);
var br = new MPos(region.mapBottomRight.U + cordon, region.mapBottomRight.V + cordon).ToCPos(region.gridType);
return new CellRegion(region.gridType, tl, br);
}
/// <summary>Returns the minimal region that covers at least the specified cells.</summary>
public static CellRegion BoundingRegion(TileShape shape, IEnumerable<CPos> cells)
public static CellRegion BoundingRegion(MapGridType shape, IEnumerable<CPos> cells)
{
if (cells == null || !cells.Any())
throw new ArgumentException("cells must not be null or empty.", "cells");
@@ -81,7 +81,7 @@ namespace OpenRA
public bool Contains(CPos cell)
{
var uv = cell.ToMPos(shape);
var uv = cell.ToMPos(gridType);
return uv.U >= mapTopLeft.U && uv.U <= mapBottomRight.U && uv.V >= mapTopLeft.V && uv.V <= mapBottomRight.V;
}
@@ -136,7 +136,7 @@ namespace OpenRA
return false;
}
current = new MPos(u, v).ToCPos(r.shape);
current = new MPos(u, v).ToCPos(r.gridType);
return true;
}

View File

@@ -9,15 +9,14 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using OpenRA.FileSystem;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Support;
@@ -114,6 +113,8 @@ namespace OpenRA
public class Map
{
public const int MinimumSupportedMapFormat = 6;
static readonly int[][] CellCornerHalfHeights = new int[][]
{
// Flat
@@ -151,8 +152,7 @@ namespace OpenRA
};
public const int MaxTilesInCircleRange = 50;
public readonly TileShape TileShape;
public readonly byte MaximumTerrainHeight;
public readonly MapGrid Grid;
[FieldLoader.Ignore] public readonly WVec[] SubCellOffsets;
public readonly SubCell DefaultSubCell;
@@ -229,6 +229,7 @@ namespace OpenRA
[FieldLoader.Ignore] public List<MiniYamlNode> VoxelSequenceDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> WeaponDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> VoiceDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> MusicDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> NotificationDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
[FieldLoader.Ignore] public List<MiniYamlNode> PlayerDefinitions = new List<MiniYamlNode>();
@@ -246,6 +247,7 @@ namespace OpenRA
[FieldLoader.Ignore] public Lazy<CellLayer<byte>> MapHeight;
[FieldLoader.Ignore] public CellLayer<byte> CustomTerrain;
[FieldLoader.Ignore] CellLayer<short> cachedTerrainIndexes;
[FieldLoader.Ignore] bool initializedCellProjection;
[FieldLoader.Ignore] CellLayer<PPos[]> cellProjection;
@@ -260,8 +262,6 @@ namespace OpenRA
[FieldLoader.Ignore] public ProjectedCellRegion ProjectedCellBounds;
[FieldLoader.Ignore] public CellRegion AllCells;
readonly Func<PPos, bool> containsTest;
void AssertExists(string filename)
{
using (var s = Container.GetContent(filename))
@@ -275,10 +275,8 @@ namespace OpenRA
/// </summary>
public Map(TileSet tileset, int width, int height)
{
containsTest = Contains;
var size = new Size(width, height);
var tileShape = Game.ModData.Manifest.TileShape;
Grid = Game.ModData.Manifest.Get<MapGrid>();
var tileRef = new TerrainTile(tileset.Templates.First().Key, (byte)0);
Title = "Name your map here";
@@ -290,25 +288,27 @@ namespace OpenRA
Videos = new MapVideos();
Options = new MapOptions();
MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(tileShape, size));
MapResources = Exts.Lazy(() => new CellLayer<ResourceTile>(Grid.Type, size));
MapTiles = Exts.Lazy(() =>
{
var ret = new CellLayer<TerrainTile>(tileShape, size);
var ret = new CellLayer<TerrainTile>(Grid.Type, size);
ret.Clear(tileRef);
if (Grid.MaximumTerrainHeight > 0)
ret.CellEntryChanged += UpdateProjection;
return ret;
});
MapHeight = Exts.Lazy(() =>
{
var ret = new CellLayer<byte>(tileShape, size);
var ret = new CellLayer<byte>(Grid.Type, size);
ret.Clear(0);
if (Grid.MaximumTerrainHeight > 0)
ret.CellEntryChanged += UpdateProjection;
return ret;
});
SpawnPoints = Exts.Lazy(() => new CPos[0]);
TileShape = tileShape;
MaximumTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight;
PostInit();
}
@@ -316,8 +316,6 @@ namespace OpenRA
/// <summary>Initializes a map loaded from disk.</summary>
public Map(string path)
{
containsTest = Contains;
Path = path;
Container = GlobalFileSystem.OpenPackage(path, null, int.MaxValue);
@@ -331,7 +329,7 @@ namespace OpenRA
// Use release-20110207 to convert older maps to format 4
// Use release-20110511 to convert older maps to format 5
// Use release-20141029 to convert older maps to format 6
if (MapFormat < 6)
if (MapFormat < MinimumSupportedMapFormat)
throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path));
var nd = yaml.ToDictionary();
@@ -364,6 +362,7 @@ namespace OpenRA
VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
WeaponDefinitions = MiniYaml.NodesOrEmpty(yaml, "Weapons");
VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices");
MusicDefinitions = MiniYaml.NodesOrEmpty(yaml, "Music");
NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications");
TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations");
PlayerDefinitions = MiniYaml.NodesOrEmpty(yaml, "Players");
@@ -375,12 +374,11 @@ namespace OpenRA
MapResources = Exts.Lazy(LoadResourceTiles);
MapHeight = Exts.Lazy(LoadMapHeight);
TileShape = Game.ModData.Manifest.TileShape;
MaximumTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight;
Grid = Game.ModData.Manifest.Get<MapGrid>();
SubCellOffsets = Game.ModData.Manifest.SubCellOffsets;
SubCellOffsets = Grid.SubCellOffsets;
LastSubCell = (SubCell)(SubCellOffsets.Length - 1);
DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex;
DefaultSubCell = (SubCell)Grid.SubCellDefaultIndex;
if (Container.Exists("map.png"))
using (var dataStream = Container.GetContent("map.png"))
@@ -418,7 +416,7 @@ namespace OpenRA
var tl = new MPos(0, 0).ToCPos(this);
var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this);
AllCells = new CellRegion(TileShape, tl, br);
AllCells = new CellRegion(Grid.Type, tl, br);
var btl = new PPos(Bounds.Left, Bounds.Top);
var bbr = new PPos(Bounds.Right - 1, Bounds.Bottom - 1);
@@ -428,10 +426,10 @@ namespace OpenRA
foreach (var uv in AllCells.MapCoords)
CustomTerrain[uv] = byte.MaxValue;
var leftDelta = TileShape == TileShape.Diamond ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
var topDelta = TileShape == TileShape.Diamond ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
var rightDelta = TileShape == TileShape.Diamond ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
var bottomDelta = TileShape == TileShape.Diamond ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
var leftDelta = Grid.Type == MapGridType.RectangularIsometric ? new WVec(-512, 0, 0) : new WVec(-512, -512, 0);
var topDelta = Grid.Type == MapGridType.RectangularIsometric ? new WVec(0, -512, 0) : new WVec(512, -512, 0);
var rightDelta = Grid.Type == MapGridType.RectangularIsometric ? new WVec(512, 0, 0) : new WVec(512, 512, 0);
var bottomDelta = Grid.Type == MapGridType.RectangularIsometric ? new WVec(0, 512, 0) : new WVec(-512, 512, 0);
CellCorners = CellCornerHalfHeights.Select(ramp => new WVec[]
{
leftDelta + new WVec(0, 0, 512 * ramp[0]),
@@ -448,34 +446,40 @@ namespace OpenRA
initializedCellProjection = true;
if (MaximumTerrainHeight != 0)
cellProjection = new CellLayer<PPos[]>(this);
inverseCellProjection = new CellLayer<List<MPos>>(this);
// Initialize collections
foreach (var cell in AllCells)
{
cellProjection = new CellLayer<PPos[]>(this);
inverseCellProjection = new CellLayer<List<MPos>>(this);
// Initialize collections
foreach (var cell in AllCells)
{
var uv = cell.ToMPos(TileShape);
cellProjection[uv] = new PPos[0];
inverseCellProjection[uv] = new List<MPos>();
}
// Initialize projections
foreach (var cell in AllCells)
UpdateProjection(cell);
var uv = cell.ToMPos(Grid.Type);
cellProjection[uv] = new PPos[0];
inverseCellProjection[uv] = new List<MPos>();
}
// Initialize projections
foreach (var cell in AllCells)
UpdateProjection(cell);
}
void UpdateProjection(CPos cell)
{
if (MaximumTerrainHeight == 0)
MPos uv;
if (Grid.MaximumTerrainHeight == 0)
{
uv = cell.ToMPos(Grid.Type);
cellProjection[cell] = new[] { (PPos)uv };
var inverse = inverseCellProjection[uv];
inverse.Clear();
inverse.Add(uv);
return;
}
if (!initializedCellProjection)
InitializeCellProjection();
var uv = cell.ToMPos(TileShape);
uv = cell.ToMPos(Grid.Type);
// Remove old reverse projection
foreach (var puv in cellProjection[uv])
@@ -571,6 +575,7 @@ namespace OpenRA
root.Add(new MiniYamlNode("VoxelSequences", null, VoxelSequenceDefinitions));
root.Add(new MiniYamlNode("Weapons", null, WeaponDefinitions));
root.Add(new MiniYamlNode("Voices", null, VoiceDefinitions));
root.Add(new MiniYamlNode("Music", null, MusicDefinitions));
root.Add(new MiniYamlNode("Notifications", null, NotificationDefinitions));
root.Add(new MiniYamlNode("Translations", null, TranslationDefinitions));
@@ -602,6 +607,9 @@ namespace OpenRA
// Update existing package
Container.Write(entries);
// Update UID to match the newly saved data
Uid = ComputeHash();
}
public CellLayer<TerrainTile> LoadMapTiles()
@@ -630,7 +638,8 @@ namespace OpenRA
}
}
tiles.CellEntryChanged += UpdateProjection;
if (Grid.MaximumTerrainHeight > 0)
tiles.CellEntryChanged += UpdateProjection;
return tiles;
}
@@ -646,11 +655,12 @@ namespace OpenRA
s.Position = header.HeightsOffset;
for (var i = 0; i < MapSize.X; i++)
for (var j = 0; j < MapSize.Y; j++)
tiles[new MPos(i, j)] = s.ReadUInt8().Clamp((byte)0, MaximumTerrainHeight);
tiles[new MPos(i, j)] = s.ReadUInt8().Clamp((byte)0, Grid.MaximumTerrainHeight);
}
}
tiles.CellEntryChanged += UpdateProjection;
if (Grid.MaximumTerrainHeight > 0)
tiles.CellEntryChanged += UpdateProjection;
return tiles;
}
@@ -694,8 +704,8 @@ namespace OpenRA
// Data offsets
var tilesOffset = 17;
var heightsOffset = MaximumTerrainHeight > 0 ? 3 * MapSize.X * MapSize.Y + 17 : 0;
var resourcesOffset = (MaximumTerrainHeight > 0 ? 4 : 3) * MapSize.X * MapSize.Y + 17;
var heightsOffset = Grid.MaximumTerrainHeight > 0 ? 3 * MapSize.X * MapSize.Y + 17 : 0;
var resourcesOffset = (Grid.MaximumTerrainHeight > 0 ? 4 : 3) * MapSize.X * MapSize.Y + 17;
writer.Write((uint)tilesOffset);
writer.Write((uint)heightsOffset);
@@ -742,9 +752,9 @@ namespace OpenRA
public bool Contains(CPos cell)
{
// .ToMPos() returns the same result if the X and Y coordinates
// are switched. X < Y is invalid in the Diamond coordinate system,
// are switched. X < Y is invalid in the RectangularIsometric coordinate system,
// so we pre-filter these to avoid returning the wrong result
if (TileShape == TileShape.Diamond && cell.X < cell.Y)
if (Grid.Type == MapGridType.RectangularIsometric && cell.X < cell.Y)
return false;
return Contains(cell.ToMPos(this));
@@ -755,7 +765,18 @@ namespace OpenRA
// The first check ensures that the cell is within the valid map region, avoiding
// potential crashes in deeper code. All CellLayers have the same geometry, and
// CustomTerrain is convenient (cellProjection may be null and others are Lazy).
return CustomTerrain.Contains(uv) && ProjectedCellsCovering(uv).All(containsTest);
return CustomTerrain.Contains(uv) && ContainsAllProjectedCellsCovering(uv);
}
bool ContainsAllProjectedCellsCovering(MPos uv)
{
if (Grid.MaximumTerrainHeight == 0)
return Contains((PPos)uv);
foreach (var puv in ProjectedCellsCovering(uv))
if (!Contains(puv))
return false;
return true;
}
public bool Contains(PPos puv)
@@ -765,10 +786,10 @@ namespace OpenRA
public WPos CenterOfCell(CPos cell)
{
if (TileShape == TileShape.Rectangle)
if (Grid.Type == MapGridType.Rectangular)
return new WPos(1024 * cell.X + 512, 1024 * cell.Y + 512, 0);
// Convert from diamond cell position (x, y) to world position (u, v):
// Convert from isometric cell position (x, y) to world position (u, v):
// (a) Consider the relationships:
// - Center of origin cell is (512, 512)
// - +x adds (512, 512) to world pos
@@ -797,10 +818,10 @@ namespace OpenRA
public CPos CellContaining(WPos pos)
{
if (TileShape == TileShape.Rectangle)
if (Grid.Type == MapGridType.Rectangular)
return new CPos(pos.X / 1024, pos.Y / 1024);
// Convert from world position to diamond cell position:
// Convert from world position to isometric cell position:
// (a) Subtract (512, 512) to move the rotation center to the middle of the corner cell
// (b) Rotate axes by -pi/4
// (c) Divide through by sqrt(2) to bring us to an equivalent world pos aligned with u,v axes
@@ -816,16 +837,12 @@ namespace OpenRA
public PPos ProjectedCellCovering(WPos pos)
{
var projectedPos = pos - new WVec(0, pos.Z, pos.Z);
return (PPos)CellContaining(projectedPos).ToMPos(TileShape);
return (PPos)CellContaining(projectedPos).ToMPos(Grid.Type);
}
static readonly PPos[] NoProjectedCells = { };
public PPos[] ProjectedCellsCovering(MPos uv)
{
// Shortcut for mods that don't use heightmaps
if (MaximumTerrainHeight == 0)
return new[] { (PPos)uv };
if (!initializedCellProjection)
InitializeCellProjection();
@@ -835,21 +852,17 @@ namespace OpenRA
return cellProjection[uv];
}
public MPos[] Unproject(PPos puv)
public List<MPos> Unproject(PPos puv)
{
var uv = (MPos)puv;
// Shortcut for mods that don't use heightmaps
if (MaximumTerrainHeight == 0)
return new[] { uv };
if (!initializedCellProjection)
InitializeCellProjection();
if (!inverseCellProjection.Contains(uv))
return new MPos[0];
return new List<MPos>();
return inverseCellProjection[uv].ToArray();
return inverseCellProjection[uv];
}
public int FacingBetween(CPos cell, CPos towards, int fallbackfacing)
@@ -871,7 +884,7 @@ namespace OpenRA
var tl = new MPos(0, 0).ToCPos(this);
var br = new MPos(MapSize.X - 1, MapSize.Y - 1).ToCPos(this);
AllCells = new CellRegion(TileShape, tl, br);
AllCells = new CellRegion(Grid.Type, tl, br);
}
public void SetBounds(PPos tl, PPos br)
@@ -883,10 +896,10 @@ namespace OpenRA
// Directly calculate the projected map corners in world units avoiding unnecessary
// conversions. This abuses the definition that the width of the cell is always
// 1024 units, and that the height of two rows is 2048 for classic cells and 1024
// for diamond cells.
// for isometric cells.
var wtop = tl.V * 1024;
var wbottom = (br.V + 1) * 1024;
if (TileShape == TileShape.Diamond)
if (Grid.Type == MapGridType.RectangularIsometric)
{
wtop /= 2;
wbottom /= 2;
@@ -945,9 +958,32 @@ namespace OpenRA
public byte GetTerrainIndex(CPos cell)
{
const short InvalidCachedTerrainIndex = -1;
// Lazily initialize a cache for terrain indexes.
if (cachedTerrainIndexes == null)
{
cachedTerrainIndexes = new CellLayer<short>(this);
cachedTerrainIndexes.Clear(InvalidCachedTerrainIndex);
// Invalidate the entry for a cell if anything could cause the terrain index to change.
Action<CPos> invalidateTerrainIndex = c => cachedTerrainIndexes[c] = InvalidCachedTerrainIndex;
CustomTerrain.CellEntryChanged += invalidateTerrainIndex;
MapTiles.Value.CellEntryChanged += invalidateTerrainIndex;
}
var uv = cell.ToMPos(this);
var custom = CustomTerrain[uv];
return custom != byte.MaxValue ? custom : cachedTileSet.Value.GetTerrainIndex(MapTiles.Value[uv]);
var terrainIndex = cachedTerrainIndexes[uv];
// Cache terrain indexes per cell on demand.
if (terrainIndex == InvalidCachedTerrainIndex)
{
var custom = CustomTerrain[uv];
terrainIndex = cachedTerrainIndexes[uv] =
custom != byte.MaxValue ? custom : cachedTileSet.Value.GetTerrainIndex(MapTiles.Value[uv]);
}
return (byte)terrainIndex;
}
public TerrainTypeInfo GetTerrainInfo(CPos cell)
@@ -962,11 +998,11 @@ namespace OpenRA
public MPos Clamp(MPos uv)
{
if (MaximumTerrainHeight == 0)
if (Grid.MaximumTerrainHeight == 0)
return (MPos)Clamp((PPos)uv);
// Already in bounds, so don't need to do anything.
if (ProjectedCellsCovering(uv).Any(containsTest))
if (ContainsAllProjectedCellsCovering(uv))
return uv;
// Clamping map coordinates is trickier than it might first look!
@@ -997,7 +1033,7 @@ namespace OpenRA
if (!unProjected.Any())
{
// Adjust V until we find a cell that works
for (var x = 2; x <= 2 * MaximumTerrainHeight; x++)
for (var x = 2; x <= 2 * Grid.MaximumTerrainHeight; x++)
{
var dv = ((x & 1) == 1 ? 1 : -1) * x / 2;
var test = new PPos(projected.U, projected.V + dv);
@@ -1028,7 +1064,7 @@ namespace OpenRA
public CPos ChooseRandomCell(MersenneTwister rand)
{
MPos[] cells;
List<MPos> cells;
do
{
var u = rand.Next(Bounds.Left, Bounds.Right);
@@ -1037,12 +1073,12 @@ namespace OpenRA
cells = Unproject(new PPos(u, v));
} while (!cells.Any());
return cells.Random(rand).ToCPos(TileShape);
return cells.Random(rand).ToCPos(Grid.Type);
}
public CPos ChooseClosestEdgeCell(CPos cell)
{
return ChooseClosestEdgeCell(cell.ToMPos(TileShape)).ToCPos(TileShape);
return ChooseClosestEdgeCell(cell.ToMPos(Grid.Type)).ToCPos(Grid.Type);
}
public MPos ChooseClosestEdgeCell(MPos uv)
@@ -1068,7 +1104,7 @@ namespace OpenRA
if (!unProjected.Any())
{
// Adjust V until we find a cell that works
for (var x = 2; x <= 2 * MaximumTerrainHeight; x++)
for (var x = 2; x <= 2 * Grid.MaximumTerrainHeight; x++)
{
var dv = ((x & 1) == 1 ? 1 : -1) * x / 2;
var test = new PPos(edge.U, edge.V + dv);
@@ -1093,7 +1129,7 @@ namespace OpenRA
public CPos ChooseRandomEdgeCell(MersenneTwister rand)
{
MPos[] cells;
List<MPos> cells;
do
{
var isU = rand.Next(2) == 0;
@@ -1104,7 +1140,7 @@ namespace OpenRA
cells = Unproject(new PPos(u, v));
} while (!cells.Any());
return cells.Random(rand).ToCPos(TileShape);
return cells.Random(rand).ToCPos(Grid.Type);
}
public WDist DistanceToEdge(WPos pos, WVec dir)

View File

@@ -23,7 +23,7 @@ namespace OpenRA
{
public sealed class MapCache : IEnumerable<MapPreview>, IDisposable
{
public static readonly MapPreview UnknownMap = new MapPreview(null, null);
public static readonly MapPreview UnknownMap = new MapPreview(null, MapGridType.Rectangular, null);
readonly Cache<string, MapPreview> previews;
readonly ModData modData;
readonly SheetBuilder sheetBuilder;
@@ -35,7 +35,9 @@ namespace OpenRA
public MapCache(ModData modData)
{
this.modData = modData;
previews = new Cache<string, MapPreview>(uid => new MapPreview(uid, this));
var gridType = Exts.Lazy(() => modData.Manifest.Get<MapGrid>().Type);
previews = new Cache<string, MapPreview>(uid => new MapPreview(uid, gridType.Value, this));
sheetBuilder = new SheetBuilder(SheetType.BGRA);
}

View File

@@ -0,0 +1,45 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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.Drawing;
using System.IO;
namespace OpenRA
{
public enum MapGridType { Rectangular, RectangularIsometric }
public class MapGrid : IGlobalModData
{
public readonly MapGridType Type = MapGridType.Rectangular;
public readonly Size TileSize = new Size(24, 24);
public readonly byte MaximumTerrainHeight = 0;
public readonly byte SubCellDefaultIndex = byte.MaxValue;
public readonly WVec[] SubCellOffsets =
{
new WVec(0, 0, 0), // full cell - index 0
new WVec(-299, -256, 0), // top left - index 1
new WVec(256, -256, 0), // top right - index 2
new WVec(0, 0, 0), // center - index 3
new WVec(-299, 256, 0), // bottom left - index 4
new WVec(256, 256, 0), // bottom right - index 5
};
public MapGrid(MiniYaml yaml)
{
FieldLoader.Load(this, yaml);
// The default subcell index defaults to the middle entry
if (SubCellDefaultIndex == byte.MaxValue)
SubCellDefaultIndex = (byte)(SubCellOffsets.Length / 2);
else if (SubCellDefaultIndex < (SubCellOffsets.Length > 1 ? 1 : 0) || SubCellDefaultIndex >= SubCellOffsets.Length)
throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells");
}
}
}

View File

@@ -28,8 +28,8 @@ namespace OpenRA
public MapPlayers(Ruleset rules, int playerCount)
{
var firstRace = rules.Actors["world"].Traits
.WithInterface<FactionInfo>().First(f => f.Selectable).InternalName;
var firstFaction = rules.Actors["world"].TraitInfos<FactionInfo>()
.First(f => f.Selectable).InternalName;
Players = new Dictionary<string, PlayerReference>
{
@@ -37,7 +37,7 @@ namespace OpenRA
"Neutral", new PlayerReference
{
Name = "Neutral",
Faction = firstRace,
Faction = firstFaction,
OwnsWorld = true,
NonCombatant = true
}
@@ -46,7 +46,7 @@ namespace OpenRA
"Creeps", new PlayerReference
{
Name = "Creeps",
Faction = firstRace,
Faction = firstFaction,
NonCombatant = true,
Enemies = Exts.MakeArray(playerCount, i => "Multi{0}".F(i))
}

View File

@@ -47,6 +47,7 @@ namespace OpenRA
public readonly int players;
public readonly Rectangle bounds;
public readonly int[] spawnpoints = { };
public readonly MapGridType map_grid_type;
public readonly string minimap;
public readonly bool downloading;
}
@@ -62,6 +63,7 @@ namespace OpenRA
public string Author { get; private set; }
public int PlayerCount { get; private set; }
public CPos[] SpawnPoints { get; private set; }
public MapGridType GridType { get; private set; }
public Rectangle Bounds { get; private set; }
public Bitmap CustomPreview { get; private set; }
public Map Map { get; private set; }
@@ -97,7 +99,7 @@ namespace OpenRA
generatingMinimap = false;
}
public MapPreview(string uid, MapCache cache)
public MapPreview(string uid, MapGridType gridType, MapCache cache)
{
this.cache = cache;
Uid = uid;
@@ -107,6 +109,7 @@ namespace OpenRA
PlayerCount = 0;
Bounds = Rectangle.Empty;
SpawnPoints = NoSpawns;
GridType = gridType;
Status = MapStatus.Unavailable;
Class = MapClassification.Unknown;
}
@@ -120,6 +123,7 @@ namespace OpenRA
Author = m.Author;
Bounds = m.Bounds;
SpawnPoints = m.SpawnPoints.Value;
GridType = m.Grid.Type;
CustomPreview = m.CustomPreview;
Status = MapStatus.Available;
Class = classification;
@@ -179,6 +183,7 @@ namespace OpenRA
for (var j = 0; j < r.spawnpoints.Length; j += 2)
spawns[j / 2] = new CPos(r.spawnpoints[j], r.spawnpoints[j + 1]);
SpawnPoints = spawns;
GridType = r.map_grid_type;
CustomPreview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap)));
}
@@ -210,20 +215,22 @@ namespace OpenRA
// Request the filename from the server
// Run in a worker thread to avoid network delays
var mapUrl = Game.Settings.Game.MapRepository + Uid;
var mapPath = string.Empty;
try
{
var request = WebRequest.Create(mapUrl);
request.Method = "HEAD";
var res = request.GetResponse();
// Map not found
if (res.Headers["Content-Disposition"] == null)
using (var res = request.GetResponse())
{
Status = MapStatus.DownloadError;
return;
}
// Map not found
if (res.Headers["Content-Disposition"] == null)
{
Status = MapStatus.DownloadError;
return;
}
var mapPath = Path.Combine(baseMapPath, res.Headers["Content-Disposition"].Replace("attachment; filename = ", ""));
mapPath = Path.Combine(baseMapPath, res.Headers["Content-Disposition"].Replace("attachment; filename = ", ""));
}
Action<DownloadProgressChangedEventArgs> onDownloadProgress = i => { DownloadBytes = i.BytesReceived; DownloadPercentage = i.ProgressPercentage; };
Action<AsyncCompletedEventArgs, bool> onDownloadComplete = (i, cancelled) =>

View File

@@ -8,10 +8,8 @@
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace OpenRA
{
@@ -41,8 +39,9 @@ namespace OpenRA
// The bottom edge is trickier: cells at MPos.V > bottomRight.V may have
// been projected into this region if they have height > 0.
// Each height step is equivalent to 512 WRange units, which is one MPos
// step for diamond cells, but only half a MPos step for classic cells. Doh!
var heightOffset = map.TileShape == TileShape.Diamond ? map.MaximumTerrainHeight : map.MaximumTerrainHeight / 2;
// step for isometric cells, but only half a MPos step for classic cells. Doh!
var maxHeight = map.Grid.MaximumTerrainHeight;
var heightOffset = map.Grid.Type == MapGridType.RectangularIsometric ? maxHeight : maxHeight / 2;
// Use the MapHeight data array to clamp the bottom coordinate so it doesn't overflow the map
mapBottomRight = map.MapHeight.Value.Clamp(new MPos(bottomRight.U, bottomRight.V + heightOffset));

View File

@@ -49,8 +49,8 @@ namespace OpenRA
static readonly TerrainTypeInfo Default = new TerrainTypeInfo();
public readonly string Type;
public readonly string[] TargetTypes = { };
public readonly string[] AcceptsSmudgeType = { };
public readonly HashSet<string> TargetTypes = new HashSet<string>();
public readonly HashSet<string> AcceptsSmudgeType = new HashSet<string>();
public readonly bool IsWater = false; // TODO: Remove this
public readonly Color Color;
public readonly string CustomCursor;
@@ -74,7 +74,7 @@ namespace OpenRA
public readonly bool PickAny;
public readonly string Category;
TerrainTileInfo[] tileInfo;
readonly TerrainTileInfo[] tileInfo;
public TerrainTemplateInfo(ushort id, string[] images, int2 size, byte[] tiles)
{
@@ -171,13 +171,13 @@ namespace OpenRA
public readonly int SheetSize = 512;
public readonly string Palette;
public readonly string PlayerPalette;
public readonly int WaterPaletteRotationBase = 0x60;
public readonly Color[] HeightDebugColors = new[] { Color.Red };
public readonly string[] EditorTemplateOrder;
public readonly bool IgnoreTileSpriteOffsets;
public readonly bool EnableDepth = false;
[FieldLoader.Ignore]
public readonly Dictionary<ushort, TerrainTemplateInfo> Templates = new Dictionary<ushort, TerrainTemplateInfo>();
public readonly IReadOnlyDictionary<ushort, TerrainTemplateInfo> Templates;
[FieldLoader.Ignore]
public readonly TerrainTypeInfo[] TerrainInfo;
@@ -217,7 +217,7 @@ namespace OpenRA
// Templates
Templates = yaml["Templates"].ToDictionary().Values
.Select(y => new TerrainTemplateInfo(this, y)).ToDictionary(t => t.Id);
.Select(y => new TerrainTemplateInfo(this, y)).ToDictionary(t => t.Id).AsReadOnly();
}
public TileSet(string name, string id, string palette, TerrainTypeInfo[] terrainInfo)

View File

@@ -74,11 +74,6 @@ namespace OpenRA
SpriteSequenceLoader = (ISpriteSequenceLoader)ctor.Invoke(new[] { this });
SpriteSequenceLoader.OnMissingSpriteError = s => Log.Write("debug", s);
// HACK: Mount only local folders so we have a half-working environment for the asset installer
GlobalFileSystem.UnmountAll();
foreach (var dir in Manifest.Folders)
GlobalFileSystem.Mount(dir);
defaultRules = Exts.Lazy(() => RulesetCache.Load());
initialThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
@@ -92,6 +87,11 @@ namespace OpenRA
LoadScreen.Display();
}
public void MountFiles()
{
GlobalFileSystem.LoadFromManifest(Manifest);
}
public void InitializeLoaders()
{
// all this manipulation of static crap here is nasty and breaks
@@ -171,6 +171,11 @@ namespace OpenRA
using (new Support.PerfTimer("Map.SequenceProvider.Preload"))
map.SequenceProvider.Preload();
// Load music with map assets mounted
using (new Support.PerfTimer("Map.Music"))
foreach (var entry in map.Rules.Music)
entry.Value.Load();
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequenceDefinitions);
VoxelLoader.Finish();

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -24,6 +25,7 @@ namespace OpenRA
public string Version;
public string Author;
public bool Hidden;
public ContentInstaller Content;
static Dictionary<string, ModMetadata> ValidateMods()
{
@@ -34,19 +36,30 @@ namespace OpenRA
var ret = new Dictionary<string, ModMetadata>();
foreach (var m in mods)
{
var yamlPath = Platform.ResolvePath(".", "mods", m, "mod.yaml");
if (!File.Exists(yamlPath))
continue;
try
{
var yamlPath = Platform.ResolvePath(".", "mods", m, "mod.yaml");
if (!File.Exists(yamlPath))
continue;
var yaml = new MiniYaml(null, MiniYaml.FromFile(yamlPath));
var nd = yaml.ToDictionary();
if (!nd.ContainsKey("Metadata"))
continue;
var yaml = new MiniYaml(null, MiniYaml.FromFile(yamlPath));
var nd = yaml.ToDictionary();
if (!nd.ContainsKey("Metadata"))
continue;
var mod = FieldLoader.Load<ModMetadata>(nd["Metadata"]);
mod.Id = m;
var mod = FieldLoader.Load<ModMetadata>(nd["Metadata"]);
mod.Id = m;
ret.Add(m, mod);
if (nd.ContainsKey("ContentInstaller"))
mod.Content = FieldLoader.Load<ContentInstaller>(nd["ContentInstaller"]);
ret.Add(m, mod);
}
catch (Exception ex)
{
Console.WriteLine("An exception occured when trying to load ModMetadata for `{0}`:".F(m));
Console.WriteLine(ex.Message);
}
}
return ret;

View File

@@ -19,6 +19,11 @@ namespace OpenRA.Network
{
public int Client;
public Order Order;
public override string ToString()
{
return "ClientId: {0} {1}".F(Client, Order);
}
}
readonly Dictionary<int, int> clientQuitTimes = new Dictionary<int, int>();

View File

@@ -72,7 +72,7 @@ namespace OpenRA
var subjectId = r.ReadUInt32();
var flags = (OrderFields)r.ReadByte();
var targetActorId = flags.HasField(OrderFields.TargetActor) ? r.ReadUInt32() : 0xffffffff;
var targetActorId = flags.HasField(OrderFields.TargetActor) ? r.ReadUInt32() : uint.MaxValue;
var targetLocation = (CPos)(flags.HasField(OrderFields.TargetLocation) ? r.ReadInt2() : int2.Zero);
var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null;
var queued = flags.HasField(OrderFields.Queued);
@@ -104,28 +104,20 @@ namespace OpenRA
static uint UIntFromActor(Actor a)
{
if (a == null) return 0xffffffff;
if (a == null) return uint.MaxValue;
return a.ActorID;
}
static bool TryGetActorFromUInt(World world, uint aID, out Actor ret)
{
if (aID == 0xFFFFFFFF)
if (aID == uint.MaxValue)
{
ret = null;
return true;
}
else
{
foreach (var a in world.Actors.Where(x => x.ActorID == aID))
{
ret = a;
return true;
}
ret = null;
return false;
}
ret = world.GetActorById(aID);
return ret != null;
}
// Named constructors for Orders.

View File

@@ -35,14 +35,13 @@ namespace OpenRA.Network
return ret;
}
public static byte[] SerializeSync(this List<int> sync)
public static byte[] SerializeSync(int sync)
{
var ms = new MemoryStream();
using (var writer = new BinaryWriter(ms))
{
writer.Write((byte)0x65);
foreach (var s in sync)
writer.Write(s);
writer.Write(sync);
}
return ms.ToArray();

View File

@@ -43,8 +43,6 @@ namespace OpenRA.Network
public bool GameStarted { get { return NetFrameNumber != 0; } }
public IConnection Connection { get; private set; }
public readonly int SyncHeaderSize = 9;
List<Order> localOrders = new List<Order>();
List<ChatLine> chatCache = new List<ChatLine>();
@@ -53,16 +51,12 @@ namespace OpenRA.Network
bool disposed;
static void OutOfSync(int frame)
void OutOfSync(int frame)
{
syncReport.DumpSyncReport(frame, frameData.OrdersForFrame(World, frame));
throw new InvalidOperationException("Out of sync in frame {0}.\n Compare syncreport.log with other players.".F(frame));
}
static void OutOfSync(int frame, string blame)
{
throw new InvalidOperationException("Out of sync in frame {0}: Blame {1}.\n Compare syncreport.log with other players.".F(frame, blame));
}
public void StartGame()
{
if (GameStarted) return;
@@ -145,41 +139,16 @@ namespace OpenRA.Network
if (syncForFrame.TryGetValue(frame, out existingSync))
{
if (packet.Length != existingSync.Length)
{
syncReport.DumpSyncReport(frame);
OutOfSync(frame);
}
else
{
for (var i = 0; i < packet.Length; i++)
{
if (packet[i] != existingSync[i])
{
syncReport.DumpSyncReport(frame);
if (i < SyncHeaderSize)
OutOfSync(frame, "Tick");
else
OutOfSync(frame, (i - SyncHeaderSize) / 4);
}
}
}
OutOfSync(frame);
}
else
syncForFrame.Add(frame, packet);
}
void OutOfSync(int frame, int index)
{
var orders = frameData.OrdersForFrame(World, frame);
// Invalid index
if (index >= orders.Count())
OutOfSync(frame);
throw new InvalidOperationException("Out of sync in frame {0}.\n {1}\n Compare syncreport.log with other players.".F(frame, orders.ElementAt(index).Order.ToString()));
}
public bool IsReadyForNextFrame
{
get { return NetFrameNumber >= 1 && frameData.IsReadyForFrame(NetFrameNumber); }
@@ -204,17 +173,10 @@ namespace OpenRA.Network
Connection.Send(NetFrameNumber + FramesAhead, localOrders.Select(o => o.Serialize()).ToList());
localOrders.Clear();
var sync = new List<int>();
sync.Add(World.SyncHash());
foreach (var order in frameData.OrdersForFrame(World, NetFrameNumber))
{
UnitOrders.ProcessOrder(this, World, order.Client, order.Order);
sync.Add(World.SyncHash());
}
var ss = sync.SerializeSync();
Connection.SendSync(NetFrameNumber, ss);
Connection.SendSync(NetFrameNumber, OrderIO.SerializeSync(World.SyncHash()));
syncReport.UpdateSyncReport();

View File

@@ -27,6 +27,7 @@ namespace OpenRA.Network
Queue<Chunk> chunks = new Queue<Chunk>();
List<byte[]> sync = new List<byte[]>();
int ordersFrame;
Dictionary<int, int> lastClientsFrame = new Dictionary<int, int>();
public int LocalClientId { get { return 0; } }
public ConnectionState ConnectionState { get { return ConnectionState.Connected; } }
@@ -55,6 +56,10 @@ namespace OpenRA.Network
var frame = BitConverter.ToInt32(packet, 0);
chunk.Packets.Add(Pair.New(client, packet));
if (frame != int.MaxValue &&
(!lastClientsFrame.ContainsKey(client) || frame > lastClientsFrame[client]))
lastClientsFrame[client] = frame;
if (packet.Length == 5 && packet[4] == 0xBF)
continue; // disconnect
else if (packet.Length >= 5 && packet[4] == 0x65)
@@ -81,6 +86,31 @@ namespace OpenRA.Network
TickCount = Math.Max(TickCount, frame);
}
}
var lastClientToDisconnect = lastClientsFrame.MaxBy(kvp => kvp.Value).Key;
// 2nd parse : replace all disconnect packets without frame with real
// disconnect frame
// NOTE: to modify/remove if a reconnect feature is set
foreach (var tmpChunk in chunks)
{
foreach (var tmpPacketPair in tmpChunk.Packets)
{
var client = tmpPacketPair.First;
// Don't replace the final disconnection packet - we still want this to end the replay.
if (client == lastClientToDisconnect)
continue;
var packet = tmpPacketPair.Second;
if (packet.Length == 5 && packet[4] == 0xBF)
{
var lastClientFrame = lastClientsFrame[client];
var lastFramePacket = BitConverter.GetBytes(lastClientFrame);
Array.Copy(lastFramePacket, packet, lastFramePacket.Length);
}
}
}
}
ordersFrame = LobbyInfo.GlobalSettings.OrderLatency;

View File

@@ -59,9 +59,13 @@ namespace OpenRA.Network
return session;
}
catch (InvalidOperationException e)
catch (YamlException)
{
throw new InvalidOperationException("Session deserialized invalid MiniYaml:\n{0}".F(data), e);
throw new YamlException("Session deserialized invalid MiniYaml:\n{0}".F(data));
}
catch (InvalidOperationException)
{
throw new YamlException("Session deserialized invalid MiniYaml:\n{0}".F(data));
}
}
@@ -102,13 +106,13 @@ namespace OpenRA.Network
public int Index;
public HSLColor PreferredColor; // Color that the client normally uses from settings.yaml.
public HSLColor Color; // Actual color that the client is using. Usually the same as PreferredColor but can be different on maps with locked colors.
public string Race;
public string Faction;
public int SpawnPoint;
public string Name;
public string IpAddress;
public ClientState State = ClientState.Invalid;
public int Team;
public string Slot; // slot ID, or null for observer
public string Slot; // Slot ID, or null for observer
public string Bot; // Bot type, null for real clients
public int BotControllerClientIndex; // who added the bot to the slot
public bool IsAdmin;
@@ -118,7 +122,7 @@ namespace OpenRA.Network
public MiniYamlNode Serialize()
{
return new MiniYamlNode("Client@{0}".F(this.Index), FieldSaver.Save(this));
return new MiniYamlNode("Client@{0}".F(Index), FieldSaver.Save(this));
}
}
@@ -141,17 +145,17 @@ namespace OpenRA.Network
public MiniYamlNode Serialize()
{
return new MiniYamlNode("ClientPing@{0}".F(this.Index), FieldSaver.Save(this));
return new MiniYamlNode("ClientPing@{0}".F(Index), FieldSaver.Save(this));
}
}
public class Slot
{
public string PlayerReference; // playerReference to bind against.
public bool Closed; // host has explicitly closed this slot.
public string PlayerReference; // PlayerReference to bind against.
public bool Closed; // Host has explicitly closed this slot.
public bool AllowBots;
public bool LockRace;
public bool LockFaction;
public bool LockColor;
public bool LockTeam;
public bool LockSpawn;
@@ -164,7 +168,7 @@ namespace OpenRA.Network
public MiniYamlNode Serialize()
{
return new MiniYamlNode("Slot@{0}".F(this.PlayerReference), FieldSaver.Save(this));
return new MiniYamlNode("Slot@{0}".F(PlayerReference), FieldSaver.Save(this));
}
}
@@ -172,6 +176,7 @@ namespace OpenRA.Network
{
public string ServerName;
public string Map;
public int Timestep = 40;
public int OrderLatency = 3; // net tick frames (x 120 = ms)
public int RandomSeed = 0;
public bool FragileAlliances = false; // Allow diplomatic stance changes after game start.
@@ -187,6 +192,7 @@ namespace OpenRA.Network
public int StartingCash = 5000;
public string TechLevel = "none";
public string StartingUnitsClass = "none";
public string GameSpeedType = "default";
public bool ShortGame = true;
public bool AllowVersionMismatch;
public string GameUid;

View File

@@ -95,7 +95,7 @@ namespace OpenRA.Network
}
}
internal void DumpSyncReport(int frame)
internal void DumpSyncReport(int frame, IEnumerable<FrameData.ClientOrder> orders)
{
foreach (var r in syncReports)
{
@@ -128,6 +128,10 @@ namespace OpenRA.Network
Log.Write("sync", "\t\t {0}: {1}".F(nvp.First[i], nvp.Second[i]));
}
Log.Write("sync", "Orders Issued:");
foreach (var o in orders)
Log.Write("sync", "\t {0}", o.ToString());
return;
}
}

View File

@@ -161,7 +161,7 @@ namespace OpenRA.Network
Name = Game.Settings.Player.Name,
PreferredColor = Game.Settings.Player.Color,
Color = Game.Settings.Player.Color,
Race = "Random",
Faction = "Random",
SpawnPoint = 0,
Team = 0,
State = Session.ClientState.Invalid

View File

@@ -84,8 +84,8 @@
<HintPath>..\thirdparty\download\MaxMind.Db.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SDL2-CS">
<HintPath>..\thirdparty\download\SDL2-CS.dll</HintPath>
<Reference Include="SmarIrc4net">
<HintPath>..\thirdparty\download\SmarIrc4net.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
@@ -98,7 +98,9 @@
<Compile Include="LogProxy.cs" />
<Compile Include="FileFormats\IdxReader.cs" />
<Compile Include="FileSystem\BagFile.cs" />
<Compile Include="Map\MapGrid.cs" />
<Compile Include="Map\MapPlayers.cs" />
<Compile Include="ContentInstaller.cs" />
<Compile Include="MPos.cs" />
<Compile Include="Graphics\QuadRenderer.cs" />
<Compile Include="Download.cs" />
@@ -120,7 +122,6 @@
<Compile Include="Graphics\LineRenderer.cs" />
<Compile Include="Graphics\MappedImage.cs" />
<Compile Include="Graphics\Minimap.cs" />
<Compile Include="Graphics\Renderer.cs" />
<Compile Include="Graphics\SequenceProvider.cs" />
<Compile Include="Graphics\Sheet.cs" />
<Compile Include="Graphics\SheetBuilder.cs" />
@@ -171,7 +172,6 @@
<Compile Include="TraitDictionary.cs" />
<Compile Include="Traits\DrawLineToTarget.cs" />
<Compile Include="Traits\EditorTilesetFilter.cs" />
<Compile Include="Traits\Health.cs" />
<Compile Include="Traits\LintAttributes.cs" />
<Compile Include="Traits\RejectsOrders.cs" />
<Compile Include="Traits\Player\DeveloperMode.cs" />
@@ -196,7 +196,6 @@
<Compile Include="Graphics\VoxelRenderer.cs" />
<Compile Include="Graphics\VoxelLoader.cs" />
<Compile Include="Graphics\VoxelProvider.cs" />
<Compile Include="Traits\BodyOrientation.cs" />
<Compile Include="Graphics\VoxelAnimation.cs" />
<Compile Include="Traits\Player\FrozenActorLayer.cs" />
<Compile Include="Graphics\Theater.cs" />
@@ -228,8 +227,6 @@
<Compile Include="Graphics\IGraphicsDevice.cs" />
<Compile Include="Sound\Sound.cs" />
<Compile Include="Sound\SoundDevice.cs" />
<Compile Include="Sound\OpenAlSound.cs" />
<Compile Include="Sound\NullSound.cs" />
<Compile Include="Effects\SpriteEffect.cs" />
<Compile Include="Graphics\SelectionBarsRenderable.cs" />
<Compile Include="Graphics\TargetLineRenderable.cs" />
@@ -249,6 +246,11 @@
<Compile Include="Graphics\TerrainSpriteLayer.cs" />
<Compile Include="Map\ProjectedCellRegion.cs" />
<Compile Include="Map\MapCoordsRegion.cs" />
<Compile Include="Renderer.cs" />
<Compile Include="Platform.cs" />
<Compile Include="GameSpeed.cs" />
<Compile Include="GlobalChat.cs" />
<Compile Include="Primitives\ObservableList.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="FileSystem\D2kSoundResources.cs" />
@@ -298,7 +300,6 @@
<Compile Include="Support\PerfTimer.cs" />
<Compile Include="Exts.cs" />
<Compile Include="MiniYaml.cs" />
<Compile Include="Platform.cs" />
<Compile Include="StreamExts.cs" />
<Compile Include="Map\Map.cs" />
<Compile Include="Map\MapCache.cs" />

View File

@@ -13,19 +13,19 @@ using OpenRA.Graphics;
namespace OpenRA.Orders
{
public class GenericSelectTarget : IOrderGenerator
public class GenericSelectTarget : UnitOrderGenerator
{
readonly IEnumerable<Actor> subjects;
readonly string order;
readonly string cursor;
readonly MouseButton expectedButton;
protected readonly IEnumerable<Actor> Subjects;
protected readonly string OrderName;
protected readonly string Cursor;
protected readonly MouseButton ExpectedButton;
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor, MouseButton button)
{
this.subjects = subjects;
this.order = order;
this.cursor = cursor;
expectedButton = button;
Subjects = subjects;
OrderName = order;
Cursor = cursor;
ExpectedButton = button;
}
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor)
@@ -37,26 +37,23 @@ namespace OpenRA.Orders
public GenericSelectTarget(Actor subject, string order, string cursor, MouseButton button)
: this(new Actor[] { subject }, order, cursor, button) { }
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
public override IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
if (mi.Button != expectedButton)
if (mi.Button != ExpectedButton)
world.CancelInputMode();
return OrderInner(world, xy, mi);
}
IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
protected virtual IEnumerable<Order> OrderInner(World world, CPos xy, MouseInput mi)
{
if (mi.Button == expectedButton && world.Map.Contains(xy))
if (mi.Button == ExpectedButton && world.Map.Contains(xy))
{
world.CancelInputMode();
foreach (var subject in subjects)
yield return new Order(order, subject, false) { TargetLocation = xy };
foreach (var subject in Subjects)
yield return new Order(OrderName, subject, false) { TargetLocation = xy };
}
}
public virtual void Tick(World world) { }
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.Contains(xy) ? cursor : "generic-blocked"; }
public override string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.Contains(xy) ? Cursor : "generic-blocked"; }
}
}

View File

@@ -15,12 +15,12 @@ using OpenRA.Traits;
namespace OpenRA.Orders
{
class UnitOrderGenerator : IOrderGenerator
public class UnitOrderGenerator : IOrderGenerator
{
public IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
public virtual IEnumerable<Order> Order(World world, CPos xy, MouseInput mi)
{
var underCursor = world.ScreenMap.ActorsAt(mi)
.Where(a => !world.FogObscures(a) && a.HasTrait<ITargetable>())
.Where(a => !world.FogObscures(a) && a.Info.HasTraitInfo<ITargetableInfo>())
.WithHighestSelectionPriority();
Target target;
@@ -29,7 +29,7 @@ namespace OpenRA.Orders
else
{
var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, mi)
.Where(a => a.Info.Traits.Contains<ITargetableInfo>() && !a.Footprint.All(world.ShroudObscures))
.Where(a => a.Info.HasTraitInfo<ITargetableInfo>() && a.Visible && a.HasRenderables)
.WithHighestSelectionPriority();
target = frozen != null ? Target.FromFrozenActor(frozen) : Target.FromCell(world, xy);
}
@@ -50,20 +50,20 @@ namespace OpenRA.Orders
yield return CheckSameOrder(o.Order, o.Trait.IssueOrder(o.Actor, o.Order, o.Target, mi.Modifiers.HasModifier(Modifiers.Shift)));
}
public void Tick(World world) { }
public IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public virtual void Tick(World world) { }
public virtual IEnumerable<IRenderable> Render(WorldRenderer wr, World world) { yield break; }
public virtual IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { yield break; }
public string GetCursor(World world, CPos xy, MouseInput mi)
public virtual string GetCursor(World world, CPos xy, MouseInput mi)
{
var useSelect = false;
var underCursor = world.ScreenMap.ActorsAt(mi)
.Where(a => !world.FogObscures(a) && a.HasTrait<ITargetable>())
.Where(a => !world.FogObscures(a) && a.Info.HasTraitInfo<ITargetableInfo>())
.WithHighestSelectionPriority();
if (underCursor != null && (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any()))
{
if (underCursor.HasTrait<Selectable>())
if (underCursor.Info.HasTraitInfo<SelectableInfo>())
useSelect = true;
}
@@ -73,7 +73,7 @@ namespace OpenRA.Orders
else
{
var frozen = world.ScreenMap.FrozenActorsAt(world.RenderPlayer, mi)
.Where(a => a.Info.Traits.Contains<ITargetableInfo>() && !a.Footprint.All(world.ShroudObscures))
.Where(a => a.Info.HasTraitInfo<ITargetableInfo>() && a.Visible && a.HasRenderables)
.WithHighestSelectionPriority();
target = frozen != null ? Target.FromFrozenActor(frozen) : Target.FromCell(world, xy);
}
@@ -119,7 +119,7 @@ namespace OpenRA.Orders
.Select(x => new { Trait = trait, Order = x }))
.OrderByDescending(x => x.Order.OrderPriority))
{
var actorsAt = self.World.ActorMap.GetUnitsAt(self.World.Map.CellContaining(target.CenterPosition)).ToList();
var actorsAt = self.World.ActorMap.GetActorsAt(self.World.Map.CellContaining(target.CenterPosition)).ToList();
var modifiers = TargetModifiers.None;
if (mi.Modifiers.HasModifier(Modifiers.Ctrl))
@@ -130,7 +130,7 @@ namespace OpenRA.Orders
modifiers |= TargetModifiers.ForceMove;
string cursor = null;
if (o.Order.CanTarget(self, target, actorsAt, modifiers, ref cursor))
if (o.Order.CanTarget(self, target, actorsAt, ref modifiers, ref cursor))
return new UnitOrderResult(self, o.Order, o.Trait, cursor, target);
}
}

View File

@@ -53,8 +53,8 @@ namespace OpenRA
static FactionInfo ChooseFaction(World world, string name, bool requireSelectable = true)
{
var selectableFactions = world.Map.Rules.Actors["world"].Traits
.WithInterface<FactionInfo>().Where(f => !requireSelectable || f.Selectable)
var selectableFactions = world.Map.Rules.Actors["world"].TraitInfos<FactionInfo>()
.Where(f => !requireSelectable || f.Selectable)
.ToList();
var selected = selectableFactions.FirstOrDefault(f => f.InternalName == name)
@@ -75,7 +75,7 @@ namespace OpenRA
static FactionInfo ChooseDisplayFaction(World world, string factionName)
{
var factions = world.Map.Rules.Actors["world"].Traits.WithInterface<FactionInfo>().ToArray();
var factions = world.Map.Rules.Actors["world"].TraitInfos<FactionInfo>().ToArray();
return factions.FirstOrDefault(f => f.InternalName == factionName) ?? factions.First();
}
@@ -95,8 +95,8 @@ namespace OpenRA
Color = client.Color;
PlayerName = client.Name;
botType = client.Bot;
Faction = ChooseFaction(world, client.Race, !pr.LockFaction);
DisplayFaction = ChooseDisplayFaction(world, client.Race);
Faction = ChooseFaction(world, client.Faction, !pr.LockFaction);
DisplayFaction = ChooseDisplayFaction(world, client.Faction);
}
else
{
@@ -154,24 +154,18 @@ namespace OpenRA
public bool CanViewActor(Actor a)
{
if (a.TraitsImplementing<IVisibilityModifier>().Any(t => !t.IsVisible(a, this)))
return false;
return a.Trait<IDefaultVisibility>().IsVisible(a, this);
return a.CanBeViewedByPlayer(this);
}
public bool CanTargetActor(Actor a)
{
if (HasFogVisibility)
if (HasFogVisibility && fogVisibilities.Any(f => f.IsVisible(a)))
return true;
if (a.TraitsImplementing<IVisibilityModifier>().Any(t => !t.IsVisible(a, this)))
return false;
return a.Trait<IDefaultVisibility>().IsVisible(a, this);
return CanViewActor(a);
}
public bool HasFogVisibility { get { return fogVisibilities.Any(f => f.HasFogVisibility(this)); } }
public bool HasFogVisibility { get { return fogVisibilities.Any(f => f.HasFogVisibility()); } }
#region Scripting interface

View File

@@ -9,6 +9,7 @@
#endregion
using System;
using System.Collections.Generic;
namespace OpenRA.Primitives
{
@@ -17,37 +18,56 @@ namespace OpenRA.Primitives
/// </summary>
public class ActionQueue
{
object syncRoot = new object();
PriorityQueue<DelayedAction> actions = new PriorityQueue<DelayedAction>();
readonly List<DelayedAction> actions = new List<DelayedAction>();
public void Add(Action a) { Add(a, 0); }
public void Add(Action a, int delay)
public void Add(Action a, int desiredTime)
{
lock (syncRoot)
actions.Add(new DelayedAction(a, Game.RunTime + delay));
if (a == null)
throw new ArgumentNullException("a");
lock (actions)
{
var action = new DelayedAction(a, desiredTime);
var index = Index(action);
actions.Insert(index, action);
}
}
public void PerformActions()
public void PerformActions(int currentTime)
{
Action a = () => { };
lock (syncRoot)
DelayedAction[] pendingActions;
lock (actions)
{
var t = Game.RunTime;
while (!actions.Empty && actions.Peek().Time <= t)
{
var da = actions.Pop();
a = da.Action + a;
}
var dummyAction = new DelayedAction(null, currentTime);
var index = Index(dummyAction);
if (index <= 0)
return;
pendingActions = new DelayedAction[index];
actions.CopyTo(0, pendingActions, 0, index);
actions.RemoveRange(0, index);
}
a();
foreach (var delayedAction in pendingActions)
delayedAction.Action();
}
int Index(DelayedAction action)
{
// Returns the index of the next action with a strictly greater time.
var index = actions.BinarySearch(action);
if (index < 0)
return ~index;
while (index < actions.Count && action.CompareTo(actions[index]) >= 0)
index++;
return index;
}
}
struct DelayedAction : IComparable<DelayedAction>
{
public int Time;
public Action Action;
public readonly int Time;
public readonly Action Action;
public DelayedAction(Action action, int time)
{
@@ -59,5 +79,10 @@ namespace OpenRA.Primitives
{
return Time.CompareTo(other.Time);
}
public override string ToString()
{
return "Time: " + Time + " Action: " + Action;
}
}
}

View File

@@ -0,0 +1,118 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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;
using System.Collections.Generic;
namespace OpenRA.Primitives
{
public class ObservableList<T> : IList<T>, IObservableCollection
{
protected IList<T> innerList;
public event Action<object> OnAdd = k => { };
public event Action<object> OnRemove = k => { };
// TODO Workaround for https://github.com/OpenRA/OpenRA/issues/6101
#pragma warning disable 67
public event Action<int> OnRemoveAt = i => { };
public event Action<object, object> OnSet = (o, n) => { };
#pragma warning restore
public event Action OnRefresh = () => { };
protected void FireOnRefresh()
{
OnRefresh();
}
public ObservableList()
{
innerList = new List<T>();
}
public virtual void Add(T item)
{
innerList.Add(item);
OnAdd(item);
}
public bool Remove(T item)
{
var found = innerList.Remove(item);
if (found)
OnRemove(item);
return found;
}
public void Clear()
{
innerList.Clear();
OnRefresh();
}
public void Insert(int index, T item)
{
innerList.Insert(index, item);
OnRefresh();
}
public int Count { get { return innerList.Count; } }
public int IndexOf(T item) { return innerList.IndexOf(item); }
public bool Contains(T item) { return innerList.Contains(item); }
public void RemoveAt(int index)
{
innerList.RemoveAt(index);
OnRemoveAt(index);
}
public T this[int index]
{
get
{
return innerList[index];
}
set
{
var oldValue = innerList[index];
innerList[index] = value;
OnSet(oldValue, value);
}
}
public void CopyTo(T[] array, int arrayIndex)
{
innerList.CopyTo(array, arrayIndex);
}
public IEnumerator<T> GetEnumerator()
{
return innerList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return innerList.GetEnumerator();
}
public IEnumerable ObservedItems
{
get { return innerList; }
}
public bool IsReadOnly
{
get { return innerList.IsReadOnly; }
}
}
}

View File

@@ -13,9 +13,10 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using OpenRA.Graphics;
using OpenRA.Support;
namespace OpenRA.Graphics
namespace OpenRA
{
public sealed class Renderer : IDisposable
{
@@ -49,7 +50,7 @@ namespace OpenRA.Graphics
var resolution = GetResolution(graphicSettings);
var rendererName = serverSettings.Dedicated ? "Null" : graphicSettings.Renderer;
var rendererPath = Platform.ResolvePath(".", "OpenRA.Renderer." + rendererName + ".dll");
var rendererPath = Platform.ResolvePath(".", "OpenRA.Platforms." + rendererName + ".dll");
Device = CreateDevice(Assembly.LoadFile(rendererPath), resolution.Width, resolution.Height, graphicSettings.Mode);
@@ -79,12 +80,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 platformDll, int width, int height, WindowMode window)
{
foreach (RendererAttribute r in rendererDll.GetCustomAttributes(typeof(RendererAttribute), false))
foreach (PlatformAttribute r in platformDll.GetCustomAttributes(typeof(PlatformAttribute), false))
{
var factory = (IDeviceFactory)r.Type.GetConstructor(Type.EmptyTypes).Invoke(null);
return factory.Create(new Size(width, height), window);
return factory.CreateGraphics(new Size(width, height), window);
}
throw new InvalidOperationException("Renderer DLL is missing RendererAttribute to tell us what type to use!");
@@ -160,11 +161,6 @@ namespace OpenRA.Graphics
DrawBatch(tempBuffer, 0, numVertices, type);
}
public Bitmap TakeScreenshot()
{
return Device.TakeScreenshot();
}
public void DrawBatch<T>(IVertexBuffer<T> vertices,
int firstVertex, int numVertices, PrimitiveType type)
where T : struct

View File

@@ -254,9 +254,9 @@ namespace OpenRA.Scripting
static readonly object[] NoArguments = new object[0];
Type[] FilterActorCommands(ActorInfo ai)
{
var method = typeof(TypeDictionary).GetMethod("Contains");
var method = typeof(ActorInfo).GetMethod("HasTraitInfo");
return knownActorCommands.Where(c => ExtractRequiredTypes(c)
.All(t => (bool)method.MakeGenericMethod(t).Invoke(ai.Traits, NoArguments)))
.All(t => (bool)method.MakeGenericMethod(t).Invoke(ai, NoArguments)))
.ToArray();
}

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Traits
{
public static int SelectionPriority(this ActorInfo a)
{
var selectableInfo = a.Traits.GetOrDefault<SelectableInfo>();
var selectableInfo = a.TraitInfoOrDefault<SelectableInfo>();
return selectableInfo != null ? selectableInfo.Priority : int.MinValue;
}
@@ -26,7 +26,7 @@ namespace OpenRA.Traits
public static int SelectionPriority(this Actor a)
{
var basePriority = a.Info.Traits.Get<SelectableInfo>().Priority;
var basePriority = a.Info.TraitInfo<SelectableInfo>().Priority;
var lp = a.World.LocalPlayer;
if (a.Owner == lp || lp == null)

View File

@@ -75,7 +75,7 @@ namespace OpenRA
if (actor.Owner != world.LocalPlayer || !actor.IsInWorld)
continue;
var selectable = actor.Info.Traits.GetOrDefault<SelectableInfo>();
var selectable = actor.Info.TraitInfoOrDefault<SelectableInfo>();
if (selectable == null || !actor.HasVoice(selectable.Voice))
continue;

View File

@@ -73,7 +73,7 @@ namespace OpenRA.Server
return;
if (pr.LockFaction)
c.Race = pr.Faction;
c.Faction = pr.Faction;
if (pr.LockSpawn)
c.SpawnPoint = pr.Spawn;
if (pr.LockTeam)
@@ -308,7 +308,7 @@ namespace OpenRA.Server
Slot = LobbyInfo.FirstEmptySlot(),
PreferredColor = handshake.Client.Color,
Color = handshake.Client.Color,
Race = "Random",
Faction = "Random",
SpawnPoint = 0,
Team = 0,
State = Session.ClientState.Invalid,
@@ -372,6 +372,9 @@ namespace OpenRA.Server
SyncLobbyInfo();
Log.Write("server", "{0} ({1}) has joined the game.",
client.Name, newConn.Socket.RemoteEndPoint);
if (!LobbyInfo.IsSinglePlayer)
SendMessage("{0} has joined the game.".F(client.Name));
@@ -408,7 +411,19 @@ namespace OpenRA.Server
void SetOrderLag()
{
LobbyInfo.GlobalSettings.OrderLatency = LobbyInfo.IsSinglePlayer ? 1 : 3;
int latency = 1;
if (!LobbyInfo.IsSinglePlayer)
{
var gameSpeeds = Game.ModData.Manifest.Get<GameSpeeds>();
GameSpeed speed;
if (gameSpeeds.Speeds.TryGetValue(LobbyInfo.GlobalSettings.GameSpeedType, out speed))
latency = speed.OrderLatency;
else
latency = 3;
}
LobbyInfo.GlobalSettings.OrderLatency = latency;
SyncLobbyGlobalSettings();
}

View File

@@ -19,7 +19,7 @@ using OpenRA.Traits;
namespace OpenRA
{
public enum MouseScrollType { Disabled, Standard, Inverted }
public enum MouseScrollType { Disabled, Standard, Inverted, Joystick }
public class ServerSettings
{
@@ -72,7 +72,7 @@ namespace OpenRA
[Desc("Disallow AI bots.")]
public bool LockBots = false;
public string TimestampFormat = "HH:mm";
public string TimestampFormat = "s";
public ServerSettings() { }
@@ -111,7 +111,7 @@ namespace OpenRA
public class GraphicSettings
{
public string Renderer = "Sdl2";
public string Renderer = "Default";
public WindowMode Mode = WindowMode.PseudoFullscreen;
public int2 FullscreenSize = new int2(0, 0);
public int2 WindowedSize = new int2(1024, 768);
@@ -139,7 +139,7 @@ namespace OpenRA
public bool Shuffle = false;
public bool Repeat = false;
public string Engine = "AL";
public string Engine = "Default";
public string Device = null;
public bool CashTicks = true;
@@ -167,6 +167,7 @@ namespace OpenRA
public float ViewportEdgeScrollStep = 10f;
public float UIScrollSpeed = 50f;
public int SelectionDeadzone = 24;
public int JoystickScrollDeadzone = 8;
public bool UseClassicMouseStyle = false;
public bool AlwaysShowStatusBars = false;
@@ -178,7 +179,6 @@ namespace OpenRA
public bool FetchNews = true;
public string NewsUrl = "http://www.openra.net/gamenews";
public DateTime NewsFetchedDate;
}
public class KeySettings
@@ -189,6 +189,11 @@ namespace OpenRA
public Hotkey SelectAllUnitsKey = new Hotkey(Keycode.Q, Modifiers.None);
public Hotkey SelectUnitsByTypeKey = new Hotkey(Keycode.W, Modifiers.None);
public Hotkey MapScrollUp = new Hotkey(Keycode.UP, Modifiers.None);
public Hotkey MapScrollDown = new Hotkey(Keycode.DOWN, Modifiers.None);
public Hotkey MapScrollLeft = new Hotkey(Keycode.LEFT, Modifiers.None);
public Hotkey MapScrollRight = new Hotkey(Keycode.RIGHT, Modifiers.None);
public Hotkey PauseKey = new Hotkey(Keycode.PAUSE, Modifiers.None);
public Hotkey PlaceBeaconKey = new Hotkey(Keycode.B, Modifiers.None);
public Hotkey SellKey = new Hotkey(Keycode.Z, Modifiers.None);
@@ -288,6 +293,17 @@ namespace OpenRA
}
}
public class ChatSettings
{
public string Hostname = "irc.openra.net";
public int Port = 6667;
public string Channel = "lobby";
public string Nickname = "Newbie";
public string QuitMessage = "Battle control terminated!";
public string TimestampFormat = "HH:mm";
public bool ConnectAutomatically = false;
}
public class Settings
{
string settingsFile;
@@ -299,6 +315,7 @@ namespace OpenRA
public ServerSettings Server = new ServerSettings();
public DebugSettings Debug = new DebugSettings();
public KeySettings Keys = new KeySettings();
public ChatSettings Chat = new ChatSettings();
public Dictionary<string, object> Sections;
@@ -314,6 +331,7 @@ namespace OpenRA
{ "Server", Server },
{ "Debug", Debug },
{ "Keys", Keys },
{ "Chat", Chat }
};
// Override fieldloader to ignore invalid entries
@@ -381,7 +399,7 @@ namespace OpenRA
public static string SanitizedPlayerName(string dirty)
{
var forbiddenNames = new string[] { "Open", "Closed" };
var botNames = OpenRA.Game.ModData.DefaultRules.Actors["player"].Traits.WithInterface<IBotInfo>().Select(t => t.Name);
var botNames = OpenRA.Game.ModData.DefaultRules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name);
var clean = SanitizedName(dirty);

View File

@@ -11,26 +11,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using OpenRA.FileFormats;
using OpenRA.FileSystem;
using OpenRA.GameRules;
using OpenRA.Primitives;
using OpenRA.Traits;
using OpenTK;
using OpenTK.Audio.OpenAL;
namespace OpenRA
{
public static class Sound
public sealed class Sound : IDisposable
{
static ISoundEngine soundEngine;
static Cache<string, ISoundSource> sounds;
static ISoundSource rawSource;
static ISound music;
static ISound video;
static MusicInfo currentMusic;
readonly ISoundEngine soundEngine;
Cache<string, ISoundSource> sounds;
ISoundSource rawSource;
ISound music;
ISound video;
MusicInfo currentMusic;
static ISoundSource LoadSound(string filename)
public Sound(string engineName)
{
var enginePath = Platform.ResolvePath(".", "OpenRA.Platforms." + engineName + ".dll");
soundEngine = CreateDevice(Assembly.LoadFile(enginePath));
}
static ISoundEngine CreateDevice(Assembly platformDll)
{
foreach (PlatformAttribute r in platformDll.GetCustomAttributes(typeof(PlatformAttribute), false))
{
var factory = (IDeviceFactory)r.Type.GetConstructor(Type.EmptyTypes).Invoke(null);
return factory.CreateSound();
}
throw new InvalidOperationException("Platform DLL is missing PlatformAttribute to tell us what type to use!");
}
ISoundSource LoadSound(string filename)
{
if (!GlobalFileSystem.Exists(filename))
{
@@ -46,35 +62,17 @@ namespace OpenRA
return LoadSoundRaw(AudLoader.LoadSound(s), 1, 16, 22050);
}
static ISoundSource LoadWave(WavLoader wave)
ISoundSource LoadWave(WavLoader wave)
{
return soundEngine.AddSoundSourceFromMemory(wave.RawOutput, wave.Channels, wave.BitsPerSample, wave.SampleRate);
}
static ISoundSource LoadSoundRaw(byte[] rawData, int channels, int sampleBits, int sampleRate)
ISoundSource LoadSoundRaw(byte[] rawData, int channels, int sampleBits, int sampleRate)
{
return soundEngine.AddSoundSourceFromMemory(rawData, channels, sampleBits, sampleRate);
}
static ISoundEngine CreateEngine(string engine)
{
engine = Game.Settings.Server.Dedicated ? "Null" : engine;
switch (engine)
{
case "AL": return new OpenAlSoundEngine();
case "Null": return new NullSoundEngine();
default:
throw new InvalidOperationException("Unsupported sound engine: {0}".F(engine));
}
}
public static void Create(string engine)
{
soundEngine = CreateEngine(engine);
}
public static void Initialize()
public void Initialize()
{
sounds = new Cache<string, ISoundSource>(LoadSound);
music = null;
@@ -82,26 +80,23 @@ namespace OpenRA
video = null;
}
public static SoundDevice[] AvailableDevices()
public SoundDevice[] AvailableDevices()
{
var defaultDevices = new[]
{
new SoundDevice("AL", null, "Default Output"),
new SoundDevice("Default", null, "Default Output"),
new SoundDevice("Null", null, "Output Disabled")
};
var devices = OpenAlSoundEngine.AvailableDevices()
.Select(d => new SoundDevice("AL", d, d));
return defaultDevices.Concat(devices).ToArray();
return defaultDevices.Concat(soundEngine.AvailableDevices()).ToArray();
}
public static void SetListenerPosition(WPos position)
public void SetListenerPosition(WPos position)
{
soundEngine.SetListenerPosition(position);
}
static ISound Play(Player player, string name, bool headRelative, WPos pos, float volumeModifier = 1f, bool loop = false)
ISound Play(Player player, string name, bool headRelative, WPos pos, float volumeModifier = 1f, bool loop = false)
{
if (string.IsNullOrEmpty(name))
return null;
@@ -113,45 +108,45 @@ namespace OpenRA
InternalSoundVolume * volumeModifier, true);
}
public static void StopAudio()
public void StopAudio()
{
soundEngine.StopAllSounds();
}
public static ISound Play(string name) { return Play(null, name, true, WPos.Zero, 1f); }
public static ISound Play(string name, WPos pos) { return Play(null, name, false, pos, 1f); }
public static ISound Play(string name, float volumeModifier) { return Play(null, name, true, WPos.Zero, volumeModifier); }
public static ISound Play(string name, WPos pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); }
public static ISound PlayToPlayer(Player player, string name) { return Play(player, name, true, WPos.Zero, 1f); }
public static ISound PlayToPlayer(Player player, string name, WPos pos) { return Play(player, name, false, pos, 1f); }
public static ISound PlayLooped(string name) { return PlayLooped(name, WPos.Zero); }
public static ISound PlayLooped(string name, WPos pos) { return Play(null, name, true, pos, 1f, true); }
public ISound Play(string name) { return Play(null, name, true, WPos.Zero, 1f); }
public ISound Play(string name, WPos pos) { return Play(null, name, false, pos, 1f); }
public ISound Play(string name, float volumeModifier) { return Play(null, name, true, WPos.Zero, volumeModifier); }
public ISound Play(string name, WPos pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); }
public ISound PlayToPlayer(Player player, string name) { return Play(player, name, true, WPos.Zero, 1f); }
public ISound PlayToPlayer(Player player, string name, WPos pos) { return Play(player, name, false, pos, 1f); }
public ISound PlayLooped(string name) { return PlayLooped(name, WPos.Zero); }
public ISound PlayLooped(string name, WPos pos) { return Play(null, name, true, pos, 1f, true); }
public static void PlayVideo(byte[] raw, int channels, int sampleBits, int sampleRate)
public void PlayVideo(byte[] raw, int channels, int sampleBits, int sampleRate)
{
rawSource = LoadSoundRaw(raw, channels, sampleBits, sampleRate);
video = soundEngine.Play2D(rawSource, false, true, WPos.Zero, InternalSoundVolume, false);
}
public static void PlayVideo()
public void PlayVideo()
{
if (video != null)
soundEngine.PauseSound(video, false);
}
public static void PauseVideo()
public void PauseVideo()
{
if (video != null)
soundEngine.PauseSound(video, true);
}
public static void StopVideo()
public void StopVideo()
{
if (video != null)
soundEngine.StopSound(video);
}
public static void Tick()
public void Tick()
{
// Song finished
if (MusicPlaying && !music.Playing)
@@ -161,16 +156,16 @@ namespace OpenRA
}
}
static Action onMusicComplete;
public static bool MusicPlaying { get; private set; }
public static MusicInfo CurrentMusic { get { return currentMusic; } }
Action onMusicComplete;
public bool MusicPlaying { get; private set; }
public MusicInfo CurrentMusic { get { return currentMusic; } }
public static void PlayMusic(MusicInfo m)
public void PlayMusic(MusicInfo m)
{
PlayMusicThen(m, () => { });
}
public static void PlayMusicThen(MusicInfo m, Action then)
public void PlayMusicThen(MusicInfo m, Action then)
{
if (m == null || !m.Exists)
return;
@@ -195,7 +190,7 @@ namespace OpenRA
MusicPlaying = true;
}
public static void PlayMusic()
public void PlayMusic()
{
if (music == null)
return;
@@ -204,13 +199,13 @@ namespace OpenRA
soundEngine.PauseSound(music, false);
}
public static void StopSound(ISound sound)
public void StopSound(ISound sound)
{
if (sound != null)
soundEngine.StopSound(sound);
}
public static void StopMusic()
public void StopMusic()
{
if (music != null)
soundEngine.StopSound(music);
@@ -219,7 +214,7 @@ namespace OpenRA
currentMusic = null;
}
public static void PauseMusic()
public void PauseMusic()
{
if (music == null)
return;
@@ -228,14 +223,14 @@ namespace OpenRA
soundEngine.PauseSound(music, true);
}
public static float GlobalVolume
public float GlobalVolume
{
get { return soundEngine.Volume; }
set { soundEngine.Volume = value; }
}
static float soundVolumeModifier = 1.0f;
public static float SoundVolumeModifier
float soundVolumeModifier = 1.0f;
public float SoundVolumeModifier
{
get
{
@@ -249,8 +244,8 @@ namespace OpenRA
}
}
static float InternalSoundVolume { get { return SoundVolume * soundVolumeModifier; } }
public static float SoundVolume
float InternalSoundVolume { get { return SoundVolume * soundVolumeModifier; } }
public float SoundVolume
{
get
{
@@ -264,7 +259,7 @@ namespace OpenRA
}
}
public static float MusicVolume
public float MusicVolume
{
get
{
@@ -279,7 +274,7 @@ namespace OpenRA
}
}
public static float VideoVolume
public float VideoVolume
{
get
{
@@ -294,18 +289,18 @@ namespace OpenRA
}
}
public static float MusicSeekPosition
public float MusicSeekPosition
{
get { return music != null ? music.SeekPosition : 0; }
}
public static float VideoSeekPosition
public float VideoSeekPosition
{
get { return video != null ? video.SeekPosition : 0; }
}
// Returns true if played successfully
public static bool PlayPredefined(Ruleset ruleset, Player p, Actor voicedActor, string type, string definition, string variant,
public bool PlayPredefined(Ruleset ruleset, Player p, Actor voicedActor, string type, string definition, string variant,
bool relative, WPos pos, float volumeModifier, bool attenuateVolume)
{
if (ruleset == null)
@@ -363,7 +358,7 @@ namespace OpenRA
return true;
}
public static bool PlayNotification(Ruleset rules, Player player, string type, string notification, string variant)
public bool PlayNotification(Ruleset rules, Player player, string type, string notification, string variant)
{
if (rules == null)
throw new ArgumentNullException("rules");
@@ -373,5 +368,10 @@ namespace OpenRA
return PlayPredefined(rules, player, null, type.ToLowerInvariant(), notification, variant, true, WPos.Zero, 1f, false);
}
public void Dispose()
{
soundEngine.Dispose();
}
}
}

View File

@@ -8,10 +8,13 @@
*/
#endregion
using System;
namespace OpenRA
{
interface ISoundEngine
public interface ISoundEngine : IDisposable
{
SoundDevice[] AvailableDevices();
ISoundSource AddSoundSourceFromMemory(byte[] data, int channels, int sampleBits, int sampleRate);
ISound Play2D(ISoundSource sound, bool loop, bool relative, WPos pos, float volume, bool attenuateVolume);
float Volume { get; set; }
@@ -41,7 +44,7 @@ namespace OpenRA
}
}
interface ISoundSource { }
public interface ISoundSource { }
public interface ISound
{

View File

@@ -61,6 +61,18 @@ namespace OpenRA
catch (IOException) { }
}
public static void Write(string channel, string value)
{
ChannelInfo info;
if (!Channels.TryGetValue(channel, out info))
throw new Exception("Tried logging to non-existant channel " + channel);
if (info.Writer == null)
return;
info.Writer.WriteLine(value);
}
public static void Write(string channel, string format, params object[] args)
{
ChannelInfo info;

View File

@@ -55,6 +55,12 @@ namespace OpenRA
Log.Write("exception", "{0} Mod at Version {1}", mod.Title, mod.Version);
}
if (Game.OrderManager != null && Game.OrderManager.World != null && Game.OrderManager.World.Map != null)
{
var map = Game.OrderManager.World.Map;
Log.Write("exception", "on map {0} ({1} by {2}).", map.Uid, map.Title, map.Author);
}
Log.Write("exception", "Operating System: {0} ({1})", Platform.CurrentPlatform, Environment.OSVersion);
Log.Write("exception", "Runtime Version: {0}", Platform.RuntimeVersion);
var rpt = BuildExceptionReport(e).ToString();

View File

@@ -84,12 +84,6 @@ namespace OpenRA
throw new InvalidOperationException("Attempted to get trait from destroyed object ({0})".F(actor));
}
public bool Contains<T>(Actor actor)
{
CheckDestroyed(actor);
return InnerGet<T>().GetMultiple(actor.ActorID).Any();
}
public T Get<T>(Actor actor)
{
CheckDestroyed(actor);

View File

@@ -8,12 +8,14 @@
*/
#endregion
using System.Collections.Generic;
namespace OpenRA.Traits
{
public class EditorTilesetFilterInfo : TraitInfo<EditorTilesetFilter>
{
public readonly string[] RequireTilesets = null;
public readonly string[] ExcludeTilesets = null;
public readonly HashSet<string> RequireTilesets = null;
public readonly HashSet<string> ExcludeTilesets = null;
}
public class EditorTilesetFilter { }

View File

@@ -43,4 +43,30 @@ namespace OpenRA.Traits
[AttributeUsage(AttributeTargets.Field)]
public sealed class UpgradeUsedReferenceAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Field)]
public sealed class PaletteDefinitionAttribute : Attribute
{
public readonly bool IsPlayerPalette;
public PaletteDefinitionAttribute(bool isPlayerPalette = false)
{
IsPlayerPalette = isPlayerPalette;
}
}
[AttributeUsage(AttributeTargets.Field)]
public sealed class PaletteReferenceAttribute : Attribute
{
public readonly bool IsPlayerPalette;
public PaletteReferenceAttribute(bool isPlayerPalette = false)
{
IsPlayerPalette = isPlayerPalette;
}
public readonly string PlayerPaletteReferenceSwitch;
public PaletteReferenceAttribute(string playerPaletteReferenceSwitch)
{
PlayerPaletteReferenceSwitch = playerPaletteReferenceSwitch;
}
}
}

View File

@@ -23,6 +23,7 @@ namespace OpenRA.Traits
public bool BuildAnywhere;
public bool ShowCombatGeometry;
public bool ShowDebugGeometry;
public bool ShowDepthPreview;
public object Create(ActorInitializer init) { return new DeveloperMode(this); }
}
@@ -41,6 +42,8 @@ namespace OpenRA.Traits
// Client side only
public bool ShowCombatGeometry;
public bool ShowDebugGeometry;
public bool ShowDepthPreview;
public bool EnableAll;
public DeveloperMode(DeveloperModeInfo info)
@@ -54,6 +57,7 @@ namespace OpenRA.Traits
BuildAnywhere = info.BuildAnywhere;
ShowCombatGeometry = info.ShowCombatGeometry;
ShowDebugGeometry = info.ShowDebugGeometry;
ShowDepthPreview = info.ShowDepthPreview;
}
public void ResolveOrder(Actor self, Order order)
@@ -123,7 +127,7 @@ namespace OpenRA.Traits
break;
}
case "DevShroudDisable":
case "DevVisibility":
{
DisableShroud ^= true;
self.Owner.Shroud.Disabled = DisableShroud;

View File

@@ -16,15 +16,20 @@ namespace OpenRA.Traits
public class FixedColorPaletteInfo : ITraitInfo
{
[Desc("The name of the palette to base off.")]
public readonly string Base = "terrain";
[PaletteReference] public readonly string Base = "terrain";
[Desc("The name of the resulting palette")]
public readonly string Name = "resources";
[PaletteDefinition] public readonly string Name = "resources";
[Desc("Remap these indices to pre-defined colors.")]
public readonly int[] RemapIndex = { };
[Desc("The fixed color to remap.")]
public readonly HSLColor Color;
[Desc("Luminosity range to span.")]
public readonly float Ramp = 0.05f;
[Desc("Allow palette modifiers to change the palette.")]
public readonly bool AllowModifiers = true;

View File

@@ -27,6 +27,8 @@ namespace OpenRA.Traits
public readonly PPos[] Footprint;
public readonly WPos CenterPosition;
public readonly Rectangle Bounds;
public readonly HashSet<string> TargetTypes;
readonly IRemoveFrozenActor[] removeFrozenActors;
readonly Actor actor;
readonly Shroud shroud;
@@ -39,13 +41,19 @@ namespace OpenRA.Traits
public DamageState DamageState;
public bool Visible = true;
public bool NeedRenderables;
public bool IsRendering { get; private set; }
public bool Shrouded { get; private set; }
public bool NeedRenderables { get; set; }
public IRenderable[] Renderables = NoRenderables;
static readonly IRenderable[] NoRenderables = new IRenderable[0];
public FrozenActor(Actor self, PPos[] footprint, Shroud shroud)
int flashTicks;
public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevealed)
{
actor = self;
this.shroud = shroud;
NeedRenderables = startsRevealed;
removeFrozenActors = self.TraitsImplementing<IRemoveFrozenActor>().ToArray();
// Consider all cells inside the map area (ignoring the current map bounds)
Footprint = footprint
@@ -54,6 +62,7 @@ namespace OpenRA.Traits
CenterPosition = self.CenterPosition;
Bounds = self.Bounds;
TargetTypes = self.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes).ToHashSet();
UpdateVisibility();
}
@@ -63,11 +72,6 @@ namespace OpenRA.Traits
public ActorInfo Info { get { return actor.Info; } }
public Actor Actor { get { return !actor.IsDead ? actor : null; } }
static readonly IRenderable[] NoRenderables = new IRenderable[0];
int flashTicks;
IRenderable[] renderables = NoRenderables;
public void Tick()
{
UpdateVisibility();
@@ -79,22 +83,25 @@ namespace OpenRA.Traits
void UpdateVisibility()
{
var wasVisible = Visible;
var isVisibleTest = shroud.IsVisibleTest;
Shrouded = true;
// We are doing the following LINQ manually for performance since this is a hot path.
// Visible = !Footprint.Any(isVisibleTest);
// Visible = !Footprint.Any(shroud.IsVisible);
Visible = true;
foreach (var uv in Footprint)
foreach (var puv in Footprint)
{
if (isVisibleTest(uv))
if (shroud.IsVisible(puv))
{
Visible = false;
Shrouded = false;
break;
}
if (Shrouded && shroud.IsExplored(puv))
Shrouded = false;
}
if (Visible && !wasVisible)
NeedRenderables = true;
NeedRenderables = Visible && !wasVisible;
}
public void Flash()
@@ -104,28 +111,30 @@ namespace OpenRA.Traits
public IEnumerable<IRenderable> Render(WorldRenderer wr)
{
if (NeedRenderables)
{
NeedRenderables = false;
if (!actor.Disposed)
{
IsRendering = true;
renderables = actor.Render(wr).ToArray();
IsRendering = false;
}
}
if (Shrouded)
return NoRenderables;
if (flashTicks > 0 && flashTicks % 2 == 0)
{
var highlight = wr.Palette("highlight");
return renderables.Concat(renderables.Where(r => !r.IsDecoration)
return Renderables.Concat(Renderables.Where(r => !r.IsDecoration)
.Select(r => r.WithPalette(highlight)));
}
return renderables;
return Renderables;
}
public bool HasRenderables { get { return renderables.Any(); } }
public bool HasRenderables { get { return !Shrouded && Renderables.Any(); } }
public bool ShouldBeRemoved(Player owner)
{
// We use a loop here for performance reasons
foreach (var rfa in removeFrozenActors)
if (rfa.RemoveActor(actor, owner))
return true;
return false;
}
public override string ToString()
{
@@ -140,7 +149,7 @@ namespace OpenRA.Traits
readonly World world;
readonly Player owner;
Dictionary<uint, FrozenActor> frozen;
readonly Dictionary<uint, FrozenActor> frozen;
public FrozenActorLayer(Actor self)
{
@@ -161,6 +170,8 @@ namespace OpenRA.Traits
VisibilityHash = 0;
FrozenHash = 0;
// TODO: Track shroud updates using Shroud.CellsChanged
// and then only tick FrozenActors that might have changed
foreach (var kvp in frozen)
{
var hash = (int)kvp.Key;
@@ -169,7 +180,9 @@ namespace OpenRA.Traits
var frozenActor = kvp.Value;
frozenActor.Tick();
if (frozenActor.Visible)
if (frozenActor.ShouldBeRemoved(owner))
remove.Add(kvp.Key);
else if (frozenActor.Visible)
VisibilityHash += hash;
else if (frozenActor.Actor == null)
remove.Add(kvp.Key);

View File

@@ -17,13 +17,17 @@ namespace OpenRA.Traits
public class PlayerColorPaletteInfo : ITraitInfo
{
[Desc("The name of the palette to base off.")]
public readonly string BasePalette = null;
[PaletteReference] public readonly string BasePalette = null;
[Desc("The prefix for the resulting player palettes")]
public readonly string BaseName = "player";
[PaletteDefinition(true)] public readonly string BaseName = "player";
[Desc("Remap these indices to player colors.")]
public readonly int[] RemapIndex = { };
[Desc("Luminosity range to span.")]
public readonly float Ramp = 0.05f;
[Desc("Allow palette modifiers to change the palette.")]
public readonly bool AllowModifiers = true;

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Traits
public class PlayerHighlightPaletteInfo : ITraitInfo
{
[Desc("The prefix for the resulting player palettes")]
public readonly string BaseName = "highlight";
[PaletteDefinition(true)] public readonly string BaseName = "highlight";
public object Create(ActorInitializer init) { return new PlayerHighlightPalette(this); }
}

View File

@@ -145,7 +145,7 @@ namespace OpenRA.Traits
{
if (Resources > 0.8 * ResourceCapacity)
{
Sound.PlayNotification(self.World.Map.Rules, owner, "Speech", "SilosNeeded", owner.Faction.InternalName);
Game.Sound.PlayNotification(self.World.Map.Rules, owner, "Speech", "SilosNeeded", owner.Faction.InternalName);
AlertSilo = true;
}
else
@@ -187,14 +187,14 @@ namespace OpenRA.Traits
public void PlayCashTickUp(Actor self)
{
if (Game.Settings.Sound.CashTicks)
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickUp", self.Owner.Faction.InternalName);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickUp", self.Owner.Faction.InternalName);
}
public void PlayCashTickDown(Actor self)
{
if (Game.Settings.Sound.CashTicks && nextCashTickTime == 0)
{
Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickDown", self.Owner.Faction.InternalName);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", "CashTickDown", self.Owner.Faction.InternalName);
nextCashTickTime = 2;
}
}

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System.Collections.Generic;
using System.Linq;
namespace OpenRA.Traits
@@ -16,14 +17,14 @@ namespace OpenRA.Traits
public class RejectsOrdersInfo : ITraitInfo
{
[Desc("Possible values include Attack, AttackMove, Guard, Move.")]
public readonly string[] Except = { };
public readonly HashSet<string> Except = new HashSet<string>();
public object Create(ActorInitializer init) { return new RejectsOrders(this); }
}
public class RejectsOrders
{
public string[] Except { get { return info.Except; } }
public HashSet<string> Except { get { return info.Except; } }
readonly RejectsOrdersInfo info;

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Traits
TargetType type;
Actor actor;
ITargetable targetable;
IEnumerable<ITargetable> targetable;
FrozenActor frozen;
WPos pos;
int generation;
@@ -48,7 +48,7 @@ namespace OpenRA.Traits
return new Target
{
actor = a,
targetable = a.TraitOrDefault<ITargetable>(),
targetable = a.TraitsImplementing<ITargetable>(),
type = TargetType.Actor,
generation = a.Generation,
};
@@ -83,15 +83,18 @@ namespace OpenRA.Traits
if (targeter == null || Type == TargetType.Invalid)
return false;
if (targetable != null && !targetable.TargetableBy(actor, targeter))
var targeted = this.actor;
if (targeted != null && !targetable.Any(t => t.IsTraitEnabled() && t.TargetableBy(targeted, targeter)))
return false;
return true;
}
// Currently all or nothing.
// TODO: either replace based on target type or put in singleton trait
public bool RequiresForceFire
{
get { return targetable != null && targetable.RequiresForceFire; }
get { return targetable != null && targetable.Any(Exts.IsTraitEnabled) && targetable.Where(Exts.IsTraitEnabled).All(t => t.RequiresForceFire); }
}
// Representative position - see Positions for the full set of targetable positions.
@@ -123,12 +126,19 @@ namespace OpenRA.Traits
switch (Type)
{
case TargetType.Actor:
var targetable = actor.TraitOrDefault<ITargetable>();
if (targetable == null)
var targetable = actor.TraitsImplementing<ITargetable>().Where(Exts.IsTraitEnabled);
if (!targetable.Any())
return new[] { actor.CenterPosition };
var positions = targetable.TargetablePositions(actor);
return positions.Any() ? positions : new[] { actor.CenterPosition };
var targetablePositions = actor.TraitOrDefault<ITargetablePositions>();
if (targetablePositions != null)
{
var positions = targetablePositions.TargetablePositions(actor);
if (positions.Any())
return positions;
}
return new[] { actor.CenterPosition };
case TargetType.FrozenActor:
return new[] { frozen.CenterPosition };
case TargetType.Terrain:

View File

@@ -19,6 +19,20 @@ using OpenRA.Primitives;
namespace OpenRA.Traits
{
public enum DamageState { Undamaged, Light, Medium, Heavy, Critical, Dead }
public interface IHealth
{
DamageState DamageState { get; }
int HP { get; }
int MaxHP { get; }
int DisplayHP { get; }
bool IsDead { get; }
void InflictDamage(Actor self, Actor attacker, int damage, IWarhead warhead, bool ignoreModifiers);
void Kill(Actor self, Actor attacker);
}
// depends on the order of pips in WorldRenderer.cs!
public enum PipType { Transparent, Green, Yellow, Red, Gray, Blue, Ammo, AmmoEmpty }
public enum TagType { None, Fake, Primary }
@@ -83,7 +97,7 @@ namespace OpenRA.Traits
{
string OrderID { get; }
int OrderPriority { get; }
bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, TargetModifiers modifiers, ref string cursor);
bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor);
bool IsQueued { get; }
bool OverrideSelection { get; }
}
@@ -115,7 +129,7 @@ namespace OpenRA.Traits
public interface ISeedableResource { void Seed(Actor self); }
public interface ISelectionDecorationsInfo
public interface ISelectionDecorationsInfo : ITraitInfo
{
int[] SelectionBoxBounds { get; }
}
@@ -128,7 +142,7 @@ namespace OpenRA.Traits
bool HasVoice(Actor self, string voice);
}
public interface IDemolishableInfo { bool IsValidTarget(ActorInfo actorInfo, Actor saboteur); }
public interface IDemolishableInfo : ITraitInfo { bool IsValidTarget(ActorInfo actorInfo, Actor saboteur); }
public interface IDemolishable
{
void Demolish(Actor self, Actor saboteur);
@@ -144,13 +158,13 @@ namespace OpenRA.Traits
Player Owner { get; }
}
public interface IToolTip
public interface ITooltip
{
ITooltipInfo TooltipInfo { get; }
Player Owner { get; }
}
public interface ITooltipInfo
public interface ITooltipInfo : ITraitInfo
{
string TooltipForPlayerStance(Stance stance);
bool IsOwnerRowVisible { get; }
@@ -172,10 +186,15 @@ namespace OpenRA.Traits
IEnumerable<Pair<CPos, Color>> RadarSignatureCells(Actor self);
}
public interface IDefaultVisibilityInfo { }
public interface IDefaultVisibilityInfo : ITraitInfo { }
public interface IDefaultVisibility { bool IsVisible(Actor self, Player byPlayer); }
public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); }
public interface IFogVisibilityModifier { bool HasFogVisibility(Player byPlayer); }
public interface IFogVisibilityModifier
{
bool IsVisible(Actor actor);
bool HasFogVisibility();
}
public interface IRadarColorModifier { Color RadarColorOverride(Actor self); }
@@ -218,6 +237,8 @@ namespace OpenRA.Traits
public interface IFirepowerModifier { int GetFirepowerModifier(); }
public interface IReloadModifier { int GetReloadModifier(); }
public interface IInaccuracyModifier { int GetInaccuracyModifier(); }
public interface IRangeModifier { int GetRangeModifier(); }
public interface IRangeModifierInfo : ITraitInfo { int GetRangeModifierDefault(); }
public interface IPowerModifier { int GetPowerModifier(); }
public interface ILoadsPalettes { void LoadPalettes(WorldRenderer wr); }
public interface ILoadsPlayerPalettes { void LoadPlayerPalettes(WorldRenderer wr, string playerName, HSLColor playerColor, bool replaceExisting); }
@@ -226,6 +247,7 @@ namespace OpenRA.Traits
public interface ITags { IEnumerable<TagType> GetTags(); }
public interface ISelectionBar { float GetValue(); Color GetColor(); }
public interface IPositionableInfo : ITraitInfo { }
public interface IPositionable : IOccupySpace
{
bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any);
@@ -268,7 +290,7 @@ namespace OpenRA.Traits
{
void OnCrush(Actor crusher);
void WarnCrush(Actor crusher);
bool CrushableBy(string[] crushClasses, Player owner);
bool CrushableBy(HashSet<string> crushClasses, Player owner);
}
public interface ITraitInfo { object Create(ActorInitializer init); }
@@ -278,14 +300,14 @@ namespace OpenRA.Traits
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1302:InterfaceNamesMustBeginWithI", Justification = "Not a real interface, but more like a tag.")]
public interface Requires<T> where T : class, ITraitInfo { }
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1302:InterfaceNamesMustBeginWithI", Justification = "Not a real interface, but more like a tag.")]
public interface UsesInit<T> where T : IActorInit { }
public interface UsesInit<T> : ITraitInfo where T : IActorInit { }
public interface INotifySelected { void Selected(Actor self); }
public interface INotifySelection { void SelectionChanged(); }
public interface IWorldLoaded { void WorldLoaded(World w, WorldRenderer wr); }
public interface ICreatePlayers { void CreatePlayers(World w); }
public interface IBotInfo { string Name { get; } }
public interface IBotInfo : ITraitInfo { string Name { get; } }
public interface IBot
{
void Activate(Player p);
@@ -296,7 +318,6 @@ namespace OpenRA.Traits
public interface INotifyBecomingIdle { void OnBecomingIdle(Actor self); }
public interface INotifyIdle { void TickIdle(Actor self); }
public interface IBlocksProjectiles { }
public interface IRenderInfantrySequenceModifier
{
bool IsModifyingSequence { get; }
@@ -304,46 +325,38 @@ namespace OpenRA.Traits
}
public interface IPostRender { void RenderAfterWorld(WorldRenderer wr, Actor self); }
public interface IRenderShroud { void RenderShroud(WorldRenderer wr, Shroud shroud); }
public interface IPostRenderSelection { IEnumerable<IRenderable> RenderAfterWorld(WorldRenderer wr); }
public interface IBodyOrientation
public interface ITargetableInfo : ITraitInfo
{
WAngle CameraPitch { get; }
int QuantizedFacings { get; }
WVec LocalToWorld(WVec vec);
WRot QuantizeOrientation(Actor self, WRot orientation);
}
public interface IBodyOrientationInfo : ITraitInfo
{
WVec LocalToWorld(WVec vec);
WRot QuantizeOrientation(WRot orientation, int facings);
}
public interface IQuantizeBodyOrientationInfo { int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race); }
public interface ITargetableInfo
{
string[] GetTargetTypes();
HashSet<string> GetTargetTypes();
}
public interface ITargetable
{
string[] TargetTypes { get; }
IEnumerable<WPos> TargetablePositions(Actor self);
// Check IsTraitEnabled or !IsTraitDisabled first
HashSet<string> TargetTypes { get; }
bool TargetableBy(Actor self, Actor byActor);
bool RequiresForceFire { get; }
}
public interface ITargetablePositions
{
IEnumerable<WPos> TargetablePositions(Actor self);
}
public interface INotifyStanceChanged
{
void StanceChanged(Actor self, Player a, Player b,
Stance oldStance, Stance newStance);
}
public interface ILintPass { void Run(Action<string> emitError, Action<string> emitWarning, Map map); }
public interface ILintPass { void Run(Action<string> emitError, Action<string> emitWarning); }
public interface ILintMapPass { void Run(Action<string> emitError, Action<string> emitWarning, Map map); }
public interface ILintRulesPass { void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules); }
public interface IObjectivesPanel
{
@@ -369,4 +382,12 @@ namespace OpenRA.Traits
bool IsValidAgainst(FrozenActor victim, Actor firedBy);
void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers);
}
public interface IRemoveFrozenActor
{
bool RemoveActor(Actor self, Player owner);
}
public interface IRulesetLoaded<TInfo> { void RulesetLoaded(Ruleset rules, TInfo info); }
public interface IRulesetLoaded : IRulesetLoaded<ActorInfo>, ITraitInfo { }
}

View File

@@ -74,6 +74,9 @@ namespace OpenRA.Traits
public static Activity RunActivity(Actor self, Activity act)
{
if (act == null)
return act;
// Note - manual iteration here for performance due to high call volume.
var longTickThresholdInStopwatchTicks = PerfTimer.LongTickThresholdInStopwatchTicks;
var start = Stopwatch.GetTimestamp();
@@ -146,5 +149,20 @@ namespace OpenRA.Traits
return (int)a;
}
public static IEnumerable<CPos> RandomWalk(CPos p, MersenneTwister r)
{
for (;;)
{
var dx = r.Next(-1, 2);
var dy = r.Next(-1, 2);
if (dx == 0 && dy == 0)
continue;
p += new CVec(dx, dy);
yield return p;
}
}
}
}

View File

@@ -9,6 +9,7 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
@@ -67,7 +68,7 @@ namespace OpenRA.Traits
return;
var oldActors = currentActors;
currentActors = Footprint.SelectMany(actorMap.GetUnitsAt).ToList();
currentActors = Footprint.SelectMany(actorMap.GetActorsAt).ToList();
var entered = currentActors.Except(oldActors);
var exited = oldActors.Except(currentActors);
@@ -186,22 +187,51 @@ namespace OpenRA.Traits
actorShouldBeRemoved = removeActorPosition.Contains;
}
public IEnumerable<Actor> GetUnitsAt(CPos a)
sealed class ActorsAtEnumerator : IEnumerator<Actor>
{
if (!influence.Contains(a))
yield break;
InfluenceNode node;
public ActorsAtEnumerator(InfluenceNode node) { this.node = node; }
public void Reset() { throw new NotSupportedException(); }
public Actor Current { get; private set; }
object IEnumerator.Current { get { return Current; } }
public void Dispose() { }
public bool MoveNext()
{
while (node != null)
{
Current = node.Actor;
node = node.Next;
if (!Current.Disposed)
return true;
}
for (var i = influence[a]; i != null; i = i.Next)
if (!i.Actor.Disposed)
yield return i.Actor;
return false;
}
}
public IEnumerable<Actor> GetUnitsAt(CPos a, SubCell sub)
sealed class ActorsAtEnumerable : IEnumerable<Actor>
{
if (!influence.Contains(a))
readonly InfluenceNode node;
public ActorsAtEnumerable(InfluenceNode node) { this.node = node; }
public IEnumerator<Actor> GetEnumerator() { return new ActorsAtEnumerator(node); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
public IEnumerable<Actor> GetActorsAt(CPos a)
{
var uv = a.ToMPos(map);
if (!influence.Contains(uv))
return Enumerable.Empty<Actor>();
return new ActorsAtEnumerable(influence[uv]);
}
public IEnumerable<Actor> GetActorsAt(CPos a, SubCell sub)
{
var uv = a.ToMPos(map);
if (!influence.Contains(uv))
yield break;
for (var i = influence[a]; i != null; i = i.Next)
for (var i = influence[uv]; i != null; i = i.Next)
if (!i.Actor.Disposed && (i.SubCell == sub || i.SubCell == SubCell.FullCell))
yield return i.Actor;
}
@@ -213,14 +243,14 @@ namespace OpenRA.Traits
public SubCell FreeSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, bool checkTransient = true)
{
if (preferredSubCell > SubCell.Any && !AnyUnitsAt(cell, preferredSubCell, checkTransient))
if (preferredSubCell > SubCell.Any && !AnyActorsAt(cell, preferredSubCell, checkTransient))
return preferredSubCell;
if (!AnyUnitsAt(cell))
if (!AnyActorsAt(cell))
return map.DefaultSubCell;
for (var i = (int)SubCell.First; i < map.SubCellOffsets.Length; i++)
if (i != (int)preferredSubCell && !AnyUnitsAt(cell, (SubCell)i, checkTransient))
if (i != (int)preferredSubCell && !AnyActorsAt(cell, (SubCell)i, checkTransient))
return (SubCell)i;
return SubCell.Invalid;
@@ -228,35 +258,37 @@ namespace OpenRA.Traits
public SubCell FreeSubCell(CPos cell, SubCell preferredSubCell, Func<Actor, bool> checkIfBlocker)
{
if (preferredSubCell > SubCell.Any && !AnyUnitsAt(cell, preferredSubCell, checkIfBlocker))
if (preferredSubCell > SubCell.Any && !AnyActorsAt(cell, preferredSubCell, checkIfBlocker))
return preferredSubCell;
if (!AnyUnitsAt(cell))
if (!AnyActorsAt(cell))
return map.DefaultSubCell;
for (var i = (int)SubCell.First; i < map.SubCellOffsets.Length; i++)
if (i != (int)preferredSubCell && !AnyUnitsAt(cell, (SubCell)i, checkIfBlocker))
if (i != (int)preferredSubCell && !AnyActorsAt(cell, (SubCell)i, checkIfBlocker))
return (SubCell)i;
return SubCell.Invalid;
}
// NOTE: always includes transients with influence
public bool AnyUnitsAt(CPos a)
public bool AnyActorsAt(CPos a)
{
if (!influence.Contains(a))
var uv = a.ToMPos(map);
if (!influence.Contains(uv))
return false;
return influence[a] != null;
return influence[uv] != null;
}
// NOTE: can not check aircraft
public bool AnyUnitsAt(CPos a, SubCell sub, bool checkTransient = true)
public bool AnyActorsAt(CPos a, SubCell sub, bool checkTransient = true)
{
if (!influence.Contains(a))
var uv = a.ToMPos(map);
if (!influence.Contains(uv))
return false;
var always = sub == SubCell.FullCell || sub == SubCell.Any;
for (var i = influence[a]; i != null; i = i.Next)
for (var i = influence[uv]; i != null; i = i.Next)
{
if (always || i.SubCell == sub || i.SubCell == SubCell.FullCell)
{
@@ -273,13 +305,14 @@ namespace OpenRA.Traits
}
// NOTE: can not check aircraft
public bool AnyUnitsAt(CPos a, SubCell sub, Func<Actor, bool> withCondition)
public bool AnyActorsAt(CPos a, SubCell sub, Func<Actor, bool> withCondition)
{
if (!influence.Contains(a))
var uv = a.ToMPos(map);
if (!influence.Contains(uv))
return false;
var always = sub == SubCell.FullCell || sub == SubCell.Any;
for (var i = influence[a]; i != null; i = i.Next)
for (var i = influence[uv]; i != null; i = i.Next)
if ((always || i.SubCell == sub || i.SubCell == SubCell.FullCell) && !i.Actor.Disposed && withCondition(i.Actor))
return true;
@@ -290,10 +323,11 @@ namespace OpenRA.Traits
{
foreach (var c in ios.OccupiedCells())
{
if (!influence.Contains(c.First))
var uv = c.First.ToMPos(map);
if (!influence.Contains(uv))
continue;
influence[c.First] = new InfluenceNode { Next = influence[c.First], SubCell = c.Second, Actor = self };
influence[uv] = new InfluenceNode { Next = influence[uv], SubCell = c.Second, Actor = self };
List<CellTrigger> triggers;
if (cellTriggerInfluence.TryGetValue(c.First, out triggers))
@@ -306,12 +340,13 @@ namespace OpenRA.Traits
{
foreach (var c in ios.OccupiedCells())
{
if (!influence.Contains(c.First))
var uv = c.First.ToMPos(map);
if (!influence.Contains(uv))
continue;
var temp = influence[c.First];
var temp = influence[uv];
RemoveInfluenceInner(ref temp, self);
influence[c.First] = temp;
influence[uv] = temp;
List<CellTrigger> triggers;
if (cellTriggerInfluence.TryGetValue(c.First, out triggers))

View File

@@ -8,6 +8,8 @@
*/
#endregion
using System.Collections.Generic;
namespace OpenRA.Traits
{
[Desc("Attach this to the `World` actor.")]
@@ -20,7 +22,7 @@ namespace OpenRA.Traits
public readonly string InternalName = null;
[Desc("Pick a random faction as the player's facton out of this list.")]
public readonly string[] RandomFactionMembers = { };
public readonly HashSet<string> RandomFactionMembers = new HashSet<string>();
[Desc("The side that the faction belongs to. For example, England belongs to the 'Allies' side.")]
public readonly string Side = null;

View File

@@ -15,9 +15,9 @@ namespace OpenRA.Traits
{
public class ResourceTypeInfo : ITraitInfo
{
public readonly string[] Variants = { };
public readonly string Palette = "terrain";
public readonly string Sequence = "resources";
[SequenceReference("Sequence")] public readonly string[] Variants = { };
[PaletteReference] public readonly string Palette = "terrain";
public readonly int ResourceType = 1;
public readonly int ValuePerUnit = 0;
@@ -25,7 +25,7 @@ namespace OpenRA.Traits
public readonly string Name = null;
public readonly string TerrainType = "Ore";
public readonly string[] AllowedTerrainTypes = { };
public readonly HashSet<string> AllowedTerrainTypes = new HashSet<string>();
public readonly bool AllowUnderActors = false;
public readonly bool AllowUnderBuildings = false;
public readonly bool AllowOnRamps = false;

View File

@@ -36,9 +36,9 @@ namespace OpenRA.Traits
public ScreenMap(World world, ScreenMapInfo info)
{
var ts = Game.ModData.Manifest.TileSize;
var width = world.Map.MapSize.X * ts.Width;
var height = world.Map.MapSize.Y * ts.Height;
var size = world.Map.Grid.TileSize;
var width = world.Map.MapSize.X * size.Width;
var height = world.Map.MapSize.Y * size.Height;
partitionedFrozenActors = new Cache<Player, SpatiallyPartitioned<FrozenActor>>(
_ => new SpatiallyPartitioned<FrozenActor>(width, height, info.BinSize));
partitionedActors = new SpatiallyPartitioned<Actor>(width, height, info.BinSize);

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Traits
public object Create(ActorInitializer init) { return new Shroud(init.Self); }
}
public class Shroud
public class Shroud : ISync
{
[Sync] public bool Disabled;
@@ -40,11 +40,6 @@ namespace OpenRA.Traits
public int Hash { get; private set; }
static readonly Func<PPos, bool> TruthPredicate = _ => true;
readonly Func<PPos, bool> shroudEdgeTest;
readonly Func<PPos, bool> isExploredTest;
readonly Func<PPos, bool> isVisibleTest;
public Shroud(Actor self)
{
this.self = self;
@@ -53,11 +48,6 @@ namespace OpenRA.Traits
visibleCount = new CellLayer<short>(map);
generatedShroudCount = new CellLayer<short>(map);
explored = new CellLayer<bool>(map);
shroudEdgeTest = map.Contains;
isExploredTest = IsExplored;
isVisibleTest = IsVisible;
}
void Invalidate(IEnumerable<PPos> changed)
@@ -270,7 +260,11 @@ namespace OpenRA.Traits
if (!map.Contains(uv))
return false;
return map.ProjectedCellsCovering(uv).Any(isExploredTest);
foreach (var puv in map.ProjectedCellsCovering(uv))
if (IsExplored(puv))
return true;
return false;
}
public bool IsExplored(PPos puv)
@@ -282,24 +276,7 @@ namespace OpenRA.Traits
return explored.Contains(uv) && explored[uv] && (generatedShroudCount[uv] == 0 || visibleCount[uv] > 0);
}
public bool ShroudEnabled { get { return !Disabled && self.World.LobbyInfo.GlobalSettings.Shroud; } }
/// <summary>
/// Returns a fast exploration lookup that skips the usual validation.
/// The return value should not be cached across ticks, and should not
/// be called with cells outside the map bounds.
/// </summary>
public Func<PPos, bool> IsExploredTest
{
get
{
// If shroud isn't enabled, then we can see everything inside the map.
if (!ShroudEnabled)
return shroudEdgeTest;
return isExploredTest;
}
}
public bool ShroudEnabled { get { return !Disabled; } }
public bool IsVisible(WPos pos)
{
@@ -316,7 +293,11 @@ namespace OpenRA.Traits
if (!visibleCount.Contains(uv))
return false;
return map.ProjectedCellsCovering(uv).Any(isVisibleTest);
foreach (var puv in map.ProjectedCellsCovering(uv))
if (IsVisible(puv))
return true;
return false;
}
// In internal shroud coords
@@ -331,24 +312,6 @@ namespace OpenRA.Traits
public bool FogEnabled { get { return !Disabled && self.World.LobbyInfo.GlobalSettings.Fog; } }
/// <summary>
/// Returns a fast visibility lookup that skips the usual validation.
/// The return value should not be cached across ticks, and should not
/// be called with cells outside the map bounds.
/// </summary>
public Func<PPos, bool> IsVisibleTest
{
get
{
// If fog isn't enabled, then we can see everything.
if (!FogEnabled)
return TruthPredicate;
// If fog is enabled, we can use the fast test that just does the core check.
return isVisibleTest;
}
}
public bool Contains(PPos uv)
{
// Check that uv is inside the map area. There is nothing special

View File

@@ -27,6 +27,7 @@ namespace OpenRA
public WDist(int r) { Length = r; }
public static readonly WDist Zero = new WDist(0);
public static readonly WDist MaxValue = new WDist(int.MaxValue);
public static WDist FromCells(int cells) { return new WDist(1024 * cells); }
public static WDist operator +(WDist a, WDist b) { return new WDist(a.Length + b.Length); }

View File

@@ -46,7 +46,7 @@ namespace OpenRA.Widgets
{
var window = Game.ModData.WidgetLoader.LoadWidget(args, Root, id);
if (WindowList.Count > 0)
Root.RemoveChild(WindowList.Peek());
Root.HideChild(WindowList.Peek());
WindowList.Push(window);
return window;
}
@@ -140,6 +140,13 @@ namespace OpenRA.Widgets
}
}
public class ChromeLogic : IDisposable
{
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
public virtual void Tick() { }
protected virtual void Dispose(bool disposing) { }
}
public abstract class Widget
{
public readonly List<Widget> Children = new List<Widget>();
@@ -151,7 +158,7 @@ namespace OpenRA.Widgets
public string Width = "0";
public string Height = "0";
public string[] Logic = { };
public object[] LogicObjects { get; private set; }
public ChromeLogic[] LogicObjects { get; private set; }
public bool Visible = true;
public bool IgnoreMouseOver;
public bool IgnoreChildMouseOver;
@@ -244,7 +251,7 @@ namespace OpenRA.Widgets
args["widget"] = this;
LogicObjects = Logic.Select(l => Game.ModData.ObjectCreator.CreateObject<object>(l, args))
LogicObjects = Logic.Select(l => Game.ModData.ObjectCreator.CreateObject<ChromeLogic>(l, args))
.ToArray();
args.Remove("widget");
@@ -430,6 +437,10 @@ namespace OpenRA.Widgets
Tick();
foreach (var child in Children)
child.TickOuter();
if (LogicObjects != null)
foreach (var l in LogicObjects)
l.Tick();
}
}
@@ -448,12 +459,32 @@ namespace OpenRA.Widgets
}
}
public virtual void HideChild(Widget child)
{
if (child != null)
{
Children.Remove(child);
child.Hidden();
}
}
public virtual void RemoveChildren()
{
while (Children.Count > 0)
RemoveChild(Children[Children.Count - 1]);
}
public virtual void Hidden()
{
// Using the forced versions because the widgets
// have been removed
ForceYieldKeyboardFocus();
ForceYieldMouseFocus();
foreach (var c in Children.OfType<Widget>().Reverse())
c.Hidden();
}
public virtual void Removed()
{
// Using the forced versions because the widgets
@@ -463,6 +494,10 @@ namespace OpenRA.Widgets
foreach (var c in Children.OfType<Widget>().Reverse())
c.Removed();
if (LogicObjects != null)
foreach (var l in LogicObjects)
l.Dispose();
}
public Widget GetOrNull(string id)

View File

@@ -158,14 +158,14 @@ namespace OpenRA.Widgets
DrawRGBA(cornerBottomRight, new float2(bounds.Right - cornerBottomRight.Size.X, bounds.Bottom - cornerBottomRight.Size.Y));
}
public static string FormatTime(int ticks)
public static string FormatTime(int ticks, int timestep)
{
return FormatTime(ticks, true);
return FormatTime(ticks, true, timestep);
}
public static string FormatTime(int ticks, bool leadingMinuteZero)
public static string FormatTime(int ticks, bool leadingMinuteZero, int timestep)
{
var seconds = (int)Math.Ceiling(ticks / 25f);
var seconds = (int)Math.Ceiling(ticks * timestep / 1000f);
return FormatTimeSeconds(seconds, leadingMinuteZero);
}
@@ -227,6 +227,22 @@ namespace OpenRA.Widgets
return text;
}
public static string TruncateText(string text, int width, SpriteFont font)
{
var trimmedWidth = font.Measure(text).X;
if (trimmedWidth <= width)
return text;
var trimmed = text;
while (trimmedWidth > width && trimmed.Length > 3)
{
trimmed = text.Substring(0, trimmed.Length - 4) + "...";
trimmedWidth = font.Measure(trimmed).X;
}
return trimmed;
}
public static Action Once(Action a) { return () => { if (a != null) { a(); a = null; } }; }
public static string ChooseInitialMap(string initialUid)
@@ -242,6 +258,32 @@ namespace OpenRA.Widgets
}
}
public class CachedTransform<T, U>
{
readonly Func<T, U> transform;
bool initialized;
T lastInput;
U lastOutput;
public CachedTransform(Func<T, U> transform)
{
this.transform = transform;
}
public U Update(T input)
{
if (initialized && ((input == null && lastInput == null) || (input != null && input.Equals(lastInput))))
return lastOutput;
lastInput = input;
lastOutput = transform(input);
initialized = true;
return lastOutput;
}
}
[Flags]
public enum PanelSides
{

View File

@@ -89,8 +89,8 @@ namespace OpenRA.Widgets
{
if (!hasBox && World.Selection.Actors.Any() && !multiClick)
{
if (!(World.ScreenMap.ActorsAt(xy).Where(x => x.HasTrait<Selectable>() &&
(x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x))).Any() && !mi.Modifiers.HasModifier(Modifiers.Ctrl) &&
if (!(World.ScreenMap.ActorsAt(xy).Any(x => x.Info.HasTraitInfo<SelectableInfo>() &&
(x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x))) && !mi.Modifiers.HasModifier(Modifiers.Ctrl) &&
!mi.Modifiers.HasModifier(Modifiers.Alt) && UnitOrderGenerator.InputOverridesSelection(World, xy, mi)))
{
// Order units instead of selecting
@@ -120,19 +120,33 @@ namespace OpenRA.Widgets
}
}
}
else if (dragStart.HasValue)
else
{
// Select actors in the dragbox
var newSelection = SelectActorsInBoxWithDeadzone(World, dragStart.Value, xy);
World.Selection.Combine(World, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
/* The block below does three things:
// 1. Allows actor selection using a selection box regardless of input mode.
// 2. Allows actor deselection with a single click in the default input mode (UnitOrderGenerator).
// 3. Prevents units from getting deselected when exiting input modes (eg. AttackMove or Guard).
//
// We cannot check for UnitOrderGenerator here since it's the default order generator that gets activated in
// World.CancelInputMode. If we did check it, actor de-selection would not be possible by just clicking somewhere,
// only by dragging an empty selection box.
*/
if (dragStart.HasValue && (!(World.OrderGenerator is GenericSelectTarget) || hasBox))
{
// Select actors in the dragbox
var newSelection = SelectActorsInBoxWithDeadzone(World, dragStart.Value, xy);
World.Selection.Combine(World, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
}
}
World.CancelInputMode();
}
dragStart = dragEnd = null;
YieldMouseFocus(mi);
}
if (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Down)
if (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Up)
{
// Don't do anything while selecting
if (!hasBox)
@@ -242,7 +256,7 @@ namespace OpenRA.Widgets
{
// Get all the selected actors' selection classes
var selectedClasses = World.Selection.Actors
.Where(x => x.Owner == player)
.Where(x => !x.IsDead && x.Owner == player)
.Select(a => a.Trait<Selectable>().Class)
.ToHashSet();
@@ -301,7 +315,7 @@ namespace OpenRA.Widgets
a = b;
return world.ScreenMap.ActorsInBox(a, b)
.Where(x => x.HasTrait<Selectable>() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x)))
.Where(x => x.Info.HasTraitInfo<SelectableInfo>() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x)))
.SubsetWithHighestSelectionPriority();
}
@@ -318,4 +332,4 @@ namespace OpenRA.Widgets
return true;
}
}
}
}

View File

@@ -26,15 +26,8 @@ namespace OpenRA
public sealed class World : IDisposable
{
class ActorIDComparer : IComparer<Actor>
{
public static readonly ActorIDComparer Instance = new ActorIDComparer();
ActorIDComparer() { }
public int Compare(Actor x, Actor y) { return x.ActorID.CompareTo(y.ActorID); }
}
internal readonly TraitDictionary TraitDict = new TraitDictionary();
readonly SortedSet<Actor> actors = new SortedSet<Actor>(ActorIDComparer.Instance);
readonly SortedDictionary<uint, Actor> actors = new SortedDictionary<uint, Actor>();
readonly List<IEffect> effects = new List<IEffect>();
readonly Queue<Action<World>> frameEndActions = new Queue<Action<World>>();
@@ -151,6 +144,7 @@ namespace OpenRA
OrderManager = orderManager;
orderGenerator = new UnitOrderGenerator();
Map = map;
Timestep = orderManager.LobbyInfo.GlobalSettings.Timestep;
TileSet = map.Rules.TileSets[Map.Tileset];
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
@@ -170,7 +164,7 @@ namespace OpenRA
if (!p.Stances.ContainsKey(q))
p.Stances[q] = Stance.Neutral;
Sound.SoundVolumeModifier = 1.0f;
Game.Sound.SoundVolumeModifier = 1.0f;
gameInfo = new GameInformation
{
@@ -180,6 +174,10 @@ namespace OpenRA
MapUid = Map.Uid,
MapTitle = Map.Title
};
if (!LobbyInfo.GlobalSettings.Shroud)
foreach (var player in Players)
player.Shroud.ExploreAll(this);
}
public void LoadComplete(WorldRenderer wr)
@@ -225,7 +223,7 @@ namespace OpenRA
public void Add(Actor a)
{
a.IsInWorld = true;
actors.Add(a);
actors.Add(a.ActorID, a);
ActorAdded(a);
foreach (var t in a.TraitsImplementing<INotifyAddedToWorld>())
@@ -235,7 +233,7 @@ namespace OpenRA
public void Remove(Actor a)
{
a.IsInWorld = false;
actors.Remove(a);
actors.Remove(a.ActorID);
ActorRemoved(a);
foreach (var t in a.TraitsImplementing<INotifyRemovedFromWorld>())
@@ -283,7 +281,7 @@ namespace OpenRA
ni.Trait.TickIdle(ni.Actor);
using (new PerfSample("tick_activities"))
foreach (var a in actors)
foreach (var a in actors.Values)
a.Tick();
ActorsWithTrait<ITick>().DoTimed(x => x.Trait.Tick(x.Actor), "Trait");
@@ -301,9 +299,17 @@ namespace OpenRA
ActorsWithTrait<ITickRender>().DoTimed(x => x.Trait.TickRender(wr, x.Actor), "Render");
}
public IEnumerable<Actor> Actors { get { return actors; } }
public IEnumerable<Actor> Actors { get { return actors.Values; } }
public IEnumerable<IEffect> Effects { get { return effects; } }
public Actor GetActorById(uint actorId)
{
Actor a;
if (actors.TryGetValue(actorId, out a))
return a;
return null;
}
uint nextAID = 0;
internal uint NextAID()
{
@@ -363,11 +369,11 @@ namespace OpenRA
frameEndActions.Clear();
Sound.StopAudio();
Sound.StopVideo();
Game.Sound.StopAudio();
Game.Sound.StopVideo();
// Dispose newer actors first, and the world actor last
foreach (var a in actors.Reverse())
foreach (var a in actors.Values.Reverse())
a.Dispose();
// Actor disposals are done in a FrameEndTask

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