базовый encounter journal

This commit is contained in:
2026-06-13 11:46:39 +04:00
parent d8d94f10b0
commit b0da9ec10b
90 changed files with 4521 additions and 366 deletions
+448
View File
@@ -0,0 +1,448 @@
# 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
<Button name="$parentGuideTab"
inherits="EncounterTierTabTemplate"
text="MW_PLAYER_GUIDE"
parentKey="guideTab"
id="5">
<Anchors>
<Anchor point="BOTTOMLEFT" relativeTo="$parentSuggestTab" relativePoint="BOTTOMRIGHT" x="35" y="0"/>
</Anchors>
<Scripts>
<OnClick function="EJ_ContentTab_OnClick"/>
</Scripts>
</Button>
```
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
```