This commit is contained in:
Chris Forbes
2009-11-15 20:34:04 +13:00
29 changed files with 377 additions and 379 deletions

View File

@@ -25,14 +25,14 @@ namespace OpenRa.Game
influence[i, j] = NoClaim; influence[i, j] = NoClaim;
Game.world.ActorAdded += Game.world.ActorAdded +=
a => { if (a.traits.Contains<Traits.Building>()) AddInfluence(a); }; a => { if (a.traits.Contains<Traits.Building>()) AddInfluence(a, a.traits.Get<Traits.Building>()); };
Game.world.ActorRemoved += Game.world.ActorRemoved +=
a => { if (a.traits.Contains<Traits.Building>()) RemoveInfluence(a); }; a => { if (a.traits.Contains<Traits.Building>()) RemoveInfluence(a, a.traits.Get<Traits.Building>()); };
} }
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), var min = int2.Max(new int2(0, 0),
tiles.Aggregate(int2.Min) - new int2(maxDistance, maxDistance)); tiles.Aggregate(int2.Min) - new int2(maxDistance, maxDistance));
var max = int2.Min(new int2(128, 128), var max = int2.Min(new int2(128, 128),
@@ -42,7 +42,7 @@ namespace OpenRa.Game
var initialTileCount = 0; 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)) if (IsValid(u))
blocked[u.X, u.Y] = true; blocked[u.X, u.Y] = true;
@@ -53,7 +53,7 @@ namespace OpenRa.Game
++initialTileCount; ++initialTileCount;
} }
if (!((UnitInfo.BuildingInfo)a.unitInfo).BaseNormal) if (!building.unitInfo.BaseNormal)
{ {
while (!pq.Empty) while (!pq.Empty)
{ {
@@ -101,15 +101,15 @@ namespace OpenRa.Game
Log.Write("Finished recalculating region. {0} cells updated.", updatedCells); 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), var min = int2.Max(new int2(0, 0),
tiles.Aggregate(int2.Min) - new int2(maxDistance, maxDistance)); tiles.Aggregate(int2.Min) - new int2(maxDistance, maxDistance));
var max = int2.Min(new int2(128, 128), var max = int2.Min(new int2(128, 128),
tiles.Aggregate(int2.Max) + new int2(maxDistance, maxDistance)); 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)) if (IsValid(u))
blocked[u.X, u.Y] = false; blocked[u.X, u.Y] = false;
@@ -130,8 +130,12 @@ namespace OpenRa.Game
Log.Write("Finished collecting candidates for evacuated region = {0}", actors.Count); Log.Write("Finished collecting candidates for evacuated region = {0}", actors.Count);
foreach (var b in actors) foreach( var b in actors )
AddInfluence(b); /* we can actually safely constrain this a bit more... */ {
var bb = a.traits.GetOrDefault<Traits.Building>();
if( bb != null )
AddInfluence( b, bb );
}
} }
bool IsValid(int2 t) bool IsValid(int2 t)

View File

