Core/Movement: fixed several edge cases at which units with a custom chase angle ended up endlessly repositioning against their target
This commit is contained in:
1 parent
e0be0caadd
commit
26e5823913
2 files changed
+36
-39
No files matched your search
@@ -98,23 +98,40 @@ bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool const mutualChase = IsMutualChase(owner, target);
|
||||
//float const hitboxSum = owner->GetCombatReach() + target->GetCombatReach();
|
||||
float const chaseRange = owner->GetCombatReach() + target->GetCombatReach();
|
||||
float const rangeTolerance = _range > 0.f ? _range : chaseRange;
|
||||
Optional<ChaseAngle> chaseAngle = mutualChase ? Optional<ChaseAngle>() : _angle;
|
||||
|
||||
// We are done moving. Trigger movement inform hook and clear chase move state
|
||||
if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE) && owner->movespline->Finalized())
|
||||
{
|
||||
if (Creature* cOwner = owner->ToCreature())
|
||||
cOwner->SetCannotReachTarget(false);
|
||||
|
||||
owner->ClearUnitState(UNIT_STATE_CHASE_MOVE);
|
||||
owner->SetInFront(target);
|
||||
owner->ClearUnitState(UNIT_STATE_CHASE_MOVE);
|
||||
DoMovementInform(owner, target);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Owner cannot reach target (example: target is in water and owner cannot swim)
|
||||
Creature* creature = owner->ToCreature();
|
||||
if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE) && creature)
|
||||
{
|
||||
if (!target->isInAccessiblePlaceFor(creature))
|
||||
{
|
||||
creature->SetCannotReachTarget(true);
|
||||
creature->StopMoving();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (creature && !target->isInAccessiblePlaceFor(creature))
|
||||
{
|
||||
creature->SetCannotReachTarget(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool const mutualChase = IsMutualChase(owner, target);
|
||||
float const chaseRange = owner->GetCombatReach() + target->GetCombatReach();
|
||||
float const rangeTolerance = _range > 0.f ? _range : chaseRange;
|
||||
Optional<ChaseAngle> chaseAngle = mutualChase ? Optional<ChaseAngle>() : _angle;
|
||||
|
||||
// Update Movement
|
||||
_nextMovementTimer.Update(diff);
|
||||
_nextRepositioningTimer.Update(diff);
|
||||
@@ -129,7 +146,7 @@ bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff)
|
||||
// Owner is too close to its target. Step back.
|
||||
if (owner->GetExactDist2d(target) < owner->GetBoundaryRadius())
|
||||
{
|
||||
LaunchMovement(owner, target, chaseRange, true);
|
||||
LaunchMovement(owner, target, chaseRange, true, mutualChase);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -145,39 +162,20 @@ bool ChaseMovementGenerator::Update(Unit* owner, uint32 diff)
|
||||
// Create new snapshot of our target's position
|
||||
_lastTargetPosition = target->GetPosition();
|
||||
|
||||
Creature* creature = owner->ToCreature();
|
||||
// Owner cannot reach target (example: target is in water and owner cannot swim)
|
||||
if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE) && creature)
|
||||
if (PositionOkay(owner, target, rangeTolerance, chaseAngle))
|
||||
{
|
||||
if (!target->isInAccessiblePlaceFor(creature))
|
||||
if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE) && !target->isMoving() && !mutualChase)
|
||||
{
|
||||
creature->SetCannotReachTarget(true);
|
||||
creature->StopMoving();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (creature && !target->isInAccessiblePlaceFor(creature))
|
||||
{
|
||||
creature->SetCannotReachTarget(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isMoving = target->HasUnitMovementFlag(MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD) || !target->movespline->Finalized();
|
||||
if (PositionOkay(owner, target, rangeTolerance, chaseAngle) && !isMoving)
|
||||
{
|
||||
if (owner->HasUnitState(UNIT_STATE_CHASE_MOVE))
|
||||
{
|
||||
// Just stopping our movement, movementinform and cleanups will be executed in the code above on the next update tick
|
||||
// Our current position is fine. Stop movement.
|
||||
owner->StopMoving();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (owner->GetExactDist2d(target) > rangeTolerance + 0.1f) // 0.1f here to avoid edge cases when the owner has stepped back before
|
||||
LaunchMovement(owner, target, chaseRange);
|
||||
LaunchMovement(owner, target, chaseRange, mutualChase);
|
||||
}
|
||||
}
|
||||
|
||||
// and then, finally, we're done for the tick
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -188,15 +186,14 @@ void ChaseMovementGenerator::Finalize(Unit* owner)
|
||||
cOwner->SetCannotReachTarget(false);
|
||||
}
|
||||
|
||||
void ChaseMovementGenerator::LaunchMovement(Unit* owner, Unit* target, float chaseRange, bool backward /*= false*/)
|
||||
void ChaseMovementGenerator::LaunchMovement(Unit* owner, Unit* target, float chaseRange, bool backward /*= false*/, bool mutualChase /*= false*/)
|
||||
{
|
||||
// Owner may launch a new spline
|
||||
Position dest = target->GetVehicle() ? target->GetVehicle()->GetBase()->GetPosition() : target->GetPosition();
|
||||
|
||||
// Player chase target is currently moving
|
||||
bool predictDestination = target->HasUnitMovementFlag(MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT | MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
|
||||
|
||||
if (!backward && predictDestination)
|
||||
// Predict chase destination to keep up with chase target
|
||||
bool predictDestination = !backward && !mutualChase && target->isMoving();
|
||||
if (predictDestination)
|
||||
{
|
||||
UnitMoveType moveType = MOVE_RUN;
|
||||
if (target->CanFly())
|
||||
@@ -211,10 +208,10 @@ void ChaseMovementGenerator::LaunchMovement(Unit* owner, Unit* target, float cha
|
||||
|
||||
float additionalRange = target->GetSpeed(moveType) * 0.5f;
|
||||
|
||||
target->MovePositionToFirstCollision(dest, additionalRange, _angle ? _angle->RelativeAngle : target->GetRelativeAngle(owner) + float(M_PI));
|
||||
target->MovePositionToFirstCollision(dest, additionalRange, _angle ? target->NormalizeOrientation(target->GetOrientation() - _angle->RelativeAngle + float(M_PI)) : target->GetRelativeAngle(owner) + float(M_PI));
|
||||
}
|
||||
else
|
||||
target->MovePositionToFirstCollision(dest, chaseRange, _angle ? _angle->RelativeAngle : target->GetRelativeAngle(owner));
|
||||
target->MovePositionToFirstCollision(dest, chaseRange, _angle ? target->NormalizeOrientation(target->GetOrientation() - _angle->RelativeAngle) : target->GetRelativeAngle(owner));
|
||||
|
||||
owner->UpdateAllowedPositionZ(dest.GetPositionX(), dest.GetPositionY(), dest.m_positionZ);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class ChaseMovementGenerator : public MovementGenerator, public AbstractFollower
|
||||
void UnitSpeedChanged() override { _lastTargetPosition.reset(); }
|
||||
|
||||
private:
|
||||
void LaunchMovement(Unit* owner, Unit* target, float chaseRange, bool backward = false);
|
||||
void LaunchMovement(Unit* owner, Unit* target, float chaseRange, bool backward = false, bool mutualChase = false);
|
||||
|
||||
static constexpr uint32 CHASE_MOVEMENT_INTERVAL = 400; // sniffed value (1 batch update cyclice)
|
||||
static constexpr uint32 REPOSITION_MOVEMENT_INTERVAL = 1200; // (3 batch update cycles) TODO: verify
|
||||
|
||||
Reference in new issue
Block a user