From 870dad61f5c5a4888d0f374bf97cead06a9b77af Mon Sep 17 00:00:00 2001 From: SylvaniaCore Date: Wed, 24 Jun 2026 07:02:01 +0000 Subject: [PATCH] Couche 3 du harnais debug quetes : commande console .qtest .qtest [complete] (allowConsole=true => SOAP sans selection) Dump objectif-par-objectif l'etat live d'une quete pour un joueur en ligne (statut, ObjectID, cur/req, OK/--). Option complete = AddQuest+ForceCompleteQuest. Valide en jeu : qtest Testy 14109 -> 3 objectifs items listes. Co-Authored-By: Claude Opus 4.8 --- src/server/scripts/Custom/custom_qtest.cpp | 108 ++++++++++++++++++ .../scripts/Custom/custom_script_loader.cpp | 10 +- 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 src/server/scripts/Custom/custom_qtest.cpp diff --git a/src/server/scripts/Custom/custom_qtest.cpp b/src/server/scripts/Custom/custom_qtest.cpp new file mode 100644 index 0000000..ca11137 --- /dev/null +++ b/src/server/scripts/Custom/custom_qtest.cpp @@ -0,0 +1,108 @@ +/* + * Sylvania custom : commande de sonde runtime de quete (Couche 3 du harnais de debug). + * .qtest [complete] + * - dump objectif-par-objectif l'etat live de la quete pour un joueur EN LIGNE + * - allowConsole=true => utilisable via SOAP/console sans selectionner le joueur + * - option "complete" : AddQuest si besoin puis ForceCompleteQuest (test du flux/rendu) + */ +#include "ScriptMgr.h" +#include "Chat.h" +#include "ObjectMgr.h" +#include "ObjectAccessor.h" +#include "Player.h" +#include "QuestDef.h" +#include "RBAC.h" +#include + +class qtest_commandscript : public CommandScript +{ +public: + qtest_commandscript() : CommandScript("qtest_commandscript") { } + + std::vector GetCommands() const override + { + static std::vector qtestCommandTable = + { + { "qtest", rbac::RBAC_PERM_COMMAND_QUEST, true, &HandleQTest, "" }, + }; + return qtestCommandTable; + } + + static bool HandleQTest(ChatHandler* handler, char const* args) + { + if (!args || !*args) + { + handler->SendSysMessage("Usage: .qtest [complete]"); + handler->SetSentErrorMessage(true); + return false; + } + + std::istringstream ss(args); + std::string name; + uint32 questId = 0; + std::string act; + ss >> name >> questId >> act; + + if (name.empty() || questId == 0) + { + handler->SendSysMessage("Usage: .qtest [complete]"); + handler->SetSentErrorMessage(true); + return false; + } + + Player* player = ObjectAccessor::FindConnectedPlayerByName(name); + if (!player) + { + handler->PSendSysMessage("qtest: joueur '%s' introuvable (doit etre en ligne).", name.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + Quest const* quest = sObjectMgr->GetQuestTemplate(questId); + if (!quest) + { + handler->PSendSysMessage("qtest: quete %u introuvable.", questId); + handler->SetSentErrorMessage(true); + return false; + } + + QuestStatus st = player->GetQuestStatus(questId); + char const* stName; + switch (st) + { + case QUEST_STATUS_NONE: stName = "NONE"; break; + case QUEST_STATUS_COMPLETE: stName = "COMPLETE"; break; + case QUEST_STATUS_INCOMPLETE: stName = "INCOMPLETE"; break; + case QUEST_STATUS_REWARDED: stName = "REWARDED"; break; + case QUEST_STATUS_FAILED: stName = "FAILED"; break; + default: stName = "?"; break; + } + + handler->PSendSysMessage("=== qtest joueur=%s quete=%u statut=%s ===", name.c_str(), questId, stName); + + QuestObjectives const& objs = quest->GetObjectives(); + handler->PSendSysMessage("Objectifs: %u", uint32(objs.size())); + for (QuestObjective const& obj : objs) + { + int32 cur = player->GetQuestObjectiveData(quest, obj.StorageIndex); + bool done = player->IsQuestObjectiveComplete(obj); + handler->PSendSysMessage(" [idx %d] Type=%u ObjectID=%d %d/%d %s", + int32(obj.StorageIndex), uint32(obj.Type), obj.ObjectID, cur, obj.Amount, done ? "OK" : "--"); + } + + if (act == "complete") + { + if (st == QUEST_STATUS_NONE && player->CanAddQuest(quest, false)) + player->AddQuestAndCheckCompletion(quest, nullptr); + player->ForceCompleteQuest(questId); + handler->PSendSysMessage("qtest: ForceCompleteQuest applique -> statut=%d", int32(player->GetQuestStatus(questId))); + } + + return true; + } +}; + +void AddSC_custom_qtest() +{ + new qtest_commandscript(); +} diff --git a/src/server/scripts/Custom/custom_script_loader.cpp b/src/server/scripts/Custom/custom_script_loader.cpp index e9231d6..c8215a1 100644 --- a/src/server/scripts/Custom/custom_script_loader.cpp +++ b/src/server/scripts/Custom/custom_script_loader.cpp @@ -18,14 +18,20 @@ // This is where scripts' loading functions should be declared: void AddSC_custom_npcs(); +void AddSC_custom_worgen_racials(); void AddSC_quest_conversation(); void AddSC_solocraft(); void AddLfgSoloScripts(); +void AddSC_custom_loot_packs(); +void AddSC_custom_qtest(); void AddCustomScripts() { - AddSC_custom_npcs(); + AddSC_custom_npcs(); + AddSC_custom_worgen_racials(); AddSC_quest_conversation(); AddSC_solocraft(); - AddLfgSoloScripts(); + AddLfgSoloScripts(); + AddSC_custom_loot_packs(); + AddSC_custom_qtest(); }