/* * Copyright (C) 2016+ AzerothCore , * released under GNU AGPL v3 license: * https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 */ #ifndef MOONWELL_PLAYER_GUIDE_MGR_H #define MOONWELL_PLAYER_GUIDE_MGR_H #include "Define.h" #include #include #include #include class Player; namespace MoonWell::PlayerGuide { enum : uint32 { PAYLOAD_VERSION = 1 }; struct Objective { uint32 id = 0; std::string type; // level | quest | quest_chain | dungeon | // raid | boss | achievement | // reputation | profession | item | // currency | custom std::string title; std::string description; bool completed = false; uint32 progress = 0; uint32 required = 0; uint32 targetId = 0; uint32 order = 0; // Optional type-specific helpers. Zero means "not set" and // serialiser omits it. uint32 questId = 0; uint32 questChainId = 0; // ej_instanceID: key into client's JOURNALINSTANCE table. // Consumed by EncounterJournal_DisplayInstance / EJ_SelectInstance. uint32 ejInstanceId = 0; // WoW map id (for telemetry / teleport / fallback). NOT used by // the client to open EJ. uint32 mapId = 0; uint32 encounterId = 0; uint32 achievementId = 0; uint32 factionId = 0; uint32 professionId = 0; uint32 itemId = 0; uint32 currencyId = 0; }; struct Recommendation { uint32 id = 0; std::string type; std::string title; std::string description; uint32 ejInstanceId = 0; // JOURNALINSTANCE key uint32 mapId = 0; // WoW map id (auxiliary) uint32 encounterId = 0; uint32 questId = 0; uint32 itemId = 0; uint32 priority = 0; }; struct Reward { std::string type; uint32 itemId = 0; uint32 count = 1; uint32 currencyId = 0; uint32 amount = 0; }; struct Payload { uint32 version = PAYLOAD_VERSION; uint64 characterGuid = 0; uint32 stageId = 0; std::string stageName; std::string stageDescription; uint32 progress = 0; // 0..100 std::vector objectives; std::vector recommendations; std::vector rewards; }; class Mgr { public: static Mgr* instance(); // Reads configuration. Safe to call multiple times. void LoadConfig(); // Builds the per-character guide payload from IPP state. // The function is read-only with respect to the player. Payload BuildFor(Player* player) const; // Serialises a payload to a single JSON string. // Validates uniqueness of objective ids and clamps progress. std::string SerializeJson(Payload const& payload) const; std::string SerializeJson(Objective const& objective) const; bool IsEnabled() const { return _enabled; } bool LogPayloads() const { return _logPayloads; } uint32 ChunkSize() const { return _chunkSize; } // Reloads (map_id -> ej_instance.id/name) cache from // custom_ej_instance. Called from LoadConfig() and from the // OnLoadCustomDatabaseTable world hook. void ReloadEncounterJournalCache(); private: Mgr() = default; // Stage helpers based on ProgressionState. std::string StageName(uint32 stage) const; std::string StageDescription(uint32 stage) const; // Filling helpers. void AppendLevelObjective(Payload& out, Player* player, uint32 requiredLevel, uint32 order) const; void AppendQuestObjective(Payload& out, Player* player, uint32 questId, std::string const& title, uint32 order) const; void AppendDungeonObjective(Payload& out, uint32 mapId, std::string const& title, uint32 order) const; void AppendRaidObjective(Payload& out, uint32 mapId, std::string const& title, uint32 order) const; void AppendRecommendations(Payload& out, Player* player) const; struct EjInstanceRef { uint32 ejId = 0; // custom_ej_instance.id std::string name; // custom_ej_instance.name }; // mapId -> EJ instance ref. Filled at config load. std::unordered_map _ejByMapId; bool _enabled = true; bool _logPayloads = false; uint32 _chunkSize = 230; // per-frame body capacity (addon channel) }; } #define sPlayerGuideMgr ::MoonWell::PlayerGuide::Mgr::instance() #endif // MOONWELL_PLAYER_GUIDE_MGR_H