diff --git a/OpenRA.Mods.RA/Activities/CaptureActor.cs b/OpenRA.Mods.RA/Activities/CaptureActor.cs index 77bd9617b1..11b8a2680b 100644 --- a/OpenRA.Mods.RA/Activities/CaptureActor.cs +++ b/OpenRA.Mods.RA/Activities/CaptureActor.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -9,10 +9,9 @@ #endregion using System.Linq; -using OpenRA.Traits; -using OpenRA.Effects; -using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Move; +using OpenRA.Traits; namespace OpenRA.Mods.RA.Activities { @@ -24,57 +23,46 @@ namespace OpenRA.Mods.RA.Activities public override Activity Tick(Actor self) { + if (IsCanceled || !target.IsValidFor(self)) + return NextActivity; + if (target.Type != TargetType.Actor) return NextActivity; - var capturable = target.Actor.Trait(); - - if (IsCanceled || !self.IsInWorld || self.IsDead() || !target.IsValidFor(self)) - { - if (capturable.CaptureInProgress) - capturable.EndCapture(); - + var actor = target.Actor; + var b = actor.TraitOrDefault(); + if (b != null && b.Locked) return NextActivity; - } - var mobile = self.Trait(); - var nearest = target.Actor.OccupiesSpace.NearestCellTo(mobile.toCell); + var capturesInfo = self.Info.Traits.Get(); + var capturableInfo = actor.Info.Traits.Get(); - if ((nearest - mobile.toCell).LengthSquared > 2) - return Util.SequenceActivities(new MoveAdjacentTo(target), this); + var health = actor.Trait(); - if (!capturable.CaptureInProgress) - capturable.BeginCapture(self); - else + self.World.AddFrameEndTask(w => { - if (capturable.Captor != self) return NextActivity; - - if (capturable.CaptureProgressTime % 25 == 0) + var lowEnoughHealth = health.HP <= capturableInfo.CaptureThreshold * health.MaxHP; + if (!capturesInfo.Sabotage || lowEnoughHealth || actor.Owner.NonCombatant) { - self.World.Add(new FlashTarget(target.Actor, self.Owner)); - self.World.Add(new FlashTarget(self)); + var oldOwner = actor.Owner; + + actor.ChangeOwner(self.Owner); + + foreach (var t in actor.TraitsImplementing()) + t.OnCapture(actor, self, oldOwner, self.Owner); + + if (b != null && b.Locked) + b.Unlock(); + } + else + { + var damage = (int)(health.MaxHP * capturesInfo.SabotageHPRemoval); + actor.InflictDamage(self, damage, null); } - if (capturable.CaptureProgressTime == capturable.Info.CaptureCompleteTime * 25) - { - var capturesInfo = self.Info.Traits.Get(); + self.Destroy(); + }); - self.World.AddFrameEndTask(w => - { - var oldOwner = target.Actor.Owner; - - target.Actor.ChangeOwner(self.Owner); - - foreach (var t in target.Actor.TraitsImplementing()) - t.OnCapture(target.Actor, self, oldOwner, self.Owner); - - capturable.EndCapture(); - - if (capturesInfo != null && capturesInfo.ConsumeActor) - self.Destroy(); - }); - } - } return this; } } diff --git a/OpenRA.Mods.RA/Activities/ExternalCaptureActor.cs b/OpenRA.Mods.RA/Activities/ExternalCaptureActor.cs new file mode 100644 index 0000000000..77c1bd7cf2 --- /dev/null +++ b/OpenRA.Mods.RA/Activities/ExternalCaptureActor.cs @@ -0,0 +1,81 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System.Linq; +using OpenRA.Traits; +using OpenRA.Effects; +using OpenRA.Mods.RA.Move; +using OpenRA.Mods.RA.Buildings; + +namespace OpenRA.Mods.RA.Activities +{ + class ExternalCaptureActor : Activity + { + Target target; + + public ExternalCaptureActor(Target target) { this.target = target; } + + public override Activity Tick(Actor self) + { + if (target.Type != TargetType.Actor) + return NextActivity; + + var capturable = target.Actor.Trait(); + + if (IsCanceled || !self.IsInWorld || self.IsDead() || !target.IsValidFor(self)) + { + if (capturable.CaptureInProgress) + capturable.EndCapture(); + + return NextActivity; + } + + var mobile = self.Trait(); + var nearest = target.Actor.OccupiesSpace.NearestCellTo(mobile.toCell); + + if ((nearest - mobile.toCell).LengthSquared > 2) + return Util.SequenceActivities(new MoveAdjacentTo(target), this); + + if (!capturable.CaptureInProgress) + capturable.BeginCapture(self); + else + { + if (capturable.Captor != self) return NextActivity; + + if (capturable.CaptureProgressTime % 25 == 0) + { + self.World.Add(new FlashTarget(target.Actor, self.Owner)); + self.World.Add(new FlashTarget(self)); + } + + if (capturable.CaptureProgressTime == capturable.Info.CaptureCompleteTime * 25) + { + var capturesInfo = self.Info.Traits.Get(); + + self.World.AddFrameEndTask(w => + { + var oldOwner = target.Actor.Owner; + + target.Actor.ChangeOwner(self.Owner); + + foreach (var t in target.Actor.TraitsImplementing()) + t.OnCapture(target.Actor, self, oldOwner, self.Owner); + + capturable.EndCapture(); + + if (capturesInfo != null && capturesInfo.ConsumeActor) + self.Destroy(); + }); + } + } + return this; + } + } +} diff --git a/OpenRA.Mods.RA/Activities/LegacyCaptureActor.cs b/OpenRA.Mods.RA/Activities/LegacyCaptureActor.cs deleted file mode 100644 index 6455e7dc72..0000000000 --- a/OpenRA.Mods.RA/Activities/LegacyCaptureActor.cs +++ /dev/null @@ -1,69 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Linq; -using OpenRA.Mods.RA.Buildings; -using OpenRA.Mods.RA.Move; -using OpenRA.Traits; - -namespace OpenRA.Mods.RA.Activities -{ - class LegacyCaptureActor : Activity - { - Target target; - - public LegacyCaptureActor(Target target) { this.target = target; } - - public override Activity Tick(Actor self) - { - if (IsCanceled || !target.IsValidFor(self)) - return NextActivity; - - if (target.Type != TargetType.Actor) - return NextActivity; - - var actor = target.Actor; - var b = actor.TraitOrDefault(); - if (b != null && b.Locked) - return NextActivity; - - var capturesInfo = self.Info.Traits.Get(); - var capturableInfo = actor.Info.Traits.Get(); - - var health = actor.Trait(); - - self.World.AddFrameEndTask(w => - { - var lowEnoughHealth = health.HP <= capturableInfo.CaptureThreshold * health.MaxHP; - if (!capturesInfo.Sabotage || lowEnoughHealth || actor.Owner.NonCombatant) - { - var oldOwner = actor.Owner; - - actor.ChangeOwner(self.Owner); - - foreach (var t in actor.TraitsImplementing()) - t.OnCapture(actor, self, oldOwner, self.Owner); - - if (b != null && b.Locked) - b.Unlock(); - } - else - { - var damage = (int)(health.MaxHP * capturesInfo.SabotageHPRemoval); - actor.InflictDamage(self, damage, null); - } - - self.Destroy(); - }); - - return this; - } - } -} diff --git a/OpenRA.Mods.RA/Capturable.cs b/OpenRA.Mods.RA/Capturable.cs index 0c3d2c5745..70f9478d65 100644 --- a/OpenRA.Mods.RA/Capturable.cs +++ b/OpenRA.Mods.RA/Capturable.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -8,25 +8,22 @@ */ #endregion -using System; using System.Linq; -using OpenRA.Effects; -using OpenRA.FileFormats; using OpenRA.Traits; -using OpenRA.Mods.RA.Buildings; +using OpenRA.FileFormats; namespace OpenRA.Mods.RA { [Desc("This actor can be captured by a unit with Captures: trait.")] - public class CapturableInfo : ITraitInfo + class CapturableInfo : TraitInfo { [Desc("Type of actor (the Captures: trait defines what Types it can capture).")] public readonly string Type = "building"; public readonly bool AllowAllies = false; public readonly bool AllowNeutral = true; public readonly bool AllowEnemies = true; - [Desc("Seconds it takes to change the owner.", "You might want to add a CapturableBar: trait, too.")] - public readonly int CaptureCompleteTime = 15; + [Desc("Health percentage the target must be at (or below) before it can be captured.")] + public readonly float CaptureThreshold = 0.5f; public bool CanBeTargetedBy(Actor captor, Player owner) { @@ -49,51 +46,7 @@ namespace OpenRA.Mods.RA return true; } - - public object Create(ActorInitializer init) { return new Capturable(init.self, this); } } - public class Capturable : ITick - { - [Sync] public int CaptureProgressTime = 0; - [Sync] public Actor Captor; - private Actor self; - public CapturableInfo Info; - public bool CaptureInProgress { get { return Captor != null; } } - - public Capturable(Actor self, CapturableInfo info) - { - this.self = self; - Info = info; - } - - public void BeginCapture(Actor captor) - { - var building = self.TraitOrDefault(); - if (building != null) - building.Lock(); - - Captor = captor; - } - - public void EndCapture() - { - var building = self.TraitOrDefault(); - if (building != null) - building.Unlock(); - - Captor = null; - } - - public void Tick(Actor self) - { - if (Captor != null && (!Captor.IsInWorld || Captor.IsDead())) - EndCapture(); - - if (!CaptureInProgress) - CaptureProgressTime = 0; - else - CaptureProgressTime++; - } - } + class Capturable { } } diff --git a/OpenRA.Mods.RA/Captures.cs b/OpenRA.Mods.RA/Captures.cs index 72c6cdc8c2..ea9f9ac274 100644 --- a/OpenRA.Mods.RA/Captures.cs +++ b/OpenRA.Mods.RA/Captures.cs @@ -1,6 +1,6 @@ -#region Copyright & License Information +#region Copyright & License Information /* - * Copyright 2007-2012 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -25,8 +25,10 @@ namespace OpenRA.Mods.RA { [Desc("Types of actors that it can capture, as long as the type also exists in the Capturable Type: trait.")] public readonly string[] CaptureTypes = { "building" }; - [Desc("Destroy the unit after capturing.")] - public readonly bool ConsumeActor = false; + [Desc("Unit will do damage to the actor instead of capturing it. Unit is destroyed when sabotaging.")] + public readonly bool Sabotage = true; + [Desc("Only used if Sabotage=true. Sabotage damage expressed as a percentage of enemy health removed.")] + public readonly float SabotageHPRemoval = 0.5f; public object Create(ActorInitializer init) { return new Captures(init.self, this); } } @@ -44,7 +46,7 @@ namespace OpenRA.Mods.RA { get { - yield return new CaptureOrderTargeter(); + yield return new CaptureOrderTargeter(Info.Sabotage); } } @@ -59,40 +61,14 @@ namespace OpenRA.Mods.RA return new Order(order.OrderID, self, queued) { TargetActor = target.Actor }; } - bool IsValidOrder(Actor self, Order order) - { - // Not targeting an actor - if (order.ExtraData == 0 && order.TargetActor == null) - return false; - - if (order.ExtraData != 0) - { - // Targeted an actor under the fog - var frozenLayer = self.Owner.PlayerActor.TraitOrDefault(); - if (frozenLayer == null) - return false; - - var frozen = frozenLayer.FromID(order.ExtraData); - if (frozen == null) - return false; - - var ci = frozen.Info.Traits.GetOrDefault(); - return ci != null && ci.CanBeTargetedBy(self, frozen.Owner); - } - - var c = order.TargetActor.TraitOrDefault(); - return c != null && !c.CaptureInProgress && c.Info.CanBeTargetedBy(self, order.TargetActor.Owner); - } - public string VoicePhraseForOrder(Actor self, Order order) { - return order.OrderString == "CaptureActor" && IsValidOrder(self, order) - ? "Attack" : null; + return order.OrderString == "CaptureActor" ? "Attack" : null; } public void ResolveOrder(Actor self, Order order) { - if (order.OrderString != "CaptureActor" || !IsValidOrder(self, order)) + if (order.OrderString != "CaptureActor") return; var target = self.ResolveFrozenActorOrder(order, Color.Red); @@ -103,30 +79,53 @@ namespace OpenRA.Mods.RA self.CancelActivity(); self.SetTargetLine(target, Color.Red); - self.QueueActivity(new CaptureActor(target)); - } - } - - class CaptureOrderTargeter : UnitOrderTargeter - { - public CaptureOrderTargeter() : base("CaptureActor", 6, "enter", true, true) { } - - public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) - { - var c = target.TraitOrDefault(); - - var canTargetActor = c != null && !c.CaptureInProgress && c.Info.CanBeTargetedBy(self, target.Owner); - cursor = canTargetActor ? "ability" : "move-blocked"; - return canTargetActor; + self.QueueActivity(new Enter(target.Actor, new CaptureActor(target))); } - public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) + class CaptureOrderTargeter : UnitOrderTargeter { - var c = target.Info.Traits.GetOrDefault(); + readonly bool sabotage; - var canTargetActor = c != null && c.CanBeTargetedBy(self, target.Owner); - cursor = canTargetActor ? "ability" : "move-blocked"; - return canTargetActor; + public CaptureOrderTargeter(bool sabotage) + : base("CaptureActor", 6, "enter", true, true) + { + this.sabotage = sabotage; + } + + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) + { + var c = target.Info.Traits.GetOrDefault(); + if (c == null || !c.CanBeTargetedBy(self, target.Owner)) + { + cursor = "enter-blocked"; + return false; + } + + var health = target.Trait(); + var lowEnoughHealth = health.HP <= c.CaptureThreshold * health.MaxHP; + + cursor = !sabotage || lowEnoughHealth || target.Owner.NonCombatant + ? "capture" : "enter"; + return true; + } + + public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) + { + var c = target.Info.Traits.GetOrDefault(); + if (c == null || !c.CanBeTargetedBy(self, target.Owner)) + { + cursor = "enter-blocked"; + return false; + } + + var health = target.Info.Traits.GetOrDefault(); + var lowEnoughHealth = target.HP <= c.CaptureThreshold * health.HP; + + cursor = !sabotage || lowEnoughHealth || target.Owner.NonCombatant + ? "capture" : "enter"; + + return true; + } } } } diff --git a/OpenRA.Mods.RA/ExternalCapturable.cs b/OpenRA.Mods.RA/ExternalCapturable.cs new file mode 100644 index 0000000000..7eaf10b59c --- /dev/null +++ b/OpenRA.Mods.RA/ExternalCapturable.cs @@ -0,0 +1,99 @@ +#region Copyright & License Information +/* + * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Linq; +using OpenRA.Effects; +using OpenRA.FileFormats; +using OpenRA.Traits; +using OpenRA.Mods.RA.Buildings; + +namespace OpenRA.Mods.RA +{ + [Desc("This actor can be captured by a unit with ExternalCaptures: trait.")] + public class ExternalCapturableInfo : ITraitInfo + { + [Desc("Type of actor (the ExternalCaptures: trait defines what Types it can capture).")] + public readonly string Type = "building"; + public readonly bool AllowAllies = false; + public readonly bool AllowNeutral = true; + public readonly bool AllowEnemies = true; + [Desc("Seconds it takes to change the owner.", "You might want to add a ExternalCapturableBar: trait, too.")] + public readonly int CaptureCompleteTime = 15; + + public bool CanBeTargetedBy(Actor captor, Player owner) + { + var c = captor.TraitOrDefault(); + if (c == null) + return false; + + var playerRelationship = owner.Stances[captor.Owner]; + if (playerRelationship == Stance.Ally && !AllowAllies) + return false; + + if (playerRelationship == Stance.Enemy && !AllowEnemies) + return false; + + if (playerRelationship == Stance.Neutral && !AllowNeutral) + return false; + + if (!c.Info.CaptureTypes.Contains(Type)) + return false; + + return true; + } + + public object Create(ActorInitializer init) { return new ExternalCapturable(init.self, this); } + } + + public class ExternalCapturable : ITick + { + [Sync] public int CaptureProgressTime = 0; + [Sync] public Actor Captor; + private Actor self; + public ExternalCapturableInfo Info; + public bool CaptureInProgress { get { return Captor != null; } } + + public ExternalCapturable(Actor self, ExternalCapturableInfo info) + { + this.self = self; + Info = info; + } + + public void BeginCapture(Actor captor) + { + var building = self.TraitOrDefault(); + if (building != null) + building.Lock(); + + Captor = captor; + } + + public void EndCapture() + { + var building = self.TraitOrDefault(); + if (building != null) + building.Unlock(); + + Captor = null; + } + + public void Tick(Actor self) + { + if (Captor != null && (!Captor.IsInWorld || Captor.IsDead())) + EndCapture(); + + if (!CaptureInProgress) + CaptureProgressTime = 0; + else + CaptureProgressTime++; + } + } +} diff --git a/OpenRA.Mods.RA/CapturableBar.cs b/OpenRA.Mods.RA/ExternalCapturableBar.cs similarity index 63% rename from OpenRA.Mods.RA/CapturableBar.cs rename to OpenRA.Mods.RA/ExternalCapturableBar.cs index 1aaa944f7d..04707a0d96 100644 --- a/OpenRA.Mods.RA/CapturableBar.cs +++ b/OpenRA.Mods.RA/ExternalCapturableBar.cs @@ -15,19 +15,19 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - [Desc("Visualize the remaining CaptureCompleteTime from Capturable: trait.")] - class CapturableBarInfo : ITraitInfo, Requires + [Desc("Visualize the remaining CaptureCompleteTime from ExternalCapturable: trait.")] + class ExternalCapturableBarInfo : ITraitInfo, Requires { - public object Create(ActorInitializer init) { return new CapturableBar(init.self); } + public object Create(ActorInitializer init) { return new ExternalCapturableBar(init.self); } } - class CapturableBar : ISelectionBar + class ExternalCapturableBar : ISelectionBar { - Capturable cap; + ExternalCapturable cap; - public CapturableBar(Actor self) + public ExternalCapturableBar(Actor self) { - this.cap = self.Trait(); + this.cap = self.Trait(); } public float GetValue() diff --git a/OpenRA.Mods.RA/ExternalCaptures.cs b/OpenRA.Mods.RA/ExternalCaptures.cs new file mode 100644 index 0000000000..1aad9fefb2 --- /dev/null +++ b/OpenRA.Mods.RA/ExternalCaptures.cs @@ -0,0 +1,132 @@ +#region Copyright & License Information +/* + * Copyright 2007-2012 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.Mods.RA.Activities; +using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Orders; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + [Desc("This actor can capture other actors which have the ExternalCapturable: trait.")] + class ExternalCapturesInfo : ITraitInfo + { + [Desc("Types of actors that it can capture, as long as the type also exists in the ExternalCapturable Type: trait.")] + public readonly string[] CaptureTypes = { "building" }; + [Desc("Destroy the unit after capturing.")] + public readonly bool ConsumeActor = false; + + public object Create(ActorInitializer init) { return new ExternalCaptures(init.self, this); } + } + + class ExternalCaptures : IIssueOrder, IResolveOrder, IOrderVoice + { + public readonly ExternalCapturesInfo Info; + + public ExternalCaptures(Actor self, ExternalCapturesInfo info) + { + Info = info; + } + + public IEnumerable Orders + { + get + { + yield return new ExternalCaptureOrderTargeter(); + } + } + + public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) + { + if (order.OrderID != "ExternalCaptureActor") + return null; + + if (target.Type == TargetType.FrozenActor) + return new Order(order.OrderID, self, queued) { ExtraData = target.FrozenActor.ID }; + + return new Order(order.OrderID, self, queued) { TargetActor = target.Actor }; + } + + bool IsValidOrder(Actor self, Order order) + { + // Not targeting an actor + if (order.ExtraData == 0 && order.TargetActor == null) + return false; + + if (order.ExtraData != 0) + { + // Targeted an actor under the fog + var frozenLayer = self.Owner.PlayerActor.TraitOrDefault(); + if (frozenLayer == null) + return false; + + var frozen = frozenLayer.FromID(order.ExtraData); + if (frozen == null) + return false; + + var ci = frozen.Info.Traits.GetOrDefault(); + return ci != null && ci.CanBeTargetedBy(self, frozen.Owner); + } + + var c = order.TargetActor.TraitOrDefault(); + return c != null && !c.CaptureInProgress && c.Info.CanBeTargetedBy(self, order.TargetActor.Owner); + } + + public string VoicePhraseForOrder(Actor self, Order order) + { + return order.OrderString == "ExternalCaptureActor" && IsValidOrder(self, order) + ? "Attack" : null; + } + + public void ResolveOrder(Actor self, Order order) + { + if (order.OrderString != "ExternalCaptureActor" || !IsValidOrder(self, order)) + return; + + var target = self.ResolveFrozenActorOrder(order, Color.Red); + if (target.Type != TargetType.Actor) + return; + + if (!order.Queued) + self.CancelActivity(); + + self.SetTargetLine(target, Color.Red); + self.QueueActivity(new ExternalCaptureActor(target)); + } + } + + class ExternalCaptureOrderTargeter : UnitOrderTargeter + { + public ExternalCaptureOrderTargeter() : base("ExternalCaptureActor", 6, "enter", true, true) { } + + public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) + { + var c = target.TraitOrDefault(); + + var canTargetActor = c != null && !c.CaptureInProgress && c.Info.CanBeTargetedBy(self, target.Owner); + cursor = canTargetActor ? "ability" : "move-blocked"; + return canTargetActor; + } + + public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) + { + var c = target.Info.Traits.GetOrDefault(); + + var canTargetActor = c != null && c.CanBeTargetedBy(self, target.Owner); + cursor = canTargetActor ? "ability" : "move-blocked"; + return canTargetActor; + } + } +} diff --git a/OpenRA.Mods.RA/LegacyCapturable.cs b/OpenRA.Mods.RA/LegacyCapturable.cs deleted file mode 100644 index 3375d1d024..0000000000 --- a/OpenRA.Mods.RA/LegacyCapturable.cs +++ /dev/null @@ -1,52 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Linq; -using OpenRA.Traits; -using OpenRA.FileFormats; - -namespace OpenRA.Mods.RA -{ - [Desc("This actor can be captured by a unit with LegacyCaptures: trait.")] - class LegacyCapturableInfo : TraitInfo - { - [Desc("Type of actor (the LegacyCaptures: trait defines what Types it can capture).")] - public readonly string Type = "building"; - public readonly bool AllowAllies = false; - public readonly bool AllowNeutral = true; - public readonly bool AllowEnemies = true; - [Desc("Health percentage the target must be at (or below) before it can be captured.")] - public readonly float CaptureThreshold = 0.5f; - - public bool CanBeTargetedBy(Actor captor, Player owner) - { - var c = captor.TraitOrDefault(); - if (c == null) - return false; - - var playerRelationship = owner.Stances[captor.Owner]; - if (playerRelationship == Stance.Ally && !AllowAllies) - return false; - - if (playerRelationship == Stance.Enemy && !AllowEnemies) - return false; - - if (playerRelationship == Stance.Neutral && !AllowNeutral) - return false; - - if (!c.Info.CaptureTypes.Contains(Type)) - return false; - - return true; - } - } - - class LegacyCapturable { } -} diff --git a/OpenRA.Mods.RA/LegacyCaptures.cs b/OpenRA.Mods.RA/LegacyCaptures.cs deleted file mode 100644 index 8193145f8a..0000000000 --- a/OpenRA.Mods.RA/LegacyCaptures.cs +++ /dev/null @@ -1,131 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using OpenRA.FileFormats; -using OpenRA.Mods.RA.Activities; -using OpenRA.Mods.RA.Buildings; -using OpenRA.Mods.RA.Orders; -using OpenRA.Traits; - -namespace OpenRA.Mods.RA -{ - [Desc("This actor can capture other actors which have the LegacyCapturable: trait.")] - class LegacyCapturesInfo : ITraitInfo - { - [Desc("Types of actors that it can capture, as long as the type also exists in the LegacyCapturable Type: trait.")] - public readonly string[] CaptureTypes = { "building" }; - [Desc("Unit will do damage to the actor instead of capturing it. Unit is destroyed when sabotaging.")] - public readonly bool Sabotage = true; - [Desc("Only used if Sabotage=true. Sabotage damage expressed as a percentage of enemy health removed.")] - public readonly float SabotageHPRemoval = 0.5f; - - public object Create(ActorInitializer init) { return new LegacyCaptures(init.self, this); } - } - - class LegacyCaptures : IIssueOrder, IResolveOrder, IOrderVoice - { - public readonly LegacyCapturesInfo Info; - - public LegacyCaptures(Actor self, LegacyCapturesInfo info) - { - Info = info; - } - - public IEnumerable Orders - { - get - { - yield return new LegacyCaptureOrderTargeter(Info.Sabotage); - } - } - - public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) - { - if (order.OrderID != "LegacyCaptureActor") - return null; - - if (target.Type == TargetType.FrozenActor) - return new Order(order.OrderID, self, queued) { ExtraData = target.FrozenActor.ID }; - - return new Order(order.OrderID, self, queued) { TargetActor = target.Actor }; - } - - public string VoicePhraseForOrder(Actor self, Order order) - { - return order.OrderString == "LegacyCaptureActor" ? "Attack" : null; - } - - public void ResolveOrder(Actor self, Order order) - { - if (order.OrderString != "LegacyCaptureActor") - return; - - var target = self.ResolveFrozenActorOrder(order, Color.Red); - if (target.Type != TargetType.Actor) - return; - - if (!order.Queued) - self.CancelActivity(); - - self.SetTargetLine(target, Color.Red); - self.QueueActivity(new Enter(target.Actor, new LegacyCaptureActor(target))); - } - - class LegacyCaptureOrderTargeter : UnitOrderTargeter - { - readonly bool sabotage; - - public LegacyCaptureOrderTargeter(bool sabotage) - : base("LegacyCaptureActor", 6, "enter", true, true) - { - this.sabotage = sabotage; - } - - public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) - { - var c = target.Info.Traits.GetOrDefault(); - if (c == null || !c.CanBeTargetedBy(self, target.Owner)) - { - cursor = "enter-blocked"; - return false; - } - - var health = target.Trait(); - var lowEnoughHealth = health.HP <= c.CaptureThreshold * health.MaxHP; - - cursor = !sabotage || lowEnoughHealth || target.Owner.NonCombatant - ? "capture" : "enter"; - return true; - } - - public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) - { - var c = target.Info.Traits.GetOrDefault(); - if (c == null || !c.CanBeTargetedBy(self, target.Owner)) - { - cursor = "enter-blocked"; - return false; - } - - var health = target.Info.Traits.GetOrDefault(); - var lowEnoughHealth = target.HP <= c.CaptureThreshold * health.HP; - - cursor = !sabotage || lowEnoughHealth || target.Owner.NonCombatant - ? "capture" : "enter"; - - return true; - } - } - } -} diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 5e8643fe0c..50f6ce7bbb 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -80,14 +80,14 @@ - + - + @@ -174,10 +174,10 @@ + + - - - + @@ -244,7 +244,7 @@ - + @@ -529,7 +529,5 @@ cd "$(SolutionDir)thirdparty/" copy "FuzzyLogicLibrary.dll" "$(SolutionDir)" cd "$(SolutionDir)" - - - + diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index a6233b7412..fb886ef859 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -328,7 +328,7 @@ RelativeToTopLeft: yes ShakeOnDeath: Sellable: - LegacyCapturable: + Capturable: CombatDebugOverlay: Guardable: Range: 3 @@ -351,7 +351,7 @@ RenderBuilding: WithBuildingExplosion: -RepairableBuilding: - -LegacyCapturable: + -Capturable: -Sellable: Tooltip: Name: Civilian Building @@ -374,7 +374,7 @@ ^TechBuilding: Inherits: ^CivBuilding - LegacyCapturable: + Capturable: RepairableBuilding: EngineerRepairable: RevealsShroud: diff --git a/mods/cnc/rules/infantry.yaml b/mods/cnc/rules/infantry.yaml index e70638735c..fa7afce410 100644 --- a/mods/cnc/rules/infantry.yaml +++ b/mods/cnc/rules/infantry.yaml @@ -166,7 +166,7 @@ E6: PipType: Yellow EngineerRepair: RepairsBridges: - LegacyCaptures: + Captures: CaptureTypes: building, husk -AutoTarget: AttackMove: diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index 492fd4f45e..0afb310914 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -208,8 +208,8 @@ SellSounds: BUILD1.WAV Adjacent: 3 GivesBuildableArea: - Capturable: - CapturableBar: + ExternalCapturable: + ExternalCapturableBar: SoundOnDamageTransition: DamagedSound: EXPLSML1.WAV DestroyedSound: EXPLHG1.WAV diff --git a/mods/d2k/rules/infantry.yaml b/mods/d2k/rules/infantry.yaml index fb2ad18e01..171bd9ff02 100644 --- a/mods/d2k/rules/infantry.yaml +++ b/mods/d2k/rules/infantry.yaml @@ -47,7 +47,7 @@ ENGINEER: Passenger: PipType: Yellow EngineerRepair: - Captures: + ExternalCaptures: -AutoTarget: AttackMove: JustMove: true diff --git a/mods/d2k/rules/structures.yaml b/mods/d2k/rules/structures.yaml index 20ad4f1205..8e891b3eb6 100644 --- a/mods/d2k/rules/structures.yaml +++ b/mods/d2k/rules/structures.yaml @@ -640,8 +640,8 @@ SIETCH: Range: 10 -GivesBuildableArea: -Sellable: - -Capturable: - -CapturableBar: + -ExternalCapturable: + -ExternalCapturableBar: STARPORTC: Inherits: ^STARPORT diff --git a/mods/ra/maps/Fort-Lonestar/map.yaml b/mods/ra/maps/Fort-Lonestar/map.yaml index 5c47c7e007..a90523ad52 100644 --- a/mods/ra/maps/Fort-Lonestar/map.yaml +++ b/mods/ra/maps/Fort-Lonestar/map.yaml @@ -529,8 +529,8 @@ Rules: Bib: RevealsShroud: Range: 3 - Capturable: - CapturableBar: + ExternalCapturable: + ExternalCapturableBar: EngineerRepairable: -MustBeDestroyed: CashTrickler: diff --git a/mods/ra/maps/apollo/map.yaml b/mods/ra/maps/apollo/map.yaml index 1ea2d94ae4..5bbe6bae01 100644 --- a/mods/ra/maps/apollo/map.yaml +++ b/mods/ra/maps/apollo/map.yaml @@ -2606,8 +2606,8 @@ Rules: HP: 2000 Armor: Heavy: - Capturable: - CapturableBar: + ExternalCapturable: + ExternalCapturableBar: CashTrickler: Period: 750 Amount: 333 diff --git a/mods/ra/maps/artemis/map.yaml b/mods/ra/maps/artemis/map.yaml index a6f69f7e82..44f27a63ef 100644 --- a/mods/ra/maps/artemis/map.yaml +++ b/mods/ra/maps/artemis/map.yaml @@ -2940,7 +2940,7 @@ Rules: HP: 1500 Armor: Heavy: - Capturable: + ExternalCapturable: CashTrickler: Period: 250 Amount: 50 diff --git a/mods/ra/maps/dionysus/map.yaml b/mods/ra/maps/dionysus/map.yaml index 6cd02b39d0..71f928340b 100644 --- a/mods/ra/maps/dionysus/map.yaml +++ b/mods/ra/maps/dionysus/map.yaml @@ -2157,8 +2157,8 @@ Rules: HP: 2000 Armor: Heavy: - Capturable: - CapturableBar: + ExternalCapturable: + ExternalCapturableBar: CashTrickler: Period: 750 Amount: 333 diff --git a/mods/ra/maps/zeus/map.yaml b/mods/ra/maps/zeus/map.yaml index 7958a6f3f5..80e23c92da 100644 --- a/mods/ra/maps/zeus/map.yaml +++ b/mods/ra/maps/zeus/map.yaml @@ -2588,7 +2588,7 @@ Rules: HP: 2000 Armor: Heavy: - Capturable: + ExternalCapturable: CashTrickler: Period: 750 Amount: 333 diff --git a/mods/ra/rules/civilian.yaml b/mods/ra/rules/civilian.yaml index 4e9c3188ae..f4de5a7020 100644 --- a/mods/ra/rules/civilian.yaml +++ b/mods/ra/rules/civilian.yaml @@ -79,8 +79,8 @@ HOSP: Dimensions: 2,2 Health: HP: 1000 - Capturable: - CapturableBar: + ExternalCapturable: + ExternalCapturableBar: EngineerRepairable: SelfHealingTech: Type: InfantryHealing @@ -101,7 +101,7 @@ V01: TransformOnCapture: IntoActor: v01.sniper SkipMakeAnims: true - LegacyCapturable: + Capturable: Type: CivilianBuilding CaptureThreshold: 1 EditorTilesetFilter: @@ -129,7 +129,7 @@ V01.SNIPER: OnExit: v01 SkipMakeAnims: true BecomeNeutral: true - -LegacyCapturable: + -Capturable: EditorTilesetFilter: ExcludeTilesets: DESERT @@ -320,8 +320,8 @@ OILB: HP: 1000 RevealsShroud: Range: 3 - Capturable: - CapturableBar: + ExternalCapturable: + ExternalCapturableBar: EngineerRepairable: -MustBeDestroyed: CashTrickler: diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 76f90d1f70..5743e46b79 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -222,8 +222,8 @@ TerrainTypes: Clear,Road RequiresBaseProvider: True GivesBuildableArea: - Capturable: - CapturableBar: + ExternalCapturable: + ExternalCapturableBar: SoundOnDamageTransition: DamagedSound: kaboom1.aud DestroyedSound: kaboom22.aud @@ -303,8 +303,8 @@ -AcceptsSupplies: -GivesBuildableArea: -Sellable: - -Capturable: - -CapturableBar: + -ExternalCapturable: + -ExternalCapturableBar: FrozenUnderFog: StartsRevealed: true -GpsDot: diff --git a/mods/ra/rules/infantry.yaml b/mods/ra/rules/infantry.yaml index 7dd2338963..f0dd80ca5e 100644 --- a/mods/ra/rules/infantry.yaml +++ b/mods/ra/rules/infantry.yaml @@ -172,7 +172,7 @@ E6: PipType: Yellow EngineerRepair: RepairsBridges: - Captures: + ExternalCaptures: TakeCover: -AutoTarget: AttackMove: @@ -489,7 +489,7 @@ SNIPER: CloakSound: UncloakSound: UncloakOnMove: yes - LegacyCaptures: + Captures: CaptureTypes: CivilianBuilding Sabotage: no SabotageHPRemoval: 0 diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index d4050f8c90..3ef39c5683 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -11,7 +11,6 @@ TerrainTypes: Clear,Road GivesBuildableArea: Capturable: - CapturableBar: SoundOnDamageTransition: DamagedSound: #TODO DestroyedSound: #TODO diff --git a/mods/ts/rules/infantry.yaml b/mods/ts/rules/infantry.yaml index c378b22d1e..fadfcbac81 100644 --- a/mods/ts/rules/infantry.yaml +++ b/mods/ts/rules/infantry.yaml @@ -163,7 +163,7 @@ ENGINEER: PipType: Yellow EngineerRepair: RepairsBridges: - LegacyCaptures: + Captures: CaptureTypes: building -AutoTarget: AttackMove: