diff --git a/OpenRa.Game/BuildingInfluenceMap.cs b/OpenRa.Game/BuildingInfluenceMap.cs index aa483f00b9..460fd9bdbd 100644 --- a/OpenRa.Game/BuildingInfluenceMap.cs +++ b/OpenRa.Game/BuildingInfluenceMap.cs @@ -25,14 +25,14 @@ namespace OpenRa.Game influence[i, j] = NoClaim; Game.world.ActorAdded += - a => { if (a.traits.Contains()) AddInfluence(a); }; + a => { if (a.traits.Contains()) AddInfluence(a, a.traits.Get()); }; Game.world.ActorRemoved += - a => { if (a.traits.Contains()) RemoveInfluence(a); }; + a => { if (a.traits.Contains()) RemoveInfluence(a, a.traits.Get()); }; } - void AddInfluence(Actor a) + void AddInfluence(Actor a, Traits.Building building) { - var tiles = Footprint.Tiles(a).ToArray(); + var tiles = Footprint.Tiles(a, building).ToArray(); var min = int2.Max(new int2(0, 0), tiles.Aggregate(int2.Min) - new int2(maxDistance, maxDistance)); var max = int2.Min(new int2(128, 128), @@ -42,7 +42,7 @@ namespace OpenRa.Game var initialTileCount = 0; - foreach (var u in Footprint.UnpathableTiles(a.unitInfo, a.Location)) + foreach (var u in Footprint.UnpathableTiles(building.unitInfo, a.Location)) if (IsValid(u)) blocked[u.X, u.Y] = true; @@ -53,7 +53,7 @@ namespace OpenRa.Game ++initialTileCount; } - if (!((UnitInfo.BuildingInfo)a.unitInfo).BaseNormal) + if (!building.unitInfo.BaseNormal) { while (!pq.Empty) { @@ -101,15 +101,15 @@ namespace OpenRa.Game Log.Write("Finished recalculating region. {0} cells updated.", updatedCells); } - void RemoveInfluence(Actor a) + void RemoveInfluence(Actor a, Traits.Building building) { - var tiles = Footprint.Tiles(a).ToArray(); + var tiles = Footprint.Tiles(a, building).ToArray(); var min = int2.Max(new int2(0, 0), tiles.Aggregate(int2.Min) - new int2(maxDistance, maxDistance)); var max = int2.Min(new int2(128, 128), tiles.Aggregate(int2.Max) + new int2(maxDistance, maxDistance)); - foreach (var u in Footprint.UnpathableTiles(a.unitInfo, a.Location)) + foreach (var u in Footprint.UnpathableTiles(building.unitInfo, a.Location)) if (IsValid(u)) blocked[u.X, u.Y] = false; @@ -130,8 +130,12 @@ namespace OpenRa.Game Log.Write("Finished collecting candidates for evacuated region = {0}", actors.Count); - foreach (var b in actors) - AddInfluence(b); /* we can actually safely constrain this a bit more... */ + foreach( var b in actors ) + { + var bb = a.traits.GetOrDefault(); + if( bb != null ) + AddInfluence( b, bb ); + } } bool IsValid(int2 t) diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index d707cb907c..5bb5b2d719 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -163,8 +163,12 @@ namespace OpenRa.Game controller.orderGenerator.Tick(); if (--oreTicks == 0) - using( new PerfSample("ore")) + { + using (new PerfSample("ore")) map.GrowOre(SharedRandom); + oreTicks = oreFrequency; + } + world.Tick(); UnitInfluence.Tick(); foreach (var player in players.Values) @@ -269,7 +273,7 @@ namespace OpenRa.Game static int2? FindAdjacentTile(Actor a, UnitMovementType umt) { - var tiles = Footprint.Tiles(a); + var tiles = Footprint.Tiles(a, a.traits.Get()); var min = tiles.Aggregate(int2.Min) - new int2(1, 1); var max = tiles.Aggregate(int2.Max) + new int2(1, 1); @@ -281,18 +285,17 @@ namespace OpenRa.Game return null; } - public static bool CanPlaceBuilding(string name, int2 xy, Actor toIgnore, bool adjust) + public static bool CanPlaceBuilding(UnitInfo.BuildingInfo building, int2 xy, Actor toIgnore, bool adjust) { - var bi = (UnitInfo.BuildingInfo)Rules.UnitInfo[name]; - return !Footprint.Tiles(bi, xy, adjust).Any( + return !Footprint.Tiles(building, xy, adjust).Any( t => Game.map.ContainsResource(t) || !Game.IsCellBuildable(t, - bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel, + building.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel, toIgnore)); } - public static bool CanPlaceBuilding(string name, int2 xy, bool adjust) + public static bool CanPlaceBuilding( UnitInfo.BuildingInfo building, int2 xy, bool adjust ) { - return CanPlaceBuilding(name, xy, null, adjust); + return CanPlaceBuilding(building, xy, null, adjust); } public static void BuildUnit(Player player, string name) diff --git a/OpenRa.Game/GameRules/Footprint.cs b/OpenRa.Game/GameRules/Footprint.cs index 47ae6fd693..8842af3d2c 100644 --- a/OpenRa.Game/GameRules/Footprint.cs +++ b/OpenRa.Game/GameRules/Footprint.cs @@ -9,14 +9,13 @@ namespace OpenRa.Game.GameRules { static class Footprint { - public static IEnumerable Tiles( UnitInfo unitInfo, int2 position ) + public static IEnumerable Tiles( UnitInfo.BuildingInfo buildingInfo, int2 position ) { - return Tiles(unitInfo, position, true); + return Tiles(buildingInfo, position, true); } - public static IEnumerable Tiles(UnitInfo unitInfo, int2 position, bool adjustForPlacement) + public static IEnumerable Tiles( UnitInfo.BuildingInfo buildingInfo, int2 position, bool adjustForPlacement ) { - var buildingInfo = unitInfo as UnitInfo.BuildingInfo; var dim = buildingInfo.Dimensions; var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x)); @@ -28,21 +27,19 @@ namespace OpenRa.Game.GameRules var adjustment = adjustForPlacement ? AdjustForBuildingSize(buildingInfo) : int2.Zero; - var tiles = TilesWhere(unitInfo.Name, dim, footprint.ToArray(), a => a != '_'); + var tiles = TilesWhere(buildingInfo.Name, dim, footprint.ToArray(), a => a != '_'); return tiles.Select(t => t + position - adjustment); } - public static IEnumerable Tiles(Actor a) + public static IEnumerable Tiles(Actor a, Traits.Building building) { - return Tiles(a.unitInfo, a.Location, false); + return Tiles( building.unitInfo, a.Location, false ); } - public static IEnumerable UnpathableTiles( UnitInfo unitInfo, int2 position ) + public static IEnumerable UnpathableTiles( UnitInfo.BuildingInfo buildingInfo, int2 position ) { - var buildingInfo = unitInfo as UnitInfo.BuildingInfo; - var footprint = buildingInfo.Footprint.Where( x => !char.IsWhiteSpace( x ) ).ToArray(); - foreach( var tile in TilesWhere( unitInfo.Name, buildingInfo.Dimensions, footprint, a => a == 'x' ) ) + foreach( var tile in TilesWhere( buildingInfo.Name, buildingInfo.Dimensions, footprint, a => a == 'x' ) ) yield return tile + position; } @@ -58,11 +55,6 @@ namespace OpenRa.Game.GameRules yield return new int2( x, y ); } - public static int2 AdjustForBuildingSize( string name ) - { - return AdjustForBuildingSize( Rules.UnitInfo[ name ] as UnitInfo.BuildingInfo ); - } - public static int2 AdjustForBuildingSize( UnitInfo.BuildingInfo unitInfo ) { var dim = unitInfo.Dimensions; diff --git a/OpenRa.Game/Graphics/OverlayRenderer.cs b/OpenRa.Game/Graphics/OverlayRenderer.cs index 1883146744..fabcf03fbe 100755 --- a/OpenRa.Game/Graphics/OverlayRenderer.cs +++ b/OpenRa.Game/Graphics/OverlayRenderer.cs @@ -58,8 +58,8 @@ namespace OpenRa.Game.Graphics var sprites = overlaySprites[o]; var spriteIndex = 0; if (Ore.overlayIsFence[o]) spriteIndex = NearbyFences(x, y); - else if (Ore.overlayIsOre[o]) spriteIndex = map.MapTiles[x,y].density; - else if (Ore.overlayIsGems[o]) spriteIndex = map.MapTiles[x,y].density; + else if (Ore.overlayIsOre[o]) spriteIndex = map.MapTiles[x,y].density - 1; + else if (Ore.overlayIsGems[o]) spriteIndex = map.MapTiles[x,y].density - 1; spriteRenderer.DrawSprite(sprites[spriteIndex], Game.CellSize * (float2)location, 0); } diff --git a/OpenRa.Game/Graphics/WorldRenderer.cs b/OpenRa.Game/Graphics/WorldRenderer.cs index 5120afa049..bdc97e0391 100644 --- a/OpenRa.Game/Graphics/WorldRenderer.cs +++ b/OpenRa.Game/Graphics/WorldRenderer.cs @@ -1,44 +1,38 @@ -using System.Drawing; -using System.Linq; -using System.Windows.Forms; -using IjwFramework.Types; -using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using IjwFramework.Types; +using System.Collections.Generic; using OpenRa.Game.Traits; using OpenRa.Game.Support; -using Ijw.DirectX; - -namespace OpenRa.Game.Graphics -{ - class WorldRenderer - { - public readonly TerrainRenderer terrainRenderer; - public readonly SpriteRenderer spriteRenderer; - public readonly LineRenderer lineRenderer; - public readonly Region region; - public readonly UiOverlay uiOverlay; - readonly Renderer renderer; - readonly Texture specialbin; - - public static bool ShowUnitPaths = false; - - public WorldRenderer(Renderer renderer) - { - terrainRenderer = new TerrainRenderer( renderer, Game.map ); - - // TODO: this is layout policy. it belongs at a higher level than this. - region = Region.Create(Game.viewport, DockStyle.Left, - Game.viewport.Width - /*128*/ 0, Draw, - Game.controller.HandleMouseInput); - - Game.viewport.AddRegion(region); - - this.renderer = renderer; - spriteRenderer = new SpriteRenderer(renderer, true); - lineRenderer = new LineRenderer(renderer); - uiOverlay = new UiOverlay(spriteRenderer); - specialbin = renderer.LoadTexture("specialbin.png"); - } +namespace OpenRa.Game.Graphics +{ + class WorldRenderer + { + public readonly TerrainRenderer terrainRenderer; + public readonly SpriteRenderer spriteRenderer; + public readonly LineRenderer lineRenderer; + public readonly Region region; + public readonly UiOverlay uiOverlay; + readonly Renderer renderer; + + public static bool ShowUnitPaths = false; + + public WorldRenderer(Renderer renderer) + { + terrainRenderer = new TerrainRenderer(renderer, Game.map); + + // TODO: this is layout policy. it belongs at a higher level than this. + region = Region.Create(Game.viewport, DockStyle.Left, + Game.viewport.Width, Draw, Game.controller.HandleMouseInput); + Game.viewport.AddRegion(region); + + this.renderer = renderer; + spriteRenderer = new SpriteRenderer(renderer, true); + lineRenderer = new LineRenderer(renderer); + uiOverlay = new UiOverlay(spriteRenderer); + } void DrawSpriteList(RectangleF rect, IEnumerable> images) @@ -47,11 +41,9 @@ namespace OpenRa.Game.Graphics { var loc = image.b; - if (loc.X > rect.Right || loc.X < rect.Left - - image.a.bounds.Width) + if (loc.X > rect.Right || loc.X < rect.Left - image.a.bounds.Width) continue; - if (loc.Y > rect.Bottom || loc.Y < rect.Top - - image.a.bounds.Height) + if (loc.Y > rect.Bottom || loc.Y < rect.Top - image.a.bounds.Height) continue; spriteRenderer.DrawSprite(image.a, loc, image.c); @@ -71,7 +63,7 @@ namespace OpenRa.Game.Graphics foreach (var a in Game.world.Actors .Where(u => u.traits.Contains()) .Select(u => u.traits.Get())) - DrawSpriteList(rect, a.RenderRoof(a.self)); + DrawSpriteList(rect, a.RenderRoof(a.self)); foreach (IEffect e in Game.world.Effects) DrawSpriteList(rect, e.Render()); @@ -96,87 +88,85 @@ namespace OpenRa.Game.Graphics DrawSelectionBox(u, Color.Yellow, false); } - var uog = Game.controller.orderGenerator as UnitOrderGenerator; - if (uog != null) - foreach (var a in uog.selection) - DrawSelectionBox(a, Color.White, true); + if (Game.controller.orderGenerator != null) + Game.controller.orderGenerator.Render(); lineRenderer.Flush(); - } - - void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar) - { - var center = selectedUnit.CenterLocation; - var size = selectedUnit.SelectedSize; - - var xy = center - 0.5f * size; - var XY = center + 0.5f * size; - var Xy = new float2(XY.X, xy.Y); - var xY = new float2(xy.X, XY.Y); - - lineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c); - lineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c); - lineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c); - lineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c); - - lineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c); - lineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c); - lineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c); - lineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c); - - if (drawHealthBar) - { - c = Color.Gray; - lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c); - lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c); - - var healthAmount = (float)selectedUnit.Health / selectedUnit.unitInfo.Strength; - var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red - : (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow - : Color.LimeGreen; - - var healthColor2 = Color.FromArgb( - 255, - healthColor.R / 2, - healthColor.G / 2, - healthColor.B / 2); - - var z = float2.Lerp(xy, Xy, healthAmount); - - lineRenderer.DrawLine(z + new float2(0, -4), Xy + new float2(0,-4), c, c); - lineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c); - - lineRenderer.DrawLine(xy + new float2(0, -3), - z + new float2(0, -3), - healthColor, healthColor); - - lineRenderer.DrawLine(xy + new float2(0, -2), - z + new float2(0, -2), - healthColor2, healthColor2); - - lineRenderer.DrawLine(xy + new float2(0, -4), - z + new float2(0, -4), - healthColor2, healthColor2); - } - - if (ShowUnitPaths) - { - var mobile = selectedUnit.traits.GetOrDefault(); - if (mobile != null) - { - var path = mobile.GetCurrentPath(); - var start = selectedUnit.Location; - - foreach (var step in path) - { - lineRenderer.DrawLine( - Game.CellSize * start + new float2(12, 12), - Game.CellSize * step + new float2(12, 12), - Color.Red, Color.Red); - start = step; - } - } - } - } - } -} + } + + public void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar) + { + var center = selectedUnit.CenterLocation; + var size = selectedUnit.SelectedSize; + + var xy = center - 0.5f * size; + var XY = center + 0.5f * size; + var Xy = new float2(XY.X, xy.Y); + var xY = new float2(xy.X, XY.Y); + + lineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c); + lineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c); + lineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c); + lineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c); + + lineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c); + lineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c); + lineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c); + lineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c); + + if (drawHealthBar) + { + c = Color.Gray; + lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c); + lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c); + + var healthAmount = (float)selectedUnit.Health / selectedUnit.unitInfo.Strength; + var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red + : (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow + : Color.LimeGreen; + + var healthColor2 = Color.FromArgb( + 255, + healthColor.R / 2, + healthColor.G / 2, + healthColor.B / 2); + + var z = float2.Lerp(xy, Xy, healthAmount); + + lineRenderer.DrawLine(z + new float2(0, -4), Xy + new float2(0, -4), c, c); + lineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c); + + lineRenderer.DrawLine(xy + new float2(0, -3), + z + new float2(0, -3), + healthColor, healthColor); + + lineRenderer.DrawLine(xy + new float2(0, -2), + z + new float2(0, -2), + healthColor2, healthColor2); + + lineRenderer.DrawLine(xy + new float2(0, -4), + z + new float2(0, -4), + healthColor2, healthColor2); + } + + if (ShowUnitPaths) + { + var mobile = selectedUnit.traits.GetOrDefault(); + if (mobile != null) + { + var path = mobile.GetCurrentPath(); + var start = selectedUnit.Location; + + foreach (var step in path) + { + lineRenderer.DrawLine( + Game.CellSize * start + new float2(12, 12), + Game.CellSize * step + new float2(12, 12), + Color.Red, Color.Red); + start = step; + } + } + } + } + } +} diff --git a/OpenRa.Game/IOrderGenerator.cs b/OpenRa.Game/IOrderGenerator.cs index 46facb49ba..fe62112832 100644 --- a/OpenRa.Game/IOrderGenerator.cs +++ b/OpenRa.Game/IOrderGenerator.cs @@ -8,5 +8,6 @@ namespace OpenRa.Game { IEnumerable Order( int2 xy, bool lmb ); void Tick(); + void Render(); } } diff --git a/OpenRa.Game/Ore.cs b/OpenRa.Game/Ore.cs index 69e58b5feb..81a5559d0f 100644 --- a/OpenRa.Game/Ore.cs +++ b/OpenRa.Game/Ore.cs @@ -81,22 +81,24 @@ namespace OpenRa.Game static byte GetOreDensity(this Map map, int i, int j) { - // perf fix. it's ugly, i know :( int sum = 0; for (var u = -1; u < 2; u++) for (var v = -1; v < 2; v++) if (map.ContainsOre(i + u, j + v)) ++sum; - sum = sum * 3 / 2; - if (sum > 11) - return 11; + sum = (sum * 4 + 2) / 3; return (byte)sum; } static byte GetGemDensity(this Map map, int i, int j) { - return (byte)Math.Min(2, (AdjacentTiles(new int2(i, j)).Sum( - p => map.ContainsGem(p.X, p.Y) ? 1 : 0) / 3)); + int sum = 0; + for (var u = -1; u < 2; u++) + for (var v = -1; v < 2; v++) + if (map.ContainsGem(i + u, j + v)) + ++sum; + sum = (sum+2) / 3; /* 3 gem units/tile is full. */ + return (byte)sum; } public static bool HasOverlay(this Map map, int i, int j) diff --git a/OpenRa.Game/PathFinder.cs b/OpenRa.Game/PathFinder.cs index 833cae1186..753cfa77b2 100644 --- a/OpenRa.Game/PathFinder.cs +++ b/OpenRa.Game/PathFinder.cs @@ -130,7 +130,10 @@ namespace OpenRa.Game return MakeBidiPath(fromSrc, fromDest, p); /* make some progress on the second search */ - fromDest.Expand( passableCost ); + var q = fromDest.Expand( passableCost ); + + if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity) + return MakeBidiPath(fromSrc, fromDest, q); } return new List(); diff --git a/OpenRa.Game/PathSearch.cs b/OpenRa.Game/PathSearch.cs index dcfee5c826..ce63bde242 100755 --- a/OpenRa.Game/PathSearch.cs +++ b/OpenRa.Game/PathSearch.cs @@ -118,7 +118,7 @@ namespace OpenRa.Game return cellInfo; } - static Func DefaultEstimator( int2 destination ) + public static Func DefaultEstimator( int2 destination ) { return here => { diff --git a/OpenRa.Game/PlaceBuilding.cs b/OpenRa.Game/PlaceBuilding.cs index 53d53adf3c..2848aaf783 100644 --- a/OpenRa.Game/PlaceBuilding.cs +++ b/OpenRa.Game/PlaceBuilding.cs @@ -9,28 +9,27 @@ namespace OpenRa.Game class PlaceBuilding : IOrderGenerator { public readonly Player Owner; - public readonly string Name; + public readonly UnitInfo.BuildingInfo Building; public PlaceBuilding(Player owner, string name) { Owner = owner; - Name = name; + Building = (UnitInfo.BuildingInfo)Rules.UnitInfo[ name ]; } public IEnumerable Order(int2 xy, bool lmb) { if( lmb ) { - if (!Game.CanPlaceBuilding(Name, xy, true)) + if( !Game.CanPlaceBuilding( Building, xy, true ) ) yield break; - var bi = (UnitInfo.BuildingInfo)Rules.UnitInfo[Name]; - var maxDistance = bi.Adjacent + 2; /* real-ra is weird. this is 1 GAP. */ - if( !Footprint.Tiles( bi, xy ).Any( + var maxDistance = Building.Adjacent + 2; /* real-ra is weird. this is 1 GAP. */ + if( !Footprint.Tiles( Building, xy ).Any( t => Game.GetDistanceToBase( t, Owner ) < maxDistance ) ) yield break; - yield return OpenRa.Game.Order.PlaceBuilding( Owner, xy, Name ); + yield return OpenRa.Game.Order.PlaceBuilding( Owner, xy, Building.Name ); } else // rmb { @@ -41,8 +40,13 @@ namespace OpenRa.Game public void Tick() { var producing = Owner.Producing( "Building" ); - if( producing == null || producing.Item != Name || producing.RemainingTime != 0 ) + if( producing == null || producing.Item != Building.Name || producing.RemainingTime != 0 ) Game.world.AddFrameEndTask( _ => { Game.controller.orderGenerator = null; } ); } + + public void Render() + { + Game.worldRenderer.uiOverlay.DrawBuildingGrid( Building ); + } } } diff --git a/OpenRa.Game/Traits/AcceptsOre.cs b/OpenRa.Game/Traits/AcceptsOre.cs index 7b0db686f1..dad718450c 100644 --- a/OpenRa.Game/Traits/AcceptsOre.cs +++ b/OpenRa.Game/Traits/AcceptsOre.cs @@ -16,7 +16,7 @@ namespace OpenRa.Game.Traits var harvester = new Actor("harv", self.Location + new int2(1, 2), self.Owner); var mobile = harvester.traits.Get(); mobile.facing = 64; - mobile.InternalSetActivity(new Harvest()); + mobile.QueueActivity(new Harvest()); w.Add(harvester); }); } diff --git a/OpenRa.Game/Traits/Activities/Attack.cs b/OpenRa.Game/Traits/Activities/Attack.cs index 545233dd35..31db0f3ce9 100644 --- a/OpenRa.Game/Traits/Activities/Attack.cs +++ b/OpenRa.Game/Traits/Activities/Attack.cs @@ -19,20 +19,13 @@ namespace OpenRa.Game.Traits.Activities public IActivity NextActivity { get; set; } - public void Tick(Actor self, Mobile mobile) + public IActivity Tick( Actor self, Mobile mobile ) { - if (Target.IsDead) - { - mobile.InternalSetActivity(NextActivity); - return; - } + if (Target == null || Target.IsDead) + return NextActivity; if ((Target.Location - self.Location).LengthSquared >= Range * Range) - { - mobile.InternalSetActivity(new Move(Target, Range)); - mobile.QueueActivity(this); - return; - } + return new Move( Target, Range ) { NextActivity = this }; var desiredFacing = Util.GetFacing((Target.Location - self.Location).ToFloat2(), 0); var renderUnit = self.traits.WithInterface().First(); @@ -40,19 +33,18 @@ namespace OpenRa.Game.Traits.Activities if (Util.QuantizeFacing(mobile.facing, renderUnit.anim.CurrentSequence.Length) != Util.QuantizeFacing(desiredFacing, renderUnit.anim.CurrentSequence.Length)) { - mobile.InternalSetActivity(new Turn(desiredFacing)); - mobile.QueueActivity(this); - return; + return new Turn( desiredFacing ) { NextActivity = this }; } var attack = self.traits.WithInterface().First(); attack.target = Target; attack.DoAttack(self); + return null; } public void Cancel(Actor self, Mobile mobile) { - mobile.InternalSetActivity(null); + Target = null; } } } diff --git a/OpenRa.Game/Traits/Activities/DeliverOre.cs b/OpenRa.Game/Traits/Activities/DeliverOre.cs index 9ce9afa2a5..4d9d26a659 100644 --- a/OpenRa.Game/Traits/Activities/DeliverOre.cs +++ b/OpenRa.Game/Traits/Activities/DeliverOre.cs @@ -12,6 +12,8 @@ namespace OpenRa.Game.Traits.Activities bool isDone; Actor refinery; + public DeliverOre() { } + public DeliverOre( Actor refinery ) { this.refinery = refinery; @@ -19,45 +21,59 @@ namespace OpenRa.Game.Traits.Activities static readonly int2 refineryDeliverOffset = new int2( 1, 2 ); - public void Tick(Actor self, Mobile mobile) + public IActivity Tick( Actor self, Mobile mobile ) { - if( self.Location != refinery.Location + refineryDeliverOffset ) + if( isDone ) { - var move = new Move( refinery.Location + refineryDeliverOffset, 0 ); - mobile.InternalSetActivity( move ); - mobile.QueueActivity( this ); - move.Tick( self, mobile ); - return; + self.traits.Get().Deliver( self ); + return NextActivity ?? new Harvest(); + } + else if( NextActivity != null ) + return NextActivity; + + if( refinery != null && refinery.IsDead ) + refinery = null; + + if( refinery == null || self.Location != refinery.Location + refineryDeliverOffset ) + { + var search = new PathSearch + { + heuristic = PathSearch.DefaultEstimator( self.Location ), + umt = mobile.GetMovementType(), + checkForBlocked = false, + }; + var refineries = Game.world.Actors.Where( x => x.unitInfo != null && x.unitInfo.Name == "proc" ).ToList(); + if( refinery != null ) + search.AddInitialCell( refinery.Location + refineryDeliverOffset ); + else + foreach( var r in refineries ) + search.AddInitialCell( r.Location + refineryDeliverOffset ); + + var path = Game.PathFinder.FindPath( search ); + path.Reverse(); + if( path.Count != 0 ) + { + refinery = refineries.FirstOrDefault( x => x.Location + refineryDeliverOffset == path[ 0 ] ); + return new Move( () => path ) { NextActivity = this }; + } + else + // no refineries reachable? + return null; } else if( mobile.facing != 64 ) - { - var turn = new Turn( 64 ); - mobile.InternalSetActivity( turn ); - mobile.QueueActivity( this ); - turn.Tick( self, mobile ); - return; - } - else if (isDone) - { - var harv = self.traits.Get(); - - harv.Deliver(self); - - if( NextActivity == null ) - NextActivity = new Harvest(); - mobile.InternalSetActivity(NextActivity); - return; - } + return new Turn( 64 ) { NextActivity = this }; var renderUnit = self.traits.WithInterface().First(); - if (renderUnit.anim.CurrentSequence.Name != "empty") - renderUnit.PlayCustomAnimation(self, "empty", - () => isDone = true); + if( renderUnit.anim.CurrentSequence.Name != "empty" ) + renderUnit.PlayCustomAnimation( self, "empty", + () => isDone = true ); + + return null; } public void Cancel(Actor self, Mobile mobile) { - mobile.InternalSetActivity(null); + // TODO: allow canceling of deliver orders? } } } diff --git a/OpenRa.Game/Traits/Activities/DeployMcv.cs b/OpenRa.Game/Traits/Activities/DeployMcv.cs index def708eed5..02ae60be48 100755 --- a/OpenRa.Game/Traits/Activities/DeployMcv.cs +++ b/OpenRa.Game/Traits/Activities/DeployMcv.cs @@ -9,13 +9,14 @@ namespace OpenRa.Game.Traits.Activities { public IActivity NextActivity { get; set; } - public void Tick( Actor self, Mobile mobile ) + public IActivity Tick( Actor self, Mobile mobile ) { Game.world.AddFrameEndTask( _ => { Game.world.Remove( self ); Game.world.Add( new Actor( "fact", self.Location - new int2( 1, 1 ), self.Owner ) ); } ); + return null; } public void Cancel( Actor self, Mobile mobile ) diff --git a/OpenRa.Game/Traits/Activities/Follow.cs b/OpenRa.Game/Traits/Activities/Follow.cs index 9b19c7aea4..18e4304a6b 100644 --- a/OpenRa.Game/Traits/Activities/Follow.cs +++ b/OpenRa.Game/Traits/Activities/Follow.cs @@ -18,24 +18,20 @@ namespace OpenRa.Game.Traits.Activities public IActivity NextActivity { get; set; } - public void Tick(Actor self, Mobile mobile) + public IActivity Tick( Actor self, Mobile mobile ) { - if (Target.IsDead) - { - mobile.InternalSetActivity(NextActivity); - return; - } + if (Target == null || Target.IsDead) + return NextActivity; - if ((Target.Location - self.Location).LengthSquared >= Range * Range) - { - mobile.InternalSetActivity(new Move(Target, Range)); - mobile.QueueActivity(this); - } + if( ( Target.Location - self.Location ).LengthSquared >= Range * Range ) + return new Move( Target, Range ) { NextActivity = this }; + + return null; } public void Cancel(Actor self, Mobile mobile) { - mobile.InternalSetActivity(null); + Target = null; } } } diff --git a/OpenRa.Game/Traits/Activities/Harvest.cs b/OpenRa.Game/Traits/Activities/Harvest.cs index ed444d8bfc..44c271062c 100644 --- a/OpenRa.Game/Traits/Activities/Harvest.cs +++ b/OpenRa.Game/Traits/Activities/Harvest.cs @@ -10,82 +10,49 @@ namespace OpenRa.Game.Traits.Activities public IActivity NextActivity { get; set; } bool isHarvesting = false; - public void Tick(Actor self, Mobile mobile) + public IActivity Tick( Actor self, Mobile mobile ) { + if( isHarvesting ) return null; + if( NextActivity != null ) - { - mobile.InternalSetActivity( NextActivity ); - NextActivity.Tick( self, mobile ); - return; - } + return NextActivity; var harv = self.traits.Get(); - var isGem = false; - if (!harv.IsFull && - Game.map.ContainsResource(self.Location) && - Game.map.Harvest(self.Location, out isGem)) + if( harv.IsFull ) + return new DeliverOre { NextActivity = NextActivity }; + + var isGem = false; + if( Game.map.ContainsResource( self.Location ) && + Game.map.Harvest( self.Location, out isGem ) ) { - var harvestAnim = "harvest" + Util.QuantizeFacing(mobile.facing, 8); + var harvestAnim = "harvest" + Util.QuantizeFacing( mobile.facing, 8 ); var renderUnit = self.traits.WithInterface().First(); /* better have one of these! */ if( harvestAnim != renderUnit.anim.CurrentSequence.Name ) { isHarvesting = true; renderUnit.PlayCustomAnimation( self, harvestAnim, () => isHarvesting = false ); } - harv.AcceptResource(isGem); - return; + harv.AcceptResource( isGem ); + return null; } - - if (isHarvesting) return; - - if (harv.IsFull) - PlanReturnToBase(self, mobile); else - PlanMoreHarvesting(self, mobile); - } - - /* maybe this doesnt really belong here, since it's the - * same as what UnitOrders has to do for an explicit return */ - - void PlanReturnToBase(Actor self, Mobile mobile) - { - /* find a proc */ - var proc = ChooseReturnLocation(self); - if( proc != null ) - mobile.QueueActivity( new DeliverOre( proc ) ); - - mobile.InternalSetActivity(NextActivity); - } - - static Actor ChooseReturnLocation(Actor self) - { - /* todo: compute paths to possible procs, taking into account enemy presence */ - /* currently, we're good at choosing close, inaccessible procs */ - - return Game.world.Actors.Where( - a => a.Owner == self.Owner && - a.traits.Contains()) - .OrderBy(p => (p.Location - self.Location).LengthSquared) - .FirstOrDefault(); - } - - void PlanMoreHarvesting(Actor self, Mobile mobile) - { - mobile.QueueActivity(new Move( - () => - { - var search = new PathSearch + { + mobile.QueueActivity( new Move( + () => { - heuristic = loc => (Game.map.ContainsResource(loc) ? 0 : 1), - umt = UnitMovementType.Wheel, - checkForBlocked = true - }; - search.AddInitialCell(self.Location); - return Game.PathFinder.FindPath(search); - })); - mobile.QueueActivity(new Harvest()); - mobile.InternalSetActivity( NextActivity ); + var search = new PathSearch + { + heuristic = loc => ( Game.map.ContainsResource( loc ) ? 0 : 1 ), + umt = UnitMovementType.Wheel, + checkForBlocked = true + }; + search.AddInitialCell( self.Location ); + return Game.PathFinder.FindPath( search ); + } ) ); + mobile.QueueActivity( new Harvest() ); + return NextActivity; + } } public void Cancel(Actor self, Mobile mobile) { } diff --git a/OpenRa.Game/Traits/Activities/IActivity.cs b/OpenRa.Game/Traits/Activities/IActivity.cs index 53eb5ace06..2ec4556871 100644 --- a/OpenRa.Game/Traits/Activities/IActivity.cs +++ b/OpenRa.Game/Traits/Activities/IActivity.cs @@ -8,7 +8,7 @@ namespace OpenRa.Game.Traits.Activities interface IActivity { IActivity NextActivity { get; set; } - void Tick( Actor self, Mobile mobile ); + IActivity Tick( Actor self, Mobile mobile ); void Cancel( Actor self, Mobile mobile ); } } diff --git a/OpenRa.Game/Traits/Activities/Move.cs b/OpenRa.Game/Traits/Activities/Move.cs index bb90417c65..df3b82b6f9 100755 --- a/OpenRa.Game/Traits/Activities/Move.cs +++ b/OpenRa.Game/Traits/Activities/Move.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using OpenRa.Game.GameRules; +using System.Diagnostics; namespace OpenRa.Game.Traits.Activities { @@ -48,43 +49,42 @@ namespace OpenRa.Game.Traits.Activities return (u == null || u == self); } - public void Tick( Actor self, Mobile mobile ) + public IActivity Tick( Actor self, Mobile mobile ) { if( move != null ) { move.TickMove( self, mobile, this ); - return; + return null; } if( destination == self.Location ) - { - mobile.InternalSetActivity( NextActivity ); - return; - } + return NextActivity; - if( path == null ) path = getPath( self, mobile ).TakeWhile( a => a != self.Location ).ToList(); + if( path == null ) + { + path = getPath( self, mobile ).TakeWhile( a => a != self.Location ).ToList(); + SanityCheckPath( mobile ); + } if( path.Count == 0 ) { destination = mobile.toCell; - return; + return null; } destination = path[ 0 ]; var nextCell = PopPath( self, mobile ); if( nextCell == null ) - return; + return null; int2 dir = nextCell.Value - mobile.fromCell; var firstFacing = Util.GetFacing( dir, mobile.facing ); if( firstFacing != mobile.facing ) { - var t = new Turn( firstFacing ) { NextActivity = this }; - mobile.InternalSetActivity( t ); path.Add( nextCell.Value ); - t.Tick( self, mobile ); + return new Turn( firstFacing ) { NextActivity = this }; } else { @@ -99,9 +99,21 @@ namespace OpenRa.Game.Traits.Activities Game.UnitInfluence.Update( mobile ); move.TickMove( self, mobile, this ); + + return null; } } + [Conditional( "SANITY_CHECKS")] + void SanityCheckPath( Mobile mobile ) + { + if( path.Count == 0 ) + return; + var d = path[path.Count-1] - mobile.toCell; + if( d.LengthSquared > 2 ) + throw new InvalidOperationException( "(Move) Sanity check failed" ); + } + int2? PopPath( Actor self, Mobile mobile ) { if( path.Count == 0 ) return null; diff --git a/OpenRa.Game/Traits/Activities/Turn.cs b/OpenRa.Game/Traits/Activities/Turn.cs index f36285101a..5b607ee4c1 100755 --- a/OpenRa.Game/Traits/Activities/Turn.cs +++ b/OpenRa.Game/Traits/Activities/Turn.cs @@ -16,16 +16,13 @@ namespace OpenRa.Game.Traits.Activities this.desiredFacing = desiredFacing; } - public void Tick( Actor self, Mobile mobile ) + public IActivity Tick( Actor self, Mobile mobile ) { if( desiredFacing == mobile.facing ) - { - mobile.InternalSetActivity( NextActivity ); - if( NextActivity != null ) - NextActivity.Tick( self, mobile ); - return; - } + return NextActivity; + Util.TickFacing( ref mobile.facing, desiredFacing, self.unitInfo.ROT ); + return null; } public void Cancel( Actor self, Mobile mobile ) diff --git a/OpenRa.Game/Traits/Building.cs b/OpenRa.Game/Traits/Building.cs index 0894e00baf..d6585296f8 100644 --- a/OpenRa.Game/Traits/Building.cs +++ b/OpenRa.Game/Traits/Building.cs @@ -8,8 +8,11 @@ namespace OpenRa.Game.Traits { class Building : ITick, INotifyBuildComplete { + public readonly UnitInfo.BuildingInfo unitInfo; + public Building(Actor self) { + unitInfo = (UnitInfo.BuildingInfo)self.unitInfo; } bool first = true; @@ -23,10 +26,7 @@ namespace OpenRa.Game.Traits public void BuildingComplete(Actor self) { - UnitInfo.BuildingInfo bi = self.unitInfo as UnitInfo.BuildingInfo; - if (bi == null) return; - - self.Owner.ChangePower(bi.Power); + self.Owner.ChangePower(unitInfo.Power); } } } diff --git a/OpenRa.Game/Traits/McvDeploy.cs b/OpenRa.Game/Traits/McvDeploy.cs index 875ab743a5..06a2866b98 100644 --- a/OpenRa.Game/Traits/McvDeploy.cs +++ b/OpenRa.Game/Traits/McvDeploy.cs @@ -1,23 +1,23 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using System.Text; -using OpenRa.Game.GameRules; - -namespace OpenRa.Game.Traits -{ - class McvDeploy : IOrder +using OpenRa.Game.GameRules; + +namespace OpenRa.Game.Traits +{ + class McvDeploy : IOrder { - public McvDeploy(Actor self) { } + public McvDeploy(Actor self) { } public Order Order(Actor self, int2 xy, bool lmb, Actor underCursor) { if (lmb) return null; - if (xy == self.Location) - return OpenRa.Game.Order.DeployMcv(self, !Game.CanPlaceBuilding("fact", xy - new int2(1,1), self, false)); + if( xy != self.Location ) return null; - return null; - } - } -} + var factBuildingInfo = (UnitInfo.BuildingInfo)Rules.UnitInfo[ "fact" ]; + return OpenRa.Game.Order.DeployMcv(self, !Game.CanPlaceBuilding(factBuildingInfo, xy - new int2(1,1), self, false)); + } + } +} diff --git a/OpenRa.Game/Traits/Mobile.cs b/OpenRa.Game/Traits/Mobile.cs index 73bfe0103b..3bddabd6ea 100644 --- a/OpenRa.Game/Traits/Mobile.cs +++ b/OpenRa.Game/Traits/Mobile.cs @@ -42,17 +42,20 @@ namespace OpenRa.Game.Traits act.NextActivity = nextActivity; } - public void InternalSetActivity( IActivity activity ) - { - currentActivity = activity; - } - public void Tick(Actor self) { - if( currentActivity != null ) - currentActivity.Tick( self, this ); - else + if( currentActivity == null ) + { fromCell = toCell; + return; + } + + var nextActivity = currentActivity; + while( nextActivity != null ) + { + currentActivity = nextActivity; + nextActivity = nextActivity.Tick( self, this ); + } } public Order Order(Actor self, int2 xy, bool lmb, Actor underCursor) @@ -81,10 +84,19 @@ namespace OpenRa.Game.Traits public UnitMovementType GetMovementType() { - var vi = self.unitInfo as UnitInfo.VehicleInfo; - if (vi == null) return UnitMovementType.Foot; - if (vi.WaterBound) return UnitMovementType.Float; - return vi.Tracked ? UnitMovementType.Track : UnitMovementType.Wheel; + switch( Rules.UnitCategory[ self.unitInfo.Name ] ) + { + case "Infantry": + return UnitMovementType.Foot; + case "Vehicle": + return ( self.unitInfo as UnitInfo.VehicleInfo ).Tracked ? UnitMovementType.Track : UnitMovementType.Wheel; + case "Ship": + return UnitMovementType.Float; + case "Plane": + return UnitMovementType.Track; // FIXME: remove this when planes actually fly. + default: + throw new InvalidOperationException( "GetMovementType on unit that shouldn't be aable to move." ); + } } public IEnumerable GetCurrentPath() diff --git a/OpenRa.Game/Traits/RallyPoint.cs b/OpenRa.Game/Traits/RallyPoint.cs index c2527f29b9..a5dce9541d 100644 --- a/OpenRa.Game/Traits/RallyPoint.cs +++ b/OpenRa.Game/Traits/RallyPoint.cs @@ -15,7 +15,7 @@ namespace OpenRa.Game.Traits public RallyPoint(Actor self) { - var bi = (UnitInfo.BuildingInfo)self.unitInfo; + var bi = self.traits.Get().unitInfo; rallyPoint = self.Location + new int2(bi.RallyPoint[0], bi.RallyPoint[1]); anim = new Animation("flagfly"); anim.PlayRepeating("idle"); diff --git a/OpenRa.Game/Traits/RenderBuilding.cs b/OpenRa.Game/Traits/RenderBuilding.cs index b8f46e28b6..3c0e449a16 100644 --- a/OpenRa.Game/Traits/RenderBuilding.cs +++ b/OpenRa.Game/Traits/RenderBuilding.cs @@ -43,7 +43,7 @@ namespace OpenRa.Game.Traits void DoBib(Actor self, bool isRemove) { - var buildingInfo = (UnitInfo.BuildingInfo)self.unitInfo; + var buildingInfo = self.traits.Get().unitInfo; if (buildingInfo.Bib) { var size = buildingInfo.Dimensions.X; diff --git a/OpenRa.Game/UiOverlay.cs b/OpenRa.Game/UiOverlay.cs index d7e5f7be2b..76cc57127c 100644 --- a/OpenRa.Game/UiOverlay.cs +++ b/OpenRa.Game/UiOverlay.cs @@ -41,30 +41,28 @@ namespace OpenRa.Game for (var i = 0; i < 128; i++) if (Game.UnitInfluence.GetUnitAt(new int2(i, j)) != null) spriteRenderer.DrawSprite(unitDebug, Game.CellSize * new float2(i, j), 0); + } - var placeBuilding = Game.controller.orderGenerator as PlaceBuilding; - if (placeBuilding == null) return; - + public void DrawBuildingGrid( UnitInfo.BuildingInfo bi ) + { var position = Game.controller.MousePosition.ToInt2(); - var bi = (UnitInfo.BuildingInfo)Rules.UnitInfo[placeBuilding.Name]; - var maxDistance = bi.Adjacent + 2; /* real-ra is weird. this is 1 GAP. */ - if (ShowBuildDebug) - for (var j = 0; j < 128; j++) - for (var i = 0; i < 128; i++) - if (Game.GetDistanceToBase(new int2(i, j), Game.LocalPlayer) < maxDistance) - if (Game.IsCellBuildable(new int2(i, j), bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel)) - if (!Game.map.ContainsResource(new int2(i,j))) - spriteRenderer.DrawSprite(unitDebug, Game.CellSize * new float2(i, j), 0); - - var tooFarFromBase = !Footprint.Tiles(bi, position).Any( - t => Game.GetDistanceToBase(t, Game.LocalPlayer) < maxDistance); + if( ShowBuildDebug ) + for( var j = 0 ; j < 128 ; j++ ) + for( var i = 0 ; i < 128 ; i++ ) + if( Game.GetDistanceToBase( new int2( i, j ), Game.LocalPlayer ) < maxDistance ) + if( Game.IsCellBuildable( new int2( i, j ), bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel ) ) + if( !Game.map.ContainsResource( new int2( i, j ) ) ) + spriteRenderer.DrawSprite( unitDebug, Game.CellSize * new float2( i, j ), 0 ); + + var tooFarFromBase = !Footprint.Tiles( bi, position ).Any( + t => Game.GetDistanceToBase( t, Game.LocalPlayer ) < maxDistance ); foreach( var t in Footprint.Tiles( bi, position ) ) - spriteRenderer.DrawSprite( (!tooFarFromBase && Game.IsCellBuildable( t, bi.WaterBound - ? UnitMovementType.Float : UnitMovementType.Wheel ) && !Game.map.ContainsResource(t)) + spriteRenderer.DrawSprite( ( !tooFarFromBase && Game.IsCellBuildable( t, bi.WaterBound + ? UnitMovementType.Float : UnitMovementType.Wheel ) && !Game.map.ContainsResource( t ) ) ? buildOk : buildBlocked, Game.CellSize * t, 0 ); spriteRenderer.Flush(); diff --git a/OpenRa.Game/UnitInfluenceMap.cs b/OpenRa.Game/UnitInfluenceMap.cs index 14bd9933a3..4f4f57f104 100644 --- a/OpenRa.Game/UnitInfluenceMap.cs +++ b/OpenRa.Game/UnitInfluenceMap.cs @@ -18,13 +18,13 @@ namespace OpenRa.Game public void Tick() { - SanityCheck(); + //SanityCheck(); - var units = Game.world.Actors - .Select( a => a.traits.GetOrDefault() ).Where( m => m != null ); + //var units = Game.world.Actors + // .Select( a => a.traits.GetOrDefault() ).Where( m => m != null ); - foreach (var u in units) - Update(u); + //foreach (var u in units) + // Update(u); SanityCheck(); } diff --git a/OpenRa.Game/UnitOrderGenerator.cs b/OpenRa.Game/UnitOrderGenerator.cs index c861e6779c..116da89e0e 100755 --- a/OpenRa.Game/UnitOrderGenerator.cs +++ b/OpenRa.Game/UnitOrderGenerator.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; -using System.Text; namespace OpenRa.Game { @@ -28,5 +28,11 @@ namespace OpenRa.Game { selection.RemoveAll(a => a.IsDead); } + + public void Render() + { + foreach( var a in selection ) + Game.worldRenderer.DrawSelectionBox( a, Color.White, true ); + } } } diff --git a/OpenRa.Game/UnitOrders.cs b/OpenRa.Game/UnitOrders.cs index df36cd1574..86734dff3c 100755 --- a/OpenRa.Game/UnitOrders.cs +++ b/OpenRa.Game/UnitOrders.cs @@ -49,7 +49,8 @@ namespace OpenRa.Game } case "DeployMcv": { - if (!Game.CanPlaceBuilding("fact", order.Subject.Location - new int2(1,1), order.Subject, false)) + var factBuildingInfo = (UnitInfo.BuildingInfo)Rules.UnitInfo[ "fact" ]; + if( !Game.CanPlaceBuilding( factBuildingInfo, order.Subject.Location - new int2( 1, 1 ), order.Subject, false ) ) break; /* throw the order on the floor */ var mobile = order.Subject.traits.Get(); @@ -77,14 +78,14 @@ namespace OpenRa.Game { Game.world.AddFrameEndTask( _ => { - var building = Rules.UnitInfo[ order.TargetString ]; + var building = (UnitInfo.BuildingInfo)Rules.UnitInfo[ order.TargetString ]; var producing = order.Player.Producing( "Building" ); if( producing == null || producing.Item != order.TargetString || producing.RemainingTime != 0 ) return; Log.Write( "Player \"{0}\" builds {1}", order.Player.PlayerName, building.Name ); - Game.world.Add( new Actor( building.Name, order.TargetLocation - GameRules.Footprint.AdjustForBuildingSize( building.Name ), order.Player ) ); + Game.world.Add( new Actor( building.Name, order.TargetLocation - GameRules.Footprint.AdjustForBuildingSize( building ), order.Player ) ); order.Player.FinishProduction(Rules.UnitCategory[building.Name]); } ); @@ -99,7 +100,7 @@ namespace OpenRa.Game * ( 25 * 60 ) /* frames per min */ /* todo: build acceleration, if we do that */ / 1000; - time = .05f * time; /* temporary hax so we can build stuff fast for test */ + time = .01f * time; /* temporary hax so we can build stuff fast for test */ order.Player.BeginProduction(group, new ProductionItem(order.TargetString, (int)time, ui.Cost, diff --git a/sequences.xml b/sequences.xml index cc38b910b7..84e522d324 100644 --- a/sequences.xml +++ b/sequences.xml @@ -259,8 +259,9 @@ - - + + +