From c762453607f3e55987cbf3f17507d27b93273a90 Mon Sep 17 00:00:00 2001 From: Forcecore Date: Sat, 21 Oct 2017 16:34:24 +0000 Subject: [PATCH] (External)Capturable are now conditional --- OpenRA.Mods.Common/AI/HackyAI.cs | 24 +++++++++++++++++-- OpenRA.Mods.Common/Activities/CaptureActor.cs | 4 ++-- OpenRA.Mods.Common/Traits/Capturable.cs | 18 ++++++++++---- OpenRA.Mods.Common/Traits/Captures.cs | 7 ++++-- .../Traits/ExternalCapturable.cs | 17 +++++++++---- OpenRA.Mods.Common/Traits/ExternalCaptures.cs | 6 +++-- 6 files changed, 58 insertions(+), 18 deletions(-) diff --git a/OpenRA.Mods.Common/AI/HackyAI.cs b/OpenRA.Mods.Common/AI/HackyAI.cs index 59653c67a2..437b70cccd 100644 --- a/OpenRA.Mods.Common/AI/HackyAI.cs +++ b/OpenRA.Mods.Common/AI/HackyAI.cs @@ -717,13 +717,33 @@ namespace OpenRA.Mods.Common.AI var capturableTargetOptions = targetOptions .Select(a => new CaptureTarget(a, "CaptureActor")) - .Where(target => target.Info != null && capturers.Any(capturer => target.Info.CanBeTargetedBy(capturer, target.Actor.Owner))) + .Where(target => + { + if (target.Info == null) + return false; + + var capturable = target.Actor.TraitOrDefault(); + if (capturable == null) + return false; + + return capturers.Any(capturer => capturable.CanBeTargetedBy(capturer, target.Actor.Owner)); + }) .OrderByDescending(target => target.Actor.GetSellValue()) .Take(maximumCaptureTargetOptions); var externalCapturableTargetOptions = targetOptions .Select(a => new CaptureTarget(a, "ExternalCaptureActor")) - .Where(target => target.Info != null && capturers.Any(capturer => target.Info.CanBeTargetedBy(capturer, target.Actor.Owner))) + .Where(target => + { + if (target.Info == null) + return false; + + var externalCapturable = target.Actor.TraitOrDefault(); + if (externalCapturable == null) + return false; + + return capturers.Any(capturer => externalCapturable.CanBeTargetedBy(capturer, target.Actor.Owner)); + }) .OrderByDescending(target => target.Actor.GetSellValue()) .Take(maximumCaptureTargetOptions); diff --git a/OpenRA.Mods.Common/Activities/CaptureActor.cs b/OpenRA.Mods.Common/Activities/CaptureActor.cs index 6d5b688bf7..aa37f629da 100644 --- a/OpenRA.Mods.Common/Activities/CaptureActor.cs +++ b/OpenRA.Mods.Common/Activities/CaptureActor.cs @@ -36,12 +36,12 @@ namespace OpenRA.Mods.Common.Activities protected override bool CanReserve(Actor self) { - return !capturable.BeingCaptured && capturable.Info.CanBeTargetedBy(self, actor.Owner); + return !capturable.BeingCaptured && capturable.CanBeTargetedBy(self, actor.Owner); } protected override void OnInside(Actor self) { - if (actor.IsDead || capturable.BeingCaptured) + if (actor.IsDead || capturable.BeingCaptured || capturable.IsTraitDisabled) return; if (building != null && !building.Lock()) diff --git a/OpenRA.Mods.Common/Traits/Capturable.cs b/OpenRA.Mods.Common/Traits/Capturable.cs index 3f584154af..8be0d0cbde 100644 --- a/OpenRA.Mods.Common/Traits/Capturable.cs +++ b/OpenRA.Mods.Common/Traits/Capturable.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("This actor can be captured by a unit with Captures: trait.")] - public class CapturableInfo : ITraitInfo + public class CapturableInfo : ConditionalTraitInfo { [Desc("CaptureTypes (from the Captures trait) that are able to capture this.")] public readonly HashSet Types = new HashSet() { "building" }; @@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Traits public readonly int CaptureThreshold = 50; public readonly bool CancelActivity = false; - public object Create(ActorInitializer init) { return new Capturable(this); } + public override object Create(ActorInitializer init) { return new Capturable(this); } public bool CanBeTargetedBy(Actor captor, Player owner) { @@ -46,11 +46,11 @@ namespace OpenRA.Mods.Common.Traits } } - public class Capturable : INotifyCapture + public class Capturable : ConditionalTrait, INotifyCapture { - public readonly CapturableInfo Info; public bool BeingCaptured { get; private set; } - public Capturable(CapturableInfo info) { Info = info; } + public Capturable(CapturableInfo info) + : base(info) { } public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner) { @@ -64,5 +64,13 @@ namespace OpenRA.Mods.Common.Traits t.ResolveOrder(self, stop); } } + + public bool CanBeTargetedBy(Actor captor, Player owner) + { + if (IsTraitDisabled) + return false; + + return Info.CanBeTargetedBy(captor, owner); + } } } diff --git a/OpenRA.Mods.Common/Traits/Captures.cs b/OpenRA.Mods.Common/Traits/Captures.cs index 225863b92d..4a1def3d7f 100644 --- a/OpenRA.Mods.Common/Traits/Captures.cs +++ b/OpenRA.Mods.Common/Traits/Captures.cs @@ -101,7 +101,7 @@ namespace OpenRA.Mods.Common.Traits public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - var c = target.Info.TraitInfoOrDefault(); + var c = target.TraitOrDefault(); if (c == null || !c.CanBeTargetedBy(self, target.Owner)) { cursor = capturesInfo.EnterBlockedCursor; @@ -109,15 +109,18 @@ namespace OpenRA.Mods.Common.Traits } var health = target.Trait(); - var lowEnoughHealth = health.HP <= c.CaptureThreshold * health.MaxHP / 100; + var lowEnoughHealth = health.HP <= c.Info.CaptureThreshold * health.MaxHP / 100; cursor = !capturesInfo.Sabotage || lowEnoughHealth || target.Owner.NonCombatant ? capturesInfo.EnterCursor : capturesInfo.SabotageCursor; + return true; } public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) { + // TODO: This doesn't account for disabled traits. + // Actors with FrozenUnderFog should not disable the Capturable trait. var c = target.Info.TraitInfoOrDefault(); if (c == null || !c.CanBeTargetedBy(self, target.Owner)) { diff --git a/OpenRA.Mods.Common/Traits/ExternalCapturable.cs b/OpenRA.Mods.Common/Traits/ExternalCapturable.cs index 456d4c9bfe..257772e2c1 100644 --- a/OpenRA.Mods.Common/Traits/ExternalCapturable.cs +++ b/OpenRA.Mods.Common/Traits/ExternalCapturable.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("This actor can be captured by a unit with ExternalCaptures: trait.")] - public class ExternalCapturableInfo : ITraitInfo + public class ExternalCapturableInfo : ConditionalTraitInfo { [Desc("CaptureTypes (from the ExternalCaptures trait) that are able to capture this.")] public readonly HashSet Types = new HashSet() { "building" }; @@ -45,21 +45,20 @@ namespace OpenRA.Mods.Common.Traits return true; } - public object Create(ActorInitializer init) { return new ExternalCapturable(init.Self, this); } + public override object Create(ActorInitializer init) { return new ExternalCapturable(init.Self, this); } } - public class ExternalCapturable : ITick, ISync, IPreventsAutoTarget + public class ExternalCapturable : ConditionalTrait, ITick, ISync, IPreventsAutoTarget { [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) + : base(info) { this.self = self; - Info = info; } public void BeginCapture(Actor captor) @@ -95,5 +94,13 @@ namespace OpenRA.Mods.Common.Traits { return Info.PreventsAutoTarget && Captor != null && attacker.AppearsFriendlyTo(Captor); } + + public bool CanBeTargetedBy(Actor captor, Player owner) + { + if (IsTraitDisabled) + return false; + + return Info.CanBeTargetedBy(captor, owner); + } } } diff --git a/OpenRA.Mods.Common/Traits/ExternalCaptures.cs b/OpenRA.Mods.Common/Traits/ExternalCaptures.cs index 3e392b190f..083f5b8755 100644 --- a/OpenRA.Mods.Common/Traits/ExternalCaptures.cs +++ b/OpenRA.Mods.Common/Traits/ExternalCaptures.cs @@ -81,7 +81,7 @@ namespace OpenRA.Mods.Common.Traits if (order.Target.Type == TargetType.Actor) { var c = order.TargetActor.TraitOrDefault(); - return c != null && !c.CaptureInProgress && c.Info.CanBeTargetedBy(self, order.TargetActor.Owner); + return c != null && !c.CaptureInProgress && c.CanBeTargetedBy(self, order.TargetActor.Owner); } return false; @@ -118,7 +118,7 @@ namespace OpenRA.Mods.Common.Traits { var c = target.TraitOrDefault(); - var canTargetActor = c != null && !c.CaptureInProgress && c.Info.CanBeTargetedBy(self, target.Owner); + var canTargetActor = c != null && !c.CaptureInProgress && c.CanBeTargetedBy(self, target.Owner); var capturesInfo = self.Trait().Info; cursor = canTargetActor ? capturesInfo.CaptureCursor : capturesInfo.CaptureBlockedCursor; return canTargetActor; @@ -126,6 +126,8 @@ namespace OpenRA.Mods.Common.Traits public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) { + // TODO: This doesn't account for disabled traits. + // Actors with FrozenUnderFog should not disable the ExternalCapturable trait. var c = target.Info.TraitInfoOrDefault(); var canTargetActor = c != null && c.CanBeTargetedBy(self, target.Owner);