From 5f5c287cd350694337bfad451b8f235a9ad8e55d Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 17 May 2026 01:12:04 -0300 Subject: [PATCH] feat(Core/Battlefield): Add OnBattlefieldPlayerKill script hook (#25871) Co-authored-by: Claude Sonnet 4.6 --- .../game/Battlefield/Zones/BattlefieldWG.cpp | 16 ++++++++++------ .../ScriptDefines/BattlefieldScript.cpp | 5 +++++ .../Scripting/ScriptDefines/BattlefieldScript.h | 12 ++++++++++++ src/server/game/Scripting/ScriptMgr.h | 1 + 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index f0f9ee4fc..501cd4151 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -21,6 +21,7 @@ #include "AreaDefines.h" #include "BattlefieldWG.h" +#include "ScriptMgr.h" #include "Chat.h" #include "GameTime.h" #include "MapMgr.h" @@ -722,16 +723,19 @@ void BattlefieldWG::HandleKill(Player* killer, Unit* victim) // xinef: tower cannons also grant rank if (victim->IsPlayer() || IsKeepNpc(victim->GetEntry()) || victim->GetEntry() == NPC_WINTERGRASP_TOWER_CANNON) { - if (victim->IsPlayer() && victim->HasAura(SPELL_LIEUTENANT)) + if (Player* victimPlayer = victim->ToPlayer()) { - // Quest - Wintergrasp - PvP Kill - Horde/Alliance - for (ObjectGuid const& playerGuid : PlayersInWar[killerTeam]) + sScriptMgr->OnBattlefieldPlayerKill(this, killer, victimPlayer); + + if (victimPlayer->HasAura(SPELL_LIEUTENANT)) { - if (Player* player = ObjectAccessor::FindPlayer(playerGuid)) + // Quest - Wintergrasp - PvP Kill - Horde/Alliance + for (ObjectGuid const& playerGuid : PlayersInWar[killerTeam]) { - if (player->GetDistance2d(killer) < 40) + if (Player* player = ObjectAccessor::FindPlayer(playerGuid)) { - player->KilledMonsterCredit(killerTeam == TEAM_HORDE ? NPC_QUEST_PVP_KILL_ALLIANCE : NPC_QUEST_PVP_KILL_HORDE); + if (player->GetDistance2d(killer) < 40) + player->KilledMonsterCredit(killerTeam == TEAM_HORDE ? NPC_QUEST_PVP_KILL_ALLIANCE : NPC_QUEST_PVP_KILL_HORDE); } } } diff --git a/src/server/game/Scripting/ScriptDefines/BattlefieldScript.cpp b/src/server/game/Scripting/ScriptDefines/BattlefieldScript.cpp index 18dabf3af..65192a206 100644 --- a/src/server/game/Scripting/ScriptDefines/BattlefieldScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/BattlefieldScript.cpp @@ -49,6 +49,11 @@ void ScriptMgr::OnBattlefieldWarEnd(Battlefield* bf, bool endByTimer) CALL_ENABLED_HOOKS(BattlefieldScript, BATTLEFIELDHOOK_ON_WAR_END, script->OnBattlefieldWarEnd(bf, endByTimer)); } +void ScriptMgr::OnBattlefieldPlayerKill(Battlefield* bf, Player* killer, Player* victim) +{ + CALL_ENABLED_HOOKS(BattlefieldScript, BATTLEFIELDHOOK_ON_PLAYER_KILL, script->OnBattlefieldPlayerKill(bf, killer, victim)); +} + BattlefieldScript::BattlefieldScript(char const* name, std::vector enabledHooks) : ScriptObject(name, BATTLEFIELDHOOK_END) { diff --git a/src/server/game/Scripting/ScriptDefines/BattlefieldScript.h b/src/server/game/Scripting/ScriptDefines/BattlefieldScript.h index df17e570f..512cbc9f3 100644 --- a/src/server/game/Scripting/ScriptDefines/BattlefieldScript.h +++ b/src/server/game/Scripting/ScriptDefines/BattlefieldScript.h @@ -29,6 +29,7 @@ enum BattlefieldHook BATTLEFIELDHOOK_ON_PLAYER_LEAVE_WAR, // 3 - fires after player is removed from the active war BATTLEFIELDHOOK_BEFORE_INVITE_PLAYER_TO_WAR, // 4 - fires in InvitePlayerToWar before InvitedPlayers insert BATTLEFIELDHOOK_ON_WAR_END, // 5 - fires in EndBattle after OnBattleEnd(), before timer reset + BATTLEFIELDHOOK_ON_PLAYER_KILL, // 6 - fires in HandleKill for every player-kills-player event BATTLEFIELDHOOK_END }; @@ -99,6 +100,17 @@ public: * @param endByTimer True if the war ended by the countdown timer expiring */ virtual void OnBattlefieldWarEnd(Battlefield* /*bf*/, bool /*endByTimer*/) { } + + /** + * @brief Called inside BattlefieldWG::HandleKill for every player-kills-player event, + * regardless of the victim's WG rank. Fired before the core's own lieutenant-gated + * quest-credit loop so modules may grant credit for non-lieutenant kills. + * + * @param bf The Battlefield instance + * @param killer The player who landed the killing blow + * @param victim The player who was killed + */ + virtual void OnBattlefieldPlayerKill(Battlefield* /*bf*/, Player* /*killer*/, Player* /*victim*/) { } }; #endif // SCRIPT_OBJECT_BATTLEFIELD_SCRIPT_H_ diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 7d9e42678..7c9015451 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -588,6 +588,7 @@ public: /* BattlefieldScript */ void OnBattlefieldPlayerLeaveWar(Battlefield* bf, Player* player); void OnBattlefieldBeforeInvitePlayerToWar(Battlefield* bf, Player* player); void OnBattlefieldWarEnd(Battlefield* bf, bool endByTimer); + void OnBattlefieldPlayerKill(Battlefield* bf, Player* killer, Player* victim); public: /* BGScript */ void OnBattlegroundStart(Battleground* bg);