@@ -163,8 +163,12 @@ namespace OpenRa.Game
controller.orderGenerator.Tick(); controller.orderGenerator.Tick();
if (--oreTicks == 0) if (--oreTicks == 0)
using( new PerfSample("ore")) {
using (new PerfSample("ore"))
map.GrowOre(SharedRandom); map.GrowOre(SharedRandom);
oreTicks = oreFrequency;
}
world.Tick(); world.Tick();
UnitInfluence.Tick(); UnitInfluence.Tick();
foreach (var player in players.Values) foreach (var player in players.Values)
@@ -269,7 +273,7 @@ namespace OpenRa.Game
static int2? FindAdjacentTile(Actor a, UnitMovementType umt) static int2? FindAdjacentTile(Actor a, UnitMovementType umt)
{ {
var tiles = Footprint.Tiles(a); var tiles = Footprint.Tiles(a, a.traits.Get<Traits.Building>());
var min = tiles.Aggregate(int2.Min) - new int2(1, 1); var min = tiles.Aggregate(int2.Min) - new int2(1, 1);
var max = tiles.Aggregate(int2.Max) + new int2(1, 1); var max = tiles.Aggregate(int2.Max) + new int2(1, 1);
@@ -281,18 +285,17 @@ namespace OpenRa.Game
return null; 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(building, xy, adjust).Any(
return !Footprint.Tiles(bi, xy, adjust).Any(
t => Game.map.ContainsResource(t) || !Game.IsCellBuildable(t, t => Game.map.ContainsResource(t) || !Game.IsCellBuildable(t,
bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel, building.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel,
toIgnore)); 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) public static void BuildUnit(Player player, string name)

View File

@@ -9,14 +9,13 @@ namespace OpenRa.Game.GameRules
{ {
static class Footprint static class Footprint
{ {
public static IEnumerable<int2> Tiles( UnitInfo unitInfo, int2 position ) public static IEnumerable<int2> Tiles( UnitInfo.BuildingInfo buildingInfo, int2 position )
{ {
return Tiles(unitInfo, position, true); return Tiles(buildingInfo, position, true);
} }
public static IEnumerable<int2> Tiles(UnitInfo unitInfo, int2 position, bool adjustForPlacement) public static IEnumerable<int2> Tiles( UnitInfo.BuildingInfo buildingInfo, int2 position, bool adjustForPlacement )
{ {
var buildingInfo = unitInfo as UnitInfo.BuildingInfo;
var dim = buildingInfo.Dimensions; var dim = buildingInfo.Dimensions;
var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x)); 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 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); return tiles.Select(t => t + position - adjustment);
} }
public static IEnumerable<int2> Tiles(Actor a) public static IEnumerable<int2> Tiles(Actor a, Traits.Building building)
{ {
return Tiles(a.unitInfo, a.Location, false); return Tiles( building.unitInfo, a.Location, false );
} }
public static IEnumerable<int2> UnpathableTiles( UnitInfo unitInfo, int2 position ) public static IEnumerable<int2> UnpathableTiles( UnitInfo.BuildingInfo buildingInfo, int2 position )
{ {
var buildingInfo = unitInfo as UnitInfo.BuildingInfo;
var footprint = buildingInfo.Footprint.Where( x => !char.IsWhiteSpace( x ) ).ToArray(); 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; yield return tile + position;
} }
@@ -58,11 +55,6 @@ namespace OpenRa.Game.GameRules
yield return new int2( x, y ); 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 ) public static int2 AdjustForBuildingSize( UnitInfo.BuildingInfo unitInfo )
{ {
var dim = unitInfo.Dimensions; var dim = unitInfo.Dimensions;

View File

@@ -58,8 +58,8 @@ namespace OpenRa.Game.Graphics
var sprites = overlaySprites[o]; var sprites = overlaySprites[o];
var spriteIndex = 0; var spriteIndex = 0;
if (Ore.overlayIsFence[o]) spriteIndex = NearbyFences(x, y); if (Ore.overlayIsFence[o]) spriteIndex = NearbyFences(x, y);
else if (Ore.overlayIsOre[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; else if (Ore.overlayIsGems[o]) spriteIndex = map.MapTiles[x,y].density - 1;
spriteRenderer.DrawSprite(sprites[spriteIndex], spriteRenderer.DrawSprite(sprites[spriteIndex],
Game.CellSize * (float2)location, 0); Game.CellSize * (float2)location, 0);
} }

View File

@@ -1,44 +1,38 @@
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using IjwFramework.Types; using IjwFramework.Types;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRa.Game.Traits; using OpenRa.Game.Traits;
using OpenRa.Game.Support; 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, void DrawSpriteList(RectangleF rect,
IEnumerable<Tuple<Sprite, float2, int>> images) IEnumerable<Tuple<Sprite, float2, int>> images)
@@ -47,11 +41,9 @@ namespace OpenRa.Game.Graphics
{ {
var loc = image.b; var loc = image.b;
if (loc.X > rect.Right || loc.X < rect.Left if (loc.X > rect.Right || loc.X < rect.Left - image.a.bounds.Width)
- image.a.bounds.Width)
continue; continue;
if (loc.Y > rect.Bottom || loc.Y < rect.Top if (loc.Y > rect.Bottom || loc.Y < rect.Top - image.a.bounds.Height)
- image.a.bounds.Height)
continue; continue;
spriteRenderer.DrawSprite(image.a, loc, image.c); spriteRenderer.DrawSprite(image.a, loc, image.c);
@@ -71,7 +63,7 @@ namespace OpenRa.Game.Graphics
foreach (var a in Game.world.Actors foreach (var a in Game.world.Actors
.Where(u => u.traits.Contains<Traits.RenderWarFactory>()) .Where(u => u.traits.Contains<Traits.RenderWarFactory>())
.Select(u => u.traits.Get<Traits.RenderWarFactory>())) .Select(u => u.traits.Get<Traits.RenderWarFactory>()))
DrawSpriteList(rect, a.RenderRoof(a.self)); DrawSpriteList(rect, a.RenderRoof(a.self));
foreach (IEffect e in Game.world.Effects) foreach (IEffect e in Game.world.Effects)
DrawSpriteList(rect, e.Render()); DrawSpriteList(rect, e.Render());
@@ -96,87 +88,85 @@ namespace OpenRa.Game.Graphics
DrawSelectionBox(u, Color.Yellow, false); DrawSelectionBox(u, Color.Yellow, false);
} }
var uog = Game.controller.orderGenerator as UnitOrderGenerator; if (Game.controller.orderGenerator != null)
if (uog != null) Game.controller.orderGenerator.Render();
foreach (var a in uog.selection)
DrawSelectionBox(a, Color.White, true);
lineRenderer.Flush(); lineRenderer.Flush();
} }
void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar) public void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar)
{ {
var center = selectedUnit.CenterLocation; var center = selectedUnit.CenterLocation;
var size = selectedUnit.SelectedSize; var size = selectedUnit.SelectedSize;
var xy = center - 0.5f * size; var xy = center - 0.5f * size;
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);
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(4, 0), c, c);
lineRenderer.DrawLine(xy, xy + new float2(0, 4), 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(-4, 0), c, c);
lineRenderer.DrawLine(Xy, Xy + new float2(0, 4), 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(4, 0), c, c);
lineRenderer.DrawLine(xY, xY + new float2(0, -4), 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(-4, 0), c, c);
lineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c); lineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c);
if (drawHealthBar) if (drawHealthBar)
{ {
c = Color.Gray; 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);
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 healthAmount = (float)selectedUnit.Health / selectedUnit.unitInfo.Strength;
var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red
: (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow : (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow
: Color.LimeGreen; : Color.LimeGreen;
var healthColor2 = Color.FromArgb( var healthColor2 = Color.FromArgb(
255, 255,
healthColor.R / 2, healthColor.R / 2,
healthColor.G / 2, healthColor.G / 2,
healthColor.B / 2); healthColor.B / 2);
var z = float2.Lerp(xy, Xy, healthAmount); 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, -4), Xy + new float2(0, -4), c, c);
lineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c); lineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c);
lineRenderer.DrawLine(xy + new float2(0, -3), lineRenderer.DrawLine(xy + new float2(0, -3),
z + new float2(0, -3), z + new float2(0, -3),
healthColor, healthColor); healthColor, healthColor);
lineRenderer.DrawLine(xy + new float2(0, -2), lineRenderer.DrawLine(xy + new float2(0, -2),
z + new float2(0, -2), z + new float2(0, -2),
healthColor2, healthColor2); healthColor2, healthColor2);
lineRenderer.DrawLine(xy + new float2(0, -4), lineRenderer.DrawLine(xy + new float2(0, -4),
z + new float2(0, -4), z + new float2(0, -4),
healthColor2, healthColor2); healthColor2, healthColor2);
} }
if (ShowUnitPaths) if (ShowUnitPaths)
{ {
var mobile = selectedUnit.traits.GetOrDefault<Mobile>(); var mobile = selectedUnit.traits.GetOrDefault<Mobile>();
if (mobile != null) if (mobile != null)
{ {
var path = mobile.GetCurrentPath(); var path = mobile.GetCurrentPath();
var start = selectedUnit.Location; var start = selectedUnit.Location;
foreach (var step in path) foreach (var step in path)
{ {
lineRenderer.DrawLine( lineRenderer.DrawLine(
Game.CellSize * start + new float2(12, 12), Game.CellSize * start + new float2(12, 12),
Game.CellSize * step + new float2(12, 12), Game.CellSize * step + new float2(12, 12),
Color.Red, Color.Red); Color.Red, Color.Red);
start = step; start = step;
} }
} }
} }
} }
} }
} }

