diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 4cd3042b9a..dd0b829c82 100755 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -241,6 +241,7 @@ + diff --git a/OpenRA.Game/PathFinder.cs b/OpenRA.Game/PathFinder.cs index 0f8c0a2b53..1384aaa0dc 100644 --- a/OpenRA.Game/PathFinder.cs +++ b/OpenRA.Game/PathFinder.cs @@ -31,18 +31,18 @@ namespace OpenRA public class PathFinder { readonly World world; - float[][,] passableCost = new float[4][,]; + float[][,] passableCost = new float[5][,]; public PathFinder( World world ) { this.world = world; var map = world.Map; - for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Float; umt++) + for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Fly; umt++) passableCost[(int)umt] = new float[map.MapSize.X, map.MapSize.Y]; for( int x = 0 ; x < map.MapSize.X ; x++ ) for( int y = 0 ; y < map.MapSize.Y ; y++ ) - for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Float; umt++ ) - passableCost[(int)umt][ x, y ] = ( world.Map.IsInMap( x, y ) ) + for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Fly; umt++ ) + passableCost[(int)umt][ x, y ] = (umt == UnitMovementType.Fly) ? 0f : ( world.Map.IsInMap( x, y ) ) ? (float)Rules.TerrainTypes[world.TileSet.GetTerrainType(world.Map.MapTiles[x, y])] .GetCost(umt) : float.PositiveInfinity; diff --git a/OpenRA.Game/PathSearch.cs b/OpenRA.Game/PathSearch.cs index 595d1c047c..9c56a9d061 100755 --- a/OpenRA.Game/PathSearch.cs +++ b/OpenRA.Game/PathSearch.cs @@ -41,7 +41,6 @@ namespace OpenRA public bool inReverse; BuildingInfluence buildingInfluence; - UnitInfluence unitInfluence; public PathSearch(Actor self) { @@ -53,7 +52,6 @@ namespace OpenRA umt = self.traits.Get().GetMovementType(); buildingInfluence = world.WorldActor.traits.Get(); - unitInfluence = world.WorldActor.traits.Get(); } public PathSearch InReverse() @@ -114,11 +112,8 @@ namespace OpenRA if (costHere == float.PositiveInfinity) continue; - if (!buildingInfluence.CanMoveHere(newHere, ignoreBuilding)) - continue; - var mobile = self.traits.Get(); - if (checkForBlocked && !mobile.CanEnterCell(newHere, ignoreBuilding)) + if (checkForBlocked && !mobile.CanEnterCell(newHere, ignoreBuilding, checkForBlocked)) continue; if (customBlock != null && customBlock(newHere)) diff --git a/OpenRA.Game/Traits/Activities/Move.cs b/OpenRA.Game/Traits/Activities/Move.cs index 4edbee0671..f1ab35d87c 100755 --- a/OpenRA.Game/Traits/Activities/Move.cs +++ b/OpenRA.Game/Traits/Activities/Move.cs @@ -167,7 +167,7 @@ namespace OpenRA.Traits.Activities { if( path.Count == 0 ) return null; var nextCell = path[ path.Count - 1 ]; - if( !mobile.CanEnterCell( nextCell, ignoreBuilding ) ) + if( !mobile.CanEnterCell( nextCell, ignoreBuilding, true ) ) { if( ( mobile.toCell - destination.Value ).LengthSquared <= nearEnough ) { @@ -185,10 +185,13 @@ namespace OpenRA.Traits.Activities if (--waitTicksRemaining >= 0) return null; - self.World.WorldActor.traits.Get().Remove( self, mobile ); + + //self.World.WorldActor.traits.Get().Remove( self, mobile ); + mobile.RemoveInfluence(); var newPath = getPath(self).TakeWhile(a => a != self.Location).ToList(); - self.World.WorldActor.traits.Get().Add( self, mobile ); + //self.World.WorldActor.traits.Get().Add( self, mobile ); + mobile.AddInfluence(); if (newPath.Count != 0) path = newPath; diff --git a/OpenRA.Game/Traits/Mobile.cs b/OpenRA.Game/Traits/Mobile.cs index 1ee6a2efb2..017e142afd 100644 --- a/OpenRA.Game/Traits/Mobile.cs +++ b/OpenRA.Game/Traits/Mobile.cs @@ -30,12 +30,12 @@ namespace OpenRA.Traits public readonly int WaitAverage = 60; public readonly int WaitSpread = 20; - public object Create(ActorInitializer init) { return new Mobile(init); } + public virtual object Create(ActorInitializer init) { return new Mobile(init); } } public class Mobile : IIssueOrder, IResolveOrder, IOccupySpace, IMove { - readonly Actor self; + public readonly Actor self; [Sync] int2 __fromCell, __toCell; @@ -53,17 +53,17 @@ namespace OpenRA.Traits void SetLocation( int2 from, int2 to ) { if( fromCell == from && toCell == to ) return; - self.World.WorldActor.traits.Get().Remove(self, this); + RemoveInfluence(); __fromCell = from; __toCell = to; - self.World.WorldActor.traits.Get().Add(self, this); + AddInfluence(); } public Mobile(ActorInitializer init) { this.self = init.self; this.__fromCell = this.__toCell = init.location; - self.World.WorldActor.traits.Get().Add(self, this); + AddInfluence(); } public void SetPosition(Actor self, int2 cell) @@ -83,7 +83,7 @@ namespace OpenRA.Traits { // force-move if (!mi.Modifiers.HasModifier(Modifiers.Alt)) return null; - if (!self.World.IsActorCrushableByActor(underCursor, self)) return null; + if (!CanEnterCell(underCursor.Location, null, true)) return null; } var umt = self.Info.Traits.Get().MovementType; if (Util.GetEffectiveSpeed(self,umt) == 0) return null; /* allow disabling move orders from modifiers */ @@ -105,7 +105,7 @@ namespace OpenRA.Traits public int2 TopLeft { get { return toCell; } } - public IEnumerable OccupiedCells() + public virtual IEnumerable OccupiedCells() { return (fromCell == toCell) ? new[] { fromCell } @@ -121,27 +121,30 @@ namespace OpenRA.Traits public bool CanEnterCell(int2 p) { - return CanEnterCell(p, null); + return CanEnterCell(p, null, true); } - public bool CanEnterCell(int2 p, Actor ignoreBuilding) + public virtual bool CanEnterCell(int2 p, Actor ignoreActor, bool checkTransientActors) { - if (!self.World.WorldActor.traits.Get().CanMoveHere(p, ignoreBuilding)) return false; - - var canShare = self.traits.Contains(); - var actors = self.World.WorldActor.traits.Get().GetUnitsAt(p); - var nonshareable = actors.Where(a => a != self && !(canShare && a.traits.Contains())); - var shareable = actors.Where(a => a != self && canShare && a.traits.Contains()); - - // only allow 5 in a cell - if (shareable.Count() >= 5) - return false; - - // We can enter a cell with nonshareable units if we can crush all of them - if (nonshareable.Any( - a => !self.World.IsActorCrushableByActor(a, self))) + if (!self.World.WorldActor.traits.Get().CanMoveHere(p, ignoreActor)) return false; + if (checkTransientActors) + { + var canShare = self.traits.Contains(); + var actors = self.World.WorldActor.traits.Get().GetUnitsAt(p).Where(a => a != self && a != ignoreActor); + var nonshareable = actors.Where(a => !(canShare && a.traits.Contains())); + var shareable = actors.Where(a => canShare && a.traits.Contains()); + + // only allow 5 in a cell + if (shareable.Count() >= 5) + return false; + + // We can enter a cell with nonshareable units if we can crush all of them + if (nonshareable.Any( + a => !self.World.IsActorCrushableByActor(a, self))) + return false; + } return self.World.Map.IsInMap(p.X, p.Y) && Rules.TerrainTypes[self.World.TileSet.GetTerrainType(self.World.Map.MapTiles[p.X, p.Y])] @@ -155,5 +158,15 @@ namespace OpenRA.Traits return Enumerable.Reverse(move.path).Select( c => Util.CenterOfCell(c) ); } + + public virtual void AddInfluence() + { + self.World.WorldActor.traits.Get().Add( self, this ); + } + + public virtual void RemoveInfluence() + { + self.World.WorldActor.traits.Get().Remove( self, this ); + } } } diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index bcacb5aed3..b694e60eca 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -67,6 +67,12 @@ namespace OpenRA.Traits int2 TopLeft { get; } IEnumerable OccupiedCells(); } + + public interface IOccupyAir + { + int2 TopLeft { get; } + IEnumerable OccupiedAirCells(); + } public static class IOccupySpaceExts { diff --git a/OpenRA.Game/Traits/World/ResourceType.cs b/OpenRA.Game/Traits/World/ResourceType.cs index 9922334491..6cdc568f57 100644 --- a/OpenRA.Game/Traits/World/ResourceType.cs +++ b/OpenRA.Game/Traits/World/ResourceType.cs @@ -44,8 +44,8 @@ namespace OpenRA.Traits public class ResourceType { public ResourceTypeInfo info; - float[] movementSpeed = new float[4]; - float[] pathCost = new float[4]; + float[] movementSpeed = new float[5]; + float[] pathCost = new float[5]; public ResourceType(ResourceTypeInfo info) { @@ -56,6 +56,8 @@ namespace OpenRA.Traits pathCost[(int)umt] = (info.PathingTerrainType != null) ? (float)Rules.TerrainTypes[TerrainType.Ore].GetCost(umt) : (info.MovementTerrainType != null) ? (float)Rules.TerrainTypes[TerrainType.Ore].GetCost(umt) : 1.0f; } + movementSpeed[(int)UnitMovementType.Fly] = 1.0f; + pathCost[(int)UnitMovementType.Fly] = 1.0f; this.info = info; } diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj index 7d11866b4b..941fac750f 100644 --- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj +++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj @@ -52,6 +52,7 @@ + diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index da3c62eace..8535ad5591 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/mods/cnc/structures.yaml b/mods/cnc/structures.yaml index bec2827142..95388f8e8c 100644 --- a/mods/cnc/structures.yaml +++ b/mods/cnc/structures.yaml @@ -315,7 +315,7 @@ HPAD: Crewed: yes Sight: 5 Bib: - ProducesHelicopters: + Production: SpawnOffset: 0,-4 Produces: Plane BelowUnits: diff --git a/mods/cnc/system.yaml b/mods/cnc/system.yaml index 57c232d67c..68c9473bcd 100644 --- a/mods/cnc/system.yaml +++ b/mods/cnc/system.yaml @@ -1,6 +1,6 @@ Player: ProductionQueue: - BuildSpeed: .4 + BuildSpeed: .004 LowPowerSlowdown: 3 PlaceBuilding: TechTreeCache: @@ -38,7 +38,7 @@ Player: UnitType: a10 ConquestVictoryConditions: PlayerResources: - InitialCash: 5000 + InitialCash: 500000 ActorGroupProxy: World: @@ -47,6 +47,7 @@ World: # WaterPaletteRotation: BuildingInfluence: UnitInfluence: + AircraftInfluence: # BridgeLoadHook: Theater@DESERT: Name:Desert diff --git a/mods/cnc/vehicles.yaml b/mods/cnc/vehicles.yaml index e80c0a7871..931e42fa05 100644 --- a/mods/cnc/vehicles.yaml +++ b/mods/cnc/vehicles.yaml @@ -406,7 +406,9 @@ TRAN: ROT: 5 Sight: 8 Speed: 15 - Helicopter: +# Helicopter: + MobileAir: + MovementType: Fly RenderUnitRotor: PrimaryOffset: 0,14,0,-4 SecondaryOffset: 0,-14,0,-2 @@ -434,15 +436,14 @@ HELI: ROT: 4 Sight: 8 Speed: 20 - AttackHeli: + AttackBase: PrimaryWeapon: HighV SecondaryWeapon: HighV PrimaryOffset: -5,0,0,2 SecondaryOffset: 5,0,0,2 - Helicopter: - RearmBuildings: - RepairBuildings: hpad - LandWhenIdle: no +# Helicopter: + MobileAir: + MovementType: Fly RenderUnitRotor: PrimaryOffset: 0,0,0,-2 WithShadow: @@ -466,15 +467,14 @@ ORCA: ROT: 4 Sight: 8 Speed: 20 - AttackHeli: + AttackBase: PrimaryWeapon: Rockets.Orca SecondaryWeapon: Rockets.Orca PrimaryOffset: -5,0,0,2 SecondaryOffset: 5,0,0,2 - Helicopter: - RearmBuildings: - RepairBuildings: hpad - LandWhenIdle: no +# Helicopter: + MobileAir: + MovementType: Fly RenderUnit: WithShadow: