diff --git a/OpenRa.DataStructures/TypeDictionary.cs b/OpenRa.DataStructures/TypeDictionary.cs index d68146a056..b30afa5465 100755 --- a/OpenRa.DataStructures/TypeDictionary.cs +++ b/OpenRa.DataStructures/TypeDictionary.cs @@ -33,6 +33,13 @@ namespace OpenRa return (T)inner[ typeof( T ) ]; } + public T GetOrDefault() + { + object o = null; + inner.TryGetValue(typeof(T), out o); + return (T)o; + } + public IEnumerable WithInterface() { foreach( var i in inner ) diff --git a/OpenRa.Game/BuildingInfluenceMap.cs b/OpenRa.Game/BuildingInfluenceMap.cs index 6159b8912d..2d531b7c61 100644 --- a/OpenRa.Game/BuildingInfluenceMap.cs +++ b/OpenRa.Game/BuildingInfluenceMap.cs @@ -14,7 +14,7 @@ namespace OpenRa.Game readonly int maxDistance; /* clip limit for voronoi cells */ static readonly Pair NoClaim = Pair.New((Actor)null, float.MaxValue); - public BuildingInfluenceMap(World world, int maxDistance) + public BuildingInfluenceMap(int maxDistance) { this.maxDistance = maxDistance; @@ -22,9 +22,9 @@ namespace OpenRa.Game for (int i = 0; i < 128; i++) influence[i, j] = NoClaim; - world.ActorAdded += + Game.world.ActorAdded += a => { if (a.traits.Contains()) AddInfluence(a); }; - world.ActorRemoved += + Game.world.ActorRemoved += a => { if (a.traits.Contains()) RemoveInfluence(a); }; } diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index cfd4760341..607db31896 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -31,48 +31,50 @@ namespace OpenRa.Game public static Dictionary players = new Dictionary(); public static Player LocalPlayer { get { return players[localPlayerIndex]; } } - public static BuildingInfluenceMap BuildingInfluence; + public static BuildingInfluenceMap BuildingInfluence; + public static UnitInfluenceMap UnitInfluence; - static ISoundEngine soundEngine; - - public static void Initialize(string mapName, Renderer renderer, int2 clientSize, int localPlayer) - { - Rules.LoadRules( mapName ); - - for( int i = 0 ; i < 8 ; i++ ) - players.Add(i, new Player(i, string.Format("Multi{0}", i), Race.Soviet)); - - localPlayerIndex = localPlayer; - - var mapFile = new IniFile( FileSystem.Open( mapName ) ); - map = new Map( mapFile ); - FileSystem.Mount(new Package(map.Theater + ".mix")); - - viewport = new Viewport(clientSize, map.Size, renderer); - - terrain = new TerrainRenderer(renderer, map, viewport); - world = new World(); - treeCache = new TreeCache(map); - - foreach( TreeReference treeReference in map.Trees ) - world.Add( new Actor( treeReference, treeCache, map.Offset ) ); - - BuildingInfluence = new BuildingInfluenceMap(world, 8); - - LoadMapBuildings( mapFile ); - LoadMapUnits( mapFile ); - - pathFinder = new PathFinder(map, terrain.tileSet, BuildingInfluence); - - network = new Network(); - - controller = new Controller(); - worldRenderer = new WorldRenderer(renderer); - - soundEngine = new ISoundEngine(); - sounds = new Cache(LoadSound); - - PlaySound("intro.aud", false); + static ISoundEngine soundEngine; + + public static void Initialize(string mapName, Renderer renderer, int2 clientSize, int localPlayer) + { + Rules.LoadRules(mapName); + + for (int i = 0; i < 8; i++) + players.Add(i, new Player(i, string.Format("Multi{0}", i), Race.Soviet)); + + localPlayerIndex = localPlayer; + + var mapFile = new IniFile(FileSystem.Open(mapName)); + map = new Map(mapFile); + FileSystem.Mount(new Package(map.Theater + ".mix")); + + viewport = new Viewport(clientSize, map.Size, renderer); + + terrain = new TerrainRenderer(renderer, map, viewport); + world = new World(); + treeCache = new TreeCache(map); + + foreach (TreeReference treeReference in map.Trees) + world.Add(new Actor(treeReference, treeCache, map.Offset)); + + BuildingInfluence = new BuildingInfluenceMap(8); + UnitInfluence = new UnitInfluenceMap(); + + LoadMapBuildings(mapFile); + LoadMapUnits(mapFile); + + pathFinder = new PathFinder(map, terrain.tileSet, BuildingInfluence); + + network = new Network(); + + controller = new Controller(); + worldRenderer = new WorldRenderer(renderer); + + soundEngine = new ISoundEngine(); + sounds = new Cache(LoadSound); + + PlaySound("intro.aud", false); } static void LoadMapBuildings( IniFile mapfile ) @@ -122,14 +124,16 @@ namespace OpenRa.Game public static void Tick() { var stuffFromOtherPlayers = network.Tick(); // todo: actually use the orders! - world.Update(); + world.Update(); + UnitInfluence.Tick(); viewport.DrawRegions(); } public static bool IsCellBuildable(int2 a, UnitMovementType umt) { - if (BuildingInfluence.GetBuildingAt(a) != null) return false; + if (BuildingInfluence.GetBuildingAt(a) != null) return false; + if (UnitInfluence.GetUnitAt(a) != null) return false; a += map.Offset; diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 8f01a9917f..157744246f 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -149,6 +149,7 @@ + diff --git a/OpenRa.Game/Traits/Mobile.cs b/OpenRa.Game/Traits/Mobile.cs index fc550e57f9..8ec9c8cb20 100644 --- a/OpenRa.Game/Traits/Mobile.cs +++ b/OpenRa.Game/Traits/Mobile.cs @@ -61,6 +61,11 @@ namespace OpenRa.Game.Traits { if (currentAction != null) currentAction.Cancel(self, this); + } + + public IEnumerable OccupiedCells() + { + return new[] { fromCell, toCell }; } public interface CurrentAction diff --git a/OpenRa.Game/UnitInfluenceMap.cs b/OpenRa.Game/UnitInfluenceMap.cs new file mode 100644 index 0000000000..29bc3f6255 --- /dev/null +++ b/OpenRa.Game/UnitInfluenceMap.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenRa.Game +{ + class UnitInfluenceMap + { + Actor[,] influence = new Actor[128, 128]; + + /* todo: incremental updates for great justice [and perf] */ + + public void Tick() + { + influence = new Actor[128, 128]; + + var units = Game.world.Actors + .Select( a => a.traits.GetOrDefault() ).Where( m => m != null ); + + foreach (var u in units) + foreach (var c in u.OccupiedCells()) + influence[c.X, c.Y] = u.self; + } + + public Actor GetUnitAt(int2 a) { return influence[a.X, a.Y]; } + } +}