View File

@@ -8,5 +8,6 @@ namespace OpenRa.Game
{ {
IEnumerable<Order> Order( int2 xy, bool lmb ); IEnumerable<Order> Order( int2 xy, bool lmb );
void Tick(); void Tick();
void Render();
} }
} }

View File

@@ -81,22 +81,24 @@ namespace OpenRa.Game
static byte GetOreDensity(this Map map, int i, int j) static byte GetOreDensity(this Map map, int i, int j)
{ {
// perf fix. it's ugly, i know :(
int sum = 0; int sum = 0;
for (var u = -1; u < 2; u++) for (var u = -1; u < 2; u++)
for (var v = -1; v < 2; v++) for (var v = -1; v < 2; v++)
if (map.ContainsOre(i + u, j + v)) if (map.ContainsOre(i + u, j + v))
++sum; ++sum;
sum = sum * 3 / 2; sum = (sum * 4 + 2) / 3;
if (sum > 11)
return 11;
return (byte)sum; return (byte)sum;
} }
static byte GetGemDensity(this Map map, int i, int j) static byte GetGemDensity(this Map map, int i, int j)
{ {
return (byte)Math.Min(2, (AdjacentTiles(new int2(i, j)).Sum( int sum = 0;
p => map.ContainsGem(p.X, p.Y) ? 1 : 0) / 3)); 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) public static bool HasOverlay(this Map map, int i, int j)

View File

@@ -130,7 +130,10 @@ namespace OpenRa.Game
return MakeBidiPath(fromSrc, fromDest, p); return MakeBidiPath(fromSrc, fromDest, p);
/* make some progress on the second search */ /* 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<int2>(); return new List<int2>();

View File

@@ -118,7 +118,7 @@ namespace OpenRa.Game
return cellInfo; return cellInfo;
} }
static Func<int2, float> DefaultEstimator( int2 destination ) public static Func<int2, float> DefaultEstimator( int2 destination )
{ {
return here => return here =>
{ {

View File

@@ -9,28 +9,27 @@ namespace OpenRa.Game
class PlaceBuilding : IOrderGenerator class PlaceBuilding : IOrderGenerator
{ {
public readonly Player Owner; public readonly Player Owner;
public readonly string Name; public readonly UnitInfo.BuildingInfo Building;
public PlaceBuilding(Player owner, string name) public PlaceBuilding(Player owner, string name)
{ {
Owner = owner; Owner = owner;
Name = name; Building = (UnitInfo.BuildingInfo)Rules.UnitInfo[ name ];
} }
public IEnumerable<Order> Order(int2 xy, bool lmb) public IEnumerable<Order> Order(int2 xy, bool lmb)
{ {
if( lmb ) if( lmb )
{ {
if (!Game.CanPlaceBuilding(Name, xy, true)) if( !Game.CanPlaceBuilding( Building, xy, true ) )
yield break; yield break;
var bi = (UnitInfo.BuildingInfo)Rules.UnitInfo[Name]; var maxDistance = Building.Adjacent + 2; /* real-ra is weird. this is 1 GAP. */
var maxDistance = bi.Adjacent + 2; /* real-ra is weird. this is 1 GAP. */ if( !Footprint.Tiles( Building, xy ).Any(
if( !Footprint.Tiles( bi, xy ).Any(
t => Game.GetDistanceToBase( t, Owner ) < maxDistance ) ) t => Game.GetDistanceToBase( t, Owner ) < maxDistance ) )
yield break; yield break;
yield return OpenRa.Game.Order.PlaceBuilding( Owner, xy, Name ); yield return OpenRa.Game.Order.PlaceBuilding( Owner, xy, Building.Name );
} }
else // rmb else // rmb
{ {
@@ -41,8 +40,13 @@ namespace OpenRa.Game
public void Tick() public void Tick()
{ {
var producing = Owner.Producing( "Building" ); 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; } ); Game.world.AddFrameEndTask( _ => { Game.controller.orderGenerator = null; } );
} }
public void Render()
{
Game.worldRenderer.uiOverlay.DrawBuildingGrid( Building );
}
} }
} }

