From e88b3fa2fefa8c9a0383243bc455d9cbb27d8b04 Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Wed, 17 Jan 2018 21:40:59 +0000 Subject: 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 --- src/Mobs/Monster.cpp | 80 ++++++++++++++++++++++++++++++---------------------- src/Mobs/Monster.h | 2 +- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 9e9d51a78..0d6b8e777 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -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. + + 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) { - // TODO: leashed mobs in vanilla can move around up to 5 blocks distance from leash origin - MoveToPosition(m_LeashedTo->GetPosition()); + // Accelerate monster towards the leashed to entity: + const auto Extension = Distance - LeashNaturalLength; + auto Acceleration = Direction * (Extension * LeashSpringConstant); - // If distance to target > 10 break leash - Vector3f a_Distance(m_LeashedTo->GetPosition() - GetPosition()); - double Distance(a_Distance.Length()); - if (Distance > 10.0) + // Stop mobs from floating up when on the ground + if (IsOnGround() && (Acceleration.y < std::abs(GetGravity()))) { - LOGD("Leash broken (distance)"); - Unleash(false); + Acceleration.y = 0.0; } + + // Apply the acceleration + using namespace std::chrono; + AddSpeed(Acceleration * duration_cast>(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 }); } } diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index 1f6bd6011..d6b02caac 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -326,6 +326,6 @@ private: cPawn * m_Target; /** Leash calculations inside Tick function */ - void CalcLeashActions(); + void CalcLeashActions(std::chrono::milliseconds a_Dt); } ; // tolua_export -- cgit v1.2.3