From ded8ae9345c21ab98d63312f3ee52a0bb764eea5 Mon Sep 17 00:00:00 2001 From: penev92 Date: Mon, 29 Dec 2014 08:46:25 +0200 Subject: [PATCH 1/2] Add Wanders trait and make AttackWander inherit that --- OpenRA.Mods.RA/Attack/AttackWander.cs | 38 ++----------- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 1 + OpenRA.Mods.RA/Traits/Wanders.cs | 79 +++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 32 deletions(-) create mode 100644 OpenRA.Mods.RA/Traits/Wanders.cs diff --git a/OpenRA.Mods.RA/Attack/AttackWander.cs b/OpenRA.Mods.RA/Attack/AttackWander.cs index b3d9ccc28b..1c586fdf69 100644 --- a/OpenRA.Mods.RA/Attack/AttackWander.cs +++ b/OpenRA.Mods.RA/Attack/AttackWander.cs @@ -8,56 +8,30 @@ */ #endregion -using OpenRA.Activities; using OpenRA.Traits; namespace OpenRA.Mods.RA.Traits { [Desc("Will AttackMove to a random location within MoveRadius when idle.", "This conflicts with player orders and should only be added to animal creeps.")] - class AttackWanderInfo : ITraitInfo, Requires + class AttackWanderInfo : WandersInfo, Requires { - public readonly int WanderMoveRadius = 10; - - [Desc("Number of ticks to wait until decreasing the effective move radius.")] - public readonly int MoveReductionRadiusScale = 5; - - public object Create(ActorInitializer init) { return new AttackWander(init.self, this); } + public override object Create(ActorInitializer init) { return new AttackWander(init.self, this); } } - class AttackWander : INotifyIdle + class AttackWander : Wanders { readonly AttackMove attackMove; - readonly AttackWanderInfo info; - - int ticksIdle; - int effectiveMoveRadius; public AttackWander(Actor self, AttackWanderInfo info) + : base(self, info) { - this.info = info; - effectiveMoveRadius = info.WanderMoveRadius; attackMove = self.TraitOrDefault(); } - public void TickIdle(Actor self) + public override void DoAction(Actor self, CPos targetPos) { - var target = self.CenterPosition + new WVec(0, -1024 * effectiveMoveRadius, 0).Rotate(WRot.FromFacing(self.World.SharedRandom.Next(255))); - var targetCell = self.World.Map.CellContaining(target); - - if (!self.World.Map.Contains(targetCell)) - { - // If MoveRadius is too big there might not be a valid cell to order the attack to (if actor is on a small island and can't leave) - if (++ticksIdle % info.MoveReductionRadiusScale == 0) - effectiveMoveRadius--; - - return; // We'll be back the next tick; better to sit idle for a few seconds than prolong this tick indefinitely with a loop - } - - attackMove.ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = targetCell }); - - ticksIdle = 0; - effectiveMoveRadius = info.WanderMoveRadius; + attackMove.ResolveOrder(self, new Order("AttackMove", self, false) { TargetLocation = targetPos }); } } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index dd600f772f..22fcc3ad43 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -79,6 +79,7 @@ + diff --git a/OpenRA.Mods.RA/Traits/Wanders.cs b/OpenRA.Mods.RA/Traits/Wanders.cs new file mode 100644 index 0000000000..168ce9a3ce --- /dev/null +++ b/OpenRA.Mods.RA/Traits/Wanders.cs @@ -0,0 +1,79 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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 OpenRA.Traits; + +namespace OpenRA.Mods.RA.Traits +{ + [Desc("Wanders around aimlesly when idle.")] + abstract class WandersInfo : ITraitInfo + { + public readonly int WanderMoveRadius = 10; + + [Desc("Number of ticks to wait until decreasing the effective move radius.")] + public readonly int MoveReductionRadiusScale = 5; + + public abstract object Create(ActorInitializer init); + } + + class Wanders : INotifyAddedToWorld, INotifyBecomingIdle + { + readonly Actor self; + readonly WandersInfo info; + + int ticksIdle; + int effectiveMoveRadius; + + public Wanders(Actor self, WandersInfo info) + { + this.self = self; + this.info = info; + effectiveMoveRadius = info.WanderMoveRadius; + } + + public void AddedToWorld(Actor self) + { + OnBecomingIdle(self); + } + + public void OnBecomingIdle(Actor self) + { + var targetPos = PickTargetLocation(); + if (targetPos != CPos.Zero) + DoAction(self, targetPos); + } + + CPos PickTargetLocation() + { + var target = self.CenterPosition + new WVec(0, -1024 * effectiveMoveRadius, 0).Rotate(WRot.FromFacing(self.World.SharedRandom.Next(255))); + var targetCell = self.World.Map.CellContaining(target); + + if (!self.World.Map.Contains(targetCell)) + { + // If MoveRadius is too big there might not be a valid cell to order the attack to (if actor is on a small island and can't leave) + if (++ticksIdle % info.MoveReductionRadiusScale == 0) + effectiveMoveRadius--; + + return CPos.Zero; // We'll be back the next tick; better to sit idle for a few seconds than prolong this tick indefinitely with a loop + } + + ticksIdle = 0; + effectiveMoveRadius = info.WanderMoveRadius; + + return targetCell; + } + + public virtual void DoAction(Actor self, CPos targetPos) + { + throw new NotImplementedException("Base class Wanders does not implement method DoAction!"); + } + } +} From 04c09dda3122db23e486dfe019fe89b283c0ffdb Mon Sep 17 00:00:00 2001 From: penev92 Date: Tue, 30 Dec 2014 02:04:32 +0200 Subject: [PATCH 2/2] Add a delay before wandering, use it on viceroids Add a Min and Max delay and make it random --- OpenRA.Mods.RA/Traits/Wanders.cs | 30 ++++++++++++++++++++---------- mods/cnc/rules/civilian.yaml | 2 ++ mods/ts/rules/infantry.yaml | 2 ++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/OpenRA.Mods.RA/Traits/Wanders.cs b/OpenRA.Mods.RA/Traits/Wanders.cs index 168ce9a3ce..dbd529846b 100644 --- a/OpenRA.Mods.RA/Traits/Wanders.cs +++ b/OpenRA.Mods.RA/Traits/Wanders.cs @@ -13,22 +13,29 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Traits { - [Desc("Wanders around aimlesly when idle.")] + [Desc("Wanders around aimlessly while idle.")] abstract class WandersInfo : ITraitInfo { public readonly int WanderMoveRadius = 10; - [Desc("Number of ticks to wait until decreasing the effective move radius.")] - public readonly int MoveReductionRadiusScale = 5; + [Desc("Number of ticks to wait before decreasing the effective move radius.")] + public readonly int TicksToWaitBeforeReducingMoveRadius = 5; + + [Desc("Mimimum ammount of ticks the actor will sit idly before starting to wander.")] + public readonly int MinMoveDelayInTicks = 0; + + [Desc("Maximum ammount of ticks the actor will sit idly before starting to wander.")] + public readonly int MaxMoveDelayInTicks = 0; public abstract object Create(ActorInitializer init); } - class Wanders : INotifyAddedToWorld, INotifyBecomingIdle + class Wanders : INotifyIdle, INotifyBecomingIdle { readonly Actor self; readonly WandersInfo info; + int countdown; int ticksIdle; int effectiveMoveRadius; @@ -39,13 +46,16 @@ namespace OpenRA.Mods.RA.Traits effectiveMoveRadius = info.WanderMoveRadius; } - public void AddedToWorld(Actor self) - { - OnBecomingIdle(self); - } - public void OnBecomingIdle(Actor self) { + countdown = self.World.SharedRandom.Next(info.MinMoveDelayInTicks, info.MaxMoveDelayInTicks); + } + + public void TickIdle(Actor self) + { + if (--countdown > 0) + return; + var targetPos = PickTargetLocation(); if (targetPos != CPos.Zero) DoAction(self, targetPos); @@ -59,7 +69,7 @@ namespace OpenRA.Mods.RA.Traits if (!self.World.Map.Contains(targetCell)) { // If MoveRadius is too big there might not be a valid cell to order the attack to (if actor is on a small island and can't leave) - if (++ticksIdle % info.MoveReductionRadiusScale == 0) + if (++ticksIdle % info.TicksToWaitBeforeReducingMoveRadius == 0) effectiveMoveRadius--; return CPos.Zero; // We'll be back the next tick; better to sit idle for a few seconds than prolong this tick indefinitely with a loop diff --git a/mods/cnc/rules/civilian.yaml b/mods/cnc/rules/civilian.yaml index 2e07980ef2..0167e02dab 100644 --- a/mods/cnc/rules/civilian.yaml +++ b/mods/cnc/rules/civilian.yaml @@ -459,6 +459,8 @@ VICE: AttackFrontal: AttackWander: WanderMoveRadius: 2 + MinMoveDelayInTicks: 25 + MaxMoveDelayInTicks: 45 RenderUnit: WithMuzzleFlash: SplitFacings: true diff --git a/mods/ts/rules/infantry.yaml b/mods/ts/rules/infantry.yaml index 78422e3035..d01208595f 100644 --- a/mods/ts/rules/infantry.yaml +++ b/mods/ts/rules/infantry.yaml @@ -584,6 +584,8 @@ DOGGIE: AttackFrontal: AttackWander: WanderMoveRadius: 2 + MinMoveDelayInTicks: 25 + MaxMoveDelayInTicks: 45 VISSML: Inherits: ^Infantry