Restructuring orders.

This commit is contained in:
Bob
2009-10-28 22:06:39 +13:00
parent 5d1ae1cb2a
commit c0cb248bc1
14 changed files with 632 additions and 621 deletions

View File

@@ -65,8 +65,8 @@ namespace OpenRa.Game
public Order Order( int2 xy, bool lmb ) public Order Order( int2 xy, bool lmb )
{ {
if (Owner != Game.LocalPlayer) if (Owner != Game.LocalPlayer)
return null; return null;
var underCursor = Game.UnitInfluence.GetUnitAt( xy ) ?? Game.BuildingInfluence.GetBuildingAt( xy ); var underCursor = Game.UnitInfluence.GetUnitAt( xy ) ?? Game.BuildingInfluence.GetBuildingAt( xy );
return traits.WithInterface<Traits.IOrder>() return traits.WithInterface<Traits.IOrder>()

View File

@@ -4,24 +4,33 @@ using System.Linq;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using IjwFramework.Types; using IjwFramework.Types;
using System.Drawing; using System.Drawing;
using OpenRa.Game.Traits; using OpenRa.Game.Traits;
namespace OpenRa.Game namespace OpenRa.Game
{ {
class Controller class Controller
{ {
public IOrderGenerator orderGenerator; public IOrderGenerator orderGenerator;
void ApplyOrders(float2 xy, bool left) void ApplyOrders(float2 xy, bool left)
{ {
var doVoice = true; var doVoice = null as Actor;
if (orderGenerator != null) if (orderGenerator != null)
foreach (var order in orderGenerator.Order(xy.ToInt2(), left)) foreach( var order in orderGenerator.Order( xy.ToInt2(), left ) )
{ {
order.Apply(doVoice); UnitOrders.ProcessOrder( order );
doVoice = false; if( order.Subject != null && order.Player == Game.LocalPlayer )
} doVoice = order.Subject;
}
if( doVoice != null )
Game.PlaySound( Game.SovietVoices.First.GetNext() + GetVoiceSuffix( doVoice ), false );
}
static string GetVoiceSuffix( Actor unit )
{
var suffixes = new[] { ".r01", ".r03" };
return suffixes[ unit.traits.Get<Traits.Mobile>().Voice ];
} }
float2 dragStart, dragEnd; float2 dragStart, dragEnd;
@@ -32,7 +41,7 @@ namespace OpenRa.Game
if (mi.Button == MouseButtons.Left && mi.Event == MouseInputEvent.Down) if (mi.Button == MouseButtons.Left && mi.Event == MouseInputEvent.Down)
{ {
if (!(orderGenerator is PlaceBuilding)) if (!(orderGenerator is PlaceBuilding))
dragStart = dragEnd = xy; dragStart = dragEnd = xy;
ApplyOrders(xy, true); ApplyOrders(xy, true);
} }
@@ -59,9 +68,9 @@ namespace OpenRa.Game
/* update the cursor to reflect the thing under us - note this /* update the cursor to reflect the thing under us - note this
* needs to also happen when the *thing* changes, so per-frame hook */ * needs to also happen when the *thing* changes, so per-frame hook */
dragStart = dragEnd = xy; dragStart = dragEnd = xy;
} }
if (mi.Button == MouseButtons.Right && mi.Event == MouseInputEvent.Down) if (mi.Button == MouseButtons.Right && mi.Event == MouseInputEvent.Down)
ApplyOrders(xy, false); ApplyOrders(xy, false);
} }
@@ -84,10 +93,10 @@ namespace OpenRa.Game
if (uog != null && uog.selection.Count > 0 if (uog != null && uog.selection.Count > 0
&& uog.selection.Any(a => a.traits.Contains<Traits.Mobile>()) && uog.selection.Any(a => a.traits.Contains<Traits.Mobile>())
&& uog.selection.All( a => a.Owner == Game.LocalPlayer )) && uog.selection.All( a => a.Owner == Game.LocalPlayer ))
{ {
var umts = uog.selection.Select(a => a.traits.GetOrDefault<Mobile>()) var umts = uog.selection.Select(a => a.traits.GetOrDefault<Mobile>())
.Where(m => m != null) .Where(m => m != null)
.Select(m => m.GetMovementType()) .Select(m => m.GetMovementType())
.Distinct(); .Distinct();
if (!umts.Any( umt => Game.IsCellBuildable( dragEnd.ToInt2(), umt ) )) if (!umts.Any( umt => Game.IsCellBuildable( dragEnd.ToInt2(), umt ) ))

View File

@@ -1,8 +1,8 @@
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;
namespace OpenRa.Game.Graphics namespace OpenRa.Game.Graphics
@@ -12,13 +12,13 @@ namespace OpenRa.Game.Graphics
public readonly SpriteRenderer spriteRenderer; public readonly SpriteRenderer spriteRenderer;
public readonly LineRenderer lineRenderer; public readonly LineRenderer lineRenderer;
public readonly Region region; public readonly Region region;
public readonly UiOverlay uiOverlay; public readonly UiOverlay uiOverlay;
public static bool ShowUnitPaths = false; public static bool ShowUnitPaths = false;
public WorldRenderer(Renderer renderer) public WorldRenderer(Renderer renderer)
{ {
// TODO: this is layout policy. it belongs at a higher level than this. // TODO: this is layout policy. it belongs at a higher level than this.
region = Region.Create(Game.viewport, DockStyle.Left, region = Region.Create(Game.viewport, DockStyle.Left,
Game.viewport.Width - 128, Draw, Game.viewport.Width - 128, Draw,
Game.controller.HandleMouseInput); Game.controller.HandleMouseInput);
@@ -28,41 +28,41 @@ namespace OpenRa.Game.Graphics
spriteRenderer = new SpriteRenderer(renderer, true); spriteRenderer = new SpriteRenderer(renderer, true);
lineRenderer = new LineRenderer(renderer); lineRenderer = new LineRenderer(renderer);
uiOverlay = new UiOverlay(spriteRenderer); uiOverlay = new UiOverlay(spriteRenderer);
} }
void DrawSpriteList(Player owner, RectangleF rect, void DrawSpriteList(Player owner, RectangleF rect,
IEnumerable<Pair<Sprite, float2>> images) IEnumerable<Pair<Sprite, float2>> images)
{ {
foreach (var image in images) foreach (var image in images)
{ {
var loc = image.Second; var loc = image.Second;
if (loc.X > rect.Right || loc.X < rect.Left if (loc.X > rect.Right || loc.X < rect.Left
- image.First.bounds.Width) - image.First.bounds.Width)
continue; continue;
if (loc.Y > rect.Bottom || loc.Y < rect.Top if (loc.Y > rect.Bottom || loc.Y < rect.Top
- image.First.bounds.Height) - image.First.bounds.Height)
continue; continue;
spriteRenderer.DrawSprite(image.First, loc, spriteRenderer.DrawSprite(image.First, loc,
(owner != null) ? owner.Palette : 0); (owner != null) ? owner.Palette : 0);
} }
} }
public void Draw() public void Draw()
{ {
var rect = new RectangleF((region.Position + Game.viewport.Location).ToPointF(), var rect = new RectangleF((region.Position + Game.viewport.Location).ToPointF(),
region.Size.ToSizeF()); region.Size.ToSizeF());
foreach (Actor a in Game.world.Actors.OrderBy( u => u.CenterLocation.Y )) foreach (Actor a in Game.world.Actors.OrderBy( u => u.CenterLocation.Y ))
DrawSpriteList(a.Owner, rect, a.Render()); DrawSpriteList(a.Owner, rect, a.Render());
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(a.self.Owner, rect, a.RenderRoof(a.self)); /* RUDE HACK */ DrawSpriteList(a.self.Owner, rect, a.RenderRoof(a.self)); /* RUDE HACK */
foreach (IEffect e in Game.world.Effects) foreach (IEffect e in Game.world.Effects)
DrawSpriteList(e.Owner, rect, e.Render()); DrawSpriteList(e.Owner, rect, e.Render());
uiOverlay.Draw(); uiOverlay.Draw();
@@ -93,7 +93,7 @@ namespace OpenRa.Game.Graphics
lineRenderer.Flush(); lineRenderer.Flush();
} }
const float conditionYellow = 0.5f; /* todo: get these from gamerules */ const float conditionYellow = 0.5f; /* todo: get these from gamerules */
const float conditionRed = 0.25f; const float conditionRed = 0.25f;
void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar) void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar)
@@ -114,60 +114,60 @@ namespace OpenRa.Game.Graphics
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 < conditionRed) ? Color.Red var healthColor = (healthAmount < conditionRed) ? Color.Red
: (healthAmount < conditionYellow) ? Color.Yellow : (healthAmount < 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

@@ -2,7 +2,7 @@ using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using OpenRa.FileFormats; using OpenRa.FileFormats;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.TechTree; using OpenRa.TechTree;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace OpenRa.Game namespace OpenRa.Game
@@ -48,9 +48,9 @@ namespace OpenRa.Game
bool windowed = !settings.GetValue("fullscreen", false); bool windowed = !settings.GetValue("fullscreen", false);
renderer = new Renderer(this, GetResolution(settings), windowed); renderer = new Renderer(this, GetResolution(settings), windowed);
SheetBuilder.Initialize(renderer); SheetBuilder.Initialize(renderer);
UiOverlay.ShowUnitDebug = settings.GetValue("udebug", false); UiOverlay.ShowUnitDebug = settings.GetValue("udebug", false);
WorldRenderer.ShowUnitPaths = settings.GetValue("pathdebug", false); WorldRenderer.ShowUnitPaths = settings.GetValue("pathdebug", false);
Game.Initialize(settings.GetValue("map", "scg11eb.ini"), renderer, new int2(ClientSize), Game.Initialize(settings.GetValue("map", "scg11eb.ini"), renderer, new int2(ClientSize),

View File

@@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using OpenRa.Game.Traits;
namespace OpenRa.Game
{
abstract class Order
{
public abstract void Apply(bool doVoice);
}
class MoveOrder : Order
{
public readonly Actor Unit;
public readonly int2 Destination;
public MoveOrder(Actor unit, int2 destination)
{
this.Unit = unit;
this.Destination = destination;
}
string GetVoiceSuffix()
{
var suffixes = new[] { ".r01", ".r03" };
return suffixes[Unit.traits.Get<Traits.Mobile>().Voice];
}
public override void Apply(bool doVoice)
{
if (doVoice && Game.LocalPlayer == Unit.Owner)
Game.PlaySound(Game.SovietVoices.First.GetNext() + GetVoiceSuffix(), false);
var mobile = Unit.traits.Get<Mobile>();
mobile.Cancel(Unit);
mobile.QueueActivity(new Mobile.MoveTo(Destination));
var attackBase = Unit.traits.WithInterface<AttackBase>().FirstOrDefault();
if (attackBase != null)
attackBase.target = null; /* move cancels attack order */
}
}
}

View File

@@ -1,196 +1,197 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion> <ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0DFB103F-2962-400F-8C6D-E2C28CCBA633}</ProjectGuid> <ProjectGuid>{0DFB103F-2962-400F-8C6D-E2C28CCBA633}</ProjectGuid>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenRa.Game</RootNamespace> <RootNamespace>OpenRa.Game</RootNamespace>
<AssemblyName>OpenRa.Game</AssemblyName> <AssemblyName>OpenRa.Game</AssemblyName>
<FileUpgradeFlags> <FileUpgradeFlags>
</FileUpgradeFlags> </FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion> <OldToolsVersion>2.0</OldToolsVersion>
<UpgradeBackupLocation> <UpgradeBackupLocation>
</UpgradeBackupLocation> </UpgradeBackupLocation>
<PublishUrl>publish\</PublishUrl> <PublishUrl>publish\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled> <UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode> <UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval> <UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits> <UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically> <UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired> <UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions> <MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion> <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper> <IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled> <BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath> <OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath> <OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Ijw.DirectX, Version=0.0.0.0, Culture=neutral, processorArchitecture=x86"> <Reference Include="Ijw.DirectX, Version=0.0.0.0, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\Ijw.DirectX\Release\Ijw.DirectX.dll</HintPath> <HintPath>..\Ijw.DirectX\Release\Ijw.DirectX.dll</HintPath>
</Reference> </Reference>
<Reference Include="IjwFramework, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="IjwFramework, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\Ijw.DirectX\Ijw.Framework\IjwFramework\bin\Debug\IjwFramework.dll</HintPath> <HintPath>..\Ijw.DirectX\Ijw.Framework\IjwFramework\bin\Debug\IjwFramework.dll</HintPath>
</Reference> </Reference>
<Reference Include="irrKlang.NET2.0, Version=1.1.3.0, Culture=neutral, PublicKeyToken=a854741bd80517c7, processorArchitecture=x86"> <Reference Include="irrKlang.NET2.0, Version=1.1.3.0, Culture=neutral, PublicKeyToken=a854741bd80517c7, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\thirdparty\irrKlang.NET2.0.dll</HintPath> <HintPath>..\thirdparty\irrKlang.NET2.0.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Actor.cs" /> <Compile Include="Traits\Activities\DeployMcv.cs" />
<Compile Include="Bullet.cs" /> <Compile Include="Actor.cs" />
<Compile Include="Controller.cs" /> <Compile Include="Bullet.cs" />
<Compile Include="Cursor.cs" /> <Compile Include="Controller.cs" />
<Compile Include="Explosion.cs" /> <Compile Include="Cursor.cs" />
<Compile Include="GameRules\FieldLoader.cs" /> <Compile Include="Explosion.cs" />
<Compile Include="GameRules\Footprint.cs" /> <Compile Include="GameRules\FieldLoader.cs" />
<Compile Include="GameRules\InfoLoader.cs" /> <Compile Include="GameRules\Footprint.cs" />
<Compile Include="GameRules\ProjectileInfo.cs" /> <Compile Include="GameRules\InfoLoader.cs" />
<Compile Include="GameRules\Rules.cs" /> <Compile Include="GameRules\ProjectileInfo.cs" />
<Compile Include="GameRules\UnitInfo.cs" /> <Compile Include="GameRules\Rules.cs" />
<Compile Include="GameRules\WarheadInfo.cs" /> <Compile Include="GameRules\UnitInfo.cs" />
<Compile Include="GameRules\WeaponInfo.cs" /> <Compile Include="GameRules\WarheadInfo.cs" />
<Compile Include="Graphics\Animation.cs" /> <Compile Include="GameRules\WeaponInfo.cs" />
<Compile Include="Game.cs" /> <Compile Include="Graphics\Animation.cs" />
<Compile Include="Graphics\CursorSequence.cs" /> <Compile Include="Game.cs" />
<Compile Include="Graphics\CursorSheetBuilder.cs" /> <Compile Include="Graphics\CursorSequence.cs" />
<Compile Include="Graphics\LineRenderer.cs" /> <Compile Include="Graphics\CursorSheetBuilder.cs" />
<Compile Include="Graphics\OverlayRenderer.cs" /> <Compile Include="Graphics\LineRenderer.cs" />
<Compile Include="Graphics\WorldRenderer.cs" /> <Compile Include="Graphics\OverlayRenderer.cs" />
<Compile Include="BuildingInfluenceMap.cs" /> <Compile Include="Graphics\WorldRenderer.cs" />
<Compile Include="IOrderGenerator.cs" /> <Compile Include="BuildingInfluenceMap.cs" />
<Compile Include="PlaceBuilding.cs" /> <Compile Include="IOrderGenerator.cs" />
<Compile Include="PlaceBuildingOrder.cs" /> <Compile Include="PlaceBuilding.cs" />
<Compile Include="TechTree\Item.cs" /> <Compile Include="TechTree\Item.cs" />
<Compile Include="Network\Packet.cs" /> <Compile Include="Network\Packet.cs" />
<Compile Include="Player.cs" /> <Compile Include="Player.cs" />
<Compile Include="Race.cs" /> <Compile Include="Race.cs" />
<Compile Include="Support\SharedResources.cs" /> <Compile Include="Support\SharedResources.cs" />
<Compile Include="Graphics\Sheet.cs" /> <Compile Include="Graphics\Sheet.cs" />
<Compile Include="Support\Log.cs" /> <Compile Include="Support\Log.cs" />
<Compile Include="Network\Network.cs" /> <Compile Include="Network\Network.cs" />
<Compile Include="PathFinder.cs" /> <Compile Include="PathFinder.cs" />
<Compile Include="Graphics\Sequence.cs" /> <Compile Include="Graphics\Sequence.cs" />
<Compile Include="MoveOrder.cs" /> <Compile Include="Order.cs" />
<Compile Include="Graphics\Region.cs" /> <Compile Include="Graphics\Region.cs" />
<Compile Include="Graphics\SequenceProvider.cs" /> <Compile Include="Graphics\SequenceProvider.cs" />
<Compile Include="Graphics\SheetBuilder.cs" /> <Compile Include="Graphics\SheetBuilder.cs" />
<Compile Include="Graphics\HardwarePalette.cs" /> <Compile Include="Graphics\HardwarePalette.cs" />
<Compile Include="MainWindow.cs"> <Compile Include="MainWindow.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="Support\Program.cs" /> <Compile Include="Support\Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Graphics\Renderer.cs" /> <Compile Include="Graphics\Renderer.cs" />
<Compile Include="Support\Settings.cs" /> <Compile Include="Support\Settings.cs" />
<Compile Include="Sidebar.cs" /> <Compile Include="Sidebar.cs" />
<Compile Include="SidebarItem.cs" /> <Compile Include="SidebarItem.cs" />
<Compile Include="Graphics\Sprite.cs" /> <Compile Include="Graphics\Sprite.cs" />
<Compile Include="Graphics\SpriteRenderer.cs" /> <Compile Include="Graphics\SpriteRenderer.cs" />
<Compile Include="Graphics\SpriteSheetBuilder.cs" /> <Compile Include="Graphics\SpriteSheetBuilder.cs" />
<Compile Include="TechTree\TechTree.cs" /> <Compile Include="TechTree\TechTree.cs" />
<Compile Include="TerrainCosts.cs" /> <Compile Include="TerrainCosts.cs" />
<Compile Include="Graphics\TerrainRenderer.cs" /> <Compile Include="Graphics\TerrainRenderer.cs" />
<Compile Include="Graphics\TreeCache.cs" /> <Compile Include="Graphics\TreeCache.cs" />
<Compile Include="Traits\AttackTurreted.cs" /> <Compile Include="Traits\AttackTurreted.cs" />
<Compile Include="Traits\Building.cs" /> <Compile Include="Traits\Building.cs" />
<Compile Include="Traits\McvDeploy.cs" /> <Compile Include="Traits\McvDeploy.cs" />
<Compile Include="Traits\Mobile.cs" /> <Compile Include="Traits\Mobile.cs" />
<Compile Include="Traits\RenderBuilding.cs" /> <Compile Include="Traits\RenderBuilding.cs" />
<Compile Include="Traits\RenderBuildingOre.cs" /> <Compile Include="Traits\RenderBuildingOre.cs" />
<Compile Include="Traits\RenderBuildingTurreted.cs" /> <Compile Include="Traits\RenderBuildingTurreted.cs" />
<Compile Include="Traits\RenderBuildingWarFactory.cs" /> <Compile Include="Traits\RenderBuildingWarFactory.cs" />
<Compile Include="Traits\RenderSimple.cs" /> <Compile Include="Traits\RenderSimple.cs" />
<Compile Include="Traits\RenderUnit.cs" /> <Compile Include="Traits\RenderUnit.cs" />
<Compile Include="Traits\RenderUnitTurreted.cs" /> <Compile Include="Traits\RenderUnitTurreted.cs" />
<Compile Include="Traits\TraitsInterfaces.cs" /> <Compile Include="Traits\TraitsInterfaces.cs" />
<Compile Include="Traits\Tree.cs" /> <Compile Include="Traits\Tree.cs" />
<Compile Include="Traits\Turreted.cs" /> <Compile Include="Traits\Turreted.cs" />
<Compile Include="Traits\Util.cs" /> <Compile Include="UnitOrders.cs" />
<Compile Include="UiOverlay.cs" /> <Compile Include="Traits\Util.cs" />
<Compile Include="Graphics\UnitSheetBuilder.cs" /> <Compile Include="UiOverlay.cs" />
<Compile Include="Graphics\Util.cs" /> <Compile Include="Graphics\UnitSheetBuilder.cs" />
<Compile Include="Graphics\Vertex.cs" /> <Compile Include="Graphics\Util.cs" />
<Compile Include="Graphics\Viewport.cs" /> <Compile Include="Graphics\Vertex.cs" />
<Compile Include="UnitInfluenceMap.cs" /> <Compile Include="Graphics\Viewport.cs" />
<Compile Include="UnitOrderGenerator.cs" /> <Compile Include="UnitInfluenceMap.cs" />
<Compile Include="VoicePool.cs" /> <Compile Include="UnitOrderGenerator.cs" />
<Compile Include="World.cs" /> <Compile Include="VoicePool.cs" />
</ItemGroup> <Compile Include="World.cs" />
<ItemGroup> </ItemGroup>
<ProjectReference Include="..\OpenRa.DataStructures\OpenRa.DataStructures.csproj"> <ItemGroup>
<Project>{2F9E7A23-56C0-4286-9C8E-1060A9B2F073}</Project> <ProjectReference Include="..\OpenRa.DataStructures\OpenRa.DataStructures.csproj">
<Name>OpenRa.DataStructures</Name> <Project>{2F9E7A23-56C0-4286-9C8E-1060A9B2F073}</Project>
</ProjectReference> <Name>OpenRa.DataStructures</Name>
<ProjectReference Include="..\OpenRa.FileFormats\OpenRa.FileFormats.csproj"> </ProjectReference>
<Project>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</Project> <ProjectReference Include="..\OpenRa.FileFormats\OpenRa.FileFormats.csproj">
<Name>OpenRa.FileFormats</Name> <Project>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</Project>
</ProjectReference> <Name>OpenRa.FileFormats</Name>
</ItemGroup> </ProjectReference>
<ItemGroup> </ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0"> <ItemGroup>
<Visible>False</Visible> <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
<ProductName>.NET Framework 2.0 %28x86%29</ProductName> <Visible>False</Visible>
<Install>true</Install> <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
</BootstrapperPackage> <Install>true</Install>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0"> </BootstrapperPackage>
<Visible>False</Visible> <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
<ProductName>.NET Framework 3.0 %28x86%29</ProductName> <Visible>False</Visible>
<Install>false</Install> <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
</BootstrapperPackage> <Install>false</Install>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5"> </BootstrapperPackage>
<Visible>False</Visible> <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
<ProductName>.NET Framework 3.5</ProductName> <Visible>False</Visible>
<Install>false</Install> <ProductName>.NET Framework 3.5</ProductName>
</BootstrapperPackage> <Install>false</Install>
</ItemGroup> </BootstrapperPackage>
<ItemGroup> </ItemGroup>
<None Include="Game Code.cd" /> <ItemGroup>
<None Include="Graphics\Graphics.cd" /> <None Include="Game Code.cd" />
</ItemGroup> <None Include="Graphics\Graphics.cd" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> </ItemGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
Other similar extension points exist, see Microsoft.Common.targets. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<Target Name="BeforeBuild"> Other similar extension points exist, see Microsoft.Common.targets.
</Target> <Target Name="BeforeBuild">
<Target Name="AfterBuild"> </Target>
</Target> <Target Name="AfterBuild">
--> </Target>
-->
</Project> </Project>

50
OpenRa.Game/Order.cs Normal file
View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using OpenRa.Game.Traits;
namespace OpenRa.Game
{
sealed class Order
{
public readonly Player Player;
public readonly string OrderString;
public readonly Actor Subject;
public readonly Actor TargetActor;
public readonly int2 TargetLocation;
public readonly string TargetString;
private Order( Player player, string orderString, Actor subject, Actor targetActor, int2 targetLocation, string targetString )
{
this.Player = player;
this.OrderString = orderString;
this.Subject = subject;
this.TargetActor = targetActor;
this.TargetLocation = targetLocation;
this.TargetString = targetString;
}
// TODO: serialize / deserialize
public static Order Attack( Actor subject, Actor target )
{
return new Order( subject.Owner, "Attack", subject, target, int2.Zero, null );
}
public static Order Move( Actor subject, int2 target )
{
return new Order( subject.Owner, "Move", subject, null, target, null );
}
public static Order DeployMcv( Actor subject )
{
return new Order( subject.Owner, "DeployMcv", subject, null, int2.Zero, null );
}
public static Order PlaceBuilding( Player subject, int2 target, string buildingName )
{
return new Order( subject, "PlaceBuilding", null, null, target, buildingName );
}
}
}

View File

@@ -1,53 +1,53 @@
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 namespace OpenRa.Game
{ {
class PlaceBuilding : IOrderGenerator class PlaceBuilding : IOrderGenerator
{ {
public readonly Player Owner; public readonly Player Owner;
public readonly string Name; public readonly string Name;
public PlaceBuilding(Player owner, string name) public PlaceBuilding(Player owner, string name)
{ {
Owner = owner; Owner = owner;
Name = name; Name = name;
} }
public IEnumerable<Order> Order(int2 xy, bool lmb) public IEnumerable<Order> Order(int2 xy, bool lmb)
{ {
if( lmb ) if( lmb )
{ {
// todo: check that space is free // todo: check that space is free
var bi = (UnitInfo.BuildingInfo)Rules.UnitInfo[ Name ]; var bi = (UnitInfo.BuildingInfo)Rules.UnitInfo[ Name ];
if( Footprint.Tiles( bi, xy ).Any( if( Footprint.Tiles( bi, xy ).Any(
t => !Game.IsCellBuildable( t, t => !Game.IsCellBuildable( t,
bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel ) ) ) bi.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel ) ) )
yield break; yield break;
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( !Footprint.Tiles( bi, 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 new PlaceBuildingOrder( this, xy ); yield return OpenRa.Game.Order.PlaceBuilding( Owner, xy, Name );
} }
else // rmb else // rmb
{ {
Game.world.AddFrameEndTask( _ => Game.world.AddFrameEndTask( _ =>
{ {
Game.controller.orderGenerator = null; Game.controller.orderGenerator = null;
Game.worldRenderer.uiOverlay.KillOverlay(); Game.worldRenderer.uiOverlay.KillOverlay();
} ); } );
} }
} }
public void PrepareOverlay(int2 xy) public void PrepareOverlay(int2 xy)
{ {
Game.worldRenderer.uiOverlay.SetCurrentOverlay(xy, Name); Game.worldRenderer.uiOverlay.SetCurrentOverlay(xy, Name);
} }
} }
} }

View File

@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game
{
class PlaceBuildingOrder : Order
{
PlaceBuilding building;
int2 xy;
public PlaceBuildingOrder( PlaceBuilding building, int2 xy )
{
this.building = building;
this.xy = xy;
}
public override void Apply(bool doVoice)
{
Game.world.AddFrameEndTask( _ =>
{
Log.Write( "Player \"{0}\" builds {1}", building.Owner.PlayerName, building.Name );
//Adjust placement for cursor to be in middle
Game.world.Add( new Actor( building.Name, xy - GameRules.Footprint.AdjustForBuildingSize( building.Name ), building.Owner ) );
Game.controller.orderGenerator = null;
Game.worldRenderer.uiOverlay.KillOverlay();
} );
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game.Traits.Activities
{
class DeployMcv : Mobile.CurrentActivity
{
public Mobile.CurrentActivity NextActivity { get; set; }
public void 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 ) );
} );
}
public void Cancel( Actor self, Mobile mobile )
{
// Cancel can't happen between this being moved to the head of the list, and it being Ticked.
throw new InvalidOperationException( "DeployMcvAction: Cancel() should never occur." );
}
}
}

View File

@@ -1,111 +1,79 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
namespace OpenRa.Game.Traits namespace OpenRa.Game.Traits
{ {
abstract class AttackBase : IOrder abstract class AttackBase : IOrder
{ {
public Actor target; public Actor target;
// time (in frames) until each weapon can fire again. // time (in frames) until each weapon can fire again.
protected int primaryFireDelay = 0; protected int primaryFireDelay = 0;
protected int secondaryFireDelay = 0; protected int secondaryFireDelay = 0;
protected bool CanAttack( Actor self ) protected bool CanAttack( Actor self )
{ {
if( primaryFireDelay > 0 ) --primaryFireDelay; if( primaryFireDelay > 0 ) --primaryFireDelay;
if( secondaryFireDelay > 0 ) --secondaryFireDelay; if( secondaryFireDelay > 0 ) --secondaryFireDelay;
if( target != null && target.IsDead ) target = null; /* he's dead, jim. */ if( target != null && target.IsDead ) target = null; /* he's dead, jim. */
if( target == null ) return false; if( target == null ) return false;
return true; return true;
} }
protected void DoAttack( Actor self ) protected void DoAttack( Actor self )
{ {
if( self.unitInfo.Primary != null && CheckFire( self, self.unitInfo.Primary, ref primaryFireDelay ) ) if( self.unitInfo.Primary != null && CheckFire( self, self.unitInfo.Primary, ref primaryFireDelay ) )
{ {
secondaryFireDelay = Math.Max( 4, secondaryFireDelay ); secondaryFireDelay = Math.Max( 4, secondaryFireDelay );
return; return;
} }
if( self.unitInfo.Secondary != null && CheckFire( self, self.unitInfo.Secondary, ref secondaryFireDelay ) ) if( self.unitInfo.Secondary != null && CheckFire( self, self.unitInfo.Secondary, ref secondaryFireDelay ) )
return; return;
} }
bool CheckFire( Actor self, string weaponName, ref int fireDelay ) bool CheckFire( Actor self, string weaponName, ref int fireDelay )
{ {
if( fireDelay > 0 ) return false; if( fireDelay > 0 ) return false;
var weapon = Rules.WeaponInfo[ weaponName ]; var weapon = Rules.WeaponInfo[ weaponName ];
if( weapon.Range * weapon.Range < ( target.Location - self.Location ).LengthSquared ) return false; if( weapon.Range * weapon.Range < ( target.Location - self.Location ).LengthSquared ) return false;
fireDelay = weapon.ROF; fireDelay = weapon.ROF;
Game.world.Add( new Bullet( weaponName, self.Owner, self, Game.world.Add( new Bullet( weaponName, self.Owner, self,
self.CenterLocation.ToInt2(), self.CenterLocation.ToInt2(),
target.CenterLocation.ToInt2() ) ); target.CenterLocation.ToInt2() ) );
return true; return true;
} }
public Order Order( Actor self, int2 xy, bool lmb, Actor underCursor ) public Order Order( Actor self, int2 xy, bool lmb, Actor underCursor )
{ {
if( lmb || underCursor == null ) return null; if( lmb || underCursor == null ) return null;
if( underCursor.Owner == self.Owner ) return null; if( underCursor.Owner == self.Owner ) return null;
return new AttackOrder( self, underCursor ); return OpenRa.Game.Order.Attack( self, underCursor );
} }
} }
class AttackTurreted : AttackBase, ITick class AttackTurreted : AttackBase, ITick
{ {
public AttackTurreted( Actor self ) { self.traits.Get<Turreted>(); } public AttackTurreted( Actor self ) { self.traits.Get<Turreted>(); }
public void Tick(Actor self) public void Tick(Actor self)
{ {
if( !CanAttack( self ) ) return; if( !CanAttack( self ) ) return;
var turreted = self.traits.Get<Turreted>(); var turreted = self.traits.Get<Turreted>();
turreted.desiredFacing = Util.GetFacing( target.CenterLocation - self.CenterLocation, turreted.turretFacing ); turreted.desiredFacing = Util.GetFacing( target.CenterLocation - self.CenterLocation, turreted.turretFacing );
if( turreted.desiredFacing != turreted.turretFacing ) if( turreted.desiredFacing != turreted.turretFacing )
return; return;
DoAttack( self ); DoAttack( self );
} }
} }
}
class AttackOrder : Order
{
public readonly Actor Attacker;
public readonly Actor Target;
const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
public AttackOrder( Actor attacker, Actor target )
{
this.Attacker = attacker;
this.Target = target;
}
public override void Apply( bool doVoice )
{
var mobile = Attacker.traits.GetOrDefault<Mobile>();
if (mobile != null)
{
var weapon = Attacker.unitInfo.Primary ?? Attacker.unitInfo.Secondary;
/* todo: choose the appropriate weapon, when only one works against this target */
var range = Rules.WeaponInfo[weapon].Range;
mobile.Cancel(Attacker);
mobile.QueueActivity(
new Mobile.MoveTo(Target,
Math.Max(0, (int)range - RangeTolerance)));
}
Attacker.traits.Get<AttackTurreted>().target = Target;
}
}
}

View File

@@ -1,64 +1,25 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
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;
// TODO: check that there's enough space at the destination. // TODO: check that there's enough space at the destination.
if( xy == self.Location ) if( xy == self.Location )
return new DeployMcvOrder( self, xy ); return OpenRa.Game.Order.DeployMcv( self );
return null; return null;
} }
} }
}
class DeployMcvOrder : Order
{
Actor Unit;
int2 Location;
public DeployMcvOrder( Actor unit, int2 location )
{
Unit = unit;
Location = location;
}
public override void Apply( bool doVoice )
{
var mobile = Unit.traits.Get<Mobile>();
mobile.QueueActivity( new Mobile.Turn( 96 ) );
mobile.QueueActivity( new DeployAction() );
}
class DeployAction : Mobile.CurrentActivity
{
public Mobile.CurrentActivity NextActivity { get; set; }
public void 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 ) );
} );
}
public void Cancel( Actor self, Mobile mobile )
{
// Cancel can't happen between this being moved to the head of the list, and it being Ticked.
throw new InvalidOperationException( "DeployMcvAction: Cancel() should never occur." );
}
}
}
}

