Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent movement pausing at invalid position. #17214

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 10 additions & 3 deletions OpenRA.Mods.Common/Activities/Air/Fly.cs
Expand Up @@ -25,6 +25,7 @@ public class Fly : Activity
readonly WDist minRange;
readonly Color? targetLineColor;
readonly WDist nearEnough;
readonly WVec offset;

Target target;
Target lastVisibleTarget;
Expand All @@ -37,6 +38,12 @@ public Fly(Actor self, Target t, WDist nearEnough, WPos? initialTargetPosition =
this.nearEnough = nearEnough;
}

public Fly(Actor self, Target t, WVec offset)
: this(self, t)
{
this.offset = offset;
}

public Fly(Actor self, Target t, WPos? initialTargetPosition = null, Color? targetLineColor = null)
{
aircraft = self.Trait<Aircraft>();
Expand Down Expand Up @@ -157,12 +164,12 @@ public override bool Tick(Actor self)

var checkTarget = useLastVisibleTarget ? lastVisibleTarget : target;
var pos = aircraft.GetPosition();
var delta = checkTarget.CenterPosition - pos;
var delta = checkTarget.CenterPosition - pos + offset;
var desiredFacing = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : aircraft.Facing;

// Inside the target annulus, so we're done
var insideMaxRange = maxRange.Length > 0 && checkTarget.IsInRange(pos, maxRange);
var insideMinRange = minRange.Length > 0 && checkTarget.IsInRange(pos, minRange);
var insideMaxRange = maxRange.Length > 0 && checkTarget.IsInRange(pos - offset, maxRange);
var insideMinRange = minRange.Length > 0 && checkTarget.IsInRange(pos - offset, minRange);
if (insideMaxRange && !insideMinRange)
return true;

Expand Down
42 changes: 36 additions & 6 deletions OpenRA.Mods.Common/Activities/Air/Land.cs
Expand Up @@ -22,17 +22,21 @@ public class Land : Activity
{
readonly Aircraft aircraft;
readonly WVec offset;
readonly int desiredFacing;
readonly bool assignTargetOnFirstRun;
readonly CPos[] clearCells;
readonly WDist landRange;
readonly Color? targetLineColor;
readonly Mobile targetMobile;
readonly BodyOrientation targetBody;
readonly IFacing targetFacing;

Target target;
WPos targetPosition;
CPos landingCell;
bool landingInitiated;
bool finishedApproach;
int desiredFacing;
WVec currentOffset;

public Land(Actor self, int facing = -1, Color? targetLineColor = null)
: this(self, Target.Invalid, new WDist(-1), WVec.Zero, facing, null)
Expand Down Expand Up @@ -64,6 +68,15 @@ public Land(Actor self, Target target, WDist landRange, WVec offset, int facing
desiredFacing = aircraft.Info.InitialFacing;
else
desiredFacing = facing;

if (target.Actor != null)
{
targetBody = target.Actor.TraitOrDefault<BodyOrientation>();
targetFacing = target.Actor.TraitOrDefault<IFacing>();
targetMobile = target.Actor.TraitOrDefault<Mobile>();
}

currentOffset = offset;
}

protected override void OnFirstRun(Actor self)
Expand Down Expand Up @@ -103,10 +116,17 @@ public override bool Tick(Actor self)
return true;
}

if (targetFacing != null)
{
desiredFacing = targetFacing.Facing;
if (targetBody != null)
currentOffset = -targetBody.LocalToWorld(offset.Rotate(targetBody.QuantizeOrientation(self, target.Actor.Orientation)));
}

var pos = aircraft.GetPosition();

// Reevaluate target position in case the target has moved.
targetPosition = target.CenterPosition + offset;
targetPosition = target.CenterPosition + currentOffset;
landingCell = self.World.Map.CellContaining(targetPosition);

// We are already at the landing location.
Expand All @@ -128,7 +148,7 @@ public override bool Tick(Actor self)
if (newLocation.Value != landingCell)
{
target = Target.FromCell(self.World, newLocation.Value);
targetPosition = target.CenterPosition + offset;
targetPosition = target.CenterPosition + currentOffset;
landingCell = self.World.Map.CellContaining(targetPosition);
}
}
Expand All @@ -138,10 +158,11 @@ public override bool Tick(Actor self)
{
if ((pos - targetPosition).HorizontalLengthSquared != 0)
{
QueueChild(new Fly(self, Target.FromPos(targetPosition)));
QueueChild(new Fly(self, target, currentOffset));
return false;
}
else if (desiredFacing != -1 && desiredFacing != aircraft.Facing)

if (desiredFacing != -1 && desiredFacing != aircraft.Facing)
{
QueueChild(new Turn(self, desiredFacing));
return false;
Expand Down Expand Up @@ -210,8 +231,8 @@ public override bool Tick(Actor self)

if (!landingInitiated)
{
// Make sure the landing spot is clear.
var blockingCells = clearCells.Append(landingCell);

if (!aircraft.CanLand(blockingCells, target.Actor))
{
// Maintain holding pattern.
Expand All @@ -222,6 +243,15 @@ public override bool Tick(Actor self)
return false;
}

// Make sure the docking actor is in a valid state for docking.
if (targetMobile != null && targetMobile.IsMovingBetweenCells)
{
// Maintain holding pattern.
QueueChild(new FlyIdle(self, 25));
finishedApproach = false;
return false;
}

if (aircraft.Info.LandingSounds.Length > 0)
Game.Sound.Play(SoundType.World, aircraft.Info.LandingSounds, self.World, aircraft.CenterPosition);

Expand Down
12 changes: 8 additions & 4 deletions OpenRA.Mods.Common/Activities/Move/Move.cs
Expand Up @@ -210,6 +210,13 @@ public override bool Tick(Actor self)

var nextCell = path[path.Count - 1];

// Something else might have moved us, so the path is no longer valid.
if (!Util.AreAdjacentCells(mobile.ToCell, nextCell))
{
path = EvalPath(BlockedByActor.Immovable);
pchote marked this conversation as resolved.
Show resolved Hide resolved
return null;
}

var containsTemporaryBlocker = WorldUtils.ContainsTemporaryBlocker(self.World, nextCell, self);

// Next cell in the move is blocked by another actor
Expand Down Expand Up @@ -407,9 +414,6 @@ public MovePart(Move move, WPos from, WPos to, int fromFacing, int toFacing, int

public override bool Tick(Actor self)
{
if (Move.mobile.IsTraitDisabled || Move.mobile.IsTraitPaused)
return false;

var ret = InnerTick(self, Move.mobile);

if (moveFraction > MoveFractionTotal)
Expand Down Expand Up @@ -491,7 +495,7 @@ protected override MovePart OnComplete(Actor self, Mobile mobile, Move parent)
var nextCell = parent.PopPath(self);
if (nextCell != null)
{
if (IsTurn(mobile, nextCell.Value.First, map))
if (!mobile.IsTraitPaused && !mobile.IsTraitDisabled && IsTurn(mobile, nextCell.Value.First, map))
{
var nextSubcellOffset = map.Grid.OffsetOfSubCell(nextCell.Value.Second);
var ret = new MoveFirstHalf(
Expand Down
64 changes: 19 additions & 45 deletions OpenRA.Mods.Common/Activities/PickupUnit.cs
Expand Up @@ -21,38 +21,37 @@ public class PickupUnit : Activity
{
readonly Actor cargo;
readonly IMove movement;

readonly Carryall carryall;
readonly IFacing carryallFacing;

readonly Carryable carryable;
readonly IFacing carryableFacing;
readonly BodyOrientation carryableBody;

readonly int delay;

enum PickupState { Intercept, LockCarryable, Pickup }

PickupState state;
bool locked;

public PickupUnit(Actor self, Actor cargo, int delay)
{
this.cargo = cargo;
this.delay = delay;
carryable = cargo.Trait<Carryable>();
carryableFacing = cargo.Trait<IFacing>();
carryableBody = cargo.Trait<BodyOrientation>();

movement = self.Trait<IMove>();
carryall = self.Trait<Carryall>();
carryallFacing = self.Trait<IFacing>();

state = PickupState.Intercept;
ChildHasPriority = false;
}

protected override void OnFirstRun(Actor self)
{
carryall.ReserveCarryable(self, cargo);

// Land at the target location
QueueChild(new Land(self, Target.FromActor(cargo), carryall.OffsetForCarryable(self, cargo)));

// Pause briefly before attachment for visual effect
if (delay > 0)
QueueChild(new Wait(delay, false));

// Remove our carryable from world
QueueChild(new AttachUnit(self, cargo));
QueueChild(new TakeOff(self));
}

public override bool Tick(Actor self)
Expand All @@ -74,41 +73,16 @@ public override bool Tick(Actor self)
return true;
}

if (carryall.State != Carryall.CarryallState.Reserved)
return true;

switch (state)
var distance = (cargo.CenterPosition - self.CenterPosition).HorizontalLength;
if (distance <= 4096 && !locked)
{
case PickupState.Intercept:
QueueChild(movement.MoveWithinRange(Target.FromActor(cargo), WDist.FromCells(4)));
state = PickupState.LockCarryable;
return false;
if (!carryable.LockForPickup(cargo, self))
Cancel(self);

case PickupState.LockCarryable:
if (!carryable.LockForPickup(cargo, self))
Cancel(self);

state = PickupState.Pickup;
return false;

case PickupState.Pickup:
{
// Land at the target location
var localOffset = carryall.OffsetForCarryable(self, cargo).Rotate(carryableBody.QuantizeOrientation(self, cargo.Orientation));
QueueChild(new Land(self, Target.FromActor(cargo), -carryableBody.LocalToWorld(localOffset), carryableFacing.Facing));

// Pause briefly before attachment for visual effect
if (delay > 0)
QueueChild(new Wait(delay, false));

// Remove our carryable from world
QueueChild(new AttachUnit(self, cargo));
QueueChild(new TakeOff(self));
return false;
}
locked = true;
}

return true;
return TickChild(self);
}

public override IEnumerable<TargetLineNode> TargetLineNodes(Actor self)
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Traits/AutoCarryable.cs
Expand Up @@ -104,7 +104,7 @@ public override bool Reserve(Actor self, Actor carrier)
// Prepare for transport pickup
public override bool LockForPickup(Actor self, Actor carrier)
{
if (state == State.Locked || !WantsTransport)
if ((state == State.Locked && Carrier != carrier) || !WantsTransport)
return false;

// Last chance to change our mind...
Expand Down
5 changes: 5 additions & 0 deletions OpenRA.Mods.Common/Traits/CaptureManager.cs
Expand Up @@ -221,6 +221,11 @@ public bool StartCapture(Actor self, Actor target, CaptureManager targetManager,
if (captures == null)
return false;

// Make sure we are in a valid state first.
var enterMobile = target.TraitOrDefault<Mobile>();
pchote marked this conversation as resolved.
Show resolved Hide resolved
if (enterMobile != null && enterMobile.IsMovingBetweenCells)
return false;

if (progressWatchers.Any() || targetManager.progressWatchers.Any())
{
currentTargetTotal = captures.Info.CaptureDelay;
Expand Down
13 changes: 8 additions & 5 deletions OpenRA.Mods.Common/Traits/Carryable.cs
Expand Up @@ -113,14 +113,17 @@ public virtual void UnReserve(Actor self)
// Prepare for transport pickup
public virtual bool LockForPickup(Actor self, Actor carrier)
{
if (state == State.Locked)
if (state == State.Locked && Carrier != carrier)
return false;

state = State.Locked;
Carrier = carrier;
if (state != State.Locked)
{
state = State.Locked;
Carrier = carrier;

if (lockedToken == ConditionManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.LockedCondition))
lockedToken = conditionManager.GrantCondition(self, Info.LockedCondition);
if (lockedToken == ConditionManager.InvalidConditionToken && !string.IsNullOrEmpty(Info.LockedCondition))
lockedToken = conditionManager.GrantCondition(self, Info.LockedCondition);
}

return true;
}
Expand Down
5 changes: 5 additions & 0 deletions OpenRA.Mods.Common/Traits/Mobile.cs
Expand Up @@ -181,6 +181,11 @@ public MovementType CurrentMovementTypes
public bool TurnToMove;
public bool IsBlocking { get; private set; }

public bool IsMovingBetweenCells
{
get { return FromCell != ToCell; }
}

#region IFacing
[Sync]
public int Facing
Expand Down
6 changes: 6 additions & 0 deletions OpenRA.Mods.Common/Util.cs
Expand Up @@ -141,6 +141,12 @@ static IEnumerable<CPos> Neighbours(CPos c, bool allowDiagonal)
}
}

public static bool AreAdjacentCells(CPos a, CPos b)
{
var offset = b - a;
return Math.Abs(offset.X) < 2 && Math.Abs(offset.Y) < 2;
}

public static IEnumerable<CPos> ExpandFootprint(IEnumerable<CPos> cells, bool allowDiagonal)
{
return cells.SelectMany(c => Neighbours(c, allowDiagonal)).Distinct();
Expand Down