From 0ad5f1d3451b624a753abf6a9021dd748d3dae91 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 3 Sep 2026 17:21:11 +0000 Subject: [PATCH] fix: skip playerbots so bot re-rolls do not spam the server PlayerbotFactory calls Player::GiveLevel() in six places while randomising a bot, and GiveLevel fires OnPlayerLevelChanged exactly as a real ding does. On a Playerbots realm that means every bot re-roll past level 10/20/.../80 sends a server-wide broadcast plus a raid warning and hands the bot gold and two reward items. Turning off CongratsPerLevel.Enable does not help: the reward-level announcements sit outside that gate. Adds Congrats.SkipBots (default 1). The bot test is guarded by #ifdef MOD_PLAYERBOTS, which the core defines for every module when mod-playerbots is present, so a core built without it is unaffected. Also adds the missing `override` on OnPlayerLogin. The signature already matched the base, so behaviour is unchanged -- it just stops a future signature change from silently detaching the hook. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_019vTNrJGsprcjdjjjDJD5ZM --- conf/mod_congratsonlevel.conf.dist | 9 +++++++++ src/mod_congratsonlevel.cpp | 29 ++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/conf/mod_congratsonlevel.conf.dist b/conf/mod_congratsonlevel.conf.dist index 393b205..7b5483d 100644 --- a/conf/mod_congratsonlevel.conf.dist +++ b/conf/mod_congratsonlevel.conf.dist @@ -19,3 +19,12 @@ Congrats.Announce = 1 # ID Acore String Message Congrats.Acore.String.ID = 60000 + +# Ignore Playerbots entirely? (1: true | 0: false) +# +# PlayerbotFactory calls Player::GiveLevel() whenever it randomises a bot, which fires +# the same level-changed hook a real ding does. With this off, every bot re-roll past a +# reward level broadcasts to the whole server and hands the bot gold and items. +# Has no effect on a core built without mod-playerbots. + +Congrats.SkipBots = 1 diff --git a/src/mod_congratsonlevel.cpp b/src/mod_congratsonlevel.cpp index 265914e..43a4eee 100644 --- a/src/mod_congratsonlevel.cpp +++ b/src/mod_congratsonlevel.cpp @@ -69,15 +69,35 @@ config file for quick modifications. #include "ScriptMgr.h" #include "WorldSessionMgr.h" +#ifdef MOD_PLAYERBOTS +#include "PlayerbotAI.h" +#include "Playerbots.h" +#endif + struct COL { uint32 acoreMessageId; bool congratsAnnounce, congratsEnable; bool CongratsPerLevelEnable; + bool skipBots; }; COL col; +// On a Playerbots server PlayerbotFactory calls Player::GiveLevel() every time it +// randomises a bot, which fires OnPlayerLevelChanged exactly like a real ding. Left +// unchecked that means a server-wide broadcast and a bag of reward items per bot +// re-roll. Bots are skipped by default; set Congrats.SkipBots = 0 to include them. +static bool IsPlayerbot(Player* player) +{ +#ifdef MOD_PLAYERBOTS + return player && GET_PLAYERBOT_AI(player) != nullptr; +#else + (void)player; + return false; +#endif +} + uint32 giveAward(Player* player) { QueryResult result = WorldDatabase.Query("SELECT * FROM `mod_congrats_on_level_items` WHERE `level`={} AND (`race`={} OR `race`=0) AND (`class`={} OR `class`=0)", player->GetLevel(), player->getRace(), player->getClass()); @@ -122,8 +142,11 @@ public: PLAYERHOOK_ON_LOGIN }) {} - void OnPlayerLogin(Player* player) + void OnPlayerLogin(Player* player) override { + if (col.skipBots && IsPlayerbot(player)) + return; + // Announce Module if (col.congratsAnnounce) ChatHandler(player->GetSession()).SendSysMessage(col.acoreMessageId); @@ -140,6 +163,9 @@ public: // Level Up Rewards void OnPlayerLevelChanged(Player* player, uint8 oldLevel) override { + if (col.skipBots && IsPlayerbot(player)) + return; + // If enabled... if (col.congratsEnable) { @@ -297,6 +323,7 @@ public: col.congratsAnnounce = sConfigMgr->GetOption("Congrats.Announce", 1); col.congratsEnable = sConfigMgr->GetOption("Congrats.Enable", 1); col.CongratsPerLevelEnable = sConfigMgr->GetOption("CongratsPerLevel.Enable", 1); + col.skipBots = sConfigMgr->GetOption("Congrats.SkipBots", 1); } } };