diff --git a/OpenRA.Game/PathSearch.cs b/OpenRA.Game/PathSearch.cs index b36e71bd9b..71e34afb3e 100755 --- a/OpenRA.Game/PathSearch.cs +++ b/OpenRA.Game/PathSearch.cs @@ -30,6 +30,7 @@ namespace OpenRA public class PathSearch { World world; + ResourceLayer resources; public CellInfo[ , ] cellInfo; public PriorityQueue queue; public Func heuristic; @@ -49,6 +50,7 @@ namespace OpenRA buildingInfluence = world.WorldActor.traits.Get(); unitInfluence = world.WorldActor.traits.Get(); + resources = world.WorldActor.traits.Get(); } public PathSearch WithCustomBlocker(Func customBlock) @@ -72,7 +74,8 @@ namespace OpenRA var thisCost = (custom2 != null) ? custom2.GetCost(p.Location, umt) : passableCost[(int)umt][p.Location.X, p.Location.Y]; - + thisCost *= resources.GetPathCost(umt, p.Location); + if (thisCost == float.PositiveInfinity) return p.Location; @@ -86,7 +89,7 @@ namespace OpenRA 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); if (costHere == float.PositiveInfinity) continue; diff --git a/OpenRA.Game/Traits/SeedsResource.cs b/OpenRA.Game/Traits/SeedsResource.cs index 503f4e90fb..948e064aa1 100644 --- a/OpenRA.Game/Traits/SeedsResource.cs +++ b/OpenRA.Game/Traits/SeedsResource.cs @@ -41,9 +41,9 @@ namespace OpenRA.Traits if (--ticks <= 0) { var info = self.Info.Traits.Get(); - var resourceType = self.World.WorldActor.Info.Traits - .WithInterface() - .FirstOrDefault(t => t.Name == info.ResourceType); + var resourceType = self.World.WorldActor.traits + .WithInterface() + .FirstOrDefault(t => t.info.Name == info.ResourceType); if (resourceType == null) throw new InvalidOperationException("No such resource type `{0}`".F(info.ResourceType)); diff --git a/OpenRA.Game/Traits/World/ResourceLayer.cs b/OpenRA.Game/Traits/World/ResourceLayer.cs index ce333cf7a2..50c8cd8c0a 100644 --- a/OpenRA.Game/Traits/World/ResourceLayer.cs +++ b/OpenRA.Game/Traits/World/ResourceLayer.cs @@ -21,6 +21,7 @@ using System; using System.Linq; using OpenRA.Graphics; +using OpenRA.GameRules; namespace OpenRA.Traits { @@ -34,7 +35,7 @@ namespace OpenRA.Traits SpriteRenderer sr; World world; - public ResourceTypeInfo[] resourceTypes; + public ResourceType[] resourceTypes; CellContents[,] content; public ResourceLayer(Actor self) @@ -55,7 +56,7 @@ namespace OpenRA.Traits if (c.image != null) sr.DrawSprite(c.image[c.density], Game.CellSize * new int2(x, y), - c.type.Palette); + c.type.info.Palette); } sr.Flush(); @@ -66,9 +67,9 @@ namespace OpenRA.Traits this.world = w; content = new CellContents[w.Map.MapSize.X, w.Map.MapSize.Y]; - resourceTypes = w.WorldActor.Info.Traits.WithInterface().ToArray(); + resourceTypes = w.WorldActor.traits.WithInterface().ToArray(); foreach (var rt in resourceTypes) - rt.Sprites = rt.SpriteNames.Select(a => SpriteSheetBuilder.LoadAllSprites(a)).ToArray(); + rt.info.Sprites = rt.info.SpriteNames.Select(a => SpriteSheetBuilder.LoadAllSprites(a)).ToArray(); var map = w.Map; @@ -76,7 +77,7 @@ namespace OpenRA.Traits for (int y = map.YOffset; y < map.YOffset + map.Height; y++) { content[x,y].type = resourceTypes.FirstOrDefault( - r => r.ResourceType == w.Map.MapResources[x,y].type); + r => r.info.ResourceType == w.Map.MapResources[x,y].type); if (content[x, y].type != null) content[x, y].image = ChooseContent(content[x, y].type); } @@ -87,17 +88,31 @@ namespace OpenRA.Traits content[x, y].density = GetIdealDensity(x, y); } - public Sprite[] ChooseContent(ResourceTypeInfo info) + public float GetMovementCost(UnitMovementType umt, int2 p) { - return info.Sprites[world.SharedRandom.Next(info.Sprites.Length)]; + if (content[p.X,p.Y].type == null) + return 1.0f; + return content[p.X,p.Y].type.GetMovementCost(umt); + } + + public float GetPathCost(UnitMovementType umt, int2 p) + { + if (content[p.X,p.Y].type == null) + return 1.0f; + return content[p.X,p.Y].type.GetPathCost(umt); + } + + public Sprite[] ChooseContent(ResourceType t) + { + return t.info.Sprites[world.SharedRandom.Next(t.info.Sprites.Length)]; } - public int GetAdjacentCellsWith(ResourceTypeInfo info, int i, int j) + public int GetAdjacentCellsWith(ResourceType t, int i, int j) { int sum = 0; for (var u = -1; u < 2; u++) for (var v = -1; v < 2; v++) - if (content[i+u, j+v].type == info) + if (content[i+u, j+v].type == t) ++sum; return sum; } @@ -108,16 +123,16 @@ namespace OpenRA.Traits (content[x, y].image.Length - 1)) / 9; } - public void AddResource(ResourceTypeInfo info, int i, int j, int n) + public void AddResource(ResourceType t, int i, int j, int n) { if (content[i, j].type == null) { - content[i, j].type = info; - content[i, j].image = ChooseContent(info); + content[i, j].type = t; + content[i, j].image = ChooseContent(t); content[i, j].density = -1; } - if (content[i, j].type != info) + if (content[i, j].type != t) return; content[i, j].density = Math.Min( @@ -125,7 +140,7 @@ namespace OpenRA.Traits content[i, j].density + n); } - public ResourceTypeInfo Harvest(int2 p) + public ResourceType Harvest(int2 p) { var type = content[p.X,p.Y].type; if (type == null) return null; @@ -145,29 +160,29 @@ namespace OpenRA.Traits content[p.X, p.Y].density = 0; } - public void Grow(ResourceTypeInfo info) + public void Grow(ResourceType t) { var map = world.Map; var newDensity = new byte[map.MapSize.X, map.MapSize.Y]; for (int i = map.TopLeft.X; i < map.BottomRight.X; i++) for (int j = map.TopLeft.Y; j < map.BottomRight.Y; j++) - if (content[i, j].type == info) + if (content[i, j].type == t) newDensity[i, j] = (byte)GetIdealDensity(i, j); for (int i = map.TopLeft.X; i < map.BottomRight.X; i++) for (int j = map.TopLeft.Y; j < map.BottomRight.Y; j++) - if (content[i, j].type == info && content[i, j].density < newDensity[i, j]) + if (content[i, j].type == t && content[i, j].density < newDensity[i, j]) ++content[i, j].density; } - public void Spread(ResourceTypeInfo info) + public void Spread(ResourceType t) { var map = world.Map; var growMask = new bool[map.MapSize.X, map.MapSize.Y]; for (int i = map.TopLeft.X; i < map.BottomRight.X; i++) for (int j = map.TopLeft.Y; j < map.BottomRight.Y; j++) if (content[i,j].type == null - && GetAdjacentCellsWith(info, i,j ) > 0 + && GetAdjacentCellsWith(t, i,j ) > 0 && world.IsCellBuildable(new int2(i, j), false)) growMask[i, j] = true; @@ -175,18 +190,18 @@ namespace OpenRA.Traits for (int j = map.TopLeft.Y; j < map.BottomRight.Y; j++) if (growMask[i, j]) { - content[i, j].type = info; - content[i, j].image = ChooseContent(info); + content[i, j].type = t; + content[i, j].image = ChooseContent(t); content[i, j].density = 0; } } - public ResourceTypeInfo GetResource(int2 p) { return content[p.X, p.Y].type; } + public ResourceType GetResource(int2 p) { return content[p.X, p.Y].type; } public struct CellContents { - public ResourceTypeInfo type; + public ResourceType type; public Sprite[] image; public int density; } diff --git a/OpenRA.Game/Traits/World/ResourceType.cs b/OpenRA.Game/Traits/World/ResourceType.cs index ae97171614..f354b8976d 100644 --- a/OpenRA.Game/Traits/World/ResourceType.cs +++ b/OpenRA.Game/Traits/World/ResourceType.cs @@ -19,6 +19,8 @@ #endregion using OpenRA.Graphics; +using OpenRA.GameRules; +using OpenRA.FileFormats; namespace OpenRA.Traits { @@ -33,33 +35,57 @@ namespace OpenRA.Traits public readonly float GrowthInterval = 0; public readonly float SpreadInterval = 0; + public readonly string MovementTerrainType = null; + public readonly string PathingTerrainType = null; public Sprite[][] Sprites; public object Create(Actor self) { return new ResourceType(this); } } - class ResourceType : ITick + public class ResourceType : ITick { int growthTicks; int spreadTicks; - ResourceTypeInfo info; + public ResourceTypeInfo info; + float[] movementCost = new float[4]; + float[] pathCost = new float[4]; - public ResourceType(ResourceTypeInfo info) { this.info = info; } + public ResourceType(ResourceTypeInfo info) + { + 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]; + } + + this.info = info; + } + + public float GetMovementCost(UnitMovementType umt) + { + return movementCost[(int)umt]; + } + + public float GetPathCost(UnitMovementType umt) + { + return pathCost[(int)umt]; + } public void Tick(Actor self) { if (info.GrowthInterval != 0 && --growthTicks <= 0) { growthTicks = (int)(info.GrowthInterval * 25 * 60); - self.World.WorldActor.traits.Get().Grow(info); + self.World.WorldActor.traits.Get().Grow(this); self.World.Minimap.InvalidateOre(); } if (info.SpreadInterval != 0 && --spreadTicks <= 0) { spreadTicks = (int)(info.SpreadInterval * 25 * 60); - self.World.WorldActor.traits.Get().Spread(info); + self.World.WorldActor.traits.Get().Spread(this); self.World.Minimap.InvalidateOre(); } } diff --git a/OpenRA.Mods.RA/Activities/Harvest.cs b/OpenRA.Mods.RA/Activities/Harvest.cs index 5406b9ce89..ce56ad4468 100755 --- a/OpenRA.Mods.RA/Activities/Harvest.cs +++ b/OpenRA.Mods.RA/Activities/Harvest.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. * This file is part of OpenRA. @@ -78,7 +78,7 @@ namespace OpenRA.Mods.RA.Activities var search = new PathSearch(self.World) { heuristic = loc => (res.GetResource(loc) != null - && harv.Resources.Contains( res.GetResource(loc).Name )) ? 0 : 1, + && harv.Resources.Contains( res.GetResource(loc).info.Name )) ? 0 : 1, umt = UnitMovementType.Wheel, checkForBlocked = true }; diff --git a/OpenRA.Mods.RA/Harvester.cs b/OpenRA.Mods.RA/Harvester.cs index a97630fa8e..d2539548dc 100755 --- a/OpenRA.Mods.RA/Harvester.cs +++ b/OpenRA.Mods.RA/Harvester.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. * This file is part of OpenRA. @@ -48,10 +48,10 @@ namespace OpenRA.Mods.RA public bool IsFull { get { return contents.Values.Sum() == self.Info.Traits.Get().Capacity; } } public bool IsEmpty { get { return contents.Values.Sum() == 0; } } - public void AcceptResource(ResourceTypeInfo type) + public void AcceptResource(ResourceType type) { - if (!contents.ContainsKey(type)) contents[type] = 1; - else contents[type]++; + if (!contents.ContainsKey(type.info)) contents[type.info] = 1; + else contents[type.info]++; } public void Deliver(Actor self, Actor proc) @@ -72,7 +72,7 @@ namespace OpenRA.Mods.RA var res = self.World.WorldActor.traits.Get().GetResource(xy); var info = self.Info.Traits.Get(); - if (underCursor == null && res != null && info.Resources.Contains(res.Name)) + if (underCursor == null && res != null && info.Resources.Contains(res.info.Name)) return new Order("Harvest", self, xy); return null; diff --git a/mods/ra/system.yaml b/mods/ra/system.yaml index 45013d3660..a89d718433 100644 --- a/mods/ra/system.yaml +++ b/mods/ra/system.yaml @@ -232,6 +232,7 @@ World: ResourceLayer: ResourceType@ore: ResourceType: 1 + MovementTerrainType: Ore Palette: terrain SpriteNames: gold01,gold02,gold03,gold04 ValuePerUnit: 25 @@ -240,6 +241,7 @@ World: SpreadInterval: 2.0 ResourceType@gem: ResourceType: 2 + MovementTerrainType: Ore Palette: terrain SpriteNames: gem01,gem02,gem03,gem04 ValuePerUnit: 50