View File

@@ -16,7 +16,7 @@ namespace OpenRa.Game.Traits
var harvester = new Actor("harv", self.Location + new int2(1, 2), self.Owner); var harvester = new Actor("harv", self.Location + new int2(1, 2), self.Owner);
var mobile = harvester.traits.Get<Mobile>(); var mobile = harvester.traits.Get<Mobile>();
mobile.facing = 64; mobile.facing = 64;
mobile.InternalSetActivity(new Harvest()); mobile.QueueActivity(new Harvest());
w.Add(harvester); w.Add(harvester);
}); });
} }

View File

@@ -19,20 +19,13 @@ namespace OpenRa.Game.Traits.Activities
public IActivity NextActivity { get; set; } public IActivity NextActivity { get; set; }
public void Tick(Actor self, Mobile mobile) public IActivity Tick( Actor self, Mobile mobile )
{ {
if (Target.IsDead) if (Target == null || Target.IsDead)
{ return NextActivity;
mobile.InternalSetActivity(NextActivity);
return;
}
if ((Target.Location - self.Location).LengthSquared >= Range * Range) if ((Target.Location - self.Location).LengthSquared >= Range * Range)
{ return new Move( Target, Range ) { NextActivity = this };
mobile.InternalSetActivity(new Move(Target, Range));
mobile.QueueActivity(this);
return;
}
var desiredFacing = Util.GetFacing((Target.Location - self.Location).ToFloat2(), 0); var desiredFacing = Util.GetFacing((Target.Location - self.Location).ToFloat2(), 0);
var renderUnit = self.traits.WithInterface<RenderUnit>().First(); var renderUnit = self.traits.WithInterface<RenderUnit>().First();
@@ -40,19 +33,18 @@ namespace OpenRa.Game.Traits.Activities
if (Util.QuantizeFacing(mobile.facing, renderUnit.anim.CurrentSequence.Length) if (Util.QuantizeFacing(mobile.facing, renderUnit.anim.CurrentSequence.Length)
!= Util.QuantizeFacing(desiredFacing, renderUnit.anim.CurrentSequence.Length)) != Util.QuantizeFacing(desiredFacing, renderUnit.anim.CurrentSequence.Length))
{ {
mobile.InternalSetActivity(new Turn(desiredFacing)); return new Turn( desiredFacing ) { NextActivity = this };
mobile.QueueActivity(this);
return;
} }
var attack = self.traits.WithInterface<AttackBase>().First(); var attack = self.traits.WithInterface<AttackBase>().First();
attack.target = Target; attack.target = Target;
attack.DoAttack(self); attack.DoAttack(self);
return null;
} }
public void Cancel(Actor self, Mobile mobile) public void Cancel(Actor self, Mobile mobile)
{ {
mobile.InternalSetActivity(null); Target = null;
} }
} }
} }

View File

@@ -12,6 +12,8 @@ namespace OpenRa.Game.Traits.Activities
bool isDone; bool isDone;
Actor refinery; Actor refinery;
public DeliverOre() { }
public DeliverOre( Actor refinery ) public DeliverOre( Actor refinery )
{ {
this.refinery = refinery; this.refinery = refinery;
@@ -19,45 +21,59 @@ namespace OpenRa.Game.Traits.Activities
static readonly int2 refineryDeliverOffset = new int2( 1, 2 ); 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 ); self.traits.Get<Harvester>().Deliver( self );
mobile.InternalSetActivity( move ); return NextActivity ?? new Harvest();
mobile.QueueActivity( this ); }
move.Tick( self, mobile ); else if( NextActivity != null )
return; 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 ) else if( mobile.facing != 64 )
{ return new Turn( 64 ) { NextActivity = this };
var turn = new Turn( 64 );
mobile.InternalSetActivity( turn );
mobile.QueueActivity( this );
turn.Tick( self, mobile );
return;
}
else if (isDone)
{
var harv = self.traits.Get<Harvester>();
harv.Deliver(self);
if( NextActivity == null )
NextActivity = new Harvest();
mobile.InternalSetActivity(NextActivity);
return;
}
var renderUnit = self.traits.WithInterface<RenderUnit>().First(); var renderUnit = self.traits.WithInterface<RenderUnit>().First();
if (renderUnit.anim.CurrentSequence.Name != "empty") if( renderUnit.anim.CurrentSequence.Name != "empty" )
renderUnit.PlayCustomAnimation(self, "empty", renderUnit.PlayCustomAnimation( self, "empty",
() => isDone = true); () => isDone = true );
return null;
} }
public void Cancel(Actor self, Mobile mobile) public void Cancel(Actor self, Mobile mobile)
{ {
mobile.InternalSetActivity(null); // TODO: allow canceling of deliver orders?
} }
} }
} }

View File

@@ -9,13 +9,14 @@ namespace OpenRa.Game.Traits.Activities
{ {
public IActivity NextActivity { get; set; } public IActivity NextActivity { get; set; }
public void Tick( Actor self, Mobile mobile ) public IActivity Tick( Actor self, Mobile mobile )
{ {
Game.world.AddFrameEndTask( _ => Game.world.AddFrameEndTask( _ =>
{ {
Game.world.Remove( self ); Game.world.Remove( self );
Game.world.Add( new Actor( "fact", self.Location - new int2( 1, 1 ), self.Owner ) ); Game.world.Add( new Actor( "fact", self.Location - new int2( 1, 1 ), self.Owner ) );
} ); } );
return null;
} }
public void Cancel( Actor self, Mobile mobile ) public void Cancel( Actor self, Mobile mobile )

View File

@@ -18,24 +18,20 @@ namespace OpenRa.Game.Traits.Activities
public IActivity NextActivity { get; set; } public IActivity NextActivity { get; set; }
public void Tick(Actor self, Mobile mobile) public IActivity Tick( Actor self, Mobile mobile )
{ {
if (Target.IsDead) if (Target == null || Target.IsDead)
{ return NextActivity;
mobile.InternalSetActivity(NextActivity);
return;
}
if ((Target.Location - self.Location).LengthSquared >= Range * Range) if( ( Target.Location - self.Location ).LengthSquared >= Range * Range )
{ return new Move( Target, Range ) { NextActivity = this };
mobile.InternalSetActivity(new Move(Target, Range));
mobile.QueueActivity(this); return null;
}
} }
public void Cancel(Actor self, Mobile mobile) public void Cancel(Actor self, Mobile mobile)
{ {
mobile.InternalSetActivity(null); Target = null;
} }
} }
} }

View File

@@ -10,82 +10,49 @@ namespace OpenRa.Game.Traits.Activities
public IActivity NextActivity { get; set; } public IActivity NextActivity { get; set; }
bool isHarvesting = false; bool isHarvesting = false;
public void Tick(Actor self, Mobile mobile) public IActivity Tick( Actor self, Mobile mobile )
{ {
if( isHarvesting ) return null;
if( NextActivity != null ) if( NextActivity != null )
{ return NextActivity;
mobile.InternalSetActivity( NextActivity );
NextActivity.Tick( self, mobile );
return;
}
var harv = self.traits.Get<Harvester>(); var harv = self.traits.Get<Harvester>();
var isGem = false;
if (!harv.IsFull && if( harv.IsFull )
Game.map.ContainsResource(self.Location) && return new DeliverOre { NextActivity = NextActivity };
Game.map.Harvest(self.Location, out isGem))
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<RenderUnit>().First(); /* better have one of these! */ var renderUnit = self.traits.WithInterface<RenderUnit>().First(); /* better have one of these! */
if( harvestAnim != renderUnit.anim.CurrentSequence.Name ) if( harvestAnim != renderUnit.anim.CurrentSequence.Name )
{ {
isHarvesting = true; isHarvesting = true;
renderUnit.PlayCustomAnimation( self, harvestAnim, () => isHarvesting = false ); renderUnit.PlayCustomAnimation( self, harvestAnim, () => isHarvesting = false );
} }
harv.AcceptResource(isGem); harv.AcceptResource( isGem );
return; return null;
} }
if (isHarvesting) return;
if (harv.IsFull)
PlanReturnToBase(self, mobile);
else else
PlanMoreHarvesting(self, mobile); {
} mobile.QueueActivity( new Move(
() =>
/* 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<AcceptsOre>())
.OrderBy(p => (p.Location - self.Location).LengthSquared)
.FirstOrDefault();
}
void PlanMoreHarvesting(Actor self, Mobile mobile)
{
mobile.QueueActivity(new Move(
() =>
{
var search = new PathSearch
{ {
heuristic = loc => (Game.map.ContainsResource(loc) ? 0 : 1), var search = new PathSearch
umt = UnitMovementType.Wheel, {
checkForBlocked = true heuristic = loc => ( Game.map.ContainsResource( loc ) ? 0 : 1 ),
}; umt = UnitMovementType.Wheel,
search.AddInitialCell(self.Location); checkForBlocked = true
return Game.PathFinder.FindPath(search); };
})); search.AddInitialCell( self.Location );
mobile.QueueActivity(new Harvest()); return Game.PathFinder.FindPath( search );
mobile.InternalSetActivity( NextActivity ); } ) );
mobile.QueueActivity( new Harvest() );
return NextActivity;
}
} }
public void Cancel(Actor self, Mobile mobile) { } public void Cancel(Actor self, Mobile mobile) { }

View File

@@ -8,7 +8,7 @@ namespace OpenRa.Game.Traits.Activities
interface IActivity interface IActivity
{ {
IActivity NextActivity { get; set; } IActivity NextActivity { get; set; }
void Tick( Actor self, Mobile mobile ); IActivity Tick( Actor self, Mobile mobile );
void Cancel( Actor self, Mobile mobile ); void Cancel( Actor self, Mobile mobile );
} }
} }

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRa.Game.GameRules; using OpenRa.Game.GameRules;
using System.Diagnostics;
namespace OpenRa.Game.Traits.Activities namespace OpenRa.Game.Traits.Activities
{ {
@@ -48,43 +49,42 @@ namespace OpenRa.Game.Traits.Activities
return (u == null || u == self); return (u == null || u == self);
} }
public void Tick( Actor self, Mobile mobile ) public IActivity Tick( Actor self, Mobile mobile )
{ {
if( move != null ) if( move != null )
{ {
move.TickMove( self, mobile, this ); move.TickMove( self, mobile, this );
return; return null;
} }
if( destination == self.Location ) if( destination == self.Location )
{ return NextActivity;
mobile.InternalSetActivity( NextActivity );
return;
}
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 ) if( path.Count == 0 )
{ {
destination = mobile.toCell; destination = mobile.toCell;
return; return null;
} }
destination = path[ 0 ]; destination = path[ 0 ];
var nextCell = PopPath( self, mobile ); var nextCell = PopPath( self, mobile );
if( nextCell == null ) if( nextCell == null )
return; return null;
int2 dir = nextCell.Value - mobile.fromCell; int2 dir = nextCell.Value - mobile.fromCell;
var firstFacing = Util.GetFacing( dir, mobile.facing ); var firstFacing = Util.GetFacing( dir, mobile.facing );
if( firstFacing != mobile.facing ) if( firstFacing != mobile.facing )
{ {
var t = new Turn( firstFacing ) { NextActivity = this };
mobile.InternalSetActivity( t );
path.Add( nextCell.Value ); path.Add( nextCell.Value );
t.Tick( self, mobile ); return new Turn( firstFacing ) { NextActivity = this };
} }
else else
{ {
@@ -99,9 +99,21 @@ namespace OpenRa.Game.Traits.Activities
Game.UnitInfluence.Update( mobile ); Game.UnitInfluence.Update( mobile );
move.TickMove( self, mobile, this ); 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 ) int2? PopPath( Actor self, Mobile mobile )
{ {
if( path.Count == 0 ) return null; if( path.Count == 0 ) return null;

View File

@@ -16,16 +16,13 @@ namespace OpenRa.Game.Traits.Activities
this.desiredFacing = desiredFacing; this.desiredFacing = desiredFacing;
} }
public void Tick( Actor self, Mobile mobile ) public IActivity Tick( Actor self, Mobile mobile )
{ {
if( desiredFacing == mobile.facing ) if( desiredFacing == mobile.facing )
{ return NextActivity;
mobile.InternalSetActivity( NextActivity );
if( NextActivity != null )
NextActivity.Tick( self, mobile );
return;
}
Util.TickFacing( ref mobile.facing, desiredFacing, self.unitInfo.ROT ); Util.TickFacing( ref mobile.facing, desiredFacing, self.unitInfo.ROT );
return null;
} }
public void Cancel( Actor self, Mobile mobile ) public void Cancel( Actor self, Mobile mobile )

View File

@@ -8,8 +8,11 @@ namespace OpenRa.Game.Traits
{ {
class Building : ITick, INotifyBuildComplete class Building : ITick, INotifyBuildComplete
{ {
public readonly UnitInfo.BuildingInfo unitInfo;
public Building(Actor self) public Building(Actor self)
{ {
unitInfo = (UnitInfo.BuildingInfo)self.unitInfo;
} }
bool first = true; bool first = true;
@@ -23,10 +26,7 @@ namespace OpenRa.Game.Traits
public void BuildingComplete(Actor self) public void BuildingComplete(Actor self)
{ {
UnitInfo.BuildingInfo bi = self.unitInfo as UnitInfo.BuildingInfo; self.Owner.ChangePower(unitInfo.Power);
if (bi == null) return;
self.Owner.ChangePower(bi.Power);
} }
} }
} }

View File

@@ -1,23 +1,23 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using OpenRa.Game.GameRules; using OpenRa.Game.GameRules;
namespace OpenRa.Game.Traits namespace OpenRa.Game.Traits
{ {
class McvDeploy : IOrder class McvDeploy : IOrder
{ {
public McvDeploy(Actor self) { } public McvDeploy(Actor self) { }
public Order Order(Actor self, int2 xy, bool lmb, Actor underCursor) public Order Order(Actor self, int2 xy, bool lmb, Actor underCursor)
{ {
if (lmb) return null; if (lmb) return null;
if (xy == self.Location) if( xy != self.Location ) return null;
return OpenRa.Game.Order.DeployMcv(self, !Game.CanPlaceBuilding("fact", xy - new int2(1,1), self, false));
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));
} }
} }
}

View File

@@ -42,17 +42,20 @@ namespace OpenRa.Game.Traits
act.NextActivity = nextActivity; act.NextActivity = nextActivity;
} }
public void InternalSetActivity( IActivity activity )
{
currentActivity = activity;
}
public void Tick(Actor self) public void Tick(Actor self)
{ {
if( currentActivity != null ) if( currentActivity == null )
currentActivity.Tick( self, this ); {
else
fromCell = toCell; 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) public Order Order(Actor self, int2 xy, bool lmb, Actor underCursor)
@@ -81,10 +84,19 @@ namespace OpenRa.Game.Traits
public UnitMovementType GetMovementType() public UnitMovementType GetMovementType()
{ {
var vi = self.unitInfo as UnitInfo.VehicleInfo; switch( Rules.UnitCategory[ self.unitInfo.Name ] )
if (vi == null) return UnitMovementType.Foot; {
if (vi.WaterBound) return UnitMovementType.Float; case "Infantry":
return vi.Tracked ? UnitMovementType.Track : UnitMovementType.Wheel; 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<int2> GetCurrentPath() public IEnumerable<int2> GetCurrentPath()

View File

@@ -15,7 +15,7 @@ namespace OpenRa.Game.Traits
public RallyPoint(Actor self) public RallyPoint(Actor self)
{ {
var bi = (UnitInfo.BuildingInfo)self.unitInfo; var bi = self.traits.Get<Building>().unitInfo;
rallyPoint = self.Location + new int2(bi.RallyPoint[0], bi.RallyPoint[1]); rallyPoint = self.Location + new int2(bi.RallyPoint[0], bi.RallyPoint[1]);
anim = new Animation("flagfly"); anim = new Animation("flagfly");
anim.PlayRepeating("idle"); anim.PlayRepeating("idle");

View File

@@ -43,7 +43,7 @@ namespace OpenRa.Game.Traits
void DoBib(Actor self, bool isRemove) void DoBib(Actor self, bool isRemove)
{ {
var buildingInfo = (UnitInfo.BuildingInfo)self.unitInfo; var buildingInfo = self.traits.Get<Building>().unitInfo;
if (buildingInfo.Bib) if (buildingInfo.Bib)
{ {
var size = buildingInfo.Dimensions.X; var size = buildingInfo.Dimensions.X;

View File

@@ -41,30 +41,28 @@ namespace OpenRa.Game
for (var i = 0; i < 128; i++) for (var i = 0; i < 128; i++)
if (Game.UnitInfluence.GetUnitAt(new int2(i, j)) != null) if (Game.UnitInfluence.GetUnitAt(new int2(i, j)) != null)
spriteRenderer.DrawSprite(unitDebug, Game.CellSize * new float2(i, j), 0); spriteRenderer.DrawSprite(unitDebug, Game.CellSize * new float2(i, j), 0);
}
var placeBuilding = Game.controller.orderGenerator as PlaceBuilding; public void DrawBuildingGrid( UnitInfo.BuildingInfo bi )
if (placeBuilding == null) return; {
var position = Game.controller.MousePosition.ToInt2(); 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. */ var maxDistance = bi.Adjacent + 2; /* real-ra is weird. this is 1 GAP. */
if (ShowBuildDebug) if( ShowBuildDebug )
for (var j = 0; j < 128; j++) for( var j = 0 ; j < 128 ; j++ )
for (var i = 0; i < 128; i++) for( var i = 0 ; i < 128 ; i++ )
if (Game.GetDistanceToBase(new int2(i, j), Game.LocalPlayer) < maxDistance) 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.IsCellBuildable( new int2( i, j ), bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel ) )
if (!Game.map.ContainsResource(new int2(i,j))) if( !Game.map.ContainsResource( new int2( i, j ) ) )
spriteRenderer.DrawSprite(unitDebug, Game.CellSize * new float2(i, j), 0); spriteRenderer.DrawSprite( unitDebug, Game.CellSize * new float2( i, j ), 0 );
var tooFarFromBase = !Footprint.Tiles(bi, position).Any( var tooFarFromBase = !Footprint.Tiles( bi, position ).Any(
t => Game.GetDistanceToBase(t, Game.LocalPlayer) < maxDistance); t => Game.GetDistanceToBase( t, Game.LocalPlayer ) < maxDistance );
foreach( var t in Footprint.Tiles( bi, position ) ) foreach( var t in Footprint.Tiles( bi, position ) )
spriteRenderer.DrawSprite( (!tooFarFromBase && Game.IsCellBuildable( t, bi.WaterBound spriteRenderer.DrawSprite( ( !tooFarFromBase && Game.IsCellBuildable( t, bi.WaterBound
? UnitMovementType.Float : UnitMovementType.Wheel ) && !Game.map.ContainsResource(t)) ? UnitMovementType.Float : UnitMovementType.Wheel ) && !Game.map.ContainsResource( t ) )
? buildOk : buildBlocked, Game.CellSize * t, 0 ); ? buildOk : buildBlocked, Game.CellSize * t, 0 );
spriteRenderer.Flush(); spriteRenderer.Flush();

View File

@@ -18,13 +18,13 @@ namespace OpenRa.Game
public void Tick() public void Tick()
{ {
SanityCheck(); //SanityCheck();
var units = Game.world.Actors //var units = Game.world.Actors
.Select( a => a.traits.GetOrDefault<Traits.Mobile>() ).Where( m => m != null ); // .Select( a => a.traits.GetOrDefault<Traits.Mobile>() ).Where( m => m != null );
foreach (var u in units) //foreach (var u in units)
Update(u); // Update(u);
SanityCheck(); SanityCheck();
} }

View File

@@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Text;
namespace OpenRa.Game namespace OpenRa.Game
{ {
@@ -28,5 +28,11 @@ namespace OpenRa.Game
{ {
selection.RemoveAll(a => a.IsDead); selection.RemoveAll(a => a.IsDead);
} }
public void Render()
{
foreach( var a in selection )
Game.worldRenderer.DrawSelectionBox( a, Color.White, true );
}
} }
} }

