docs: add GUID reference, object vs NPC distinction, and settings backfill prereq to verification guide

This commit is contained in:
Xurkon
2026-03-16 22:10:26 -05:00
parent b2ca8fa660
commit 6b9d1d548f
+111 -38
View File
@@ -17,6 +17,15 @@ 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
@@ -47,6 +56,8 @@ Target the quest giver NPC and run:
/script local guid = UnitGUID("target"); local id = tonumber(select(6, strsplit("-", guid))); print("NPC ID:", id)
```
> **Note:** This only works for dash-format GUIDs (e.g. `Creature-0-...`). If the GUID is in hex format (`0xF110...`), use the hex decode method in the GUID Reference section below.
### 2b — Clear it from learned data, then hover
```
@@ -86,10 +97,12 @@ Mouseover any wolf, enemy soldier, or non-quest creature.
Pick up any quest from an NPC. Look for:
```
[QuestieLearner] Learned Quest: <id> <QuestName>
[QuestieLearner] Learned NPC: <id> <GiverName> ← or "Learned Object" if quest giver is a chest/object
[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)
@@ -97,10 +110,15 @@ Verify data was stored:
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]) end
/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
```
Expected: `name: <quest name> level: <number> zone: <mapId>`
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
```
---
@@ -108,8 +126,7 @@ Expected: `name: <quest name> level: <number> zone: <mapId>`
Complete and turn in a quest. Look for:
```
[QuestieLearner] Learned Quest: <id> <QuestName>
[QuestieLearner] Learned NPC: <id> <FinisherName>
[QuestieLearner] New NPC learned: <id> <FinisherName>
```
Verify both starter and finisher are recorded:
@@ -131,40 +148,39 @@ Have an active kill quest in your quest log (e.g., "Kill 10 Wolves"). Kill one o
**Expected output:**
```
[QuestieLearner] UNIT_DIED: recording kill NPC <id> <MobName>
[QuestieLearner] Learned NPC: <id> <MobName>
[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 clusters") end end
/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 single kill — only when you move to a meaningfully different location (>2% of zone width away).
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] UNIT_DIED` should NOT appear.
**Expected output:** Nothing. `[QuestieLearner] Kill recorded` should NOT appear.
---
## Test 6 — Item Loot Recording
Loot a mob or chest that drops a **quest item** (purple/green bag icon in loot window, or any item that appears in the loot frame).
Loot a mob or chest that drops a quest item.
**Expected output (immediate, if item was already cached):**
**Expected output (immediate):**
```
[QuestieLearner] Learned Item: <id> <ItemName>
[QuestieLearner] New item learned: <id> <ItemName>
```
**Expected output (delayed by ~1 second if item was never seen before):**
```
[QuestieLearner] Learned Item: <id> <ItemName>
```
**Expected output (delayed ~1 second if item never seen before):**
This fires when `GET_ITEM_INFO_RECEIVED` resolves the async `GetItemInfo` call.
Same line, but fires when `GET_ITEM_INFO_RECEIVED` resolves the async `GetItemInfo` call.
Verify:
```
@@ -175,27 +191,54 @@ Verify:
## Test 7 — Object Recording
Interact with a **clickable quest object** (a chest, a crate, a brazier, a scroll — any game object that starts or is part of a quest).
Interact with a clickable game object (chest, crate, brazier, scroll, etc.).
**Expected output:**
> **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:
```
[QuestieLearner] Learned Object: <id> <ObjectName>
/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
```
Verify:
| 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
```
/script local o=Questie.db.global.learnedData.objects; local n=0; for _ in pairs(o) do n=n+1 end; print("Learned objects:", n)
/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("Prefix:", p, "ID:", tostring(id)) end
```
> `strsplit("-", guid)` does **not** work on hex-format GUIDs — it returns the full string as the first value and nil for everything else. Always use the hex decode method above for `0x...` GUIDs.
### 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 of what has been learned this session:
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
@@ -213,8 +256,8 @@ The export string starts with `QxLD:1!`. Copy it from the Database tab → Expor
## Test 10 — Import (Round-Trip)
1. Export your data (Test 9).
2. Run `/script QuestieLoader:ImportModule("QuestieLearner"):ClearAllData()` to wipe learned data.
3. Open Questie Options → Database → paste the export string into the Import box → click Import.
2. Wipe learned data: `/script QuestieLoader:ImportModule("QuestieLearner"):ClearAllData()`
3. Open Questie Options → Database → paste the export string → click Import.
Expected in chat:
```
@@ -222,20 +265,20 @@ 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).
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 → Advanced** and scroll to **Loaded Questie-X Plugins**.
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, the `QuestieX_WotLKDB_Counts` global was not set before the Loader.lua read it. Check that `QuestieInit:LoadBaseDB()` is running before `PLAYER_LOGIN` completes.
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.
---
@@ -248,17 +291,43 @@ On Client 2, run:
/script print(type(Questie.db.global.learnedData.npcs[<npcId>]))
```
Expected: `table` (the NPC data arrived via the hidden `questiecomm` channel or AceComm guild broadcast).
Expected: `table` (arrived via hidden `questiecomm` channel or AceComm guild broadcast).
> **Note:** Both clients must be in the same guild OR on the same server (for the hidden channel). Allow up to 10 seconds for the token-bucket throttle to release the message.
> 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)); local id=math.mod(tonumber(string.sub(g,11,18),16),8388608); print("Prefix:",p,"ID:",id)
```
---
## Quick Diagnostic — All At Once
Paste this block into chat for a full snapshot:
```
/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 ld=Questie.db.global.learnedData; print("Enabled:", tostring(ld.settings.enabled)); print("Learn NPCs:", tostring(ld.settings.learnNpcs)); print("Learn Quests:", tostring(ld.settings.learnQuests)); print("Learn Items:", tostring(ld.settings.learnItems)); print("Learn Objects:", tostring(ld.settings.learnObjects))
/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))
```
---
@@ -268,8 +337,12 @@ Paste this block into chat for a full snapshot:
| Symptom | Cause | Fix |
|---|---|---|
| Nothing prints at all | Debug level not set to DEVELOP | `/script Questie.db.profile.debugLevel = Questie.DEBUG_DEVELOP` |
| Random mobs being recorded | Old QuestieLearner.lua still loaded | Confirm v1.2.6+ is deployed, `/reload` |
| Kill coords not recording | NPC not in QuestieDB and not explicitly targeted/hovered before kill | Target the mob before killing it, or ensure your DB plugin is loaded |
| `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 | `QuestieX_WotLKDB_Counts` not set | Verify `QuestieInit:LoadBaseDB()` has the count-before-pull logic |
| Item not recorded after loot | `GetItemInfo` async — item never seen before | Wait 12 seconds; if still missing, the item may not be a quest item |
| 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` |