# Player Guide Requirements ## Goal Create a `Путеводитель` tab inside the existing Encounter Journal UI. The guide must show personal character progress calculated by `mod-individual-progress` and recommend the next relevant content: quests, dungeons, raids, bosses, requirements, activities, and rewards. This feature is not a third Encounter Journal instance type. It is a separate panel inside the same interface. ## High-Level Architecture ```text AzerothCore / mod-individual-progress -> calculates player progress -> builds a guide payload AIO / MoonWell bridge -> sends guide data to the client MoonWellClient / EncounterJournal -> receives the payload -> stores it in C_PlayerGuide -> renders the Player Guide tab ``` ## Client Components Add separate client-side files: ```text EncounterJournal/Utils/C_PlayerGuide.lua EncounterJournal/Custom_EncounterJournal/PlayerGuide.lua EncounterJournal/Custom_EncounterJournal/PlayerGuide.xml ``` Responsibilities: ```text C_PlayerGuide.lua - stores current guide data - exposes a small UI-facing API - receives server payloads - requests refreshes from the server PlayerGuide.lua - renders guide data - refreshes objective rows - handles clicks on objectives/recommendations PlayerGuide.xml - defines the guide panel - defines static frames, headers, scroll area, row templates ``` Register these files in `MoonWellClient.toc` before `Custom_EncounterJournal.lua`. ## Encounter Journal Tab Add a new top-level tab near `Подземелья` and `Рейды`: ```text Путеводитель | Подземелья | Рейды | Комплекты ``` The tab must live in: ```text EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.xml ``` Expected XML shape: ```xml ``` If the guide tab is inserted before existing tabs, anchors for `DungeonTab`, `RaidTab`, and `LootJournalTab` must be adjusted. Add a localized string: ```lua MW_PLAYER_GUIDE = "Путеводитель" ``` ## Tab Selection Behavior When the guide tab is selected: ```text - hide instance cards - hide Encounter Journal detail panel - hide suggested content panel - hide loot journal panel - hide or disable the expansion/tier dropdown unless explicitly needed - show PlayerGuideFrame ``` When any other top-level tab is selected: ```text - hide PlayerGuideFrame ``` Do not route this tab through: ```lua EJ_GetInstanceByIndex(index, isRaid) ``` That API is only for dungeon/raid instance lists. ## Client API Create: ```lua C_PlayerGuide = C_PlayerGuide or {} ``` Required methods: ```lua C_PlayerGuide.SetData(data) C_PlayerGuide.GetStageInfo() C_PlayerGuide.GetNumObjectives() C_PlayerGuide.GetObjectiveInfo(index) C_PlayerGuide.GetNumRecommendations() C_PlayerGuide.GetRecommendationInfo(index) C_PlayerGuide.GetNumRewards() C_PlayerGuide.GetRewardInfo(index) C_PlayerGuide.RequestRefresh() ``` Minimum behavior: ```text SetData(data) - validate payload is a table - replace current data - fire/trigger a UI refresh if the guide panel is visible GetStageInfo() - returns stageID, stageName, stageDescription, progress GetObjectiveInfo(index) - returns a normalized objective record or unpacked objective fields RequestRefresh() - asks the server to resend the current payload ``` ## Server Payload The server should send one normalized payload per character. Minimum shape: ```lua { version = 1, characterGuid = 123, stageID = 10, stageName = "Подготовка к Нордсколу", stageDescription = "Завершите ключевые шаги перед переходом дальше.", progress = 40, objectives = { { id = 1, type = "level", title = "Достигнуть 68 уровня", description = "", completed = true, progress = 68, required = 68, targetID = 68, order = 1, }, { id = 2, type = "quest", title = "Завершить цепочку Темного портала", description = "", completed = false, progress = 3, required = 8, targetID = 10119, order = 2, }, { id = 3, type = "dungeon", title = "Пройти Кузню Крови", description = "", completed = false, progress = 0, required = 1, targetID = 256, instanceID = 256, order = 3, }, }, recommendations = { { id = 1, type = "dungeon", title = "Кузня Крови", description = "Подходит для текущего этапа.", instanceID = 256, priority = 100, }, }, rewards = { { type = "item", itemID = 12345, count = 1, }, }, } ``` ## Objective Types Support at least: ```text level quest quest_chain dungeon raid boss achievement reputation profession item currency custom ``` Every objective should use the common fields: ```text id type title description completed progress required targetID order ``` Optional type-specific fields: ```text questID questChainID instanceID encounterID achievementID factionID professionID itemID currencyID ``` ## Objective Click Behavior Recommended behavior: ```text quest - show quest link or quest hint if available dungeon - open Encounter Journal on instanceID raid - open Encounter Journal on instanceID boss - open Encounter Journal on encounterID item - show item tooltip achievement - show achievement UI/link custom - show text-only detail or request a server action ``` If a target cannot be opened, the UI should fail quietly and keep the guide visible. ## AIO Contract Use a separate handler namespace: ```text MoonWellPlayerGuide ``` Server to client: ```lua SetData(payload) UpdateObjective(objective) SetStage(stagePayload) Notify(message) ``` Client to server: ```lua RequestRefresh() RequestTrackObjective(objectiveID) RequestOpenTarget(objectiveID) ``` Minimum MVP only needs: ```lua SetData(payload) RequestRefresh() ``` ## AzerothCore / mod-individual-progress Requirements `mod-individual-progress` must: ```text - determine the player's current progression stage - calculate objective completion state - calculate objective progress values - build the guide payload - send the payload on login - send updates when progress changes - respond to explicit client refresh requests ``` Recommended update events: ```text login level up quest accepted quest completed quest rewarded achievement earned boss kill dungeon completed reputation changed profession changed item acquired, if item objectives are used ``` ## UI Requirements MVP UI: ```text - guide tab - stage title - stage description - total progress percentage - objective list - completed/incomplete visual state - recommendation list - manual refresh button ``` Later UI: ```text - categories - filters: all / active / completed - tracked objective pinning - reward preview - requirement tooltips - direct "Open in Journal" buttons - server notifications ``` ## Non-Goals Do not: ```text - store guide progress in JOURNALINSTANCE - make the guide a third dungeon/raid instance category - overload EJ_GetInstanceByIndex(index, isRaid) - depend on Sirus-only globals or realm constants - block the old dungeon/raid Encounter Journal if guide data is missing ``` ## MVP Implementation Order 1. Add the `Путеводитель` tab. 2. Add an empty `PlayerGuideFrame`. 3. Add `C_PlayerGuide.lua` with static test data. 4. Render the stage title and three test objectives. 5. Wire tab switching and hide/show behavior. 6. Add AIO `MoonWellPlayerGuide.SetData`. 7. Send test payload from the server. 8. Replace static data with real `mod-individual-progress` data. 9. Add click behavior for dungeon/raid/boss objectives. 10. Add polish: progress bar, icons, rewards, filters. ## Validation Client should tolerate missing or malformed fields: ```text - missing payload -> show empty state - missing objectives -> show "no active objectives" - missing recommendations -> hide recommendations block - unknown objective type -> render as text-only custom objective - invalid instanceID/encounterID -> do not throw Lua errors ``` Server should validate: ```text - objective ids are unique within the payload - order is stable - type is known or custom - progress <= required when required is present - dungeon/raid/boss targets exist in Encounter Journal data when used ```