From 4aade202e006738a0baf4c3190cff8ce6b91003c Mon Sep 17 00:00:00 2001 From: LogicParrot Date: Mon, 1 Feb 2016 22:49:34 +0200 Subject: cMonster::m_Target safety across worlds --- src/Mobs/Monster.cpp | 121 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 27 deletions(-) (limited to 'src/Mobs/Monster.cpp') diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 4a543e400..28cb10238 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -74,7 +74,6 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A : super(etMonster, a_Width, a_Height) , m_EMState(IDLE) , m_EMPersonality(AGGRESSIVE) - , m_Target(nullptr) , m_PathFinder(a_Width, a_Height) , m_PathfinderActivated(false) , m_JumpCoolDown(0) @@ -101,6 +100,7 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A , m_RelativeWalkSpeed(1) , m_Age(1) , m_AgingTimer(20 * 60 * 20) // about 20 minutes + , m_Target(nullptr) { if (!a_ConfigName.empty()) { @@ -112,6 +112,25 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A +cMonster::~cMonster() +{ + ASSERT(GetTarget() == nullptr); +} + + + + + +void cMonster::Destroyed() +{ + SetTarget(nullptr); // Tell them we're no longer targeting them. + super::Destroyed(); +} + + + + + void cMonster::SpawnOn(cClientHandle & a_Client) { a_Client.SendSpawnMob(*this); @@ -214,6 +233,7 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) super::Tick(a_Dt, a_Chunk); GET_AND_VERIFY_CURRENT_CHUNK(Chunk, POSX_TOINT, POSZ_TOINT); + ASSERT((GetTarget() == nullptr) || (GetTarget()->IsPawn() && (GetTarget()->GetWorld() == GetWorld()))); if (m_AttackCoolDownTicksLeft > 0) { m_AttackCoolDownTicksLeft -= 1; @@ -234,17 +254,15 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { ++m_TicksSinceLastDamaged; } - if ((m_Target != nullptr)) + if ((GetTarget() != nullptr)) { - if (m_Target->IsDestroyed()) - { - m_Target = nullptr; - } - else if (m_Target->IsPlayer()) + ASSERT(!GetTarget()->IsDestroyed()); + + if (GetTarget()->IsPlayer()) { - if (static_cast(m_Target)->IsGameModeCreative()) + if (static_cast(GetTarget())->IsGameModeCreative()) { - m_Target = nullptr; + SetTarget(nullptr); m_EMState = IDLE; } } @@ -343,11 +361,10 @@ void cMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) void cMonster::SetPitchAndYawFromDestination(bool a_IsFollowingPath) { - /* Todo Buggy */ Vector3d BodyDistance; - if (!a_IsFollowingPath && (m_Target != nullptr)) + if (!a_IsFollowingPath && (GetTarget() != nullptr)) { - BodyDistance = m_Target->GetPosition() - GetPosition(); + BodyDistance = GetTarget()->GetPosition() - GetPosition(); } else { @@ -359,17 +376,16 @@ void cMonster::SetPitchAndYawFromDestination(bool a_IsFollowingPath) SetYaw(BodyRotation); Vector3d HeadDistance; - if (m_Target != nullptr) + if (GetTarget() != nullptr) { - if (m_Target->IsPlayer()) // Look at a player + if (GetTarget()->IsPlayer()) // Look at a player { - HeadDistance = m_Target->GetPosition() - GetPosition(); - // HeadDistance.y = static_cast(m_Target)->GetStance() - 1; + HeadDistance = GetTarget()->GetPosition() - GetPosition(); } else // Look at some other entity { - HeadDistance = m_Target->GetPosition() - GetPosition(); - // HeadDistance.y = m_Target->GetPosY() + GetHeight(); + HeadDistance = GetTarget()->GetPosition() - GetPosition(); + // HeadDistance.y = GetTarget()->GetPosY() + GetHeight(); } } else // Look straight @@ -448,9 +464,9 @@ bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI) m_World->BroadcastSoundEffect(m_SoundHurt, GetPosX(), GetPosY(), GetPosZ(), 1.0f, 0.8f); } - if (a_TDI.Attacker != nullptr) + if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn()) { - m_Target = a_TDI.Attacker; + SetTarget(static_cast(a_TDI.Attacker)); m_TicksSinceLastDamaged = 0; } return true; @@ -577,9 +593,9 @@ void cMonster::CheckEventSeePlayer(cChunk & a_Chunk) void cMonster::CheckEventLostPlayer(void) { - if (m_Target != nullptr) + if (GetTarget() != nullptr) { - if ((m_Target->GetPosition() - GetPosition()).Length() > m_SightDistance) + if ((GetTarget()->GetPosition() - GetPosition()).Length() > m_SightDistance) { EventLosePlayer(); } @@ -598,7 +614,9 @@ void cMonster::CheckEventLostPlayer(void) // default to change state to chasing void cMonster::EventSeePlayer(cEntity * a_SeenPlayer, cChunk & a_Chunk) { - m_Target = a_SeenPlayer; + UNUSED(a_Chunk); + ASSERT(a_SeenPlayer->IsPlayer()); + SetTarget(static_cast(a_SeenPlayer)); } @@ -607,7 +625,7 @@ void cMonster::EventSeePlayer(cEntity * a_SeenPlayer, cChunk & a_Chunk) void cMonster::EventLosePlayer(void) { - m_Target = nullptr; + SetTarget(nullptr); m_EMState = IDLE; } @@ -678,11 +696,11 @@ void cMonster::InStateEscaping(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); - if (m_Target != nullptr) + if (GetTarget() != nullptr) { Vector3d newloc = GetPosition(); - newloc.x = (m_Target->GetPosition().x < newloc.x)? (newloc.x + m_SightDistance): (newloc.x - m_SightDistance); - newloc.z = (m_Target->GetPosition().z < newloc.z)? (newloc.z + m_SightDistance): (newloc.z - m_SightDistance); + newloc.x = (GetTarget()->GetPosition().x < newloc.x)? (newloc.x + m_SightDistance): (newloc.x - m_SightDistance); + newloc.z = (GetTarget()->GetPosition().z < newloc.z)? (newloc.z + m_SightDistance): (newloc.z - m_SightDistance); MoveToPosition(newloc); } else @@ -890,6 +908,55 @@ int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily) + +/** Sets the target. */ +void cMonster::SetTarget (cPawn * a_NewTarget) +{ + ASSERT((a_NewTarget == nullptr) || (!IsDestroyed())); + if (m_Target == a_NewTarget) + { + return; + } + cPawn * OldTarget = m_Target; + m_Target = a_NewTarget; + + if (OldTarget != nullptr) + { + // Notify the old target that we are no longer targeting it. + OldTarget->NoLongerTargetingMe(this); + } + + if (a_NewTarget != nullptr) + { + ASSERT(!a_NewTarget->IsDestroyed()); + // Notify the new target that we are now targeting it. + m_Target->TargetingMe(this); + } + +} + + + + + +void cMonster::UnsafeUnsetTarget() +{ + m_Target = nullptr; +} + + + + + +cPawn * cMonster::GetTarget () +{ + return m_Target; +} + + + + + cMonster * cMonster::NewMonsterFromType(eMonsterType a_MobType) { cFastRandom Random; -- cgit v1.2.3