New movement system for leashed entities (#4147)
* New movement system for leashed entities Entities are accelerated towards the leashed to entity as if by a spring. * Mobs now pathfind close to but not directly to the leashing entity. * Also minor comment changes
This commit is contained in:
parent
ec9e0eecf6
commit
e88b3fa2fe
@ -22,10 +22,6 @@
|
||||
|
||||
|
||||
|
||||
// Ticks to wait to do leash calculations
|
||||
#define LEASH_ACTIONS_TICK_STEP 10
|
||||
|
||||
|
||||
|
||||
/** Map for eType <-> string
|
||||
Needs to be alpha-sorted by the strings, because binary search is used in StringToMobType()
|
||||
@ -239,28 +235,12 @@ void cMonster::MoveToWayPoint(cChunk & a_Chunk)
|
||||
AddSpeedX(Distance.x);
|
||||
AddSpeedZ(Distance.z);
|
||||
}
|
||||
|
||||
// Speed up leashed mobs getting far from player
|
||||
if (IsLeashed() && GetLeashedTo()->IsPlayer())
|
||||
{
|
||||
Distance = GetLeashedTo()->GetPosition() - GetPosition();
|
||||
Distance.Normalize();
|
||||
AddSpeedX(Distance.x);
|
||||
AddSpeedZ(Distance.z);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMonster::MoveToPosition(const Vector3d & a_Position)
|
||||
{
|
||||
m_FinalDestination = a_Position;
|
||||
@ -400,10 +380,7 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
} // switch (m_EMState)
|
||||
|
||||
// Leash calculations
|
||||
if ((m_TicksAlive % LEASH_ACTIONS_TICK_STEP) == 0)
|
||||
{
|
||||
CalcLeashActions();
|
||||
}
|
||||
CalcLeashActions(a_Dt);
|
||||
|
||||
BroadcastMovementUpdate();
|
||||
|
||||
@ -422,7 +399,7 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
|
||||
|
||||
|
||||
void cMonster::CalcLeashActions()
|
||||
void cMonster::CalcLeashActions(std::chrono::milliseconds a_Dt)
|
||||
{
|
||||
// This mob just spotted in the world and [m_LeashToPos not null] shows that should be leashed to a leash knot at m_LeashToPos.
|
||||
// This keeps trying until knot is found. Leash knot may be in a different chunk that needn't or can't be loaded yet.
|
||||
@ -435,19 +412,54 @@ void cMonster::CalcLeashActions()
|
||||
SetLeashToPos(nullptr);
|
||||
}
|
||||
}
|
||||
else if (IsLeashed()) // Mob is already leashed to an entity: follow it.
|
||||
{
|
||||
// TODO: leashed mobs in vanilla can move around up to 5 blocks distance from leash origin
|
||||
MoveToPosition(m_LeashedTo->GetPosition());
|
||||
|
||||
// If distance to target > 10 break leash
|
||||
Vector3f a_Distance(m_LeashedTo->GetPosition() - GetPosition());
|
||||
double Distance(a_Distance.Length());
|
||||
if (Distance > 10.0)
|
||||
if (!IsLeashed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static const double CloseFollowDistance = 1.8; // The closest the mob will path towards the leashed to entity
|
||||
static const double LeashNaturalLength = 5.0; // The closest the mob is actively pulled towards the entity
|
||||
static const double LeashMaximumLength = 10.0; // Length where the leash breaks
|
||||
static const double LeashSpringConstant = 20.0; // How stiff the leash is
|
||||
|
||||
const auto LeashedToPos = m_LeashedTo->GetPosition();
|
||||
const auto Displacement = LeashedToPos - GetPosition();
|
||||
const auto Distance = Displacement.Length();
|
||||
const auto Direction = Displacement.NormalizeCopy();
|
||||
|
||||
// If the leash is over-extended, break the leash:
|
||||
if (Distance > LeashMaximumLength)
|
||||
{
|
||||
LOGD("Leash broken (distance)");
|
||||
Unleash(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the mob isn't following close enough, pull the mob towards the leashed to entity:
|
||||
if (Distance > LeashNaturalLength)
|
||||
{
|
||||
// Accelerate monster towards the leashed to entity:
|
||||
const auto Extension = Distance - LeashNaturalLength;
|
||||
auto Acceleration = Direction * (Extension * LeashSpringConstant);
|
||||
|
||||
// Stop mobs from floating up when on the ground
|
||||
if (IsOnGround() && (Acceleration.y < std::abs(GetGravity())))
|
||||
{
|
||||
Acceleration.y = 0.0;
|
||||
}
|
||||
|
||||
// Apply the acceleration
|
||||
using namespace std::chrono;
|
||||
AddSpeed(Acceleration * duration_cast<duration<double>>(a_Dt).count());
|
||||
}
|
||||
|
||||
// Passively follow the leashed to entity:
|
||||
if (Distance > CloseFollowDistance)
|
||||
{
|
||||
const Vector3d TargetBlock((LeashedToPos - Direction * CloseFollowDistance).Floor());
|
||||
// Move to centre of target block face
|
||||
MoveToPosition(TargetBlock + Vector3d{ 0.5, 0.0, 0.5 });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,6 +326,6 @@ private:
|
||||
cPawn * m_Target;
|
||||
|
||||
/** Leash calculations inside Tick function */
|
||||
void CalcLeashActions();
|
||||
void CalcLeashActions(std::chrono::milliseconds a_Dt);
|
||||
|
||||
} ; // tolua_export
|
||||
|
Loading…
Reference in New Issue
Block a user