diff options
Diffstat (limited to 'src/Mobs/Monster.cpp')
-rw-r--r-- | src/Mobs/Monster.cpp | 279 |
1 files changed, 110 insertions, 169 deletions
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 70c3b096b..01077bcdd 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -75,10 +75,8 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A , m_EMPersonality(AGGRESSIVE) , m_Target(nullptr) , m_Path(nullptr) - , m_PathStatus(ePathFinderStatus::PATH_NOT_FOUND) , m_IsFollowingPath(false) , m_GiveUpCounter(0) - , m_bMovingToDestination(false) , m_LastGroundHeight(POSY_TOINT) , m_JumpCoolDown(0) , m_IdleInterval(0) @@ -122,101 +120,124 @@ void cMonster::SpawnOn(cClientHandle & a_Client) -void cMonster::TickPathFinding(cChunk & a_Chunk) +bool cMonster::TickPathFinding(cChunk & a_Chunk) { - - if (m_Path == nullptr) + if (!m_IsFollowingPath) { - Vector3d position = GetPosition(); - Vector3d Dest = m_FinalDestination; - - // Can someone explain why are these two NOT THE SAME??? - // m_Path = new cPath(GetWorld(), GetPosition(), m_FinalDestination, 30); - m_Path = new cPath(a_Chunk, Vector3d(floor(position.x), floor(position.y), floor(position.z)), Vector3d(floor(Dest.x), floor(Dest.y), floor(Dest.z)), 20); - + return false; + } - m_IsFollowingPath = false; + if (ReachedFinalDestination()) + { + StopMovingToPosition(); + return false; } - m_PathStatus = m_Path->Step(a_Chunk); - switch (m_PathStatus) + + if (m_Path == nullptr) { + m_Path = new cPath(a_Chunk, GetPosition().Floor(), m_FinalDestination.Floor(), 20); + } + switch (m_Path->Step(a_Chunk)) + { case ePathFinderStatus::PATH_NOT_FOUND: { - ResetPathFinding(); + StopMovingToPosition(); // Give up pathfinding to that destination break; } - - case ePathFinderStatus::CALCULATING: { - m_Destination = GetPosition(); + // Pathfinder needs more time break; } - - case ePathFinderStatus::PATH_FOUND: { - if (ReachedDestination() || !m_IsFollowingPath) + if (--m_GiveUpCounter == 0) { - m_Destination = m_Path->GetNextPoint(); - m_IsFollowingPath = true; - m_GiveUpCounter = 40; // Give up after 40 ticks (2 seconds) if failed to reach m_Dest. + ResetPathFinding(); // Try to calculate a path again + return false; } - if (m_Path->IsLastPoint()) + else if (!m_Path->IsLastPoint() && (m_Path->IsFirstPoint() || ReachedDestination())) // Have we arrived at the next cell, as denoted by m_Destination? { - ResetPathFinding(); + m_Destination = Vector3d(0.5, 0, 0.5) + m_Path->GetNextPoint(); + m_GiveUpCounter = 40; // Give up after 40 ticks (2 seconds) if failed to reach m_Destination. } - break; - + return true; } } -} - - - - -/* Currently, the mob will only start moving to a new position after the position it is -currently going to is reached. */ -void cMonster::MoveToPosition(const Vector3d & a_Position) -{ - m_FinalDestination = a_Position; - m_bMovingToDestination = true; + return false; } -void cMonster::StopMovingToPosition() +void cMonster::MoveToWayPoint(cChunk & a_Chunk) { - m_bMovingToDestination = false; - ResetPathFinding(); -} - - - + if (m_JumpCoolDown == 0) + { + // We're not moving and waypoint is above us, it means we are hitting something and we should jump. + if ((GetSpeedX() < 0.1) && (GetSpeedY() < 0.1) && DoesPosYRequireJump(FloorC(m_Destination.y))) + { + if (IsOnGround() || IsSwimming()) + { + m_bOnGround = false; + m_JumpCoolDown = 20; + // TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport + AddPosY(1.6); // Jump!! + SetSpeedX(3.2 * (m_Destination.x - GetPosition().x)); // Move forward in a preset speed. + SetSpeedZ(3.2 * (m_Destination.z - GetPosition().z)); // The numbers were picked based on trial and error and 1.6 and 3.2 are perfect. + } + } + } + else + { + --m_JumpCoolDown; + } + Vector3d Distance = m_Destination - GetPosition(); + if ((Distance.x != 0) || (Distance.z != 0)) + { + Distance.y = 0; + Distance.Normalize(); -bool cMonster::IsCoordinateInTraversedList(Vector3i a_Coords) -{ - return (std::find(m_TraversedCoordinates.begin(), m_TraversedCoordinates.end(), a_Coords) != m_TraversedCoordinates.end()); + if (m_bOnGround) + { + Distance *= 2.5f; + } + else if (IsSwimming()) + { + Distance *= 1.3f; + } + else + { + // Don't let the mob move too much if he's falling. + Distance *= 0.25f; + } + // Apply walk speed: + Distance *= m_RelativeWalkSpeed; + /* Reduced default speed. + Close to Vanilla, easier for mobs to follow m_Destinations, hence + better pathfinding. */ + Distance *= 0.5; + AddSpeedX(Distance.x); + AddSpeedZ(Distance.z); + } } -/* No one should call this except the pathfinder orthe monster tick or StopMovingToPosition. -Resets the pathfinder, usually starting a brand new path, unless called from StopMovingToPosition. */ -void cMonster::ResetPathFinding(void) +void cMonster::MoveToPosition(const Vector3d & a_Position) { - if (m_Path != nullptr) + if ((m_FinalDestination - a_Position).Length() > 0.25) { - delete m_Path; - m_Path = nullptr; + ResetPathFinding(); + m_FinalDestination = a_Position; + m_IsFollowingPath = true; } } @@ -224,28 +245,23 @@ void cMonster::ResetPathFinding(void) -bool cMonster::ReachedDestination() +void cMonster::StopMovingToPosition() { - if ((m_Destination - GetPosition()).Length() < 0.5f) - { - return true; - } - - return false; + m_IsFollowingPath = false; + ResetPathFinding(); } -bool cMonster::ReachedFinalDestination() +void cMonster::ResetPathFinding(void) { - if ((GetPosition() - m_FinalDestination).Length() <= m_AttackRange) + if (m_Path != nullptr) { - return true; + delete m_Path; + m_Path = nullptr; } - - return false; } @@ -277,83 +293,18 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) m_Target = nullptr; } - // Burning in daylight - bool WouldBurnRightNow = WouldBurnAt(GetPosition(), *Chunk); // cached so that we use it twice, spares some cycles. - HandleDaylightBurning(*Chunk, WouldBurnRightNow); - - - - if (m_bMovingToDestination) + // Process the undead burning in daylight + HandleDaylightBurning(*Chunk, WouldBurnAt(GetPosition(), *Chunk)); + if (TickPathFinding(*Chunk)) { - if (m_bOnGround) - { - if (m_JumpCoolDown == 0) - { - if (DoesPosYRequireJump(static_cast<int>(floor(m_Destination.y)))) - { - m_bOnGround = false; - m_JumpCoolDown = 20; - // TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport - AddPosY(1.6); // Jump!! - SetSpeedX(3.2 * (m_Destination.x - GetPosition().x)); // Move forward in a preset speed. - SetSpeedZ(3.2 * (m_Destination.z - GetPosition().z)); // The numbers were picked based on trial and error and 1.6 and 3.2 are perfect. - } - } - else - { - --m_JumpCoolDown; - } - } - - TickPathFinding(a_Chunk); - - Vector3d Distance = m_Destination - GetPosition(); - if (!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move + if (m_BurnsInDaylight && WouldBurnAt(m_Destination, *Chunk->GetNeighborChunk(FloorC(m_Destination.x), FloorC(m_Destination.z))) && !IsOnFire() && (m_TicksSinceLastDamaged == 100)) { - if (--m_GiveUpCounter == 0) - { - ResetPathFinding(); // Not to be confused with StopMovingToPosition, this just discards the current path and calculates another. - } - else if (m_BurnsInDaylight && WouldBurnAt(m_Destination, *Chunk) && !WouldBurnRightNow && (m_TicksSinceLastDamaged == 100)) - { - // If we burn in daylight, and we would burn at the next step, and we won't burn where we are right now, and we weren't provoked recently: - StopMovingToPosition(); - } - else - { - Distance.y = 0; - Distance.Normalize(); - - if (m_bOnGround) - { - Distance *= 2.5f; - } - else if (IsSwimming()) - { - Distance *= 1.3f; - } - else - { - // Don't let the mob move too much if he's falling. - Distance *= 0.25f; - } - - // Apply walk speed: - Distance *= m_RelativeWalkSpeed; - - /* Reduced default speed. - Close to Vanilla, easier for mobs to follow m_Destinations, hence - better pathfinding. */ - Distance *= 0.5; - - AddSpeedX(Distance.x); - AddSpeedZ(Distance.z); - - } + // If we burn in daylight, and we would burn at the next step, and we won't burn where we are right now, and we weren't provoked recently: + StopMovingToPosition(); } - else if (ReachedFinalDestination()) + else { - StopMovingToPosition(); + MoveToWayPoint(*Chunk); } } @@ -379,12 +330,11 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) InStateEscaping(a_Dt); break; } - case ATTACKING: break; } // switch (m_EMState) BroadcastMovementUpdate(); - } +} @@ -397,32 +347,29 @@ void cMonster::SetPitchAndYawFromDestination() { if (m_Target->IsPlayer()) { - FinalDestination.y = ((cPlayer *)m_Target)->GetStance(); + FinalDestination.y = static_cast<cPlayer *>(m_Target)->GetStance() - 1; } else { - FinalDestination.y = GetHeight(); + FinalDestination.y = m_Target->GetPosY() + GetHeight(); } } Vector3d Distance = FinalDestination - GetPosition(); - if (Distance.SqrLength() > 0.1f) { - { - double Rotation, Pitch; - Distance.Normalize(); - VectorToEuler(Distance.x, Distance.y, Distance.z, Rotation, Pitch); - SetHeadYaw(Rotation); - SetPitch(-Pitch); - } + double Rotation, Pitch; + Distance.Normalize(); + VectorToEuler(Distance.x, Distance.y, Distance.z, Rotation, Pitch); + SetHeadYaw(Rotation); + SetPitch(-Pitch); + } - { - Vector3d BodyDistance = m_Destination - GetPosition(); - double Rotation, Pitch; - Distance.Normalize(); - VectorToEuler(BodyDistance.x, BodyDistance.y, BodyDistance.z, Rotation, Pitch); - SetYaw(Rotation); - } + { + Vector3d BodyDistance = m_Destination - GetPosition(); + double Rotation, Pitch; + BodyDistance.Normalize(); + VectorToEuler(BodyDistance.x, BodyDistance.y, BodyDistance.z, Rotation, Pitch); + SetYaw(Rotation); } } @@ -662,7 +609,7 @@ void cMonster::EventLosePlayer(void) void cMonster::InStateIdle(std::chrono::milliseconds a_Dt) { - if (m_bMovingToDestination) + if (m_IsFollowingPath) { return; // Still getting there } @@ -682,14 +629,8 @@ void cMonster::InStateIdle(std::chrono::milliseconds a_Dt) if ((Dist.SqrLength() > 2) && (rem >= 3)) { Vector3d Destination(GetPosX() + Dist.x, 0, GetPosZ() + Dist.z); - - int NextHeight = FindFirstNonAirBlockPosition(Destination.x, Destination.z); - - if (IsNextYPosReachable(NextHeight)) - { - Destination.y = NextHeight; - MoveToPosition(Destination); - } + Destination.y = FindFirstNonAirBlockPosition(Destination.x, Destination.z); + MoveToPosition(Destination); } } } |