summaryrefslogtreecommitdiffstats
path: root/src/Mobs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Mobs')
-rw-r--r--src/Mobs/AggressiveMonster.cpp12
-rw-r--r--src/Mobs/Blaze.cpp2
-rw-r--r--src/Mobs/CaveSpider.cpp6
-rw-r--r--src/Mobs/Creeper.cpp2
-rw-r--r--src/Mobs/Enderman.cpp2
-rw-r--r--src/Mobs/Ghast.cpp2
-rw-r--r--src/Mobs/Monster.cpp121
-rw-r--r--src/Mobs/Monster.h21
-rw-r--r--src/Mobs/PassiveAggressiveMonster.cpp4
-rw-r--r--src/Mobs/Skeleton.cpp4
-rw-r--r--src/Mobs/Wolf.cpp33
11 files changed, 145 insertions, 64 deletions
diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp
index 512bfb4a1..c67f01b8f 100644
--- a/src/Mobs/AggressiveMonster.cpp
+++ b/src/Mobs/AggressiveMonster.cpp
@@ -26,9 +26,9 @@ void cAggressiveMonster::InStateChasing(std::chrono::milliseconds a_Dt, cChunk &
{
super::InStateChasing(a_Dt, a_Chunk);
- if (m_Target != nullptr)
+ if (GetTarget() != nullptr)
{
- MoveToPosition(m_Target->GetPosition());
+ MoveToPosition(GetTarget()->GetPosition());
}
}
@@ -62,14 +62,14 @@ void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
CheckEventSeePlayer(a_Chunk);
}
- if (m_Target == nullptr)
+ if (GetTarget() == nullptr)
{
return;
}
cTracer LineOfSight(GetWorld());
Vector3d MyHeadPosition = GetPosition() + Vector3d(0, GetHeight(), 0);
- Vector3d AttackDirection(m_Target->GetPosition() + Vector3d(0, m_Target->GetHeight(), 0) - MyHeadPosition);
+ Vector3d AttackDirection(GetTarget()->GetPosition() + Vector3d(0, GetTarget()->GetHeight(), 0) - MyHeadPosition);
if (TargetIsInRange() && !LineOfSight.Trace(MyHeadPosition, AttackDirection, static_cast<int>(AttackDirection.Length())) && (GetHealth() > 0.0))
@@ -85,14 +85,14 @@ void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
bool cAggressiveMonster::Attack(std::chrono::milliseconds a_Dt)
{
- if ((m_Target == nullptr) || (m_AttackCoolDownTicksLeft != 0))
+ if ((GetTarget() == nullptr) || (m_AttackCoolDownTicksLeft != 0))
{
return false;
}
// Setting this higher gives us more wiggle room for attackrate
ResetAttackCooldown();
- m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0);
+ GetTarget()->TakeDamage(dtMobAttack, this, m_AttackDamage, 0);
return true;
}
diff --git a/src/Mobs/Blaze.cpp b/src/Mobs/Blaze.cpp
index bd3b3f776..d002e14e7 100644
--- a/src/Mobs/Blaze.cpp
+++ b/src/Mobs/Blaze.cpp
@@ -34,7 +34,7 @@ void cBlaze::GetDrops(cItems & a_Drops, cEntity * a_Killer)
bool cBlaze::Attack(std::chrono::milliseconds a_Dt)
{
- if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0))
+ if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0))
{
// Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20;
diff --git a/src/Mobs/CaveSpider.cpp b/src/Mobs/CaveSpider.cpp
index ee3f4803c..2a4975126 100644
--- a/src/Mobs/CaveSpider.cpp
+++ b/src/Mobs/CaveSpider.cpp
@@ -33,11 +33,11 @@ bool cCaveSpider::Attack(std::chrono::milliseconds a_Dt)
{
return false;
}
-
- if (m_Target->IsPawn())
+
+ if (GetTarget()->IsPawn())
{
// TODO: Easy = no poison, Medium = 7 seconds, Hard = 15 seconds
- static_cast<cPawn *>(m_Target)->AddEntityEffect(cEntityEffect::effPoison, 7 * 20, 0);
+ static_cast<cPawn *>(GetTarget())->AddEntityEffect(cEntityEffect::effPoison, 7 * 20, 0);
}
return true;
}
diff --git a/src/Mobs/Creeper.cpp b/src/Mobs/Creeper.cpp
index d88c99953..47d294a30 100644
--- a/src/Mobs/Creeper.cpp
+++ b/src/Mobs/Creeper.cpp
@@ -27,7 +27,7 @@ void cCreeper::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
- if ((m_Target == nullptr) || (!TargetIsInRange() && !m_BurnedWithFlintAndSteel))
+ if ((GetTarget() == nullptr) || (!TargetIsInRange() && !m_BurnedWithFlintAndSteel))
{
if (m_bIsBlowing)
{
diff --git a/src/Mobs/Enderman.cpp b/src/Mobs/Enderman.cpp
index 4a30a0acd..ccfd44110 100644
--- a/src/Mobs/Enderman.cpp
+++ b/src/Mobs/Enderman.cpp
@@ -104,7 +104,7 @@ void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cEnderman::CheckEventSeePlayer(cChunk & a_Chunk)
{
- if (m_Target != nullptr)
+ if (GetTarget() != nullptr)
{
return;
}
diff --git a/src/Mobs/Ghast.cpp b/src/Mobs/Ghast.cpp
index 61813d0fe..0544255df 100644
--- a/src/Mobs/Ghast.cpp
+++ b/src/Mobs/Ghast.cpp
@@ -34,7 +34,7 @@ void cGhast::GetDrops(cItems & a_Drops, cEntity * a_Killer)
bool cGhast::Attack(std::chrono::milliseconds a_Dt)
{
- if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0))
+ if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0))
{
// Setting this higher gives us more wiggle room for attackrate
Vector3d Speed = GetLookVector() * 20;
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;
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index 7c4683942..2155a4a7c 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -44,6 +44,10 @@ public:
*/
cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height);
+ ~cMonster();
+
+ virtual void Destroyed() override;
+
CLASS_PROTODEF(cMonster)
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
@@ -156,6 +160,16 @@ public:
// tolua_end
+ /** Sets the target that this mob will chase. Pass a nullptr to unset. */
+ void SetTarget (cPawn * a_NewTarget);
+
+ /** Unset the target without notifying the target entity. Do not use this, use SetTarget(nullptr) instead.
+ This is only used by cPawn internally. */
+ void UnsafeUnsetTarget();
+
+ /** Returns the current target. */
+ cPawn * GetTarget ();
+
/** Creates a new object of the specified mob.
a_MobType is the type of the mob to be created
Asserts and returns null if mob type is not specified
@@ -164,9 +178,6 @@ public:
protected:
- /** A pointer to the entity this mobile is aiming to reach */
- cEntity * m_Target;
-
/** The pathfinder instance handles pathfinding for this monster. */
cPathFinder m_PathFinder;
@@ -255,4 +266,8 @@ protected:
/** Adds weapon that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if picked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop */
void AddRandomWeaponDropItem(cItems & a_Drops, unsigned int a_LootingLevel);
+private:
+ /** A pointer to the entity this mobile is aiming to reach */
+ cPawn * m_Target;
+
} ; // tolua_export
diff --git a/src/Mobs/PassiveAggressiveMonster.cpp b/src/Mobs/PassiveAggressiveMonster.cpp
index 71ac7bd89..a1bb1138f 100644
--- a/src/Mobs/PassiveAggressiveMonster.cpp
+++ b/src/Mobs/PassiveAggressiveMonster.cpp
@@ -26,9 +26,9 @@ bool cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
return false;
}
- if ((m_Target != nullptr) && (m_Target->IsPlayer()))
+ if ((GetTarget() != nullptr) && (GetTarget()->IsPlayer()))
{
- if (!static_cast<cPlayer *>(m_Target)->IsGameModeCreative())
+ if (!static_cast<cPlayer *>(GetTarget())->IsGameModeCreative())
{
m_EMState = CHASING;
}
diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp
index adad543d2..7697f1279 100644
--- a/src/Mobs/Skeleton.cpp
+++ b/src/Mobs/Skeleton.cpp
@@ -52,10 +52,10 @@ bool cSkeleton::Attack(std::chrono::milliseconds a_Dt)
{
StopMovingToPosition(); // Todo handle this in a better way, the skeleton does some uneeded recalcs due to inStateChasing
cFastRandom Random;
- if ((m_Target != nullptr) && (m_AttackCoolDownTicksLeft == 0))
+ if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0))
{
Vector3d Inaccuracy = Vector3d(Random.NextFloat(0.5) - 0.25, Random.NextFloat(0.5) - 0.25, Random.NextFloat(0.5) - 0.25);
- Vector3d Speed = (m_Target->GetPosition() + Inaccuracy - GetPosition()) * 5;
+ Vector3d Speed = (GetTarget()->GetPosition() + Inaccuracy - GetPosition()) * 5;
Speed.y = Speed.y - 1 + Random.NextInt(3);
cArrowEntity * Arrow = new cArrowEntity(this, GetPosX(), GetPosY() + 1, GetPosZ(), Speed);
if (Arrow == nullptr)
diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp
index 3be14211b..d188d91eb 100644
--- a/src/Mobs/Wolf.cpp
+++ b/src/Mobs/Wolf.cpp
@@ -30,7 +30,7 @@ cWolf::cWolf(void) :
bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- cEntity * PreviousTarget = m_Target;
+ cPawn * PreviousTarget = GetTarget();
if (!super::DoTakeDamage(a_TDI))
{
return false;
@@ -38,14 +38,13 @@ bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn())
{
- cPawn * Pawn = static_cast<cPawn*>(m_Target);
- if (Pawn->IsPlayer())
+ if (GetTarget()->IsPlayer())
{
if (m_IsTame)
{
- if ((static_cast<cPlayer*>(Pawn)->GetUUID() == m_OwnerUUID))
+ if ((static_cast<cPlayer*>(GetTarget())->GetUUID() == m_OwnerUUID))
{
- m_Target = PreviousTarget; // Do not attack owner
+ SetTarget(PreviousTarget); // Do not attack owner
}
else
{
@@ -100,16 +99,16 @@ bool cWolf::Attack(std::chrono::milliseconds a_Dt)
{
UNUSED(a_Dt);
- if ((m_Target != nullptr) && (m_Target->IsPlayer()))
+ if ((GetTarget() != nullptr) && (GetTarget()->IsPlayer()))
{
- if (static_cast<cPlayer *>(m_Target)->GetUUID() == m_OwnerUUID)
+ if (static_cast<cPlayer *>(GetTarget())->GetUUID() == m_OwnerUUID)
{
- m_Target = nullptr;
+ SetTarget(nullptr);
return false;
}
}
- NotifyAlliesOfFight(static_cast<cPawn*>(m_Target));
+ NotifyAlliesOfFight(static_cast<cPawn*>(GetTarget()));
return super::Attack(a_Dt);
}
@@ -129,7 +128,7 @@ void cWolf::ReceiveNearbyFightInfo(AString a_PlayerID, cPawn * a_Opponent, bool
}
// If we already have a target
- if (m_Target != nullptr)
+ if (GetTarget() != nullptr)
{
// If a wolf is asking for help and we already have a target, do nothing
if (!a_IsPlayerInvolved)
@@ -159,7 +158,7 @@ void cWolf::ReceiveNearbyFightInfo(AString a_PlayerID, cPawn * a_Opponent, bool
}
}
- m_Target = a_Opponent;
+ SetTarget(a_Opponent);
}
@@ -264,7 +263,7 @@ void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
super::Tick(a_Dt, a_Chunk);
}
- if (m_Target == nullptr)
+ if (GetTarget() == nullptr)
{
cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance));
if (a_Closest_Player != nullptr)
@@ -311,11 +310,11 @@ void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
if (IsSitting())
{
- m_Target = nullptr;
+ SetTarget(nullptr);
}
else
{
- MoveToPosition(m_Target->GetPosition());
+ MoveToPosition(GetTarget()->GetPosition());
if (TargetIsInRange())
{
Attack(a_Dt);
@@ -359,18 +358,18 @@ void cWolf::TickFollowPlayer()
{
Callback.OwnerPos.y = FindFirstNonAirBlockPosition(Callback.OwnerPos.x, Callback.OwnerPos.z);
TeleportToCoords(Callback.OwnerPos.x, Callback.OwnerPos.y, Callback.OwnerPos.z);
- m_Target = nullptr;
+ SetTarget(nullptr);
}
if (Distance < 2)
{
- if (m_Target == nullptr)
+ if (GetTarget() == nullptr)
{
StopMovingToPosition();
}
}
else
{
- if (m_Target == nullptr)
+ if (GetTarget() == nullptr)
{
MoveToPosition(Callback.OwnerPos);
}