Remove obsolete LegacyEnter and ResolveFrozenActorOrder.
This commit is contained in:
committed by
Oliver Brakmann
parent
42068f380e
commit
08e3e429db
@@ -1,309 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2019 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, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Activities;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Activities
|
||||
{
|
||||
public abstract class LegacyEnter : Activity
|
||||
{
|
||||
public enum ReserveStatus { None, TooFar, Pending, Ready }
|
||||
enum EnterState { ApproachingOrEntering, WaitingToEnter, Inside, Exiting, Done }
|
||||
|
||||
readonly IMove move;
|
||||
readonly int maxTries = 0;
|
||||
readonly EnterBehaviour enterBehaviour;
|
||||
readonly bool repathWhileMoving;
|
||||
readonly Color? targetLineColor;
|
||||
|
||||
public Target Target { get { return target; } }
|
||||
Target target;
|
||||
EnterState nextState = EnterState.ApproachingOrEntering; // Hint/starting point for next state
|
||||
bool isEnteringOrInside = false; // Used to know if exiting should be used
|
||||
WPos savedPos; // Position just before entering
|
||||
Activity inner;
|
||||
bool firstApproach = true;
|
||||
|
||||
protected LegacyEnter(Actor self, Actor target, EnterBehaviour enterBehaviour, int maxTries = 1,
|
||||
bool repathWhileMoving = true, Color? targetLineColor = null)
|
||||
{
|
||||
move = self.Trait<IMove>();
|
||||
this.target = Target.FromActor(target);
|
||||
this.maxTries = maxTries;
|
||||
this.enterBehaviour = enterBehaviour;
|
||||
this.repathWhileMoving = repathWhileMoving;
|
||||
this.targetLineColor = targetLineColor;
|
||||
}
|
||||
|
||||
// CanEnter(target) should to be true; otherwise, Enter may abort.
|
||||
// Tries counter starts at 1 (reset every tick)
|
||||
protected virtual bool TryGetAlternateTarget(Actor self, int tries, ref Target target) { return false; }
|
||||
protected virtual bool CanReserve(Actor self) { return true; }
|
||||
protected virtual ReserveStatus Reserve(Actor self)
|
||||
{
|
||||
return !CanReserve(self) ? ReserveStatus.None : move.CanEnterTargetNow(self, target) ? ReserveStatus.Ready : ReserveStatus.TooFar;
|
||||
}
|
||||
|
||||
protected virtual void Unreserve(Actor self, bool abort) { }
|
||||
protected virtual void OnInside(Actor self) { }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the actor is ready to transition from approaching to entering the target.
|
||||
/// Return true to start entering, or false to wait in the WaitingToEnter state.
|
||||
/// </summary>
|
||||
protected virtual bool TryStartEnter(Actor self) { return true; }
|
||||
|
||||
protected bool TryGetAlternateTargetInCircle(
|
||||
Actor self, WDist radius, Action<Target> update, Func<Actor, bool> primaryFilter, Func<Actor, bool>[] preferenceFilters = null)
|
||||
{
|
||||
var diff = new WVec(radius, radius, WDist.Zero);
|
||||
var candidates = self.World.ActorMap.ActorsInBox(self.CenterPosition - diff, self.CenterPosition + diff)
|
||||
.Where(primaryFilter).Select(a => new { Actor = a, Ls = (self.CenterPosition - a.CenterPosition).HorizontalLengthSquared })
|
||||
.Where(p => p.Ls <= radius.LengthSquared).OrderBy(p => p.Ls).Select(p => p.Actor);
|
||||
if (preferenceFilters != null)
|
||||
foreach (var filter in preferenceFilters)
|
||||
{
|
||||
var preferredCandidate = candidates.FirstOrDefault(filter);
|
||||
if (preferredCandidate == null)
|
||||
continue;
|
||||
target = Target.FromActor(preferredCandidate);
|
||||
update(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
var candidate = candidates.FirstOrDefault();
|
||||
if (candidate == null)
|
||||
return false;
|
||||
target = Target.FromActor(candidate);
|
||||
update(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called when inner activity is this and returns inner activity for next tick.
|
||||
protected virtual Activity InsideTick(Actor self) { return null; }
|
||||
|
||||
// Abort entering and/or leave if necessary
|
||||
protected virtual void AbortOrExit(Actor self)
|
||||
{
|
||||
if (nextState == EnterState.Done)
|
||||
return;
|
||||
nextState = isEnteringOrInside ? EnterState.Exiting : EnterState.Done;
|
||||
if (inner == this)
|
||||
inner = null;
|
||||
else if (inner != null)
|
||||
inner.Cancel(self);
|
||||
if (isEnteringOrInside)
|
||||
Unreserve(self, true);
|
||||
}
|
||||
|
||||
// Cancel inner activity and mark as done unless already leaving or done
|
||||
protected void Done(Actor self)
|
||||
{
|
||||
if (nextState == EnterState.Done)
|
||||
return;
|
||||
nextState = EnterState.Done;
|
||||
if (inner == this)
|
||||
inner = null;
|
||||
else if (inner != null)
|
||||
inner.Cancel(self);
|
||||
}
|
||||
|
||||
public override bool Cancel(Actor self, bool keepQueue = false)
|
||||
{
|
||||
AbortOrExit(self);
|
||||
if (nextState < EnterState.Exiting)
|
||||
return base.Cancel(self);
|
||||
else
|
||||
NextActivity = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ReserveStatus TryReserveElseTryAlternateReserve(Actor self)
|
||||
{
|
||||
for (var tries = 0;;)
|
||||
{
|
||||
switch (Reserve(self))
|
||||
{
|
||||
case ReserveStatus.None:
|
||||
if (++tries > maxTries || !TryGetAlternateTarget(self, tries, ref target))
|
||||
return ReserveStatus.None;
|
||||
continue;
|
||||
case ReserveStatus.TooFar:
|
||||
// Always goto to transport on first approach
|
||||
if (firstApproach)
|
||||
{
|
||||
firstApproach = false;
|
||||
return ReserveStatus.TooFar;
|
||||
}
|
||||
|
||||
if (++tries > maxTries)
|
||||
return ReserveStatus.TooFar;
|
||||
Target t = target;
|
||||
if (!TryGetAlternateTarget(self, tries, ref t))
|
||||
return ReserveStatus.TooFar;
|
||||
|
||||
var targetPosition = target.Positions.PositionClosestTo(self.CenterPosition);
|
||||
var alternatePosition = t.Positions.PositionClosestTo(self.CenterPosition);
|
||||
if ((targetPosition - self.CenterPosition).HorizontalLengthSquared <= (alternatePosition - self.CenterPosition).HorizontalLengthSquared)
|
||||
return ReserveStatus.TooFar;
|
||||
target = t;
|
||||
continue;
|
||||
case ReserveStatus.Pending:
|
||||
return ReserveStatus.Pending;
|
||||
case ReserveStatus.Ready:
|
||||
return ReserveStatus.Ready;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EnterState FindAndTransitionToNextState(Actor self)
|
||||
{
|
||||
switch (nextState)
|
||||
{
|
||||
case EnterState.ApproachingOrEntering:
|
||||
|
||||
// Reserve to enter or approach
|
||||
isEnteringOrInside = false;
|
||||
switch (TryReserveElseTryAlternateReserve(self))
|
||||
{
|
||||
case ReserveStatus.None:
|
||||
return EnterState.Done; // No available target -> abort to next activity
|
||||
case ReserveStatus.TooFar:
|
||||
{
|
||||
var moveTarget = repathWhileMoving ? target : Target.FromPos(target.Positions.PositionClosestTo(self.CenterPosition));
|
||||
inner = move.MoveToTarget(self, moveTarget, targetLineColor: targetLineColor); // Approach
|
||||
return EnterState.ApproachingOrEntering;
|
||||
}
|
||||
|
||||
case ReserveStatus.Pending:
|
||||
return EnterState.ApproachingOrEntering; // Retry next tick
|
||||
case ReserveStatus.Ready:
|
||||
break; // Reserved target -> start entering target
|
||||
}
|
||||
|
||||
// Can we enter yet?
|
||||
if (!TryStartEnter(self))
|
||||
return EnterState.WaitingToEnter;
|
||||
|
||||
// Entering
|
||||
isEnteringOrInside = true;
|
||||
savedPos = self.CenterPosition; // Save position of self, before entering, for returning on exit
|
||||
|
||||
inner = move.VisualMove(self, self.CenterPosition, target.Positions.PositionClosestTo(self.CenterPosition));
|
||||
|
||||
if (inner != null)
|
||||
{
|
||||
nextState = EnterState.Inside; // Should be inside once inner activity is null
|
||||
return EnterState.ApproachingOrEntering;
|
||||
}
|
||||
|
||||
// Can enter but there is no activity for it, so go inside without one
|
||||
goto case EnterState.Inside;
|
||||
|
||||
case EnterState.Inside:
|
||||
// Might as well teleport into target if there is no MoveIntoTarget activity
|
||||
if (nextState == EnterState.ApproachingOrEntering)
|
||||
nextState = EnterState.Inside;
|
||||
|
||||
// Otherwise, try to recover from moving target
|
||||
else if (target.Positions.PositionClosestTo(self.CenterPosition) != self.CenterPosition)
|
||||
{
|
||||
nextState = EnterState.ApproachingOrEntering;
|
||||
Unreserve(self, false);
|
||||
if (Reserve(self) == ReserveStatus.Ready)
|
||||
{
|
||||
inner = move.VisualMove(self, self.CenterPosition, target.Positions.PositionClosestTo(self.CenterPosition));
|
||||
if (inner != null)
|
||||
return EnterState.ApproachingOrEntering;
|
||||
|
||||
nextState = EnterState.ApproachingOrEntering;
|
||||
goto case EnterState.ApproachingOrEntering;
|
||||
}
|
||||
|
||||
nextState = EnterState.ApproachingOrEntering;
|
||||
isEnteringOrInside = false;
|
||||
inner = move.MoveIntoWorld(self, self.World.Map.CellContaining(savedPos));
|
||||
|
||||
return EnterState.ApproachingOrEntering;
|
||||
}
|
||||
|
||||
OnInside(self);
|
||||
|
||||
if (enterBehaviour == EnterBehaviour.Suicide)
|
||||
self.Kill(self);
|
||||
else if (enterBehaviour == EnterBehaviour.Dispose)
|
||||
self.Dispose();
|
||||
|
||||
// Return if Abort(Actor) or Done(self) was called from OnInside.
|
||||
if (nextState >= EnterState.Exiting)
|
||||
return EnterState.Inside;
|
||||
|
||||
inner = this; // Start inside activity
|
||||
nextState = EnterState.Exiting; // Exit once inner activity is null (unless Done(self) is called)
|
||||
return EnterState.Inside;
|
||||
|
||||
// TODO: Handle target moved while inside or always call done for movable targets and use a separate exit activity
|
||||
case EnterState.Exiting:
|
||||
inner = move.MoveIntoWorld(self, self.World.Map.CellContaining(savedPos));
|
||||
|
||||
// If not successfully exiting, retry on next tick
|
||||
if (inner == null)
|
||||
return EnterState.Exiting;
|
||||
isEnteringOrInside = false;
|
||||
nextState = EnterState.Done;
|
||||
return EnterState.Exiting;
|
||||
|
||||
case EnterState.Done:
|
||||
return EnterState.Done;
|
||||
}
|
||||
|
||||
return EnterState.Done; // dummy to quiet dumb compiler
|
||||
}
|
||||
|
||||
Activity CanceledTick(Actor self)
|
||||
{
|
||||
if (inner == null)
|
||||
return ActivityUtils.RunActivity(self, NextActivity);
|
||||
inner.Cancel(self);
|
||||
inner.Queue(NextActivity);
|
||||
return ActivityUtils.RunActivity(self, inner);
|
||||
}
|
||||
|
||||
public override Activity Tick(Actor self)
|
||||
{
|
||||
if (IsCanceled)
|
||||
return CanceledTick(self);
|
||||
|
||||
// Check target validity if not exiting or done
|
||||
if (nextState != EnterState.Done && (target.Type != TargetType.Actor || !target.IsValidFor(self)))
|
||||
AbortOrExit(self);
|
||||
|
||||
// If no current activity, tick next activity
|
||||
if (inner == null && FindAndTransitionToNextState(self) == EnterState.Done)
|
||||
return CanceledTick(self);
|
||||
|
||||
// Run inner activity/InsideTick
|
||||
inner = inner == this ? InsideTick(self) : ActivityUtils.RunActivity(self, inner);
|
||||
|
||||
// If we are finished, move on to next activity
|
||||
if (inner == null && nextState == EnterState.Done)
|
||||
return NextActivity;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,43 +59,6 @@ namespace OpenRA.Mods.Common
|
||||
return stance == Stance.Enemy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DEPRECATED: Write code that can handle FrozenActors correctly instead.
|
||||
/// </summary>
|
||||
public static Target ResolveFrozenActorOrder(this Actor self, Order order, Color targetLineColor)
|
||||
{
|
||||
// Not targeting a frozen actor
|
||||
if (order.Target.Type != TargetType.FrozenActor)
|
||||
return order.Target;
|
||||
|
||||
var frozen = order.Target.FrozenActor;
|
||||
|
||||
self.SetTargetLine(order.Target, targetLineColor, true);
|
||||
|
||||
// Target is still alive - resolve the real order
|
||||
if (frozen.Actor != null && frozen.Actor.IsInWorld)
|
||||
return Target.FromActor(frozen.Actor);
|
||||
|
||||
if (!order.Queued)
|
||||
self.CancelActivity();
|
||||
|
||||
var move = self.TraitOrDefault<IMove>();
|
||||
if (move != null)
|
||||
{
|
||||
// Move within sight range of the frozen actor
|
||||
var range = self.TraitsImplementing<RevealsShroud>()
|
||||
.Where(s => !s.IsTraitDisabled)
|
||||
.Select(s => s.Range)
|
||||
.Append(WDist.FromCells(2))
|
||||
.Max();
|
||||
|
||||
self.QueueActivity(move.MoveWithinRange(Target.FromPos(frozen.CenterPosition), range,
|
||||
targetLineColor: targetLineColor));
|
||||
}
|
||||
|
||||
return Target.Invalid;
|
||||
}
|
||||
|
||||
public static void NotifyBlocker(this Actor self, IEnumerable<Actor> blockers)
|
||||
{
|
||||
foreach (var blocker in blockers)
|
||||
|
||||
@@ -92,7 +92,6 @@
|
||||
<Compile Include="Activities\DonateCash.cs" />
|
||||
<Compile Include="Activities\DonateExperience.cs" />
|
||||
<Compile Include="Activities\Enter.cs" />
|
||||
<Compile Include="Activities\LegacyEnter.cs" />
|
||||
<Compile Include="Activities\EnterTransport.cs" />
|
||||
<Compile Include="Activities\FindResources.cs" />
|
||||
<Compile Include="Activities\HarvestResource.cs" />
|
||||
|
||||
Reference in New Issue
Block a user