Change terrain type from string based dictionaries to arrays
This commit is contained in:
@@ -102,7 +102,7 @@ namespace OpenRA.Mods.RA.AI
|
||||
BuildingInfo rallypointTestBuilding;
|
||||
internal readonly HackyAIInfo Info;
|
||||
|
||||
string[] resourceTypes;
|
||||
HashSet<int> resourceTypeIndices;
|
||||
|
||||
RushFuzzy rushFuzzy = new RushFuzzy();
|
||||
|
||||
@@ -152,8 +152,10 @@ namespace OpenRA.Mods.RA.AI
|
||||
|
||||
random = new MersenneTwister((int)p.PlayerActor.ActorID);
|
||||
|
||||
resourceTypes = Map.Rules.Actors["world"].Traits.WithInterface<ResourceTypeInfo>()
|
||||
.Select(t => t.TerrainType).ToArray();
|
||||
resourceTypeIndices = new HashSet<int>(
|
||||
Map.Rules.Actors["world"].Traits
|
||||
.WithInterface<ResourceTypeInfo>()
|
||||
.Select(t => world.TileSet.GetTerrainIndex(t.TerrainType)));
|
||||
}
|
||||
|
||||
static int GetPowerProvidedBy(ActorInfo building)
|
||||
@@ -364,7 +366,7 @@ namespace OpenRA.Mods.RA.AI
|
||||
|
||||
case BuildingType.Refinery:
|
||||
var tilesPos = world.FindTilesInCircle(baseCenter, MaxBaseDistance)
|
||||
.Where(a => resourceTypes.Contains(world.GetTerrainType(new CPos(a.X, a.Y))));
|
||||
.Where(a => resourceTypeIndices.Contains(world.GetTerrainIndex(new CPos(a.X, a.Y))));
|
||||
if (tilesPos.Any())
|
||||
{
|
||||
var pos = tilesPos.MinBy(a => (a.CenterPosition - baseCenter.CenterPosition).LengthSquared);
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace OpenRA.Mods.RA.Air
|
||||
if (self.World.ActorMap.AnyUnitsAt(cell))
|
||||
return false;
|
||||
|
||||
var type = self.World.GetTerrainType(cell);
|
||||
var type = self.World.GetTerrainInfo(cell).Type;
|
||||
return info.LandableTerrainTypes.Contains(type);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,11 +94,11 @@ namespace OpenRA.Mods.RA
|
||||
self.World.Map.CustomTerrain[c.X, c.Y] = GetTerrainType(c);
|
||||
}
|
||||
|
||||
string GetTerrainType(CPos cell)
|
||||
int GetTerrainType(CPos cell)
|
||||
{
|
||||
var dx = cell - self.Location;
|
||||
var index = dx.X + self.World.TileSet.Templates[template].Size.X * dx.Y;
|
||||
return self.World.TileSet.GetTerrainType(new TileReference<ushort, byte>(template, (byte)index));
|
||||
return self.World.TileSet.GetTerrainIndex(new TileReference<ushort, byte>(template, (byte)index));
|
||||
}
|
||||
|
||||
public void LinkNeighbouringBridges(World world, BridgeLayer bridges)
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
var cellOffset = new CVec(i % width, i / width + bibOffset);
|
||||
|
||||
// Some mods may define terrain-specific bibs
|
||||
var terrain = self.World.GetTerrainType(location + cellOffset);
|
||||
var terrain = self.World.GetTerrainInfo(location + cellOffset).Type;
|
||||
var testSequence = info.Sequence + "-" + terrain;
|
||||
var sequence = anim.HasSequence(testSequence) ? testSequence : info.Sequence;
|
||||
anim.PlayFetchIndex(sequence, () => index);
|
||||
|
||||
@@ -54,34 +54,34 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
foreach (var c in FootprintUtils.Tiles(self))
|
||||
{
|
||||
// Only place on allowed terrain types
|
||||
if (!info.TerrainTypes.Contains(self.World.GetTerrainType(c)))
|
||||
if (!info.TerrainTypes.Contains(self.World.GetTerrainInfo(c).Type))
|
||||
continue;
|
||||
|
||||
// Don't place under other buildings or custom terrain
|
||||
if (bi.GetBuildingAt(c) != self || self.World.Map.CustomTerrain[c.X, c.Y] != null)
|
||||
if (bi.GetBuildingAt(c) != self || self.World.Map.CustomTerrain[c.X, c.Y] != -1)
|
||||
continue;
|
||||
|
||||
var index = template.Tiles.Keys.Random(Game.CosmeticRandom);
|
||||
layer.AddTile(c, new TileReference<ushort, byte>(template.Id, index));
|
||||
var index = Game.CosmeticRandom.Next(template.TilesCount);
|
||||
layer.AddTile(c, new TileReference<ushort, byte>(template.Id, (byte)index));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var origin = self.Location + info.Offset;
|
||||
foreach (var i in template.Tiles.Keys)
|
||||
for (var i = 0; i < template.TilesCount; i++)
|
||||
{
|
||||
var c = origin + new CVec(i % template.Size.X, i / template.Size.X);
|
||||
|
||||
// Only place on allowed terrain types
|
||||
if (!info.TerrainTypes.Contains(self.World.GetTerrainType(c)))
|
||||
if (!info.TerrainTypes.Contains(self.World.GetTerrainInfo(c).Type))
|
||||
continue;
|
||||
|
||||
// Don't place under other buildings or custom terrain
|
||||
if (bi.GetBuildingAt(c) != self || self.World.Map.CustomTerrain[c.X, c.Y] != null)
|
||||
if (bi.GetBuildingAt(c) != self || self.World.Map.CustomTerrain[c.X, c.Y] != -1)
|
||||
continue;
|
||||
|
||||
layer.AddTile(c, new TileReference<ushort, byte>(template.Id, i));
|
||||
layer.AddTile(c, new TileReference<ushort, byte>(template.Id, (byte)i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
if (world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(a) != null) return false;
|
||||
if (world.ActorMap.GetUnitsAt(a).Any(b => b != toIgnore)) return false;
|
||||
|
||||
return world.Map.IsInMap(a) && bi.TerrainTypes.Contains(world.GetTerrainType(a));
|
||||
return world.Map.IsInMap(a) && bi.TerrainTypes.Contains(world.GetTerrainInfo(a).Type);
|
||||
}
|
||||
|
||||
public static bool CanPlaceBuilding(this World world, string name, BuildingInfo building, CPos topLeft, Actor toIgnore)
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
if (!self.World.Map.IsInMap(cell.X, cell.Y)) return false;
|
||||
|
||||
var type = self.World.GetTerrainType(cell);
|
||||
var type = self.World.GetTerrainInfo(cell).Type;
|
||||
if (!info.TerrainTypes.Contains(type))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace OpenRA.Mods.RA
|
||||
var p = self.World.ChooseRandomCell(self.World.SharedRandom);
|
||||
|
||||
// Is this valid terrain?
|
||||
var terrainType = self.World.GetTerrainType(p);
|
||||
var terrainType = self.World.GetTerrainInfo(p).Type;
|
||||
if (!(inWater ? info.ValidWater : info.ValidGround).Contains(terrainType))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace OpenRA.Mods.RA.Effects
|
||||
|| (info.RangeLimit != 0 && ticks > info.RangeLimit) // Ran out of fuel
|
||||
|| (!info.High && world.ActorMap.GetUnitsAt(cell)
|
||||
.Any(a => a.HasTrait<IBlocksBullets>())) // Hit a wall
|
||||
|| (!string.IsNullOrEmpty(info.BoundToTerrainType) && world.GetTerrainType(cell) != info.BoundToTerrainType); // Hit incompatible terrain
|
||||
|| (!string.IsNullOrEmpty(info.BoundToTerrainType) && world.GetTerrainInfo(cell).Type != info.BoundToTerrainType); // Hit incompatible terrain
|
||||
|
||||
if (shouldExplode)
|
||||
Explode(world);
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA
|
||||
if (!self.World.Map.IsInMap(cell.X, cell.Y))
|
||||
return false;
|
||||
|
||||
if (!info.AllowedTerrain.Contains(self.World.GetTerrainType(cell)))
|
||||
if (!info.AllowedTerrain.Contains(self.World.GetTerrainInfo(cell).Type))
|
||||
return false;
|
||||
|
||||
if (!checkTransientActors)
|
||||
|
||||
@@ -48,16 +48,55 @@ namespace OpenRA.Mods.RA.Move
|
||||
var cost = nodesDict.ContainsKey("PathingCost")
|
||||
? FieldLoader.GetValue<int>("cost", nodesDict["PathingCost"].Value)
|
||||
: (int)(10000 / speed);
|
||||
ret.Add(t.Key, new TerrainInfo { Speed = speed, Cost = cost });
|
||||
ret.Add(t.Key, new TerrainInfo(speed, cost));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TerrainInfo[] LoadTilesetSpeeds(TileSet tileSet)
|
||||
{
|
||||
var info = new TerrainInfo[tileSet.TerrainsCount];
|
||||
for (var i = 0; i < info.Length; i++)
|
||||
info[i] = TerrainInfo.Impassable;
|
||||
|
||||
foreach (var kvp in TerrainSpeeds)
|
||||
{
|
||||
int index;
|
||||
if (tileSet.TryGetTerrainIndex(kvp.Key, out index))
|
||||
info[index] = kvp.Value;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public class TerrainInfo
|
||||
{
|
||||
public int Cost = int.MaxValue;
|
||||
public decimal Speed = 0;
|
||||
public static readonly TerrainInfo Impassable = new TerrainInfo();
|
||||
|
||||
public readonly int Cost;
|
||||
public readonly decimal Speed;
|
||||
|
||||
public TerrainInfo()
|
||||
{
|
||||
Cost = int.MaxValue;
|
||||
Speed = 0;
|
||||
}
|
||||
|
||||
public TerrainInfo(decimal speed, int cost)
|
||||
{
|
||||
Speed = speed;
|
||||
Cost = cost;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly Cache<TileSet, TerrainInfo[]> TilesetTerrainInfo;
|
||||
public readonly Cache<TileSet, int> TilesetMovementClass;
|
||||
|
||||
public MobileInfo()
|
||||
{
|
||||
TilesetTerrainInfo = new Cache<TileSet, TerrainInfo[]>(LoadTilesetSpeeds);
|
||||
TilesetMovementClass = new Cache<TileSet, int>(CalculateTilesetMovementClass);
|
||||
}
|
||||
|
||||
public int MovementCostForCell(World world, CPos cell)
|
||||
@@ -65,20 +104,22 @@ namespace OpenRA.Mods.RA.Move
|
||||
if (!world.Map.IsInMap(cell.X, cell.Y))
|
||||
return int.MaxValue;
|
||||
|
||||
var type = world.GetTerrainType(cell);
|
||||
if (!TerrainSpeeds.ContainsKey(type))
|
||||
var index = world.GetTerrainIndex(cell);
|
||||
if (index == -1)
|
||||
return int.MaxValue;
|
||||
|
||||
return TerrainSpeeds[type].Cost;
|
||||
return TilesetTerrainInfo[world.TileSet][index].Cost;
|
||||
}
|
||||
|
||||
public int CalculateTilesetMovementClass(TileSet tileset)
|
||||
{
|
||||
/* collect our ability to cross *all* terraintypes, in a bitvector */
|
||||
return TilesetTerrainInfo[tileset].Select(ti => ti.Cost < int.MaxValue).ToBits();
|
||||
}
|
||||
|
||||
public int GetMovementClass(TileSet tileset)
|
||||
{
|
||||
/* collect our ability to cross *all* terraintypes, in a bitvector */
|
||||
var passability = tileset.Terrain.OrderBy(t => t.Key)
|
||||
.Select(t => TerrainSpeeds.ContainsKey(t.Key) && TerrainSpeeds[t.Key].Cost < int.MaxValue);
|
||||
|
||||
return passability.ToBits();
|
||||
return TilesetMovementClass[tileset];
|
||||
}
|
||||
|
||||
public static readonly Dictionary<SubCell, WVec> SubCellOffsets = new Dictionary<SubCell, WVec>()
|
||||
@@ -440,12 +481,15 @@ namespace OpenRA.Mods.RA.Move
|
||||
|
||||
public int MovementSpeedForCell(Actor self, CPos cell)
|
||||
{
|
||||
var type = self.World.GetTerrainType(cell);
|
||||
|
||||
if (!Info.TerrainSpeeds.ContainsKey(type))
|
||||
var index = self.World.GetTerrainIndex(cell);
|
||||
if (index == -1)
|
||||
return 0;
|
||||
|
||||
decimal speed = Info.Speed * Info.TerrainSpeeds[type].Speed;
|
||||
var speed = Info.TilesetTerrainInfo[self.World.TileSet][index].Speed;
|
||||
if (speed == decimal.Zero)
|
||||
return 0;
|
||||
|
||||
speed *= Info.Speed;
|
||||
foreach (var t in self.TraitsImplementing<ISpeedModifier>())
|
||||
speed *= t.GetSpeedModifier();
|
||||
return (int)(speed / 100);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public RadarColorFromTerrain(Actor self, string terrain)
|
||||
{
|
||||
c = self.World.TileSet.Terrain[terrain].Color;
|
||||
c = self.World.TileSet[self.World.TileSet.GetTerrainIndex(terrain)].Color;
|
||||
}
|
||||
|
||||
public bool VisibleOnRadar(Actor self) { return true; }
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA.Render
|
||||
return false;
|
||||
|
||||
return cargo.CurrentAdjacentCells
|
||||
.Any(c => self.World.Map.IsInMap(c) && info.OpenTerrainTypes.Contains(self.World.GetTerrainType(c)));
|
||||
.Any(c => self.World.Map.IsInMap(c) && info.OpenTerrainTypes.Contains(self.World.GetTerrainInfo(c).Type));
|
||||
}
|
||||
|
||||
void Open()
|
||||
|
||||
@@ -71,36 +71,18 @@ namespace OpenRA.Mods.RA
|
||||
var range = ((ChronoshiftPowerInfo)Info).Range;
|
||||
var sourceTiles = self.World.FindTilesInCircle(xy, range);
|
||||
var destTiles = self.World.FindTilesInCircle(sourceLocation, range);
|
||||
var sourceTerrain = new List<string>();
|
||||
var destTerrain = new List<string>();
|
||||
|
||||
int j = 0;
|
||||
foreach (var t in sourceTiles)
|
||||
using (var se = sourceTiles.GetEnumerator())
|
||||
using (var de = destTiles.GetEnumerator())
|
||||
while (se.MoveNext() && de.MoveNext())
|
||||
{
|
||||
j = j + 1;
|
||||
if (!self.Owner.Shroud.IsExplored(t))
|
||||
return false;
|
||||
sourceTerrain.Add(self.World.GetTerrainType(t));
|
||||
}
|
||||
var a = se.Current;
|
||||
var b = de.Current;
|
||||
|
||||
j = 0;
|
||||
foreach (var t in destTiles)
|
||||
{
|
||||
j = j + 1;
|
||||
if (!self.Owner.Shroud.IsExplored(t))
|
||||
if (!self.Owner.Shroud.IsExplored(a) || !self.Owner.Shroud.IsExplored(b))
|
||||
return false;
|
||||
|
||||
self.World.GetTerrainType(t);
|
||||
destTerrain.Add(self.World.GetTerrainType(t));
|
||||
}
|
||||
|
||||
// HACK but I don't want to write a comparison function
|
||||
if (sourceTerrain.Count != destTerrain.Count)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < sourceTerrain.Count; i++)
|
||||
{
|
||||
if (!sourceTerrain[i].Equals(destTerrain[i]))
|
||||
if (self.World.GetTerrainIndex(a) != self.World.GetTerrainIndex(b))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public void AddTile(CPos cell, TileReference<ushort, byte> tile)
|
||||
{
|
||||
map.CustomTerrain[cell.X, cell.Y] = tileset.GetTerrainType(tile);
|
||||
map.CustomTerrain[cell.X, cell.Y] = tileset.GetTerrainIndex(tile);
|
||||
|
||||
// Terrain tiles define their origin at the topleft
|
||||
var s = theater.TileSprite(tile);
|
||||
|
||||
@@ -59,10 +59,6 @@ namespace OpenRA.Mods.RA
|
||||
int[,] domains;
|
||||
Dictionary<int, HashSet<int>> transientConnections;
|
||||
|
||||
// Each terrain has an offset corresponding to its location in a
|
||||
// movement class bitmask. This caches each offset.
|
||||
Dictionary<string, int> terrainOffsets;
|
||||
|
||||
public MovementClassDomainIndex(World world, uint movementClass)
|
||||
{
|
||||
bounds = world.Map.Bounds;
|
||||
@@ -70,14 +66,6 @@ namespace OpenRA.Mods.RA
|
||||
domains = new int[(bounds.Width + bounds.X), (bounds.Height + bounds.Y)];
|
||||
transientConnections = new Dictionary<int, HashSet<int>>();
|
||||
|
||||
terrainOffsets = new Dictionary<string, int>();
|
||||
var terrains = world.TileSet.Terrain.OrderBy(t => t.Key).ToList();
|
||||
foreach (var terrain in terrains)
|
||||
{
|
||||
var terrainOffset = terrains.FindIndex(x => x.Key == terrain.Key);
|
||||
terrainOffsets[terrain.Key] = terrainOffset;
|
||||
}
|
||||
|
||||
BuildDomains(world);
|
||||
}
|
||||
|
||||
@@ -181,8 +169,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
bool CanTraverseTile(World world, CPos p)
|
||||
{
|
||||
var currentTileType = WorldUtils.GetTerrainType(world, p);
|
||||
var terrainOffset = terrainOffsets[currentTileType];
|
||||
var terrainOffset = world.GetTerrainIndex(p);
|
||||
return (movementClass & (1 << terrainOffset)) > 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user