View File

@@ -21,7 +21,7 @@ namespace OpenRa.Game.Traits
public Mobile(Actor self) public Mobile(Actor self)
{ {
this.self = self; this.self = self;
fromCell = toCell; fromCell = toCell;
Game.UnitInfluence.Update( this ); Game.UnitInfluence.Update( this );
} }
@@ -55,8 +55,8 @@ namespace OpenRa.Game.Traits
if( underCursor != null ) if( underCursor != null )
return null; return null;
if (xy != toCell) if( xy != toCell )
return new MoveOrder(self, xy); return OpenRa.Game.Order.Move( self, xy );
return null; return null;
} }

73
OpenRa.Game/UnitOrders.cs Executable file
View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRa.Game.Traits;
namespace OpenRa.Game
{
static class UnitOrders
{
public static void ProcessOrder( Order order )
{
switch( order.OrderString )
{
case "Move":
{
var mobile = order.Subject.traits.Get<Mobile>();
mobile.Cancel( order.Subject );
mobile.QueueActivity( new Mobile.MoveTo( order.TargetLocation ) );
var attackBase = order.Subject.traits.WithInterface<AttackBase>().FirstOrDefault();
if( attackBase != null )
attackBase.target = null; /* move cancels attack order */
break;
}
case "Attack":
{
const int RangeTolerance = 1; /* how far inside our maximum range we should try to sit */
var mobile = order.Subject.traits.GetOrDefault<Mobile>();
var weapon = order.Subject.unitInfo.Primary ?? order.Subject.unitInfo.Secondary;
mobile.Cancel( order.Subject );
// TODO: this block should be a separate activity; "MoveNear", maybe?
{
/* todo: choose the appropriate weapon, when only one works against this target */
var range = Rules.WeaponInfo[ weapon ].Range;
mobile.QueueActivity(
new Mobile.MoveTo( order.TargetActor,
Math.Max( 0, (int)range - RangeTolerance ) ) );
}
order.Subject.traits.Get<AttackTurreted>().target = order.TargetActor;
break;
}
case "DeployMcv":
{
var mobile = order.Subject.traits.Get<Mobile>();
mobile.QueueActivity( new Mobile.Turn( 96 ) );
mobile.QueueActivity( new Traits.Activities.DeployMcv() );
break;
}
case "PlaceBuilding":
{
Game.world.AddFrameEndTask( _ =>
{
var building = Rules.UnitInfo[ order.TargetString ];
Log.Write( "Player \"{0}\" builds {1}", order.Player.PlayerName, building.Name );
//Adjust placement for cursor to be in middle
Game.world.Add( new Actor( building.Name, order.TargetLocation - GameRules.Footprint.AdjustForBuildingSize( building.Name ), order.Player ) );
Game.controller.orderGenerator = null;
Game.worldRenderer.uiOverlay.KillOverlay();
} );
break;
}
default:
throw new NotImplementedException();
}
}
}
}