1
0

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:
peterbell10 2018-01-17 21:40:59 +00:00 committed by Alexander Harkness
parent ec9e0eecf6
commit e88b3fa2fe
2 changed files with 48 additions and 36 deletions

View File

@ -22,10 +22,6 @@
// Ticks to wait to do leash calculations
#define LEASH_ACTIONS_TICK_STEP 10
/** Map for eType <-> string /** Map for eType <-> string
Needs to be alpha-sorted by the strings, because binary search is used in StringToMobType() 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); AddSpeedX(Distance.x);
AddSpeedZ(Distance.z); 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) void cMonster::MoveToPosition(const Vector3d & a_Position)
{ {
m_FinalDestination = a_Position; m_FinalDestination = a_Position;
@ -400,10 +380,7 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
} // switch (m_EMState) } // switch (m_EMState)
// Leash calculations // Leash calculations
if ((m_TicksAlive % LEASH_ACTIONS_TICK_STEP) == 0) CalcLeashActions(a_Dt);
{
CalcLeashActions();
}
BroadcastMovementUpdate(); 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 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. // 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); 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 if (!IsLeashed())
Vector3f a_Distance(m_LeashedTo->GetPosition() - GetPosition()); {
double Distance(a_Distance.Length()); return;
if (Distance > 10.0) }
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())))
{ {
LOGD("Leash broken (distance)"); Acceleration.y = 0.0;
Unleash(false);
} }
// 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 });
} }
} }

View File

@ -326,6 +326,6 @@ private:
cPawn * m_Target; cPawn * m_Target;
/** Leash calculations inside Tick function */ /** Leash calculations inside Tick function */
void CalcLeashActions(); void CalcLeashActions(std::chrono::milliseconds a_Dt);
} ; // tolua_export } ; // tolua_export