diff --git a/OpenRA.Mods.Cnc/Activities/Infiltrate.cs b/OpenRA.Mods.Cnc/Activities/Infiltrate.cs index f92124fd47..0cd288ce75 100644 --- a/OpenRA.Mods.Cnc/Activities/Infiltrate.cs +++ b/OpenRA.Mods.Cnc/Activities/Infiltrate.cs @@ -9,6 +9,8 @@ */ #endregion +using OpenRA.Activities; +using OpenRA.Mods.Cnc.Traits; using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Traits; using OpenRA.Traits; @@ -18,18 +20,14 @@ namespace OpenRA.Mods.Cnc.Activities class Infiltrate : Enter { readonly Actor target; - readonly Stance validStances; + readonly Infiltrates infiltrates; readonly Cloak cloak; - readonly string notification; - readonly int experience; - public Infiltrate(Actor self, Actor target, EnterBehaviour enterBehaviour, Stance validStances, string notification, int experience) - : base(self, target, enterBehaviour) + public Infiltrate(Actor self, Actor target, Infiltrates infiltrate) + : base(self, target, infiltrate.Info.EnterBehaviour) { this.target = target; - this.validStances = validStances; - this.notification = notification; - this.experience = experience; + infiltrates = infiltrate; cloak = self.TraitOrDefault(); } @@ -39,7 +37,7 @@ namespace OpenRA.Mods.Cnc.Activities return; var stance = self.Owner.Stances[target.Owner]; - if (!validStances.HasStance(stance)) + if (!infiltrates.Info.ValidStances.HasStance(stance)) return; if (cloak != null && cloak.Info.UncloakOn.HasFlag(UncloakType.Infiltrate)) @@ -50,11 +48,19 @@ namespace OpenRA.Mods.Cnc.Activities var exp = self.Owner.PlayerActor.TraitOrDefault(); if (exp != null) - exp.GiveExperience(experience); + exp.GiveExperience(infiltrates.Info.PlayerExperience); - if (!string.IsNullOrEmpty(notification)) + if (!string.IsNullOrEmpty(infiltrates.Info.Notification)) Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", - notification, self.Owner.Faction.InternalName); + infiltrates.Info.Notification, self.Owner.Faction.InternalName); + } + + public override Activity Tick(Actor self) + { + if (infiltrates.IsTraitDisabled) + Cancel(self); + + return base.Tick(self); } } } diff --git a/OpenRA.Mods.Cnc/Scripting/Properties/InfiltrateProperties.cs b/OpenRA.Mods.Cnc/Scripting/Properties/InfiltrateProperties.cs index 1a64dd7194..3f9071b8ed 100644 --- a/OpenRA.Mods.Cnc/Scripting/Properties/InfiltrateProperties.cs +++ b/OpenRA.Mods.Cnc/Scripting/Properties/InfiltrateProperties.cs @@ -9,6 +9,9 @@ */ #endregion +using System.Collections.Generic; +using System.Linq; +using Eluant; using OpenRA.Mods.Cnc.Activities; using OpenRA.Mods.Cnc.Traits; using OpenRA.Scripting; @@ -19,18 +22,23 @@ namespace OpenRA.Mods.Cnc.Scripting [ScriptPropertyGroup("Ability")] public class InfiltrateProperties : ScriptActorProperties, Requires { - readonly InfiltratesInfo info; + readonly Infiltrates[] infiltratesTraits; public InfiltrateProperties(ScriptContext context, Actor self) : base(context, self) { - info = Self.Info.TraitInfo(); + infiltratesTraits = Self.TraitsImplementing().ToArray(); } [Desc("Infiltrate the target actor.")] public void Infiltrate(Actor target) { - Self.QueueActivity(new Infiltrate(Self, target, info.EnterBehaviour, info.ValidStances, info.Notification, info.PlayerExperience)); + var infiltrates = infiltratesTraits.FirstOrDefault(x => !x.IsTraitDisabled && x.Info.Types.Overlaps(target.GetEnabledTargetTypes())); + + if (infiltrates == null) + throw new LuaException("{0} tried to infiltrate invalid target {1}!".F(Self, target)); + + Self.QueueActivity(new Infiltrate(Self, target, infiltrates)); } } } diff --git a/OpenRA.Mods.Cnc/Traits/Infiltration/Infiltrates.cs b/OpenRA.Mods.Cnc/Traits/Infiltration/Infiltrates.cs index 1e45f834f8..46ef3c9102 100644 --- a/OpenRA.Mods.Cnc/Traits/Infiltration/Infiltrates.cs +++ b/OpenRA.Mods.Cnc/Traits/Infiltration/Infiltrates.cs @@ -21,7 +21,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Cnc.Traits { - class InfiltratesInfo : ITraitInfo + public class InfiltratesInfo : ConditionalTraitInfo { public readonly HashSet Types = new HashSet(); @@ -40,21 +40,23 @@ namespace OpenRA.Mods.Cnc.Traits [Desc("Experience to grant to the infiltrating player.")] public readonly int PlayerExperience = 0; - public object Create(ActorInitializer init) { return new Infiltrates(this); } + public override object Create(ActorInitializer init) { return new Infiltrates(this); } } - class Infiltrates : IIssueOrder, IResolveOrder, IOrderVoice + public class Infiltrates : ConditionalTrait, IIssueOrder, IResolveOrder, IOrderVoice { - readonly InfiltratesInfo info; - public Infiltrates(InfiltratesInfo info) - { - this.info = info; - } + : base(info) { } public IEnumerable Orders { - get { yield return new InfiltrationOrderTargeter(info); } + get + { + if (IsTraitDisabled) + yield break; + + yield return new InfiltrationOrderTargeter(Info); + } } public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued) @@ -70,6 +72,9 @@ namespace OpenRA.Mods.Cnc.Traits bool IsValidOrder(Actor self, Order order) { + if (IsTraitDisabled) + return false; + // Not targeting an actor if (order.ExtraData == 0 && order.TargetActor == null) return false; @@ -92,30 +97,30 @@ namespace OpenRA.Mods.Cnc.Traits else targetTypes = order.TargetActor.GetEnabledTargetTypes(); - return info.Types.Overlaps(targetTypes); + return Info.Types.Overlaps(targetTypes); } public string VoicePhraseForOrder(Actor self, Order order) { return order.OrderString == "Infiltrate" && IsValidOrder(self, order) - ? info.Voice : null; + ? Info.Voice : null; } public void ResolveOrder(Actor self, Order order) { - if (order.OrderString != "Infiltrate" || !IsValidOrder(self, order)) + if (order.OrderString != "Infiltrate" || !IsValidOrder(self, order) || IsTraitDisabled) return; var target = self.ResolveFrozenActorOrder(order, Color.Red); if (target.Type != TargetType.Actor - || !info.Types.Overlaps(target.Actor.GetAllTargetTypes())) + || !Info.Types.Overlaps(target.Actor.GetAllTargetTypes())) return; if (!order.Queued) self.CancelActivity(); self.SetTargetLine(target, Color.Red); - self.QueueActivity(new Infiltrate(self, target.Actor, info.EnterBehaviour, info.ValidStances, info.Notification, info.PlayerExperience)); + self.QueueActivity(new Infiltrate(self, target.Actor, this)); } }