diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index 689aafae86..09df0ab8cb 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -106,7 +106,6 @@
True
Resources.resx
-
@@ -114,7 +113,6 @@
-
diff --git a/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs b/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs
deleted file mode 100644
index a270fe08e9..0000000000
--- a/OpenRa.Game/Orders/ChronoshiftDestinationOrderGenerator.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Drawing;
-using OpenRa.Traits;
-
-namespace OpenRa.Orders
-{
- class ChronoshiftDestinationOrderGenerator : IOrderGenerator
- {
- public readonly Actor self;
-
- public ChronoshiftDestinationOrderGenerator(Actor self)
- {
- this.self = self;
- }
-
- public IEnumerable Order(World world, int2 xy, MouseInput mi)
- {
- if (mi.Button == MouseButton.Right)
- {
- Game.controller.CancelInputMode();
- yield break;
- }
-
- yield return new Order("Chronoshift", self, xy);
- yield return new Order("ChronosphereFinish", self.Owner.PlayerActor);
- }
-
- public void Tick( World world ) {}
- public void Render( World world )
- {
- world.WorldRenderer.DrawSelectionBox(self, Color.White, true);
- }
-
- public Cursor GetCursor(World world, int2 xy, MouseInput mi)
- {
- if (!world.LocalPlayer.Shroud.IsExplored(xy))
- return Cursor.MoveBlocked;
-
- var movement = self.traits.GetOrDefault();
- return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked;
- }
- }
-}
diff --git a/OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs b/OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs
deleted file mode 100644
index 0dc07e3bfd..0000000000
--- a/OpenRa.Game/Orders/ChronosphereSelectOrderGenerator.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using OpenRa.GameRules;
-using OpenRa.Traits;
-
-namespace OpenRa.Orders
-{
- class ChronosphereSelectOrderGenerator : IOrderGenerator
- {
- public ChronosphereSelectOrderGenerator() {}
-
- public IEnumerable Order(World world, int2 xy, MouseInput mi)
- {
- if (mi.Button == MouseButton.Right)
- Game.controller.CancelInputMode();
-
- return OrderInner(world, xy, mi);
- }
-
- IEnumerable OrderInner(World world, int2 xy, MouseInput mi)
- {
- if (mi.Button == MouseButton.Left)
- {
- var loc = mi.Location + Game.viewport.Location;
- var underCursor = world.FindUnits(loc, loc)
- .Where(a => a.Owner == world.LocalPlayer
- && a.traits.Contains()
- && a.traits.Contains()).FirstOrDefault();
-
- if (underCursor != null)
- yield return new Order("ChronosphereSelect", world.LocalPlayer.PlayerActor, underCursor);
- }
-
- yield break;
- }
-
- public void Tick( World world )
- {
- var hasChronosphere = world.Actors
- .Any(a => a.Owner == world.LocalPlayer && a.traits.Contains());
-
- if (!hasChronosphere)
- Game.controller.CancelInputMode();
- }
-
- public void Render( World world ) { }
-
- public Cursor GetCursor(World world, int2 xy, MouseInput mi)
- {
- mi.Button = MouseButton.Left;
- return OrderInner(world, xy, mi).Any()
- ? Cursor.ChronoshiftSelect : Cursor.MoveBlocked;
- }
- }
-}
diff --git a/OpenRa.Game/Orders/UnitOrderGenerator.cs b/OpenRa.Game/Orders/UnitOrderGenerator.cs
index 945b8d1cfa..c58b19617a 100644
--- a/OpenRa.Game/Orders/UnitOrderGenerator.cs
+++ b/OpenRa.Game/Orders/UnitOrderGenerator.cs
@@ -74,11 +74,6 @@ namespace OpenRa.Orders
else
return Cursor.DeployBlocked;
case "Deploy": return Cursor.Deploy;
- case "Chronoshift":
- if (movement.CanEnterCell(location))
- return Cursor.Chronoshift;
- else
- return Cursor.MoveBlocked;
case "Enter": return Cursor.Enter;
case "EnterTransport": return Cursor.Enter;
case "Deliver": return Cursor.Enter;
diff --git a/OpenRa.Game/Traits/ChronoshiftPower.cs b/OpenRa.Game/Traits/ChronoshiftPower.cs
index 1c0c15487c..4a735b2d2e 100644
--- a/OpenRa.Game/Traits/ChronoshiftPower.cs
+++ b/OpenRa.Game/Traits/ChronoshiftPower.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Drawing;
using OpenRa.Orders;
namespace OpenRa.Traits
@@ -14,43 +15,155 @@ namespace OpenRa.Traits
}
class ChronoshiftPower : SupportPower, IResolveOrder
- {
+ {
public ChronoshiftPower(Actor self, ChronoshiftPowerInfo info) : base(self, info) { }
protected override void OnBeginCharging() { Sound.Play("chrochr1.aud"); }
protected override void OnFinishCharging() { Sound.Play("chrordy1.aud"); }
-
protected override void OnActivate()
{
- Game.controller.orderGenerator = new ChronosphereSelectOrderGenerator();
+ Game.controller.orderGenerator = new SelectTarget();
Sound.Play("slcttgt1.aud");
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "ChronosphereSelect" && self.Owner == self.World.LocalPlayer)
- Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(order.TargetActor);
+ {
+ Game.controller.orderGenerator = new SelectDestination(order.TargetActor);
+ }
- if (order.OrderString == "ChronosphereFinish")
+ if (order.OrderString == "ChronosphereActivate")
{
if (self.Owner == self.World.LocalPlayer)
Game.controller.CancelInputMode();
+
+ // Cannot chronoshift into unexplored location
+ if (!self.Owner.Shroud.IsExplored(order.TargetLocation))
+ return;
+
+ // Ensure the target cell is valid for the unit
+ var movement = order.TargetActor.traits.GetOrDefault();
+ if (!movement.CanEnterCell(order.TargetLocation))
+ return;
- FinishActivate();
-
- Sound.Play("chrono2.aud");
-
- var chronosphere = self.World.Actors.Where(a => a.Owner == self.Owner
- && a.traits.Contains()).FirstOrDefault();
- if( chronosphere != null )
+ var chronosphere = self.World.Actors.Where(a => a.Owner == self.Owner
+ && a.traits.Contains()).FirstOrDefault();
+ if (chronosphere != null)
chronosphere.traits.Get().PlayCustomAnim( chronosphere, "active" );
// Trigger screen desaturate effect
foreach (var a in self.World.Actors.Where(a => a.traits.Contains()))
a.traits.Get().DoChronoshift();
+
+ Sound.Play("chrono2.aud");
+
+ order.TargetActor.traits.Get().Activate(order.TargetActor,
+ order.TargetLocation,
+ (int)((Info as ChronoshiftPowerInfo).Duration * 25 * 60),
+ (Info as ChronoshiftPowerInfo).KillCargo,
+ chronosphere);
+
+ Game.controller.CancelInputMode();
+ FinishActivate();
+ }
+ }
+
+ class SelectTarget : IOrderGenerator
+ {
+ public SelectTarget() { }
+
+ public IEnumerable Order(World world, int2 xy, MouseInput mi)
+ {
+ if (mi.Button == MouseButton.Right)
+ Game.controller.CancelInputMode();
+
+ return OrderInner(world, xy, mi);
+ }
+
+ IEnumerable OrderInner(World world, int2 xy, MouseInput mi)
+ {
+ if (mi.Button == MouseButton.Left)
+ {
+ var loc = mi.Location + Game.viewport.Location;
+ var underCursor = world.FindUnits(loc, loc)
+ .Where(a => a.Owner == world.LocalPlayer
+ && a.traits.Contains()
+ && a.traits.Contains()).FirstOrDefault();
+
+ if (underCursor != null)
+ yield return new Order("ChronosphereSelect", world.LocalPlayer.PlayerActor, underCursor);
+ }
+
+ yield break;
+ }
+
+ public void Tick( World world )
+ {
+ var hasChronosphere = world.Actors
+ .Any(a => a.Owner == world.LocalPlayer && a.traits.Contains());
+
+ if (!hasChronosphere)
+ Game.controller.CancelInputMode();
+
+ // TODO: Check if the selected unit is still alive
+ }
+
+ public void Render( World world ) { }
+
+ public Cursor GetCursor(World world, int2 xy, MouseInput mi)
+ {
+ mi.Button = MouseButton.Left;
+ return OrderInner(world, xy, mi).Any()
+ ? Cursor.ChronoshiftSelect : Cursor.MoveBlocked;
+ }
+ }
+
+ class SelectDestination : IOrderGenerator
+ {
+ Actor self;
+ public SelectDestination(Actor self)
+ {
+ this.self = self;
+ }
+
+ public IEnumerable Order(World world, int2 xy, MouseInput mi)
+ {
+ if (mi.Button == MouseButton.Right)
+ {
+ Game.controller.CancelInputMode();
+ yield break;
+ }
+
+ yield return new Order("ChronosphereActivate", world.LocalPlayer.PlayerActor, self, xy);
+ }
+
+ public void Tick(World world)
+ {
+ var hasChronosphere = world.Actors
+ .Any(a => a.Owner == world.LocalPlayer && a.traits.Contains());
+
+ if (!hasChronosphere)
+ Game.controller.CancelInputMode();
+
+ // TODO: Check if the selected unit is still alive
+ }
+
+ public void Render(World world)
+ {
+ world.WorldRenderer.DrawSelectionBox(self, Color.Red, true);
+ }
+
+ public Cursor GetCursor(World world, int2 xy, MouseInput mi)
+ {
+ if (!world.LocalPlayer.Shroud.IsExplored(xy))
+ return Cursor.MoveBlocked;
+
+ var movement = self.traits.GetOrDefault();
+ return (movement.CanEnterCell(xy)) ? Cursor.Chronoshift : Cursor.MoveBlocked;
}
}
}
-
+
// tag trait to identify the building
class ChronosphereInfo : StatelessTraitInfo { }
public class Chronosphere { }
diff --git a/OpenRa.Game/Traits/Chronoshiftable.cs b/OpenRa.Game/Traits/Chronoshiftable.cs
index 0c8e049c28..9c6de67a25 100644
--- a/OpenRa.Game/Traits/Chronoshiftable.cs
+++ b/OpenRa.Game/Traits/Chronoshiftable.cs
@@ -10,7 +10,7 @@ namespace OpenRa.Traits
public object Create(Actor self) { return new Chronoshiftable(self); }
}
- public class Chronoshiftable : IResolveOrder, ITick
+ public class Chronoshiftable : ITick
{
// Return-to-sender logic
[Sync]
@@ -37,37 +37,26 @@ namespace OpenRa.Traits
}
}
- public void ResolveOrder(Actor self, Order order)
+ public virtual void Activate(Actor self, int2 targetLocation, int duration, bool killCargo, Actor chronosphere)
{
- var movement = self.traits.GetOrDefault();
- if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation))
+ /// Set up return-to-sender info
+ chronoshiftOrigin = self.Location;
+ chronoshiftReturnTicks = duration;
+
+ // Kill cargo
+ if (killCargo && self.traits.Contains())
{
- // Cannot chronoshift into unexplored location
- if (!self.Owner.Shroud.IsExplored(order.TargetLocation))
- return;
-
- var info = self.Owner.PlayerActor.Info.Traits.Get();
-
- // Set up return-to-sender info
- chronoshiftOrigin = self.Location;
- chronoshiftReturnTicks = (int)(info.Duration * 60 * 25);
-
- // Kill cargo
- if (info.KillCargo && self.traits.Contains())
+ var cargo = self.traits.Get();
+ while (!cargo.IsEmpty(self))
{
- var cargo = self.traits.Get();
- while (!cargo.IsEmpty(self))
- {
- order.Player.Kills++;
- cargo.Unload(self);
- }
+ chronosphere.Owner.Kills++;
+ cargo.Unload(self);
}
-
- // Set up the teleport
- self.CancelActivity();
- self.QueueActivity(new Activities.Teleport(order.TargetLocation));
}
+
+ // Set up the teleport
+ self.CancelActivity();
+ self.QueueActivity(new Activities.Teleport(targetLocation));
}
}
-
}
diff --git a/OpenRa.Mods.Aftermath/DemoTruck.cs b/OpenRa.Mods.Aftermath/DemoTruck.cs
index 8ff1eb2159..f67776abeb 100644
--- a/OpenRa.Mods.Aftermath/DemoTruck.cs
+++ b/OpenRa.Mods.Aftermath/DemoTruck.cs
@@ -12,22 +12,14 @@ namespace OpenRa.Mods.Aftermath
public object Create(Actor self) { return new DemoTruck(self); }
}
- class DemoTruck : Chronoshiftable, IResolveOrder, INotifyDamage
+ class DemoTruck : Chronoshiftable, INotifyDamage
{
public DemoTruck(Actor self) : base(self) { }
- public new void ResolveOrder(Actor self, Order order)
+ // Explode on chronoshift
+ public override void Activate(Actor self, int2 targetLocation, int duration, bool killCargo, Actor chronosphere)
{
- // Override chronoshifting action to detonate vehicle
- var movement = self.traits.GetOrDefault();
- var chronosphere = self.World.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains()).FirstOrDefault();
- if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation))
- {
- self.InflictDamage(chronosphere, self.Health, Rules.WarheadInfo["Super"]);
- return;
- }
-
- base.ResolveOrder(self, order);
+ Detonate(self, chronosphere);
}
// Fire primary on death
diff --git a/mods/aftermath/rules.yaml b/mods/aftermath/rules.yaml
index 6941b2caba..9a0050e92d 100644
--- a/mods/aftermath/rules.yaml
+++ b/mods/aftermath/rules.yaml
@@ -71,6 +71,7 @@ DTRK:
AttackBase:
PrimaryWeapon: Democharge
RenderUnit:
+ -Chronoshiftable:
DemoTruck:
QTNK: