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: 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/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); 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..fbad8f0afc 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; @@ -16,35 +18,97 @@ namespace OpenRA.Mods.RA.Activities public class MoveAdjacentTo : Activity { readonly Target target; + readonly Mobile mobile; + readonly PathFinder pathFinder; + readonly DomainIndex domainIndex; + readonly int movementClass; - public MoveAdjacentTo(Target target) { this.target = target; } + 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(); + domainIndex = self.World.WorldActor.TraitOrDefault(); + movementClass = mobile.Info.GetMovementClass(self.World.TileSet); + + repath = true; + } 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, - 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 loc = self.Location; + var searchCells = new List(); + foreach (var cell in adjacentCells) + { + if (cell == loc) + return NextActivity; + else if (domainIndex == null || domainIndex.IsPassable(loc, cell, (uint)movementClass)) + searchCells.Add(cell); + } + + if (searchCells.Any()) + { + var ps1 = new PathSearch(self.World, mobile.Info, self) + { + checkForBlocked = true, + heuristic = location => 0, + inReverse = true + }; + + 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); + } } - 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); + // 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; } } } 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; } } } 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));