diff --git a/OpenRa.Game/Actor.cs b/OpenRa.Game/Actor.cs
index 9a73b02f03..ec720892f5 100644
--- a/OpenRa.Game/Actor.cs
+++ b/OpenRa.Game/Actor.cs
@@ -10,7 +10,7 @@ namespace OpenRa.Game
{
abstract class Actor
{
- protected readonly Game game;
+ public readonly Game game;
public abstract float2 RenderLocation { get; }
public Player owner;
diff --git a/OpenRa.Game/Building.cs b/OpenRa.Game/Building.cs
index 2f47e992fb..7dbf501924 100644
--- a/OpenRa.Game/Building.cs
+++ b/OpenRa.Game/Building.cs
@@ -4,18 +4,13 @@ using System.Text;
namespace OpenRa.Game
{
- class Building : Actor
+ class Building : PlayerOwned
{
- protected Animation animation;
- protected int2 location;
-
public Building( string name, int2 location, Player owner, Game game )
- : base( game )
+ : base( game, name, location )
{
- this.location = location;
this.owner = owner;
- animation = new Animation( name );
animation.PlayThen( "make", delegate { animation.PlayRepeating( "idle" ); } );
owner.TechTree.Build( name, true );
}
@@ -25,14 +20,5 @@ namespace OpenRa.Game
animation.Tick( t );
}
- public override Sprite[] CurrentImages
- {
- get { return animation.Images; }
- }
-
- public override float2 RenderLocation
- {
- get { return 24.0f * (float2)location; }
- }
}
}
diff --git a/OpenRa.Game/Harvester.cs b/OpenRa.Game/Harvester.cs
deleted file mode 100644
index 8ec7d5f458..0000000000
--- a/OpenRa.Game/Harvester.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace OpenRa.Game
-{
- class Harvester : Unit
- {
- public Harvester( int2 cell, Player owner, Game game )
- : base( "harv", cell, owner, new float2( 12, 12 ), game )
- {
- }
-
- public override IOrder Order( Game game, int2 xy )
- {
- if( ( fromCell == toCell || moveFraction == 0 ) && fromCell == xy )
- return new HarvestOrder( this );
- return base.Order( game, xy );
- }
-
- void AcceptHarvestOrder()
- {
- TickFunc order = null;
- order = nextOrder = delegate
- {
- // TODO: check that there's actually some ore in this cell :)
-
- // face in one of the 8 directions
- if( Turn( ( facing + 1 ) & ~3 ) )
- return;
-
- currentOrder = delegate { };
- if( nextOrder == null )
- nextOrder = order;
-
- string sequenceName = string.Format( "harvest{0}", facing / 4 );
- animation.PlayThen( sequenceName, delegate
- {
- currentOrder = null;
- animation.PlayFetchIndex( "idle", delegate { return facing; } );
- } );
- };
- }
-
- public class HarvestOrder : IOrder
- {
- Harvester harvester;
-
- public HarvestOrder( Harvester harv )
- {
- harvester = harv;
- }
-
- public void Apply( Game game )
- {
- harvester.AcceptHarvestOrder();
- }
- }
- }
-}
diff --git a/OpenRa.Game/MainWindow.cs b/OpenRa.Game/MainWindow.cs
index a0bd8303c9..ff7d709ac0 100644
--- a/OpenRa.Game/MainWindow.cs
+++ b/OpenRa.Game/MainWindow.cs
@@ -45,9 +45,9 @@ namespace OpenRa.Game
SequenceProvider.ForcePrecache();
- game.world.Add( new Mcv( new int2( 5, 5 ), game.players[ 3 ], game ) );
- game.world.Add( new Mcv( new int2( 7, 5 ), game.players[ 2 ], game ) );
- Mcv mcv = new Mcv( new int2( 9, 5 ), game.players[ 1 ], game );
+ game.world.Add( new Unit( "mcv", new int2( 5, 5 ), game.players[ 3 ], game ) );
+ game.world.Add( new Unit( "mcv", new int2( 7, 5 ), game.players[ 2 ], game ) );
+ Unit mcv = new Unit( "mcv", new int2( 9, 5 ), game.players[ 1 ], game );
game.world.orderGenerator = mcv;
game.world.Add( mcv );
diff --git a/OpenRa.Game/Mcv.cs b/OpenRa.Game/Mcv.cs
deleted file mode 100644
index 98637ab3e6..0000000000
--- a/OpenRa.Game/Mcv.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using OpenRa.FileFormats;
-using System.Drawing;
-using BluntDirectX.Direct3D;
-
-namespace OpenRa.Game
-{
- class Mcv : Unit
- {
- public Mcv( int2 location, Player owner, Game game )
- : base( "mcv", location, owner, new float2( 12, 12 ), game )
- {
- }
-
- public void AcceptDeployOrder()
- {
- nextOrder = delegate( Game game, int t )
- {
- if( Turn( 12 ) )
- return;
-
- World world = game.world;
- world.AddFrameEndTask( delegate
- {
- world.Remove( this );
- world.Add( new ConstructionYard( fromCell - new int2( 1, 1 ), owner, game ) );
- } );
- currentOrder = null;
- };
- }
-
- public override IOrder Order( Game game, int2 xy )
- {
- if( ( fromCell == toCell || moveFraction == 0 ) && fromCell == xy )
- return new DeployMcvOrder( this );
-
- return base.Order( game, xy );
- }
- }
-}
diff --git a/OpenRa.Game/MoveOrder.cs b/OpenRa.Game/MoveOrder.cs
index 8611f756e0..87aeebb36f 100644
--- a/OpenRa.Game/MoveOrder.cs
+++ b/OpenRa.Game/MoveOrder.cs
@@ -22,22 +22,37 @@ namespace OpenRa.Game
public void Apply( Game game )
{
- Unit.AcceptMoveOrder( Destination );
+ Unit.nextOrder = UnitMissions.Move( Unit, Destination );
}
}
class DeployMcvOrder : IOrder
{
- public Mcv Mcv;
+ Unit unit;
- public DeployMcvOrder( Mcv mcv )
+ public DeployMcvOrder( Unit unit )
{
- this.Mcv = mcv;
+ this.unit = unit;
}
public void Apply( Game game )
{
- Mcv.AcceptDeployOrder();
+ unit.nextOrder = UnitMissions.Deploy( unit );
+ }
+ }
+
+ class HarvestOrder : IOrder
+ {
+ Unit unit;
+
+ public HarvestOrder( Unit unit )
+ {
+ this.unit = unit;
+ }
+
+ public void Apply( Game game )
+ {
+ unit.nextOrder = UnitMissions.Harvest( unit );
}
}
}
diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index 0ecffd43f7..17fef9f087 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -47,9 +47,9 @@
+
-
@@ -63,7 +63,6 @@
Form
-
@@ -80,6 +79,7 @@
+
diff --git a/OpenRa.Game/PathFinder.cs b/OpenRa.Game/PathFinder.cs
index 9518711354..e4672d857e 100644
--- a/OpenRa.Game/PathFinder.cs
+++ b/OpenRa.Game/PathFinder.cs
@@ -26,9 +26,9 @@ namespace OpenRa.Game
// returns estimate to destination, 0.0 is cell is dest
public delegate double DistanceHeuristic( int2 cell );
- public List FindUnitPath( Unit unit, DistanceHeuristic estimator )
+ public List FindUnitPath( int2 unitLocation, DistanceHeuristic estimator )
{
- int2 startLocation = unit.Location + map.Offset;
+ int2 startLocation = unitLocation + map.Offset;
CellInfo[ , ] cellInfo = new CellInfo[ 128, 128 ];
diff --git a/OpenRa.Game/PlayerOwned.cs b/OpenRa.Game/PlayerOwned.cs
new file mode 100644
index 0000000000..c1dda4eb2f
--- /dev/null
+++ b/OpenRa.Game/PlayerOwned.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenRa.Game
+{
+ abstract class PlayerOwned : Actor
+ {
+ public Animation animation;
+ protected int2 location;
+
+ public UnitMission currentOrder = null;
+ public UnitMission nextOrder = null;
+
+ protected PlayerOwned( Game game, string name, int2 location )
+ : base( game )
+ {
+ animation = new Animation( name );
+ this.location = location;
+ }
+
+ public override float2 RenderLocation
+ {
+ get { return 24.0f * (float2)location; }
+ }
+
+ public override Sprite[] CurrentImages { get { return animation.Images; } }
+ }
+}
diff --git a/OpenRa.Game/Refinery.cs b/OpenRa.Game/Refinery.cs
index 3e575c9f2e..49d1ad3b29 100644
--- a/OpenRa.Game/Refinery.cs
+++ b/OpenRa.Game/Refinery.cs
@@ -18,7 +18,7 @@ namespace OpenRa.Game
game.world.AddFrameEndTask(delegate
{
- Unit harvester = new Harvester(location + new int2(1, 2), owner, game);
+ Unit harvester = new Unit( "harv", location + new int2( 1, 2 ), owner, game );
harvester.facing = 8;
game.world.Add(harvester);
game.world.orderGenerator = harvester;
diff --git a/OpenRa.Game/Rules.cs b/OpenRa.Game/Rules.cs
index 4744de0b32..8d13b2a0dc 100644
--- a/OpenRa.Game/Rules.cs
+++ b/OpenRa.Game/Rules.cs
@@ -16,14 +16,14 @@ namespace OpenRa.Game
foreach (string line in Util.ReadAllLines(FileSystem.Open("units.txt")))
{
- string unit = line.Substring(0, line.IndexOf(','));
- IniSection section = rulesIni.GetSection(unit.ToUpperInvariant());
+ string unit = line.Substring( 0, line.IndexOf( ',' ) ).ToUpperInvariant();
+ IniSection section = rulesIni.GetSection( unit );
if (section == null)
{
Log.Write("rules.ini doesnt contain entry for unit \"{0}\"", unit);
continue;
}
- unitInfos.Add(unit, new UnitInfo(section));
+ unitInfos.Add( unit, new UnitInfo( unit, section ) );
}
}
@@ -36,37 +36,17 @@ namespace OpenRa.Game
class UnitInfo
{
public readonly int Speed;
+ public readonly SupportedMissions supportedMissions;
- public UnitInfo( IniSection ini )
+ public UnitInfo( string unitName, IniSection ini )
{
Speed = int.Parse( ini.GetValue( "Speed", "0" ) );
+
+ supportedMissions = SupportedMissions.Stop;
+ if( unitName == "MCV" )
+ supportedMissions |= SupportedMissions.Deploy;
+ if( unitName == "HARV" )
+ supportedMissions |= SupportedMissions.Harvest;
}
}
-
- //Unit Missions:
- //{
- // Sleep - no-op
- // Harmless - no-op, and also not considered a threat
- // Sticky
- // Attack
- // Move
- // QMove
- // Retreat
- // Guard
- // Enter
- // Capture
- // Harvest
- // Area Guard
- // [Return]
- // Stop
- // [Ambush]
- // Hunt
- // Unload
- // Sabotage
- // Construction
- // Selling
- // Repair
- // Rescue
- // Missile
- //}
}
diff --git a/OpenRa.Game/Unit.cs b/OpenRa.Game/Unit.cs
index c88bce2450..f9fa5d0cac 100644
--- a/OpenRa.Game/Unit.cs
+++ b/OpenRa.Game/Unit.cs
@@ -4,26 +4,26 @@ using System.Text;
namespace OpenRa.Game
{
- abstract class Unit : Actor, IOrderGenerator
+ class Unit : PlayerOwned, IOrderGenerator
{
- protected Animation animation;
-
public int facing = 0;
- protected int2 fromCell, toCell;
- protected int moveFraction, moveFractionTotal;
+ public int2 fromCell;
+ public int2 toCell
+ {
+ get { return location; }
+ set { location = value; }
+ }
- protected delegate void TickFunc( Game game, int t );
- protected TickFunc currentOrder = null;
- protected TickFunc nextOrder = null;
+ public int moveFraction, moveFractionTotal;
- protected readonly float2 renderOffset;
- protected readonly UnitInfo unitInfo;
+ readonly float2 renderOffset;
+ public readonly UnitInfo unitInfo;
- public Unit( string name, int2 cell, Player owner, float2 renderOffset, Game game )
- : base( game )
+ public Unit( string name, int2 cell, Player owner, Game game )
+ : base( game, name, cell )
{
fromCell = toCell = cell;
- this.renderOffset = renderOffset;
+ this.renderOffset = new float2( 12, 12 ); // TODO: pull this from the sprite
this.owner = owner;
this.unitInfo = Rules.UnitInfo( name );
@@ -34,7 +34,7 @@ namespace OpenRa.Game
static float2[] fvecs = Util.MakeArray( 32,
delegate( int i ) { return -float2.FromAngle( i / 16.0f * (float)Math.PI ) * new float2( 1f, 1.3f ); } );
- int GetFacing( float2 d )
+ public int GetFacing( float2 d )
{
if( float2.WithinEpsilon( d, float2.Zero, 0.001f ) )
return facing;
@@ -65,70 +65,37 @@ namespace OpenRa.Game
}
if( currentOrder != null )
- currentOrder( game, t );
- }
-
- public void AcceptMoveOrder( int2 destination )
- {
- nextOrder = delegate( Game game, int t )
- {
- if( nextOrder != null )
- destination = toCell;
-
- if( Turn( GetFacing( toCell - fromCell ) ) )
- return;
-
- moveFraction += t * unitInfo.Speed;
- if( moveFraction < moveFractionTotal )
- return;
-
- moveFraction = 0;
- moveFractionTotal = 0;
- fromCell = toCell;
-
- if( toCell == destination )
- {
- currentOrder = null;
- return;
- }
-
- List res = game.pathFinder.FindUnitPath( this, PathFinder.DefaultEstimator( destination ) );
- if( res.Count != 0 )
- {
- toCell = res[ res.Count - 1 ];
-
- int2 dir = toCell - fromCell;
- moveFractionTotal = ( dir.X != 0 && dir.Y != 0 ) ? 2500 : 2000;
- }
- else
- destination = toCell;
- };
- }
-
- protected bool Turn( int desiredFacing )
- {
- if( facing == desiredFacing )
- return false;
-
- int df = ( desiredFacing - facing + 32 ) % 32;
- facing = ( facing + ( df > 16 ? 31 : 1 ) ) % 32;
- return true;
+ currentOrder( t );
}
public override float2 RenderLocation
{
get
{
- float fraction = (moveFraction > 0) ? (float)moveFraction / moveFractionTotal : 0f;
+ float fraction = ( moveFraction > 0 ) ? (float)moveFraction / moveFractionTotal : 0f;
float2 location = 24 * float2.Lerp( fromCell, toCell, fraction );
- return ( location - renderOffset ).Round(); ;
+ return ( location - renderOffset ).Round();
}
}
- public int2 Location { get { return toCell; } }
- public virtual IOrder Order(Game game, int2 xy) { return new MoveOrder(this, xy); }
- public override Sprite[] CurrentImages { get { return animation.Images; } }
+ bool SupportsMission( SupportedMissions mission )
+ {
+ return mission == ( unitInfo.supportedMissions & mission );
+ }
+
+ public IOrder Order( Game game, int2 xy )
+ {
+ if( ( fromCell == toCell || moveFraction == 0 ) && fromCell == xy )
+ {
+ if( SupportsMission( SupportedMissions.Deploy ) )
+ return new DeployMcvOrder( this );
+ if( SupportsMission( SupportedMissions.Harvest ) )
+ return new HarvestOrder( this );
+ }
+
+ return new MoveOrder( this, xy );
+ }
public void PrepareOverlay(Game game, int2 xy) { }
}
diff --git a/OpenRa.Game/UnitMissions.cs b/OpenRa.Game/UnitMissions.cs
new file mode 100644
index 0000000000..b391176fb4
--- /dev/null
+++ b/OpenRa.Game/UnitMissions.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenRa.Game
+{
+ //Unit Missions:
+ //{
+ //in rules.ini:
+ // Sleep - no-op
+ // Harmless - no-op, and also not considered a threat
+ // Sticky
+ // Attack
+ // Move
+ // QMove
+ // Retreat
+ // Guard
+ // Enter
+ // Capture
+ // Harvest
+ // Area Guard
+ // [Return] - unused
+ // Stop
+ // [Ambush] - unused
+ // Hunt
+ // Unload
+ // Sabotage
+ // Construction
+ // Selling
+ // Repair
+ // Rescue
+ // Missile
+ //
+ //not in original RA:
+ // Deploy (Mcv -> Fact) [should this be construction/unload?]
+ //}
+
+ [Flags]
+ enum SupportedMissions
+ {
+ Stop = 0,
+ Harvest = 1,
+ Deploy = 2,
+ }
+
+ delegate void UnitMission( int t );
+ static class UnitMissions
+ {
+ public static UnitMission Sleep()
+ {
+ return delegate { };
+ }
+
+ public static UnitMission Move( Unit unit, int2 destination )
+ {
+ return delegate( int t )
+ {
+ Game game = unit.game;
+
+ if( unit.nextOrder != null )
+ destination = unit.toCell;
+
+ if( Turn( unit, unit.GetFacing( unit.toCell - unit.fromCell ) ) )
+ return;
+
+ unit.moveFraction += t * unit.unitInfo.Speed;
+ if( unit.moveFraction < unit.moveFractionTotal )
+ return;
+
+ unit.moveFraction = 0;
+ unit.moveFractionTotal = 0;
+ unit.fromCell = unit.toCell;
+
+ if( unit.toCell == destination )
+ {
+ unit.currentOrder = null;
+ return;
+ }
+
+ List res = game.pathFinder.FindUnitPath( unit.toCell, PathFinder.DefaultEstimator( destination ) );
+ if( res.Count != 0 )
+ {
+ unit.toCell = res[ res.Count - 1 ];
+
+ int2 dir = unit.toCell - unit.fromCell;
+ unit.moveFractionTotal = ( dir.X != 0 && dir.Y != 0 ) ? 2500 : 2000;
+ }
+ else
+ destination = unit.toCell;
+ };
+ }
+
+ public static UnitMission Deploy( Unit unit )
+ {
+ return delegate( int t )
+ {
+ Game game = unit.game;
+
+ if( Turn( unit, 12 ) )
+ return;
+
+ game.world.AddFrameEndTask( delegate
+ {
+ game.world.Remove( unit );
+ game.world.Add( new ConstructionYard( unit.fromCell - new int2( 1, 1 ), unit.owner, game ) );
+ } );
+ unit.currentOrder = null;
+ };
+ }
+
+
+ public static UnitMission Harvest( Unit unit )
+ {
+ UnitMission order = null;
+ order = delegate
+ {
+ // TODO: check that there's actually some ore in this cell :)
+
+ // face in one of the 8 directions
+ if( Turn( unit, ( unit.facing + 1 ) & ~3 ) )
+ return;
+
+ unit.currentOrder = delegate { };
+ if( unit.nextOrder == null )
+ unit.nextOrder = order;
+
+ string sequenceName = string.Format( "harvest{0}", unit.facing / 4 );
+ unit.animation.PlayThen( sequenceName, delegate
+ {
+ unit.currentOrder = null;
+ unit.animation.PlayFetchIndex( "idle", delegate { return unit.facing; } );
+ } );
+ };
+ return order;
+ }
+
+ static bool Turn( Unit unit, int desiredFacing )
+ {
+ if( unit.facing == desiredFacing )
+ return false;
+
+ int df = ( desiredFacing - unit.facing + 32 ) % 32;
+ unit.facing = ( unit.facing + ( df > 16 ? 31 : 1 ) ) % 32;
+ return true;
+ }
+ }
+}