1
0
Fork 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
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())))
{
LOGD("Leash broken (distance)");
Unleash(false);
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 });
}
}

View File

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