diff --git a/Research/QuestieLearner-Verification.md b/Research/QuestieLearner-Verification.md index 33cf33c..e06c152 100644 --- a/Research/QuestieLearner-Verification.md +++ b/Research/QuestieLearner-Verification.md @@ -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: -[QuestieLearner] Learned NPC: ← or "Learned Object" if quest giver is a chest/object +[QuestieLearner] New quest learned: +[QuestieLearner] New NPC learned: ``` +> 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 `` with the ID you just accepted): ``` -/script local q=Questie.db.global.learnedData.quests[]; 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[]; if q then print("name:", q[1], "level:", q[5], "reqLvl:", q[4], "zone:", q[8]) else print("NOT captured") end ``` -Expected: `name: level: zone: ` +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(); if q then print("In DB:", q[1]) else print("NOT in DB - learner should capture it") end +``` --- @@ -108,8 +126,7 @@ Expected: `name: level: zone: ` Complete and turn in a quest. Look for: ``` -[QuestieLearner] Learned Quest: -[QuestieLearner] Learned NPC: +[QuestieLearner] New NPC learned: ``` 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 -[QuestieLearner] Learned NPC: +[QuestieLearner] Kill recorded: NPC +[QuestieLearner] New NPC learned: ``` +> "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[]; 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[]; 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: +[QuestieLearner] New item learned: ``` -**Expected output (delayed by ~1 second if item was never seen before):** -``` -[QuestieLearner] Learned Item: -``` +**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: +/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[])) ``` -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 3–6 = unit type prefix (`F110`, `F130`, `F140`, etc.) +- Characters 11–18 = 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 2–7 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 1–2 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 1–2 seconds for `GET_ITEM_INFO_RECEIVED` |