From 27ef3352f48f5e3a4db2e66b764baca064226d21 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 9 Jan 2014 17:52:35 +1300 Subject: [PATCH 1/6] Fix AttackMove nits. Clears StyleCop warnings and adds GetTargets implementation for the unit path debug. --- OpenRA.Mods.RA/AttackMove.cs | 40 ++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/OpenRA.Mods.RA/AttackMove.cs b/OpenRA.Mods.RA/AttackMove.cs index 022485625a..f5b0a23ef7 100644 --- a/OpenRA.Mods.RA/AttackMove.cs +++ b/OpenRA.Mods.RA/AttackMove.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * 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, @@ -8,6 +8,7 @@ */ #endregion +using System.Collections.Generic; using System.Drawing; using OpenRA.Mods.RA.Move; using OpenRA.Traits; @@ -27,11 +28,11 @@ namespace OpenRA.Mods.RA public CPos? TargetLocation = null; readonly Mobile mobile; - readonly AttackMoveInfo Info; + readonly AttackMoveInfo info; public AttackMove(Actor self, AttackMoveInfo info) { - Info = info; + this.info = info; mobile = self.Trait(); } @@ -39,6 +40,7 @@ namespace OpenRA.Mods.RA { if (order.OrderString == "AttackMove") return "AttackMove"; + return null; } @@ -61,7 +63,7 @@ namespace OpenRA.Mods.RA if (order.OrderString == "AttackMove") { - if (Info.JustMove) + if (info.JustMove) mobile.ResolveOrder(self, new Order("Move", order)); else { @@ -73,19 +75,19 @@ namespace OpenRA.Mods.RA public class AttackMoveActivity : Activity { + const int ScanInterval = 7; + Activity inner; int scanTicks; AutoTarget autoTarget; - const int ScanInterval = 7; - - public AttackMoveActivity( Actor self, Activity inner ) + public AttackMoveActivity(Actor self, Activity inner) { this.inner = inner; - this.autoTarget = self.TraitOrDefault(); + autoTarget = self.TraitOrDefault(); } - public override Activity Tick( Actor self ) + public override Activity Tick(Actor self) { if (autoTarget != null && --scanTicks <= 0) { @@ -93,20 +95,28 @@ namespace OpenRA.Mods.RA scanTicks = ScanInterval; } - if( inner == null ) + if (inner == null) return NextActivity; - inner = Util.RunActivity( self, inner ); + inner = Util.RunActivity(self, inner); return this; } - public override void Cancel( Actor self ) + public override void Cancel(Actor self) { - if( inner != null ) - inner.Cancel( self ); + if (inner != null) + inner.Cancel(self); - base.Cancel( self ); + base.Cancel(self); + } + + public override IEnumerable GetTargets(Actor self) + { + if (inner != null) + return inner.GetTargets(self); + + return Target.None; } } } From c333b59eb9e844486e671ce0cfb19338a9aa95e2 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 9 Jan 2014 17:59:20 +1300 Subject: [PATCH 2/6] Cache trait lookups in MoveAdjacentTo. --- OpenRA.Mods.RA/Activities/Enter.cs | 2 +- OpenRA.Mods.RA/Activities/ExternalCaptureActor.cs | 2 +- OpenRA.Mods.RA/Activities/LayMines.cs | 2 +- OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs | 12 +++++++++--- OpenRA.Mods.RA/DemoTruck.cs | 2 +- OpenRA.Mods.RA/MadTank.cs | 2 +- OpenRA.Mods.RA/Passenger.cs | 2 +- OpenRA.Mods.RA/Repairable.cs | 2 +- 8 files changed, 16 insertions(+), 10 deletions(-) diff --git a/OpenRA.Mods.RA/Activities/Enter.cs b/OpenRA.Mods.RA/Activities/Enter.cs index cd74111176..cb12e5b8f5 100755 --- a/OpenRA.Mods.RA/Activities/Enter.cs +++ b/OpenRA.Mods.RA/Activities/Enter.cs @@ -34,7 +34,7 @@ namespace OpenRA.Mods.RA.Activities return NextActivity; if (!Util.AdjacentCells(target).Any(c => c == self.Location)) - return Util.SequenceActivities(new MoveAdjacentTo(target), this); + return Util.SequenceActivities(new MoveAdjacentTo(self, target), this); // Move to the middle of the target, ignoring impassable tiles var mobile = self.Trait(); diff --git a/OpenRA.Mods.RA/Activities/ExternalCaptureActor.cs b/OpenRA.Mods.RA/Activities/ExternalCaptureActor.cs index 8d56c20ca3..5d9f5978d6 100644 --- a/OpenRA.Mods.RA/Activities/ExternalCaptureActor.cs +++ b/OpenRA.Mods.RA/Activities/ExternalCaptureActor.cs @@ -39,7 +39,7 @@ namespace OpenRA.Mods.RA.Activities var nearest = target.Actor.OccupiesSpace.NearestCellTo(mobile.toCell); if ((nearest - mobile.toCell).LengthSquared > 2) - return Util.SequenceActivities(new MoveAdjacentTo(target), this); + return Util.SequenceActivities(new MoveAdjacentTo(self, target), this); if (!capturable.CaptureInProgress) capturable.BeginCapture(self); diff --git a/OpenRA.Mods.RA/Activities/LayMines.cs b/OpenRA.Mods.RA/Activities/LayMines.cs index 1cd5bfbeda..3d14ee2c53 100644 --- a/OpenRA.Mods.RA/Activities/LayMines.cs +++ b/OpenRA.Mods.RA/Activities/LayMines.cs @@ -37,7 +37,7 @@ namespace OpenRA.Mods.RA.Activities return new Wait(20); return Util.SequenceActivities( - new MoveAdjacentTo(Target.FromActor(rearmTarget)), + new MoveAdjacentTo(self, Target.FromActor(rearmTarget)), mobile.MoveTo(rearmTarget.CenterPosition.ToCPos(), rearmTarget), new Rearm(self), new Repair(rearmTarget), diff --git a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs index 083a8b04be..224a7ec441 100755 --- a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs +++ b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs @@ -16,15 +16,21 @@ namespace OpenRA.Mods.RA.Activities public class MoveAdjacentTo : Activity { readonly Target target; + readonly Mobile mobile; + readonly PathFinder pathFinder; - public MoveAdjacentTo(Target target) { this.target = target; } + public MoveAdjacentTo(Actor self, Target target) + { + this.target = target; + mobile = self.Trait(); + pathFinder = self.World.WorldActor.Trait(); + } public override Activity Tick(Actor self) { if (IsCanceled || !target.IsValidFor(self)) return NextActivity; - var mobile = self.Trait(); var ps1 = new PathSearch(self.World, mobile.Info, self) { checkForBlocked = true, @@ -42,7 +48,7 @@ namespace OpenRA.Mods.RA.Activities ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell); var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterPosition.ToCPos(), true); - var ret = self.World.WorldActor.Trait().FindBidiPath(ps1, ps2); + var ret = pathFinder.FindBidiPath(ps1, ps2); return Util.SequenceActivities(mobile.MoveTo(() => ret), this); } diff --git a/OpenRA.Mods.RA/DemoTruck.cs b/OpenRA.Mods.RA/DemoTruck.cs index f1050b4d71..fb1aa97baf 100644 --- a/OpenRA.Mods.RA/DemoTruck.cs +++ b/OpenRA.Mods.RA/DemoTruck.cs @@ -65,7 +65,7 @@ namespace OpenRA.Mods.RA self.CancelActivity(); self.SetTargetLine(target, Color.Red); - self.QueueActivity(new MoveAdjacentTo(target)); + self.QueueActivity(new MoveAdjacentTo(self, target)); self.QueueActivity(new CallFunc(() => Explode(self))); } diff --git a/OpenRA.Mods.RA/MadTank.cs b/OpenRA.Mods.RA/MadTank.cs index 04e5c0c205..8dedafd03b 100644 --- a/OpenRA.Mods.RA/MadTank.cs +++ b/OpenRA.Mods.RA/MadTank.cs @@ -146,7 +146,7 @@ namespace OpenRA.Mods.RA self.CancelActivity(); self.SetTargetLine(target, Color.Red); - self.QueueActivity(new MoveAdjacentTo(target)); + self.QueueActivity(new MoveAdjacentTo(self, target)); self.QueueActivity(new CallFunc(StartDetonationSequence)); } diff --git a/OpenRA.Mods.RA/Passenger.cs b/OpenRA.Mods.RA/Passenger.cs index b9e06883fe..4a04de827c 100644 --- a/OpenRA.Mods.RA/Passenger.cs +++ b/OpenRA.Mods.RA/Passenger.cs @@ -79,7 +79,7 @@ namespace OpenRA.Mods.RA self.SetTargetLine(target, Color.Green); self.CancelActivity(); - self.QueueActivity(new MoveAdjacentTo(target)); + self.QueueActivity(new MoveAdjacentTo(self, target)); self.QueueActivity(new EnterTransport(self, order.TargetActor)); } } diff --git a/OpenRA.Mods.RA/Repairable.cs b/OpenRA.Mods.RA/Repairable.cs index 1fb9c2b5a9..e34488d9f0 100644 --- a/OpenRA.Mods.RA/Repairable.cs +++ b/OpenRA.Mods.RA/Repairable.cs @@ -78,7 +78,7 @@ namespace OpenRA.Mods.RA self.SetTargetLine(target, Color.Green); self.CancelActivity(); - self.QueueActivity(new MoveAdjacentTo(target)); + self.QueueActivity(new MoveAdjacentTo(self, target)); self.QueueActivity(mobile.MoveTo(order.TargetActor.CenterPosition.ToCPos(), order.TargetActor)); self.QueueActivity(new Rearm(self)); self.QueueActivity(new Repair(order.TargetActor)); From 3cdeea009b8fb0b4a7ad1a4a337d4c346d2fa274 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 9 Jan 2014 18:49:15 +1300 Subject: [PATCH 3/6] Make MoveAdjacentTo aware of moving targets. Units moving toward another actor (passengers, hijackers, etc) will now repath if their target moves. Fixes excessive repathing if the target cannot be reached. --- OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs | 77 ++++++++++++++++----- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs index 224a7ec441..d4563b79d1 100755 --- a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs +++ b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * 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, @@ -8,6 +8,8 @@ */ #endregion +using System.Collections.Generic; +using System.Linq; using OpenRA.Mods.RA.Move; using OpenRA.Traits; @@ -19,11 +21,19 @@ namespace OpenRA.Mods.RA.Activities readonly Mobile mobile; readonly PathFinder pathFinder; + Activity inner; + CPos cachedTargetPosition; + CPos[] adjacentCells; + bool repath; + public MoveAdjacentTo(Actor self, Target target) { this.target = target; + mobile = self.Trait(); pathFinder = self.World.WorldActor.Trait(); + + repath = true; } public override Activity Tick(Actor self) @@ -31,26 +41,61 @@ namespace OpenRA.Mods.RA.Activities if (IsCanceled || !target.IsValidFor(self)) return NextActivity; - var ps1 = new PathSearch(self.World, mobile.Info, self) - { - checkForBlocked = true, - heuristic = location => 0, - inReverse = true - }; + var targetPosition = target.CenterPosition.ToCPos(); - foreach (var cell in Util.AdjacentCells(target)) + // Calculate path to target + if (inner == null && repath) { - if (cell == self.Location) - return NextActivity; - else - ps1.AddInitialCell(cell); + cachedTargetPosition = targetPosition; + adjacentCells = Util.AdjacentCells(target).ToArray(); + repath = false; + + var ps1 = new PathSearch(self.World, mobile.Info, self) + { + checkForBlocked = true, + heuristic = location => 0, + inReverse = true + }; + + foreach (var cell in adjacentCells) + { + if (cell == self.Location) + return NextActivity; + else + ps1.AddInitialCell(cell); + } + + ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell); + var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterPosition.ToCPos(), true); + var ret = pathFinder.FindBidiPath(ps1, ps2); + + inner = mobile.MoveTo(() => ret); } - ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell); - var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterPosition.ToCPos(), true); - var ret = pathFinder.FindBidiPath(ps1, ps2); + // Force a repath once the actor reaches the next cell + if (!repath && cachedTargetPosition != targetPosition) + { + if (inner != null) + inner.Cancel(self); - return Util.SequenceActivities(mobile.MoveTo(() => ret), this); + repath = true; + } + + inner = Util.RunActivity(self, inner); + + // Move completed + if (inner == null && adjacentCells.Contains(self.Location)) + return NextActivity; + + return this; + } + + public override IEnumerable GetTargets(Actor self) + { + if (inner != null) + return inner.GetTargets(self); + + return Target.None; } } } From 29e689178d78d2480ba94bc898fd5de05ec27860 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 9 Jan 2014 20:23:05 +1300 Subject: [PATCH 4/6] Make EnterTransport more consistent with MoveAdjacentTo. --- OpenRA.Mods.RA/Activities/EnterTransport.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/OpenRA.Mods.RA/Activities/EnterTransport.cs b/OpenRA.Mods.RA/Activities/EnterTransport.cs index 96a47412a4..84df9db0f1 100644 --- a/OpenRA.Mods.RA/Activities/EnterTransport.cs +++ b/OpenRA.Mods.RA/Activities/EnterTransport.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * 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, @@ -8,31 +8,37 @@ */ #endregion +using System.Linq; using OpenRA.Traits; namespace OpenRA.Mods.RA.Activities { class EnterTransport : Activity { - public Actor transport; + readonly Actor transport; + readonly Cargo cargo; public EnterTransport(Actor self, Actor transport) { this.transport = transport; + cargo = transport.Trait(); } public override Activity Tick(Actor self) { - if (IsCanceled) return NextActivity; - if (transport == null || !transport.IsInWorld) return NextActivity; + if (IsCanceled) + return NextActivity; + + if (transport == null || !transport.IsInWorld) + return NextActivity; - var cargo = transport.Trait(); if (!cargo.CanLoad(transport, self)) return NextActivity; // TODO: Queue a move order to the transport? need to be // careful about units that can't path to the transport - if ((transport.Location - self.Location).LengthSquared > 2) + var cells = Util.AdjacentCells(Target.FromActor(transport)); + if (!cells.Contains(self.Location)) return NextActivity; cargo.Load(transport, self); From d2fa1a12f96e925a4bae03950eb7f0306686650d Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 12 Jan 2014 22:35:06 +1300 Subject: [PATCH 5/6] Use DomainIndex to fix naval transport path perf. --- OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs | 39 ++++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs index d4563b79d1..fbad8f0afc 100755 --- a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs +++ b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs @@ -20,6 +20,8 @@ namespace OpenRA.Mods.RA.Activities readonly Target target; readonly Mobile mobile; readonly PathFinder pathFinder; + readonly DomainIndex domainIndex; + readonly int movementClass; Activity inner; CPos cachedTargetPosition; @@ -32,6 +34,8 @@ namespace OpenRA.Mods.RA.Activities mobile = self.Trait(); pathFinder = self.World.WorldActor.Trait(); + domainIndex = self.World.WorldActor.TraitOrDefault(); + movementClass = mobile.Info.GetMovementClass(self.World.TileSet); repath = true; } @@ -50,26 +54,35 @@ namespace OpenRA.Mods.RA.Activities adjacentCells = Util.AdjacentCells(target).ToArray(); repath = false; - var ps1 = new PathSearch(self.World, mobile.Info, self) - { - checkForBlocked = true, - heuristic = location => 0, - inReverse = true - }; + var loc = self.Location; + var searchCells = new List(); foreach (var cell in adjacentCells) { - if (cell == self.Location) + if (cell == loc) return NextActivity; - else - ps1.AddInitialCell(cell); + else if (domainIndex == null || domainIndex.IsPassable(loc, cell, (uint)movementClass)) + searchCells.Add(cell); } - ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell); - var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterPosition.ToCPos(), true); - var ret = pathFinder.FindBidiPath(ps1, ps2); + if (searchCells.Any()) + { + var ps1 = new PathSearch(self.World, mobile.Info, self) + { + checkForBlocked = true, + heuristic = location => 0, + inReverse = true + }; - inner = mobile.MoveTo(() => ret); + foreach (var cell in searchCells) + ps1.AddInitialCell(cell); + + ps1.heuristic = PathSearch.DefaultEstimator(mobile.toCell); + var ps2 = PathSearch.FromPoint(self.World, mobile.Info, self, mobile.toCell, target.CenterPosition.ToCPos(), true); + var ret = pathFinder.FindBidiPath(ps1, ps2); + + inner = mobile.MoveTo(() => ret); + } } // Force a repath once the actor reaches the next cell From 13ccfa0b3442240104071ce2625a2ff17ab435b1 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 12 Jan 2014 22:37:32 +1300 Subject: [PATCH 6/6] Update change log. --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 09a0c4b799..97c77b5fab 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -25,6 +25,8 @@ NEW: Added a new Launch.Replay=$FILEPATH parameter for OpenRA.Game.exe to instantly start watching a *.rep file. Added HackyAI settings: ExcessPowerFactor, MinimumExcessPower, IdleBaseUnitsMaximum, RushAttackScanRadius, ProtectUnitScanRadius, RallyPointScanRadius. See the traits documentation for more information. Added HitAnimPalette trait for LaserZap projectiles. Laser hit animations can now specify individual palettes. Defaults to effect palette. + Fixed performance issues with units pathing to naval transports. + Fixed unit moving to transports that have moved. Server: Message of the day is now shared between all mods and a default motd.txt gets created in the user directory. Asset Browser: