From 65dacb0de7b47cee70677856cf4561f0c0402c05 Mon Sep 17 00:00:00 2001 From: SylvaniaCore deploy Date: Sun, 16 Aug 2026 00:15:23 +0200 Subject: [PATCH] =?UTF-8?q?Titre=20=C2=AB=20Mercenaire=20=C2=BB=20obligato?= =?UTF-8?q?ire=20sur=20tous=20les=20playerbots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CharTitles.db2 (7.3.5) ne contient aucun titre « Mercenaire » : 364 entrees, ID max 522, MaskID max 373. On cree donc l entree custom 600 / MaskID 380 dans la table `char_titles` de la base hotfix, poussee au client par une ligne `hotfix_data` (TableHash CharTitles = 0x85DF9E8E). PlayerBotMgr::ApplyBotTitle() accorde puis selectionne ce titre a chaque connexion de bot, depuis OnPlayerBotLogin(). Un bot ne peut donc pas s en defaire, et les vrais joueurs les reconnaissent d un coup d oeil. Cle de configuration pbottitle (600 par defaut, 0 = aucun titre force). Co-Authored-By: Claude Opus 5 --- sql/sylvania/mercenary_title.sql | 20 +++++++++++ src/server/game/PlayerBot/PlayerBotMgr.cpp | 36 ++++++++++++++++++++ src/server/game/PlayerBot/PlayerBotMgr.h | 1 + src/server/worldserver/worldserver.conf.dist | 12 +++++++ 4 files changed, 69 insertions(+) create mode 100644 sql/sylvania/mercenary_title.sql diff --git a/sql/sylvania/mercenary_title.sql b/sql/sylvania/mercenary_title.sql new file mode 100644 index 0000000..2b33dbe --- /dev/null +++ b/sql/sylvania/mercenary_title.sql @@ -0,0 +1,20 @@ +-- ===================================================================== +-- Sylvania Legion — Titre custom « Mercenaire » pour les PlayerBots +-- Base : dc_hotfixes +-- +-- CharTitles.db2 (7.3.5, build 26972) : 364 enregistrements, +-- ID max = 522, MaskID max = 373. MAX_TITLE_INDEX du core = 384. +-- On prend donc un ID hors plage Blizzard (600) et un MaskID libre (380). +-- +-- La ligne hotfix_data est indispensable : c'est elle qui pousse +-- l'enregistrement au client (SMSG_AVAILABLE_HOTFIXES -> CMSG_HOTFIX_REQUEST). +-- TableHash CharTitles = 0x85DF9E8E = 2246024846. +-- ===================================================================== + +DELETE FROM `char_titles` WHERE `ID` = 600; +INSERT INTO `char_titles` (`ID`, `Name`, `Name1`, `MaskID`, `Flags`, `VerifiedBuild`) VALUES +(600, 'Mercenaire %s', 'Mercenaire %s', 380, 0, 0); + +DELETE FROM `hotfix_data` WHERE `TableHash` = 2246024846 AND `RecordId` = 600; +INSERT INTO `hotfix_data` (`TableHash`, `RecordId`, `Deleted`) VALUES +(2246024846, 600, 0); diff --git a/src/server/game/PlayerBot/PlayerBotMgr.cpp b/src/server/game/PlayerBot/PlayerBotMgr.cpp index 1c3d348..65e3de7 100644 --- a/src/server/game/PlayerBot/PlayerBotMgr.cpp +++ b/src/server/game/PlayerBot/PlayerBotMgr.cpp @@ -1194,9 +1194,45 @@ void PlayerBotMgr::OnAccountBotDelete(ObjectGuid& guid, uint32 accountId) pInfo->RemoveCharacterByGUID(guid); } +// Titre obligatoire des playerbots. +// Tous les bots portent le titre custom « Mercenaire » (CharTitles 600 / +// MaskID 380, pousse au client par la table hotfix `char_titles`), afin que +// les vrais joueurs les distinguent d'un coup d'oeil. Le titre est accorde +// puis selectionne a chaque connexion : un bot ne peut donc pas s'en defaire. +void PlayerBotMgr::ApplyBotTitle(Player* pPlayer) +{ + if (!pPlayer) + return; + + uint32 titleId = uint32(sConfigMgr->GetIntDefault("pbottitle", 600)); + if (!titleId) + return; + + CharTitlesEntry const* title = sCharTitlesStore.LookupEntry(titleId); + if (!title) + { + static bool s_titleWarned = false; + if (!s_titleWarned) + { + s_titleWarned = true; + TC_LOG_ERROR("server.loading", "PlayerBotMgr: titre de bot %u absent de CharTitles - verifier la table `char_titles` de la base hotfix", titleId); + } + return; + } + + if (!pPlayer->HasTitle(title)) + pPlayer->SetTitle(title); + + if (pPlayer->GetUInt32Value(PLAYER_CHOSEN_TITLE) != uint32(title->MaskID)) + pPlayer->SetUInt32Value(PLAYER_CHOSEN_TITLE, uint32(title->MaskID)); +} + void PlayerBotMgr::OnPlayerBotLogin(WorldSession* pSession, Player* pPlayer) { ++m_BotOnlineCount; + + ApplyBotTitle(pPlayer); + Group* pGroup = pPlayer->GetGroup(); if (pGroup) { diff --git a/src/server/game/PlayerBot/PlayerBotMgr.h b/src/server/game/PlayerBot/PlayerBotMgr.h index 55ec622..49b762c 100644 --- a/src/server/game/PlayerBot/PlayerBotMgr.h +++ b/src/server/game/PlayerBot/PlayerBotMgr.h @@ -325,6 +325,7 @@ public: void OnAccountBotCreate(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level); void OnAccountBotDelete(ObjectGuid& guid, uint32 accountId); void OnPlayerBotLogin(WorldSession* pSession, Player* pPlayer); + void ApplyBotTitle(Player* pPlayer); void OnPlayerBotLogout(WorldSession* pSession); void OnPlayerBotLeaveOriginalGroup(Player* pPlayer); void LoginGroupBotByPlayer(Player* pPlayer); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 3484a7b..7e1df3b 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -4653,6 +4653,18 @@ pbotbg_idlelogout = 300 pbotasl = 88 +# +# pbottitle +# Description: ID CharTitles du titre porte obligatoirement par tous les +# playerbots, pour les distinguer des vrais joueurs. +# 600 = « Mercenaire », entree custom fournie par la table +# `char_titles` de la base hotfix (MaskID 380). +# Default: 600 - (titre Mercenaire) +# 0 - (aucun titre force) + +pbottitle = 600 + + # #################################################################################################### ###################################################################################################