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: