Files
Questie-X/Research/QuestieLearner-Verification.md
T

366 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QuestieLearner — In-Game Verification Guide
This guide walks you through verifying every subsystem of QuestieLearner is working correctly after the v1.2.6 rewrite. Run each test in order and check expected outputs.
---
## Prerequisites
### Enable Develop Debug Output
In chat before starting any test:
```
/script Questie.db.profile.debugLevel = Questie.DEBUG_DEVELOP
```
Or enable **Develop** in Questie Options → Advanced → Debug Level.
> You do NOT need Critical enabled separately — Develop includes Critical-tier output.
### Verify Settings Are Enabled
If you upgraded from an older version, `learnedData` in your SavedVariables may be missing the newer settings keys (fixed in v1.2.7). Confirm all are `true` before testing:
```
/script local s=Questie.db.global.learnedData.settings; print("enabled:", tostring(s.enabled), "npcs:", tostring(s.learnNpcs), "quests:", tostring(s.learnQuests), "items:", tostring(s.learnItems), "objects:", tostring(s.learnObjects))
```
All five should print `true`. If any print `nil`, do a `/reload` — v1.2.7's `EnsureLearnedData` backfill will fix it on next load.
---
## Test 1 — Initialization
After `/reload`, look for this in chat:
```
[QuestieLearner] Events registered
[QuestieLearner] Initialized
```
If you also had previously learned data, you should see:
```
[QuestieLearner] Injected learned data: N NPCs, N quests, N items, N objects
```
**Failure:** If you see nothing, check that `QuestieLearner.lua` and `QuestieLearnerComms.lua` are in the TOC and loading without errors.
---
## Test 2 — Mouseover Filter (Quest Giver ONLY)
> **Note:** Since v1.2.6, debug output only prints when an NPC is seen for the **first time ever**. If the NPC already exists in `learnedData` from a previous session, mouseover is silent — this is correct behavior. Use the steps below to force a visible test.
### 2a — Find the NPC ID
**For normal NPCs you can target** (dash-format GUID, e.g. `Creature-0-...`):
```
/script local g=UnitGUID("target"); print(g)
```
Then parse the 6th dash-separated field — that is the NPC ID.
**For GameObjects / objects you interact with** (must have gossip window open):
```
/script print(UnitGUID("npc"))
```
> `UnitGUID("target")` returns `nil` for GameObjects — they cannot be traditionally targeted. Always use `UnitGUID("npc")` during an active gossip/click interaction. If you are not in a gossip window, `UnitGUID("npc")` also returns nil.
**Hex GUID decode** (if the GUID starts with `0x`, not dash-separated):
```
/script local g=UnitGUID("npc") or UnitGUID("target"); if g then local p=string.upper(string.sub(g,3,6)); local id=math.mod(tonumber(string.sub(g,11,18),16),8388608); print(p,id) end
```
### 2b — Clear it from learned data, then hover
```
/script local id = <npcId>; Questie.db.global.learnedData.npcs[id] = nil; print("Cleared NPC", id)
```
Now move your cursor off and back onto the quest giver.
**Expected output:**
```
[QuestieLearner] New NPC learned: <id> <NpcName>
```
### 2c — Verify the npcFlags filter directly
While mousing over the quest giver:
```
/script print("Flags:", UnitNPCFlags and UnitNPCFlags("mouseover") or "nil")
```
Expected: a number with bit 1 set (e.g. `2`, `3`, `35` — any value where `math.floor(value/2) % 2 == 1`).
While mousing over a random mob:
```
/script print("Flags:", UnitNPCFlags and UnitNPCFlags("mouseover") or "nil")
```
Expected: `0` or a value without the questgiver bit — and **no** `[QuestieLearner]` line should appear.
### 2d — Random Mob (Should Be Ignored)
Mouseover any wolf, enemy soldier, or non-quest creature.
**Expected:** Nothing printed. No `[QuestieLearner]` line.
---
## Test 3 — Quest Accept
Pick up any quest from an NPC. Look for:
```
[QuestieLearner] New quest learned: <id> <QuestName>
[QuestieLearner] New NPC learned: <id> <GiverName>
```
> Only prints on the **first time** each quest/NPC is learned. Subsequent accepts of the same quest are silent (data is updated internally).
Verify data was stored:
```
/script local q=Questie.db.global.learnedData.quests; local n=0; for _ in pairs(q) do n=n+1 end; print("Learned quests:", n)
```
Inspect a specific quest (replace `<questId>` with the ID you just accepted):
```
/script local q=Questie.db.global.learnedData.quests[<questId>]; if q then print("name:", q[1], "level:", q[5], "reqLvl:", q[4], "zone:", q[8]) else print("NOT captured") end
```
If it says `NOT captured`, check your settings (Prerequisites section) — `learnQuests` being `nil` silently blocks all quest recording.
Check if the quest is already in a DB plugin (if so, learner skips it):
```
/script local q = QuestieDB:GetQuest(<questId>); if q then print("In DB:", q[1]) else print("NOT in DB - learner should capture it") end
```
---
## Test 4 — Quest Turn-In
Complete and turn in a quest. Look for:
```
[QuestieLearner] New NPC learned: <id> <FinisherName>
```
Verify both starter and finisher are recorded:
```
/script local q=Questie.db.global.learnedData.quests[<questId>]; if q then print("starters:", tostring(q[2]), "finishers:", tostring(q[3])) end
```
Expected: Both `q[2]` and `q[3]` should be tables, not nil.
- `q[2][1]` = list of NPC IDs that start the quest
- `q[3][1]` = list of NPC IDs that finish the quest
---
## Test 5 — Kill Coordinate Recording
### 5a — Quest Objective Kill (Should Record)
Have an active kill quest in your quest log (e.g., "Kill 10 Wolves"). Kill one of the objective mobs.
**Expected output:**
```
[QuestieLearner] Kill recorded: NPC <id> <MobName>
[QuestieLearner] New NPC learned: <id> <MobName>
```
> "New NPC learned" only appears the first time. Subsequent kills of the same NPC type are silent but still update coordinates.
Verify coordinates were stored:
```
/script local n=Questie.db.global.learnedData.npcs[<npcId>]; if n and n[7] then for z,c in pairs(n[7]) do print("zone "..z.." has "..#c.." coord cluster(s)") end else print("no coords") end
```
Kill the same mob type multiple times in the same area. The cluster count should NOT increase for every kill — only when you move to a meaningfully different location (>2% of zone width apart).
### 5b — Non-Quest Mob (Should Be Ignored)
Kill a mob that is NOT a quest objective and is NOT in QuestieDB.
**Expected output:** Nothing. `[QuestieLearner] Kill recorded` should NOT appear.
---
## Test 6 — Item Loot Recording
Loot a mob or chest that drops a quest item.
**Expected output (immediate):**
```
[QuestieLearner] New item learned: <id> <ItemName>
```
**Expected output (delayed ~1 second if item never seen before):**
Same line, but fires when `GET_ITEM_INFO_RECEIVED` resolves the async `GetItemInfo` call.
Verify:
```
/script local i=Questie.db.global.learnedData.items; local n=0; for _ in pairs(i) do n=n+1 end; print("Learned items:", n)
```
---
## Test 7 — Object Recording
Interact with a clickable game object (chest, crate, brazier, scroll, etc.).
> **Important:** Some objects that look like interactable objects (e.g. Objectives Board) are actually implemented as **Creature NPCs** by the server. These will be recorded as NPCs, not objects — this is correct behavior.
### 7a — Identify what type an object/NPC is
With the gossip/interaction window open, run:
```
/script local g=UnitGUID("npc"); if g then local p=string.upper(string.sub(g,3,6)); print("GUID:", g, "Prefix:", p, "IsGameObject:", tostring(p=="F140")) end
```
| Prefix | Type | Recorded as |
|---|---|---|
| `F140` | GameObject | Object (`learnedData.objects`) |
| `F130` | Creature | NPC (`learnedData.npcs`) |
| `F110` | Creature/Pet | NPC (`learnedData.npcs`) |
| `F131` | Vehicle | NPC (`learnedData.npcs`) |
### 7b — Decode a hex GUID to get the ID
With the gossip window open (hex format `0xF110...`):
```
/script local g=UnitGUID("npc"); if g then local p=string.upper(string.sub(g,3,6)); local id=math.mod(tonumber(string.sub(g,11,18),16),8388608); print(p,id) end
```
> `strsplit("-", guid)` does **not** work on hex-format GUIDs. Always use substring extraction for `0x...` GUIDs.
Standalone decode for any known hex GUID string (replace the value):
```
/script local g="0xF110092A18000718"; local p=string.upper(string.sub(g,3,6)); print(p, math.mod(tonumber(string.sub(g,11,18),16),8388608))
```
### 7c — Print all learned objects
```
/script for id, data in pairs(Questie.db.global.learnedData.objects) do print("Object ID:", id, "Name:", tostring(data[1]), "Zone:", tostring(data[5])) end
```
With coordinates:
```
/script for id, data in pairs(Questie.db.global.learnedData.objects) do print("Object:", id, data[1]); if data[4] then for z, coords in pairs(data[4]) do print(" zone "..z.." - "..#coords.." coord(s)") end end end
```
---
## Test 8 — Overall Stats Check
Run this anytime to see a full summary:
```
/script local QL=QuestieLoader:ImportModule("QuestieLearner"); local n,q,i,o=QL:GetStats(); print("NPCs:"..n.." Quests:"..q.." Items:"..i.." Objects:"..o)
```
Expected counts increase as you play. `Quests:0` after accepting quests = settings backfill issue (see Prerequisites).
---
## Test 9 — Export
```
/script local E=QuestieLoader:ImportModule("QuestieLearnerExport"); local s,stats=E:Export(); if stats then print("Export OK | total:", stats.total, "| len:", string.len(s)) else print("Export FAILED:", tostring(stats)) end
```
Expected: `Export OK | total: N | len: XXXX`
The export string starts with `QxLD:1!`. Copy it from the Database tab → Export box in Questie Options.
---
## Test 10 — Import (Round-Trip)
1. Export your data (Test 9).
2. Wipe learned data: `/script QuestieLoader:ImportModule("QuestieLearner"):ClearAllData()`
3. Open Questie Options → Database → paste the export string → click Import.
Expected in chat:
```
Import complete: merged N entries, skipped 0 (already known).
[QuestieLearner] Injected learned data: N NPCs, N quests, N items, N objects
```
Verify stats match original count (Test 8). Data takes effect immediately — no `/reload` required for override-based map pins.
---
## Test 11 — Plugin Panel Stats (WotLKDB)
Open **Questie Options → Database** tab → scroll to **Loaded Questie-X Plugins**.
Expected for WotLKDB:
```
[Questie-WotLKDB] Quests: 9086 NPCs: XXXX Objects: XXXX Items: XXXX
```
If you see all zeros: `QuestieX_WotLKDB_Counts` is not set yet. This global is written by `LoadBaseDB()` inside an async coroutine — open the options panel a few seconds after login rather than immediately.
---
## Test 12 — Peer Sharing (Requires Two Clients)
On Client 1, learn a new NPC (walk up to a quest giver not previously recorded).
On Client 2, run:
```
/script print(type(Questie.db.global.learnedData.npcs[<npcId>]))
```
Expected: `table` (arrived via hidden `questiecomm` channel or AceComm guild broadcast).
> Both clients must be in the same guild OR on the same server. Allow up to 10 seconds for the token-bucket throttle.
---
## GUID Reference
WoW uses two GUID formats. The learner handles both automatically.
### Dash-format (modern)
```
Creature-0-3726-0-189-5638296-000001ABCD
```
Parse with: `strsplit("-", guid)` → 6th element = ID, 1st = unit type string
### Hex-format (legacy, common on private servers)
```
0xF110092A18000718
```
Parse with position extraction:
- Characters 36 = unit type prefix (`F110`, `F130`, `F140`, etc.)
- Characters 1118 = low 32 bits → `math.mod(tonumber(low32hex, 16), 8388608)` = entity ID
**Do NOT use `strsplit("-", ...)` on hex GUIDs** — it will return nil for all fields after the first.
Quick decode command for any hex GUID:
```
/script local g="0xF110092A18000718"; local p=string.upper(string.sub(g,3,6)); print(p, math.mod(tonumber(string.sub(g,11,18),16),8388608))
```
---
## Quick Diagnostic — All At Once
```
/script local QL=QuestieLoader:ImportModule("QuestieLearner"); local n,q,i,o=QL:GetStats(); print("=== QuestieLearner Stats ==="); print("NPCs:"..n.." Quests:"..q.." Items:"..i.." Objects:"..o); local s=Questie.db.global.learnedData.settings; print("enabled:", tostring(s.enabled), "| npcs:", tostring(s.learnNpcs), "| quests:", tostring(s.learnQuests), "| items:", tostring(s.learnItems), "| objects:", tostring(s.learnObjects))
```
---
## Common Issues
| Symptom | Cause | Fix |
|---|---|---|
| Nothing prints at all | Debug level not set to DEVELOP | `/script Questie.db.profile.debugLevel = Questie.DEBUG_DEVELOP` |
| `Quests:0` despite accepting quests | `learnQuests = nil` in old SavedVariables | `/reload` — v1.2.7 backfill sets it to `true` |
| Random mobs being recorded | Old QuestieLearner.lua still loaded | Confirm v1.2.6+ deployed, `/reload` |
| Kill coords not recording | NPC not in QuestieDB and not targeted/hovered | Target the mob before killing it |
| Object recorded as NPC | Server implements it as a Creature (`F110`/`F130`) | Correct behavior — check prefix to confirm |
| `strsplit` returns nil | GUID is hex format, not dash-separated | Use hex decode method (see GUID Reference) |
| `UnitGUID("target")` returns nil | GameObjects can't be traditionally targeted | Use `UnitGUID("npc")` during gossip interaction instead |
| Export returns nil | `learnedData` is empty | Run Tests 27 first to accumulate data |
| WotLKDB shows 0s in plugin panel | Options opened before async init completed | Wait a few seconds after login then reopen options |
| Item not recorded after loot | `GetItemInfo` async on first encounter | Wait 12 seconds for `GET_ITEM_INFO_RECEIVED` |