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