базовый encounter journal
This commit is contained in:
@@ -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
|
||||
```
|
||||
Reference in New Issue
Block a user