summaryrefslogtreecommitdiffstats
path: root/src/Mobs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Mobs')
-rw-r--r--src/Mobs/Wolf.cpp128
-rw-r--r--src/Mobs/Wolf.h17
2 files changed, 109 insertions, 36 deletions
diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp
index 174fee9b1..3be14211b 100644
--- a/src/Mobs/Wolf.cpp
+++ b/src/Mobs/Wolf.cpp
@@ -18,7 +18,8 @@ cWolf::cWolf(void) :
m_IsBegging(false),
m_IsAngry(false),
m_OwnerName(""),
- m_CollarColor(E_META_DYE_ORANGE)
+ m_CollarColor(E_META_DYE_ORANGE),
+ m_NotificationCooldown(0)
{
m_RelativeWalkSpeed = 2;
}
@@ -29,15 +30,42 @@ cWolf::cWolf(void) :
bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
{
+ cEntity * PreviousTarget = m_Target;
if (!super::DoTakeDamage(a_TDI))
{
return false;
}
- if (!m_IsTame)
+ if ((a_TDI.Attacker != nullptr) && a_TDI.Attacker->IsPawn())
{
- m_IsAngry = true;
+ cPawn * Pawn = static_cast<cPawn*>(m_Target);
+ if (Pawn->IsPlayer())
+ {
+ if (m_IsTame)
+ {
+ if ((static_cast<cPlayer*>(Pawn)->GetUUID() == m_OwnerUUID))
+ {
+ m_Target = PreviousTarget; // Do not attack owner
+ }
+ else
+ {
+ SetIsSitting(false);
+ NotifyAlliesOfFight(static_cast<cPawn*>(a_TDI.Attacker));
+ }
+ }
+ else
+ {
+ m_IsAngry = true;
+ }
+ }
+ else if (m_IsTame)
+ {
+ SetIsSitting(false);
+ NotifyAlliesOfFight(static_cast<cPawn*>(a_TDI.Attacker));
+ }
}
+
+
m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face
return true;
}
@@ -46,56 +74,94 @@ bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
+void cWolf::NotifyAlliesOfFight(cPawn * a_Opponent)
+{
+ if (GetOwnerName() == "")
+ {
+ return;
+ }
+ m_NotificationCooldown = 15;
+ class cCallback : public cPlayerListCallback
+ {
+ virtual bool Item(cPlayer * a_Player) override
+ {
+ a_Player->NotifyNearbyWolves(m_Opponent, false);
+ return false;
+ }
+ public:
+ cPawn * m_Opponent;
+ } Callback;
+
+ Callback.m_Opponent = a_Opponent;
+ m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback);
+}
+
bool cWolf::Attack(std::chrono::milliseconds a_Dt)
{
UNUSED(a_Dt);
if ((m_Target != nullptr) && (m_Target->IsPlayer()))
{
- if (static_cast<cPlayer *>(m_Target)->GetName() != m_OwnerName)
- {
- return super::Attack(a_Dt);
- }
- else
+ if (static_cast<cPlayer *>(m_Target)->GetUUID() == m_OwnerUUID)
{
m_Target = nullptr;
+ return false;
}
}
- else
- {
- return super::Attack(a_Dt);
- }
- return false;
+ NotifyAlliesOfFight(static_cast<cPawn*>(m_Target));
+ return super::Attack(a_Dt);
+
}
-void cWolf::NearbyPlayerIsFighting(cPlayer * a_Player, cPawn * a_Opponent)
+void cWolf::ReceiveNearbyFightInfo(AString a_PlayerID, cPawn * a_Opponent, bool a_IsPlayerInvolved)
{
- if (a_Opponent == nullptr)
+ if (
+ (a_Opponent == nullptr) || IsSitting() || (!IsTame()) ||
+ (!a_Opponent->IsPawn()) || (a_PlayerID != m_OwnerUUID)
+ )
{
return;
}
- if ((m_Target == nullptr) && (a_Player->GetName() == m_OwnerName) && !IsSitting() && (a_Opponent->IsPawn()))
+
+ // If we already have a target
+ if (m_Target != nullptr)
{
- m_Target = a_Opponent;
- if (m_Target->IsPlayer() && static_cast<cPlayer *>(m_Target)->GetName() == m_OwnerName)
+ // If a wolf is asking for help and we already have a target, do nothing
+ if (!a_IsPlayerInvolved)
{
- m_Target = nullptr; // Our owner has hurt himself, avoid attacking them.
+ return;
}
- if (m_Target->IsMob() && static_cast<cMonster *>(m_Target)->GetMobType() == mtWolf)
+ // If a player is asking for help and we already have a target,
+ // there's a 50% chance of helping and a 50% chance of doing nothing
+ // This helps spread a wolf pack's targets over several mobs
+ else if (m_World->GetTickRandomNumber(9)> 4)
{
- cWolf * Wolf = static_cast<cWolf *>(m_Target);
- if (Wolf->GetOwnerUUID() == GetOwnerUUID())
- {
- m_Target = nullptr; // Our owner attacked one of their wolves. Abort attacking wolf.
- }
+ return;
}
}
+ if (a_Opponent->IsPlayer() && static_cast<cPlayer *>(a_Opponent)->GetUUID() == m_OwnerUUID)
+ {
+ return; // Our owner has hurt himself, avoid attacking them.
+ }
+
+ if (a_Opponent->IsMob() && static_cast<cMonster *>(a_Opponent)->GetMobType() == mtWolf)
+ {
+ cWolf * Wolf = static_cast<cWolf *>(a_Opponent);
+ if (Wolf->GetOwnerUUID() == GetOwnerUUID())
+ {
+ return; // Our owner attacked one of their wolves. Abort attacking wolf.
+ }
+ }
+
+ m_Target = a_Opponent;
+
+
}
@@ -156,7 +222,7 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
}
case E_ITEM_DYE:
{
- if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog?
+ if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog?
{
SetCollarColor(a_Player.GetEquippedItem().m_ItemDamage);
if (!a_Player.IsGameModeCreative())
@@ -168,7 +234,7 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
}
default:
{
- if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog?
+ if (a_Player.GetUUID() == m_OwnerUUID) // Is the player the owner of the dog?
{
SetIsSitting(!IsSitting());
}
@@ -188,6 +254,10 @@ void cWolf::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
if (!IsAngry())
{
cMonster::Tick(a_Dt, a_Chunk);
+ if (m_NotificationCooldown > 0)
+ {
+ m_NotificationCooldown -= 1;
+ }
}
else
{
@@ -275,13 +345,13 @@ void cWolf::TickFollowPlayer()
virtual bool Item(cPlayer * a_Player) override
{
OwnerPos = a_Player->GetPosition();
- return false;
+ return true;
}
public:
Vector3d OwnerPos;
} Callback;
- if (m_World->DoWithPlayer(m_OwnerName, Callback))
+ if (m_World->DoWithPlayerByUUID(m_OwnerUUID, Callback))
{
// The player is present in the world, follow him:
double Distance = (Callback.OwnerPos - GetPosition()).Length();
diff --git a/src/Mobs/Wolf.h b/src/Mobs/Wolf.h
index 90d38f15c..70e761469 100644
--- a/src/Mobs/Wolf.h
+++ b/src/Mobs/Wolf.h
@@ -18,6 +18,7 @@ public:
CLASS_PROTODEF(cWolf)
+ void NotifyAlliesOfFight(cPawn * a_Opponent);
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
@@ -45,13 +46,14 @@ public:
m_OwnerUUID = a_NewOwnerUUID;
}
- /** Notfies the wolf that the player a_Player is being attacked by a_Attacker.
- The wolf will then defend the player by attacking a_Attacker if all these conditions are met:
- - a_Player is the wolf's owner.
- - The wolf is not already attacking a mob.
- - The wolf is not sitting.
- This is called by cPlayer::NotifyFriendlyWolves whenever a player takes or deals damage and a wolf is nearby. */
- void NearbyPlayerIsFighting(cPlayer * a_Player, cPawn * a_Opponent);
+ /** Notfies the wolf of a nearby fight.
+ The wolf may then decide to attack a_Opponent.
+ If a_IsPlayer is true, then the player whose ID is a_PlayerID is fighting a_Opponent
+ If false, then a wolf owned by the player whose ID is a_PlayerID is fighting a_Opponent
+ @param a_PlayerID The ID of the fighting player, or the ID of the owner whose wolf is fighting.
+ @param a_Opponent The opponent who is being faught.
+ @param a_IsPlayerInvolved Whether the fighter a player or a wolf. */
+ void ReceiveNearbyFightInfo(AString a_PlayerID, cPawn * a_Opponent, bool a_IsPlayerInvolved);
virtual void InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
@@ -64,6 +66,7 @@ protected:
AString m_OwnerName;
AString m_OwnerUUID;
int m_CollarColor;
+ int m_NotificationCooldown;
} ;