diff --git a/OpenRA.Game/GameRules/TerrainCost.cs b/OpenRA.Game/GameRules/TerrainCost.cs index 5510e66a70..716bda50e3 100644 --- a/OpenRA.Game/GameRules/TerrainCost.cs +++ b/OpenRA.Game/GameRules/TerrainCost.cs @@ -40,7 +40,21 @@ namespace OpenRA.GameRules public readonly bool AcceptSmudge = true; public TerrainCost(MiniYaml y) { FieldLoader.Load(this, y); } - + + public float GetSpeedMultiplier(UnitMovementType umt) + { + switch (umt) /* todo: make this nice */ + { + case UnitMovementType.Fly: return 1; + case UnitMovementType.Foot: return Foot; + case UnitMovementType.Wheel: return Wheel; + case UnitMovementType.Track: return Track; + case UnitMovementType.Float: return Float; + default: + throw new InvalidOperationException("wtf?"); + } + } + public float GetCost(UnitMovementType umt) { switch (umt) /* todo: make this nice */ diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index dc051a956c..c9c3d24f78 100755 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -1,4 +1,4 @@ - + Debug @@ -138,7 +138,6 @@ - @@ -304,6 +303,7 @@ + @@ -339,4 +339,4 @@ --> - + \ No newline at end of file diff --git a/OpenRA.Game/PathSearch.cs b/OpenRA.Game/PathSearch.cs index 71e34afb3e..60f8f42fc0 100755 --- a/OpenRA.Game/PathSearch.cs +++ b/OpenRA.Game/PathSearch.cs @@ -69,12 +69,9 @@ namespace OpenRA { var p = queue.Pop(); cellInfo[ p.Location.X, p.Location.Y ].Seen = true; - - var custom2 = world.customTerrain[p.Location.X, p.Location.Y]; - var thisCost = (custom2 != null) - ? custom2.GetCost(p.Location, umt) - : passableCost[(int)umt][p.Location.X, p.Location.Y]; - thisCost *= resources.GetPathCost(umt, p.Location); + + var thisCost = passableCost[(int)umt][p.Location.X, p.Location.Y]* + world.WorldActor.traits.WithInterface().Aggregate(1f, (a, x) => a * x.GetCost(p.Location,umt)); if (thisCost == float.PositiveInfinity) return p.Location; @@ -87,9 +84,9 @@ namespace OpenRA if( cellInfo[ newHere.X, newHere.Y ].Seen ) continue; - var custom = world.customTerrain[newHere.X, newHere.Y]; - var costHere = (custom != null) ? custom.GetCost(newHere, umt) : passableCost[(int)umt][newHere.X, newHere.Y]; - costHere *= resources.GetPathCost(umt, newHere); + var costHere = passableCost[(int)umt][newHere.X, newHere.Y]* + world.WorldActor.traits.WithInterface().Aggregate(1f, (a, x) => a * x.GetCost(p.Location,umt)); + if (costHere == float.PositiveInfinity) continue; diff --git a/OpenRA.Game/Traits/Bridge.cs b/OpenRA.Game/Traits/Bridge.cs index b5c70cf3a4..a1f4039bd9 100644 --- a/OpenRA.Game/Traits/Bridge.cs +++ b/OpenRA.Game/Traits/Bridge.cs @@ -36,14 +36,13 @@ namespace OpenRA.Traits public object Create(Actor self) { return new Bridge(self); } } - class Bridge: IRender, ICustomTerrain, INotifyDamage + class Bridge: IRender, INotifyDamage { Dictionary Tiles; List> TileSprites = new List>(); List Templates = new List(); Actor self; int state; - Bridge northNeighbour, southNeighbour; public Bridge(Actor self) { this.self = self; self.RemoveOnDeath = false; } @@ -57,6 +56,25 @@ namespace OpenRA.Traits yield return new Renderable(t.Value, Game.CellSize * t.Key, "terrain"); } + public void FinalizeBridges(World world, Bridge[,] bridges) + { + // go looking for our neighbors, if this is a long bridge. + var info = self.Info.Traits.Get(); + if (info.NorthOffset != null) + northNeighbour = GetNeighbor(world, info.NorthOffset, bridges); + if (info.SouthOffset != null) + southNeighbour = GetNeighbor(world, info.SouthOffset, bridges); + } + + public Bridge GetNeighbor(World world, int[] offset, Bridge[,] bridges) + { + if (offset == null) return null; + var pos = self.Location + new int2(offset[0], offset[1]); + if (!world.Map.IsInMap(pos.X, pos.Y)) return null; + return bridges[pos.X, pos.Y]; + } + + public int StateFromTemplate(TileTemplate t) { var info = self.Info.Traits.Get(); @@ -83,10 +101,7 @@ namespace OpenRA.Traits { Tiles = replacedTiles; state = StateFromTemplate(template); - - foreach (var t in replacedTiles.Keys) - world.customTerrain[t.X, t.Y] = this; - + if (cachedTileset != world.Map.Tileset) { cachedTileset = world.Map.Tileset; @@ -109,24 +124,6 @@ namespace OpenRA.Traits self.Health = (int)(self.GetMaxHP() * template.HP); } - Bridge GetNeighbor(World world, int[] offset) - { - if (offset == null) return null; - var pos = self.Location + new int2(offset[0], offset[1]); - if (!world.Map.IsInMap(pos.X, pos.Y)) return null; - return world.customTerrain[pos.X, pos.Y] as Bridge; - } - - public void FinalizeBridges(World world) - { - // go looking for our neighbors, if this is a long bridge. - var info = self.Info.Traits.Get(); - if (info.NorthOffset != null) - northNeighbour = GetNeighbor(world, info.NorthOffset); - if (info.SouthOffset != null) - southNeighbour = GetNeighbor(world, info.SouthOffset); - } - public float GetCost(int2 p, UnitMovementType umt) { return Rules.TerrainTypes[Templates[state].TerrainType[Tiles[p]]].GetCost(umt); diff --git a/OpenRA.Game/Traits/World/BridgeLoadHook.cs b/OpenRA.Game/Traits/World/BridgeLayer.cs similarity index 75% rename from OpenRA.Game/Traits/World/BridgeLoadHook.cs rename to OpenRA.Game/Traits/World/BridgeLayer.cs index 79fdda80e7..78ccb6a418 100644 --- a/OpenRA.Game/Traits/World/BridgeLoadHook.cs +++ b/OpenRA.Game/Traits/World/BridgeLayer.cs @@ -20,14 +20,18 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.GameRules; namespace OpenRA.Traits { - class BridgeLoadHookInfo : TraitInfo { } + class BridgeLayerInfo : TraitInfo { } - class BridgeLoadHook : ILoadWorldHook + class BridgeLayer : ILoadWorldHook, ICustomTerrain { - static void MakeBridges(World w) + // for tricky things like bridges. + Bridge[,] customTerrain; + + void MakeBridges(World w) { var tl = w.Map.TopLeft; var br = w.Map.BottomRight; @@ -38,10 +42,10 @@ namespace OpenRA.Traits ConvertBridgeToActor(w, i, j); foreach (var b in w.Actors.SelectMany(a => a.traits.WithInterface())) - b.FinalizeBridges(w); + b.FinalizeBridges(w, customTerrain); } - static void ConvertBridgeToActor(World w, int i, int j) + void ConvertBridgeToActor(World w, int i, int j) { Log.Write("Converting bridge at {0} {1}",i,j); @@ -77,15 +81,30 @@ namespace OpenRA.Traits { var a = w.CreateActor(template.Bridge, new int2(ni, nj), w.NeutralPlayer); var br = a.traits.Get(); + + foreach (var t in replacedTiles.Keys) + customTerrain[t.X, t.Y] = br; + br.SetTiles(w, template, replacedTiles); } } + + public float GetCost(int2 p, UnitMovementType umt) + { + if (customTerrain[p.X, p.Y] != null) + return customTerrain[p.X,p.Y].GetCost(p,umt); + return 1f; + } static bool IsBridge(World w, ushort t) { return w.TileSet.walk[t].Bridge != null; } - public void WorldLoaded(World w) { MakeBridges(w); } + public void WorldLoaded(World w) + { + customTerrain = new Bridge[w.Map.MapSize.X, w.Map.MapSize.Y]; + MakeBridges(w); + } } } diff --git a/OpenRA.Game/Traits/World/ResourceLayer.cs b/OpenRA.Game/Traits/World/ResourceLayer.cs index 50c8cd8c0a..3c1ef7faf3 100644 --- a/OpenRA.Game/Traits/World/ResourceLayer.cs +++ b/OpenRA.Game/Traits/World/ResourceLayer.cs @@ -30,7 +30,7 @@ namespace OpenRA.Traits public object Create(Actor self) { return new ResourceLayer(self); } } - public class ResourceLayer: IRenderOverlay, ILoadWorldHook + public class ResourceLayer: IRenderOverlay, ILoadWorldHook, ICustomTerrain { SpriteRenderer sr; World world; @@ -88,18 +88,18 @@ namespace OpenRA.Traits content[x, y].density = GetIdealDensity(x, y); } - public float GetMovementCost(UnitMovementType umt, int2 p) + public float GetSpeedMultiplier(UnitMovementType umt, int2 p) { if (content[p.X,p.Y].type == null) return 1.0f; - return content[p.X,p.Y].type.GetMovementCost(umt); + return content[p.X,p.Y].type.GetSpeedMultiplier(umt); } - public float GetPathCost(UnitMovementType umt, int2 p) + public float GetCost(int2 p,UnitMovementType umt) { if (content[p.X,p.Y].type == null) return 1.0f; - return content[p.X,p.Y].type.GetPathCost(umt); + return content[p.X,p.Y].type.GetCost(umt); } public Sprite[] ChooseContent(ResourceType t) diff --git a/OpenRA.Game/Traits/World/ResourceType.cs b/OpenRA.Game/Traits/World/ResourceType.cs index f354b8976d..42e9cbb4ff 100644 --- a/OpenRA.Game/Traits/World/ResourceType.cs +++ b/OpenRA.Game/Traits/World/ResourceType.cs @@ -48,7 +48,7 @@ namespace OpenRA.Traits int growthTicks; int spreadTicks; public ResourceTypeInfo info; - float[] movementCost = new float[4]; + float[] movementSpeed = new float[4]; float[] pathCost = new float[4]; public ResourceType(ResourceTypeInfo info) @@ -56,19 +56,20 @@ namespace OpenRA.Traits for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Float; umt++ ) { // HACK: hardcode "ore" terraintype for now - movementCost[(int)umt] = (info.MovementTerrainType != null) ? (float)Rules.TerrainTypes[TerrainType.Ore].GetCost(umt) : 1.0f; - pathCost[(int)umt] = (info.PathingTerrainType != null) ? (float)Rules.TerrainTypes[TerrainType.Ore].GetCost(umt) : movementCost[(int)umt]; + movementSpeed[(int)umt] = (info.MovementTerrainType != null) ? (float)Rules.TerrainTypes[TerrainType.Ore].GetSpeedMultiplier(umt) : 1.0f; + 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; } this.info = info; } - public float GetMovementCost(UnitMovementType umt) + public float GetSpeedMultiplier(UnitMovementType umt) { - return movementCost[(int)umt]; + return movementSpeed[(int)umt]; } - public float GetPathCost(UnitMovementType umt) + public float GetCost(UnitMovementType umt) { return pathCost[(int)umt]; } diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index d3e6768c5d..2660e86847 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -70,9 +70,6 @@ namespace OpenRA public readonly TileSet TileSet; public GlobalDefaultsInfo Defaults { get {return WorldActor.Info.Traits.Get();}} - // for tricky things like bridges. - public readonly ICustomTerrain[,] customTerrain; - public readonly WorldRenderer WorldRenderer; internal readonly Minimap Minimap; @@ -80,9 +77,6 @@ namespace OpenRA { Timer.Time( "----World.ctor" ); Map = map; - - customTerrain = new ICustomTerrain[Map.MapSize.X, Map.MapSize.Y]; - Timer.Time( "new Map: {0}" ); Rules.LoadRules(manifest,Map); Timer.Time( "load rules: {0}" ); diff --git a/mods/cnc/system.yaml b/mods/cnc/system.yaml index 2b54aa2423..c0cc1b6b6a 100644 --- a/mods/cnc/system.yaml +++ b/mods/cnc/system.yaml @@ -203,6 +203,7 @@ World: ResourceLayer: ResourceType@green-tib: ResourceType: 1 + MovementTerrainType: Tiberium Palette: terrain SpriteNames: ti1,ti2,ti3,ti4,ti5,ti6,ti7,ti8,ti9,ti10,ti11,ti12 ValuePerUnit: 30 diff --git a/mods/ra/system.yaml b/mods/ra/system.yaml index a89d718433..d9e49ff51c 100644 --- a/mods/ra/system.yaml +++ b/mods/ra/system.yaml @@ -90,7 +90,7 @@ World: BuildingInfluence: UnitInfluence: ChoosePaletteOnSelect: - BridgeLoadHook: + BridgeLayer: CrateSpawner: Minimum: 1 Maximum: 3