From 3b35a00397d7919b0613be8f6f756beabad53edc Mon Sep 17 00:00:00 2001 From: TheHyper45 <86074167+TheHyper45@users.noreply.github.com> Date: Sat, 19 Jun 2021 22:25:24 +0100 Subject: Death messages for tamed pets and ocelots are now tamable. (#5243) * Fixing bugs regarding wolfs and ocelots * Death messages appear after killing tamed ocelots and wolfs * Style fix * Added myself to the CONTRIBUTORS file * Removed redundant string initialization * Removed an unsafe cast. * Changed the order of initialization of fields in constuctor of class cOcelot --- CONTRIBUTORS | 1 + src/Entities/Entity.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ src/Entities/Entity.h | 2 + src/Entities/Player.cpp | 59 +--------------------------- src/Mobs/Monster.cpp | 9 +++++ src/Mobs/Ocelot.cpp | 1 + src/Mobs/Wolf.cpp | 1 + 7 files changed, 115 insertions(+), 58 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index f1dec6c97..e6a1fa7ec 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -72,6 +72,7 @@ structinf (xdot) sweetgiorni Sxw1212 Taugeshtu +TheHyper45 theophriene tigerw (Tiger Wang) tonibm19 diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 5c79e58d1..a3388a18f 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -2285,3 +2285,103 @@ void cEntity::BroadcastLeashedMobs() } } } + + + + + +void cEntity::BroadcastDeathMessage(TakeDamageInfo & a_TDI) +{ + cPluginManager * PluginManager = cRoot::Get()->GetPluginManager(); + + AString Name; + if (IsPlayer()) + { + cPlayer * Player = static_cast(this); + Name = Player->GetName(); + } + else if (IsMob()) + { + cMonster * Monster = static_cast(this); + if (Monster->HasCustomName()) + { + Name = Monster->GetCustomName(); + } + else + { + // Tamed ocelots are really cats in vanilla. + if (Monster->IsTame() && (Monster->GetClass() == AString("cOcelot"))) + { + Name = "Cat"; + } + else + { + Name = Monster->GetClass(); + Name.erase(Name.begin()); // Erase the 'c' of the class (e.g. "cWitch" -> "Witch") + } + } + } + else + { + // If the entity is neither a player nor a mob, we should quit. + return; + } + + if (a_TDI.Attacker == nullptr) + { + const AString DamageText = [&] + { + switch (a_TDI.DamageType) + { + case dtRangedAttack: return "was shot"; + case dtLightning: return "was plasmified by lightining"; + case dtFalling: return GetRandomProvider().RandBool() ? "fell to death" : "hit the ground too hard"; + case dtDrowning: return "drowned"; + case dtSuffocating: return GetRandomProvider().RandBool() ? "git merge'd into a block" : "fused with a block"; + case dtStarving: return "forgot the importance of food"; + case dtCactusContact: return "was impaled on a cactus"; + case dtMagmaContact: return "discovered the floor was lava"; + case dtLavaContact: return "was melted by lava"; + case dtPoisoning: return "died from septicaemia"; + case dtWithering: return "is a husk of their former selves"; + case dtOnFire: return "forgot to stop, drop, and roll"; + case dtFireContact: return "burnt themselves to death"; + case dtInVoid: return "somehow fell out of the world"; + case dtPotionOfHarming: return "was magicked to death"; + case dtEnderPearl: return "misused an ender pearl"; + case dtAdmin: return "was administrator'd"; + case dtExplosion: return "blew up"; + case dtAttack: return "was attacked by thin air"; + case dtEnvironment: return "played too much dress up"; // This is not vanilla - added a own pun + } + UNREACHABLE("Unsupported damage type"); + }(); + AString DeathMessage = Printf("%s %s", Name.c_str(), DamageText.c_str()); + PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); + if (DeathMessage != AString("")) + { + GetWorld()->BroadcastChatDeath(DeathMessage); + } + } + else if (a_TDI.Attacker->IsPlayer()) + { + cPlayer * Killer = static_cast(a_TDI.Attacker); + AString DeathMessage = Printf("%s was killed by %s", Name.c_str(), Killer->GetName().c_str()); + PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); + if (DeathMessage != AString("")) + { + GetWorld()->BroadcastChatDeath(DeathMessage); + } + } + else + { + AString KillerClass = a_TDI.Attacker->GetClass(); + KillerClass.erase(KillerClass.begin()); // Erase the 'c' of the class (e.g. "cWitch" -> "Witch") + AString DeathMessage = Printf("%s was killed by a %s", Name.c_str(), KillerClass.c_str()); + PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); + if (DeathMessage != AString("")) + { + GetWorld()->BroadcastChatDeath(DeathMessage); + } + } +} diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index af80d0687..1384870b8 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -550,6 +550,8 @@ public: /** Returs whether the entity has any mob leashed to it. */ bool HasAnyMobLeashed() const { return m_LeashedMobs.size() > 0; } + /** Announces a death message on chat about killing the entity. */ + void BroadcastDeathMessage(TakeDamageInfo & a_TDI); protected: diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 235433cf8..fcdbcf64c 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -863,65 +863,8 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI) m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10); SaveToDisk(); // Save it, yeah the world is a tough place ! - cPluginManager * PluginManager = cRoot::Get()->GetPluginManager(); - if (a_TDI.Attacker == nullptr) - { - const AString DamageText = [&] - { - switch (a_TDI.DamageType) - { - case dtRangedAttack: return "was shot"; - case dtLightning: return "was plasmified by lightining"; - case dtFalling: return GetRandomProvider().RandBool() ? "fell to death" : "hit the ground too hard"; - case dtDrowning: return "drowned"; - case dtSuffocating: return GetRandomProvider().RandBool() ? "git merge'd into a block" : "fused with a block"; - case dtStarving: return "forgot the importance of food"; - case dtCactusContact: return "was impaled on a cactus"; - case dtMagmaContact: return "discovered the floor was lava"; - case dtLavaContact: return "was melted by lava"; - case dtPoisoning: return "died from septicaemia"; - case dtWithering: return "is a husk of their former selves"; - case dtOnFire: return "forgot to stop, drop, and roll"; - case dtFireContact: return "burnt themselves to death"; - case dtInVoid: return "somehow fell out of the world"; - case dtPotionOfHarming: return "was magicked to death"; - case dtEnderPearl: return "misused an ender pearl"; - case dtAdmin: return "was administrator'd"; - case dtExplosion: return "blew up"; - case dtAttack: return "was attacked by thin air"; - case dtEnvironment: return "played too much dress up"; // This is not vanilla - added a own pun - } - UNREACHABLE("Unsupported damage type"); - }(); - AString DeathMessage = Printf("%s %s", GetName().c_str(), DamageText.c_str()); - PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); - if (DeathMessage != AString("")) - { - GetWorld()->BroadcastChatDeath(DeathMessage); - } - } - else if (a_TDI.Attacker->IsPlayer()) - { - cPlayer * Killer = static_cast(a_TDI.Attacker); - AString DeathMessage = Printf("%s was killed by %s", GetName().c_str(), Killer->GetName().c_str()); - PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); - if (DeathMessage != AString("")) - { - GetWorld()->BroadcastChatDeath(DeathMessage); - } - } - else - { - AString KillerClass = a_TDI.Attacker->GetClass(); - KillerClass.erase(KillerClass.begin()); // Erase the 'c' of the class (e.g. "cWitch" -> "Witch") - AString DeathMessage = Printf("%s was killed by a %s", GetName().c_str(), KillerClass.c_str()); - PluginManager->CallHookKilled(*this, a_TDI, DeathMessage); - if (DeathMessage != AString("")) - { - GetWorld()->BroadcastChatDeath(DeathMessage); - } - } + BroadcastDeathMessage(a_TDI); m_Stats.Custom[CustomStatistic::Deaths]++; m_Stats.Custom[CustomStatistic::TimeSinceDeath] = 0; diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 447e66261..d99f2cddc 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -605,6 +605,15 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI) { m_World->BroadcastSoundEffect(m_SoundDeath, GetPosition(), 1.0f, 0.8f); } + + if (IsTame()) + { + if ((m_MobType == mtWolf) || (m_MobType == mtOcelot) || (m_MobType == mtCat) || (m_MobType == mtParrot)) + { + BroadcastDeathMessage(a_TDI); + } + } + int Reward; switch (m_MobType) { diff --git a/src/Mobs/Ocelot.cpp b/src/Mobs/Ocelot.cpp index e095e827a..a3c505e96 100644 --- a/src/Mobs/Ocelot.cpp +++ b/src/Mobs/Ocelot.cpp @@ -26,6 +26,7 @@ cOcelot::cOcelot(void) : m_IsTame(false), m_IsBegging(false), m_CatType(ctWildOcelot), + m_CheckPlayerTickCount(), m_OwnerName() { } diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 0a3a12ea7..2b45faa2b 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -166,6 +166,7 @@ void cWolf::ReceiveNearbyFightInfo(const cUUID & a_PlayerID, cPawn * a_Opponent, void cWolf::OnRightClicked(cPlayer & a_Player) { + cMonster::OnRightClicked(a_Player); const cItem & EquippedItem = a_Player.GetEquippedItem(); const int EquippedItemType = EquippedItem.m_ItemType; -- cgit v1.2.3