View File

@@ -49,7 +49,8 @@ namespace OpenRa.Game
} }
case "DeployMcv": 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 */ break; /* throw the order on the floor */
var mobile = order.Subject.traits.Get<Mobile>(); var mobile = order.Subject.traits.Get<Mobile>();
@@ -77,14 +78,14 @@ namespace OpenRa.Game
{ {
Game.world.AddFrameEndTask( _ => Game.world.AddFrameEndTask( _ =>
{ {
var building = Rules.UnitInfo[ order.TargetString ]; var building = (UnitInfo.BuildingInfo)Rules.UnitInfo[ order.TargetString ];
var producing = order.Player.Producing( "Building" ); var producing = order.Player.Producing( "Building" );
if( producing == null || producing.Item != order.TargetString || producing.RemainingTime != 0 ) if( producing == null || producing.Item != order.TargetString || producing.RemainingTime != 0 )
return; return;
Log.Write( "Player \"{0}\" builds {1}", order.Player.PlayerName, building.Name ); 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]); 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 */ * ( 25 * 60 ) /* frames per min */ /* todo: build acceleration, if we do that */
/ 1000; / 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, order.Player.BeginProduction(group,
new ProductionItem(order.TargetString, (int)time, ui.Cost, new ProductionItem(order.TargetString, (int)time, ui.Cost,

View File

@@ -259,8 +259,9 @@
<!-- v2 rocket launcher --> <!-- v2 rocket launcher -->
<unit name="v2rl"> <unit name="v2rl">
<sequence name="idle" start="0" length="32" /> <sequence name="idle" start="0" length="32" />
<sequence name="reloading" start="32" length="32" /> <sequence name="empty-idle" start="32" length="32" />
<sequence name="aiming" start="64" length="16" /> <sequence name="aim" start="64" length="8" />
<sequence name="empty-aim" start="72" length="8" />
</unit> </unit>
<!-- artillery --> <!-- artillery -->
<unit name="arty"> <unit name="arty">