1
0

Merge pull request #2193 from nounoursheureux/master

Added HOOK_KILLED
This commit is contained in:
Alexander Harkness 2015-06-13 11:59:07 +01:00
commit ce93cfc34c
9 changed files with 96 additions and 11 deletions

View File

@ -0,0 +1,22 @@
return
{
HOOK_KILLED =
{
CalledWhen = "A player or a mob died.",
DefaultFnName = "OnKilled",
Desc = [[
This hook is called whenever player or a mob dies. It can be used to change the death message.
]]
Params =
{
{ Name = "Victim", Type = "{{cEntity}}", Notes = "The player or mob that died" },
{ Name = "TDI", Type = "{{TakeDamageInfo}}", Notes = "Informations about the death" },
{ Name = "DeathMessage", Type = "string", Notes = "The default death message. An empty string if the victim is not a player" },
},
Returns = [[
The function may return two values. The first value is a boolean specifying whether other plugins should be called. If it is true, the other plugins won't get notified of the death. If it is false, the other plugins will get notified.</p>
<p>The second value is a string containing the death message. If the victim is a player, this death message is broadcasted instead of the default death message. If it is empty, no death message is broadcasted. If it is nil, the message is left unchanged. If the victim is not a player, the death message is never broadcasted.</p>
<p>In either case, the victim is dead.
]],
}, -- HOOK_KILLED
}

View File

@ -7,11 +7,7 @@ return
Desc = [[
This hook is called whenever a {{cPawn|pawn}}'s (a player's or a mob's) health reaches zero. This
means that the pawn is about to be killed, unless a plugin "revives" them by setting their health
back to a positive value.</p>
<p>
FIXME: There is no HOOK_KILLED notification hook yet; this is deliberate because HOOK_KILLED has
been recently renamed to HOOK_KILLING, and plugins need to be updated. Once updated, the HOOK_KILLED
notification will be implemented.
back to a positive value.
]],
Params =
{

View File

@ -64,6 +64,7 @@ public:
virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) = 0;
virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) = 0;
virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) = 0;
virtual bool OnKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) = 0;
virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) = 0;
virtual bool OnLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username) = 0;
virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) = 0;

View File

@ -750,6 +750,30 @@ bool cPluginLua::OnHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper,
bool cPluginLua::OnKilled(cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage)
{
cCSLock Lock(m_CriticalSection);
if (!m_LuaState.IsValid())
{
return false;
}
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_KILLED];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
m_LuaState.Call((int)(**itr), &a_Victim, &a_TDI, a_DeathMessage, cLuaState::Return, res, a_DeathMessage);
if (res)
{
return true;
}
}
return false;
}
bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI)
{
cCSLock Lock(m_CriticalSection);

View File

@ -123,6 +123,7 @@ public:
virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) override;
virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) override;
virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) override;
virtual bool OnKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage) override;
virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) override;
virtual bool OnLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username) override;
virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) override;

View File

@ -675,6 +675,25 @@ bool cPluginManager::CallHookHopperPushingItem(cWorld & a_World, cHopperEntity &
bool cPluginManager::CallHookKilled(cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage)
{
FIND_HOOK(HOOK_KILLED);
VERIFY_HOOK;
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnKilled(a_Victim, a_TDI, a_DeathMessage))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI)
{
FIND_HOOK(HOOK_KILLING);

View File

@ -94,6 +94,7 @@ public:
HOOK_HANDSHAKE,
HOOK_HOPPER_PULLING_ITEM,
HOOK_HOPPER_PUSHING_ITEM,
HOOK_KILLED,
HOOK_KILLING,
HOOK_LOGIN,
HOOK_PLAYER_BREAKING_BLOCK,
@ -211,6 +212,7 @@ public:
bool CallHookHandshake (cClientHandle & a_ClientHandle, const AString & a_Username);
bool CallHookHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum);
bool CallHookHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum);
bool CallHookKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage);
bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI);
bool CallHookLogin (cClientHandle & a_Client, int a_ProtocolVersion, const AString & a_Username);
bool CallHookPlayerAnimation (cPlayer & a_Player, int a_Animation);

View File

@ -744,6 +744,13 @@ void cEntity::KilledBy(TakeDamageInfo & a_TDI)
return;
}
// If the victim is a player the hook is handled by the cPlayer class
if (!IsPlayer())
{
AString emptystring = AString("");
cRoot::Get()->GetPluginManager()->CallHookKilled(*this, a_TDI, emptystring);
}
// Drop loot:
cItems Drops;
GetDrops(Drops, a_TDI.Attacker);

View File

@ -920,11 +920,11 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
{
Pickups.Add(cItem(E_ITEM_RED_APPLE));
}
m_Stats.AddValue(statItemsDropped, (StatValue)Pickups.Size());
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) && m_World->ShouldBroadcastDeathMessages())
{
@ -950,7 +950,12 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
case dtExplosion: DamageText = "blew up"; break;
default: DamageText = "died, somehow; we've no idea how though"; break;
}
GetWorld()->BroadcastChatDeath(Printf("%s %s", GetName().c_str(), DamageText.c_str()));
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 == nullptr) // && !m_World->ShouldBroadcastDeathMessages() by fallthrough
{
@ -959,15 +964,23 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
else if (a_TDI.Attacker->IsPlayer())
{
cPlayer * Killer = (cPlayer *)a_TDI.Attacker;
GetWorld()->BroadcastChatDeath(Printf("%s was killed by %s", GetName().c_str(), Killer->GetName().c_str()));
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")
GetWorld()->BroadcastChatDeath(Printf("%s was killed by a %s", GetName().c_str(), KillerClass.c_str()));
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);
}
}
m_Stats.AddValue(statDeaths);