diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index aad4f5aa23..b38db302fa 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -273,7 +273,7 @@ - + diff --git a/OpenRA.Mods.Common/Traits/Attack/AttackWander.cs b/OpenRA.Mods.Common/Traits/AttackWander.cs similarity index 95% rename from OpenRA.Mods.Common/Traits/Attack/AttackWander.cs rename to OpenRA.Mods.Common/Traits/AttackWander.cs index fa467db1c5..7f6438d038 100644 --- a/OpenRA.Mods.Common/Traits/Attack/AttackWander.cs +++ b/OpenRA.Mods.Common/Traits/AttackWander.cs @@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Traits public AttackWander(Actor self, AttackWanderInfo info) : base(self, info) { - attackMove = self.TraitOrDefault(); + attackMove = self.Trait(); } public override void DoAction(Actor self, CPos targetCell) diff --git a/OpenRA.Mods.Common/Traits/Wanders.cs b/OpenRA.Mods.Common/Traits/Wanders.cs index b8ec03010c..02a963cc91 100644 --- a/OpenRA.Mods.Common/Traits/Wanders.cs +++ b/OpenRA.Mods.Common/Traits/Wanders.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Wanders around aimlessly while idle.")] - public abstract class WandersInfo : ITraitInfo + public class WandersInfo : UpgradableTraitInfo, Requires { public readonly int WanderMoveRadius = 1; @@ -28,13 +28,14 @@ namespace OpenRA.Mods.Common.Traits [Desc("Maximum amount of ticks the actor will sit idly before starting to wander.")] public readonly int MaxMoveDelay = 0; - public abstract object Create(ActorInitializer init); + public override object Create(ActorInitializer init) { return new Wanders(init.Self, this); } } - public class Wanders : INotifyIdle, INotifyBecomingIdle + public class Wanders : UpgradableTrait, INotifyCreated, INotifyIdle, INotifyBecomingIdle { readonly Actor self; readonly WandersInfo info; + IResolveOrder move; int countdown; int ticksIdle; @@ -42,12 +43,18 @@ namespace OpenRA.Mods.Common.Traits bool firstTick = true; public Wanders(Actor self, WandersInfo info) + : base(info) { this.self = self; this.info = info; effectiveMoveRadius = info.WanderMoveRadius; } + void INotifyCreated.Created(Actor self) + { + move = self.Trait() as IResolveOrder; + } + public virtual void OnBecomingIdle(Actor self) { countdown = self.World.SharedRandom.Next(info.MinMoveDelay, info.MaxMoveDelay); @@ -55,9 +62,13 @@ namespace OpenRA.Mods.Common.Traits public virtual void TickIdle(Actor self) { - // The countdown has not have been set at this point, so don't check yet + if (IsTraitDisabled) + return; + + // OnBecomingIdle has not been called yet at this point, so set the initial countdown here if (firstTick) { + countdown = self.World.SharedRandom.Next(info.MinMoveDelay, info.MaxMoveDelay); firstTick = false; return; } @@ -92,7 +103,7 @@ namespace OpenRA.Mods.Common.Traits public virtual void DoAction(Actor self, CPos targetCell) { - throw new NotImplementedException("Base class Wanders does not implement method DoAction!"); + move.ResolveOrder(self, new Order("Move", self, false) { TargetLocation = targetCell }); } } } diff --git a/OpenRA.Mods.D2k/Activities/SwallowActor.cs b/OpenRA.Mods.D2k/Activities/SwallowActor.cs index 9e58d7821f..a8344700c6 100644 --- a/OpenRA.Mods.D2k/Activities/SwallowActor.cs +++ b/OpenRA.Mods.D2k/Activities/SwallowActor.cs @@ -152,7 +152,7 @@ namespace OpenRA.Mods.D2k.Activities sandworm.IsAttacking = false; // There is a chance that the worm would just go away after attacking - if (self.World.SharedRandom.Next(100) <= sandworm.Info.ChanceToDisappear) + if (self.World.SharedRandom.Next(100) <= sandworm.WormInfo.ChanceToDisappear) { self.CancelActivity(); self.World.AddFrameEndTask(w => self.Dispose()); diff --git a/OpenRA.Mods.D2k/Traits/Sandworm.cs b/OpenRA.Mods.D2k/Traits/Sandworm.cs index aed5aef875..0fd131dbb3 100644 --- a/OpenRA.Mods.D2k/Traits/Sandworm.cs +++ b/OpenRA.Mods.D2k/Traits/Sandworm.cs @@ -35,7 +35,7 @@ namespace OpenRA.Mods.D2k.Traits class Sandworm : Wanders, ITick, INotifyActorDisposing { - public readonly SandwormInfo Info; + public readonly SandwormInfo WormInfo; readonly WormManager manager; readonly Mobile mobile; @@ -50,7 +50,7 @@ namespace OpenRA.Mods.D2k.Traits public Sandworm(Actor self, SandwormInfo info) : base(self, info) { - Info = info; + WormInfo = info; mobile = self.Trait(); attackTrait = self.Trait(); manager = self.World.WorldActor.Trait(); @@ -78,10 +78,10 @@ namespace OpenRA.Mods.D2k.Traits void RescanForTargets(Actor self) { - targetCountdown = Info.TargetRescanInterval; + targetCountdown = WormInfo.TargetRescanInterval; // If close enough, we don't care about other actors. - var target = self.World.FindActorsInCircle(self.CenterPosition, Info.IgnoreNoiseAttackRange) + var target = self.World.FindActorsInCircle(self.CenterPosition, WormInfo.IgnoreNoiseAttackRange) .FirstOrDefault(x => attackTrait.HasAnyValidWeapons(Target.FromActor(x))); if (target != null) { @@ -98,7 +98,7 @@ namespace OpenRA.Mods.D2k.Traits return mobile.CanEnterCell(a.Location, null, false); }; - var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, Info.MaxSearchRadius) + var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, WormInfo.MaxSearchRadius) .Where(isValidTarget).SelectMany(a => a.TraitsImplementing()); var noiseDirection = actorsInRange.Aggregate(WVec.Zero, (a, b) => a + b.AttractionAtPosition(self.CenterPosition)); diff --git a/mods/cnc/rules/civilian.yaml b/mods/cnc/rules/civilian.yaml index e92d052f30..2595f32730 100644 --- a/mods/cnc/rules/civilian.yaml +++ b/mods/cnc/rules/civilian.yaml @@ -503,6 +503,7 @@ C10: DELPHI: Inherits: ^CivInfantry Inherits@armed: ^ArmedCivilian + -Wanders: Tooltip: Name: Agent Delphi @@ -513,6 +514,7 @@ CHAN: MOEBIUS: Inherits: ^CivInfantry + -Wanders: Voiced: VoiceSet: MoebiusVoice Tooltip: diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index 8096acdb46..b79e89bd02 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -301,6 +301,9 @@ CrushSound: squish2.aud Voiced: VoiceSet: CivilianMaleVoice + Wanders: + MinMoveDelay: 150 + MaxMoveDelay: 750 ^ArmedCivilian: Armament: diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index 2b23090d49..332faf3ffe 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -290,6 +290,9 @@ ScaredyCat: Voiced: VoiceSet: CivilianMaleVoice + Wanders: + MinMoveDelay: 150 + MaxMoveDelay: 750 ^ArmedCivilian: Armament: diff --git a/mods/ra/rules/infantry.yaml b/mods/ra/rules/infantry.yaml index 2d278e7588..c13125b7aa 100644 --- a/mods/ra/rules/infantry.yaml +++ b/mods/ra/rules/infantry.yaml @@ -362,6 +362,7 @@ MECH: EINSTEIN: Inherits: ^CivInfantry + -Wanders: Tooltip: Name: Prof. Einstein Mobile: @@ -371,6 +372,7 @@ EINSTEIN: DELPHI: Inherits: ^CivInfantry + -Wanders: Tooltip: Name: Agent Delphi Mobile: @@ -388,6 +390,7 @@ CHAN: GNRL: Inherits@1: ^CivInfantry Inherits@2: ^ArmedCivilian + -Wanders: Tooltip: Name: General Selectable: diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index 1dfe1c91e2..d4fa156c20 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -403,6 +403,9 @@ Tooltip: Name: Civilian ScaredyCat: + Wanders: + MinMoveDelay: 150 + MaxMoveDelay: 750 ^Vehicle: Inherits@1: ^GainsExperience