From 531da1d0b4bd04bfe22cba0c3dd6a1d5cadfa1bf Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:30:02 -0300 Subject: [PATCH] feat(Scripts/Commands): allow achievement add from console for offline players (#25283) Co-authored-by: Claude Opus 4.6 --- .../rev_achievement_add_strings.sql | 5 ++++ src/server/game/Miscellaneous/Language.h | 6 ++++- .../scripts/Commands/cs_achievement.cpp | 26 ++++++++++++++----- 3 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_achievement_add_strings.sql diff --git a/data/sql/updates/pending_db_world/rev_achievement_add_strings.sql b/data/sql/updates/pending_db_world/rev_achievement_add_strings.sql new file mode 100644 index 000000000..fbe386a68 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_achievement_add_strings.sql @@ -0,0 +1,5 @@ +-- Achievement add command feedback strings +DELETE FROM `acore_string` WHERE `entry` IN (30126, 30127); +INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES +(30126, 'Achievement {} ({}) added to player {}.', '업적 {} ({})이(가) 플레이어 {}에게 추가되었습니다.', 'Le haut fait {} ({}) a été ajouté au joueur {}.', 'Erfolg {} ({}) wurde Spieler {} hinzugefügt.', '成就 {} ({}) 已添加给玩家 {}。', '成就 {} ({}) 已新增給玩家 {}。', 'El logro {} ({}) ha sido añadido al jugador {}.', 'El logro {} ({}) ha sido añadido al jugador {}.', 'Достижение {} ({}) добавлено игроку {}.'), +(30127, 'Achievement {} ({}) will be added to player {} on next login.', '업적 {} ({})이(가) 다음 로그인 시 플레이어 {}에게 추가됩니다.', 'Le haut fait {} ({}) sera ajouté au joueur {} à la prochaine connexion.', 'Erfolg {} ({}) wird Spieler {} beim nächsten Login hinzugefügt.', '成就 {} ({}) 将在玩家 {} 下次登录时添加。', '成就 {} ({}) 將在玩家 {} 下次登入時新增。', 'El logro {} ({}) será añadido al jugador {} en el próximo inicio de sesión.', 'El logro {} ({}) será añadido al jugador {} en el próximo inicio de sesión.', 'Достижение {} ({}) будет добавлено игроку {} при следующем входе.'); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 5fc80fca9..2172cf6ec 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1445,6 +1445,10 @@ enum AcoreStrings LANG_DEBUG_FACTIONCHANGE_GOLD_FAIL = 30122, LANG_DEBUG_FACTIONCHANGE_GOLD_OK = 30123, LANG_DEBUG_FACTIONCHANGE_GOLD_NOLIMIT = 30124, - LANG_DEBUG_FACTIONCHANGE_NA = 30125 + LANG_DEBUG_FACTIONCHANGE_NA = 30125, + + // Achievement commands + LANG_ACHIEVEMENT_ADD_ONLINE = 30126, + LANG_ACHIEVEMENT_ADD_OFFLINE = 30127 }; #endif diff --git a/src/server/scripts/Commands/cs_achievement.cpp b/src/server/scripts/Commands/cs_achievement.cpp index be1ea77f2..8557f46ae 100644 --- a/src/server/scripts/Commands/cs_achievement.cpp +++ b/src/server/scripts/Commands/cs_achievement.cpp @@ -15,8 +15,10 @@ * with this program. If not, see . */ +#include "AchievementMgr.h" #include "Chat.h" #include "CommandScript.h" +#include "Language.h" #include "Player.h" using namespace Acore::ChatCommands; @@ -30,7 +32,7 @@ public: { static ChatCommandTable achievementCommandTable = { - { "add", HandleAchievementAddCommand, SEC_GAMEMASTER, Console::No }, + { "add", HandleAchievementAddCommand, SEC_GAMEMASTER, Console::Yes }, { "checkall", HandleAchievementCheckAllCommand, SEC_ADMINISTRATOR, Console::Yes } }; static ChatCommandTable commandTable = @@ -40,15 +42,27 @@ public: return commandTable; } - static bool HandleAchievementAddCommand(ChatHandler* handler, AchievementEntry const* achievementEntry) + static bool HandleAchievementAddCommand(ChatHandler* handler, AchievementEntry const* achievementEntry, Optional player) { - Player* target = handler->getSelectedPlayer(); - if (!target) + if (!player) + player = PlayerIdentifier::FromTargetOrSelf(handler); + + if (!player) { - handler->SendErrorMessage(LANG_NO_CHAR_SELECTED); + handler->SendErrorMessage(LANG_PLAYER_NOT_FOUND); return false; } - target->CompletedAchievement(achievementEntry); + + if (player->IsConnected()) + { + player->GetConnectedPlayer()->CompletedAchievement(achievementEntry); + handler->PSendSysMessage(LANG_ACHIEVEMENT_ADD_ONLINE, achievementEntry->ID, achievementEntry->name[0], player->GetName()); + } + else + { + sAchievementMgr->CompletedAchievementForOfflinePlayer(player->GetGUID().GetCounter(), achievementEntry); + handler->PSendSysMessage(LANG_ACHIEVEMENT_ADD_OFFLINE, achievementEntry->ID, achievementEntry->name[0], player->GetName()); + } return true; }