summaryrefslogtreecommitdiffstats
path: root/src/Mobs/Monster.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Mobs/Monster.cpp121
1 files changed, 94 insertions, 27 deletions
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<cPlayer *>(m_Target)->IsGameModeCreative())
+ if (static_cast<cPlayer *>(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<cPlayer *>(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<cPawn*>(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<cPawn*>(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;