Files
Questie-X/handoff.md
T
Xurkon 164584ca87 fix: Sunstrider pin regression, ghost pins, and learner zone normalization
- Fix: isSunstrider block in _MergeSpawnEvidence now checks IsAscensionProtected
  before writing learner data to npcDataOverrides. Without this guard, each Mana
  Wyrm kill overwrote AscensionDB's z1241=5 data with learner z3431 coords.

- Fix: Clustering disabled for zone 1241 (Sunstrider Isle) in _DrawObjectiveIcons
  so all 5 AscensionDB spawn pins display individually instead of collapsing to 2.

- Fix: Ghost pin loop in AvailableQuests.lua -- 'while frames[i]' was iterating a
  string-keyed table with a numeric index (never iterated). Changed to pairs().

- Fix: NormalizeSpawnZoneKey now uses ZoneDB.areaIdToUiMapId for all zones so
  learner evidence is stored under map IDs (e.g. 1241) not area IDs (e.g. 3431),
  matching AscensionDB's key space. Applied in LearnNPC and _StoreGuidSpawnEvidence.

- Fix: isSunstrider detection in _MergeSpawnEvidence updated from hardcoded
  zoneId==3431 check to IsSunstriderNativeZone() since zone IDs are now normalized
  to map IDs at storage time.
2026-05-25 19:02:56 -05:00

5.2 KiB
Raw Blame History

Questie-X Learner Module — Pin Collapse Handoff

Session: 2025-05-25 Repo: C:\Users\kance\Documents\GitHub\Questie-X File: Modules/QuestieLearner.lua


Problem Statement

Killing multiple Mana Wyrms (npcId ~15274) on Sunstrider Isle (zoneId 3431) at distinct map coordinates still results in only 2 map pins rendering instead of 3+ distinct pins. The collapse is caused by the coordinate bucketing logic in _MergeSpawnEvidence and InsertIfNewBucket.


Two Identified Bucketing Layers

Layer 1 — _MergeSpawnEvidence lines ~10461048

Groups all per-GUID evidence into buckets by rounding (x, y) to 2 decimal places:

local rx = floor(evidenceX * 100 + 0.5) / 100
local ry = floor(evidenceY * -100 + 0.5) / 100
local key = entry.zoneId .. "|" .. rx .. "|" .. ry

Each unique 2-decimal (rx, ry) becomes one evidence group. If two distinct kill locations fall within the same 0.01×0.01 square, they merge into one evidence group here — before InsertIfNewBucket is even called.

Layer 2 — InsertIfNewBucket lines 205221

For Sunstrider, uses grid = 0.5. Checks if any existing spawn in the zone falls in the same floor(x/0.5)*0.5 bucket:

local bx, by = floor(x / grid) * grid, floor(y / grid) * grid

Two kills at x=50.54 and x=50.55 both land in bucket 50.5 → first is inserted, second is rejected as duplicate. This is the documented intentional collapse — but it's killing genuinely distinct spawn points that a 0.5 grid rounds to the same bucket.


Fixes Already Applied

  1. GetCoordGridForZone hoisted outside evidence loop (line ~1114)
    Grid is now computed once before the Sunstrider promotion loop. Previously it was computed inside InsertIfNewBucket via customGrid parameter.

  2. NormalizeCoordPair comment (line 958959)
    Updated to document that it handles native 01, already-scaled 0100, and buggy 010000 input formats.

  3. QUESTIE_LEARNER_debug log comment (line 963964)
    Noted it is commented out — re-enable for live debugging if needed.


The fix in this session did not resolve the 2-pin collapse. The next agent should:

  1. In _MergeSpawnEvidence (~line 10461048): comment out or replace the 2-decimal rounding entirely. Instead of grouping by (zoneId|rx|ry), use the raw normalized coordinates directly. This makes every distinct kill location a separate evidence group.

  2. In the Sunstrider promotion block (~lines 11111121): bypass InsertIfNewBucket entirely for Sunstrider. Instead of bucketing, insert the raw coordinates of every evidence group into zoneSpawns directly.

Exact Changes to Make

_MergeSpawnEvidence (~line 10451048) — REMOVE 2-decimal rounding:

Replace:

-- Round to 2 decimal places for grouping
local rx = floor(evidenceX * 100 + 0.5) / 100
local ry = floor(evidenceY * 100 + 0.5) / 100
local key = entry.zoneId .. "|" .. rx .. "|" .. ry

With:

-- Use raw normalized coordinates as group key (no bucket collapse)
local rx = evidenceX
local ry = evidenceY
local key = entry.zoneId .. "|" .. rx .. "|" .. ry

Sunstrider loop (~lines 11141121) — DIRECT INSERT (bypass InsertIfNewBucket):

Replace:

local grid = GetCoordGridForZone(topEvidence.zoneId)
for _, spawnEvidence in pairs(evidence) do
    if InsertIfNewBucket(zoneSpawns, spawnEvidence.x, spawnEvidence.y, grid) then
        promoted = promoted + 1
    else
        duplicates = duplicates + 1
    end
end

With:

-- Directly insert every distinct evidence coordinate without bucketing
for _, spawnEvidence in pairs(evidence) do
    tinsert(zoneSpawns, { spawnEvidence.x, spawnEvidence.y })
    promoted = promoted + 1
end
duplicates = 0

Rationale: Bucketing was designed to reduce noise from GPS drift — but on Sunstrider with a 0.5 grid, it collapses spawn points that are legitimately different. Removing bucketing entirely ensures every distinct kill location gets its own pin.


Key Code Locations

Function Lines Purpose
NormalizeCoordPair ~168197 Scales coords to 0100; handles buggy inputs
CoordBucket ~200201 Bucket key for (x, y) using COORD_GRID
InsertIfNewBucket ~205224 Inserts coord only if no existing in same bucket
GetCoordGridForZone ~108113 Returns 0.5 for Sunstrider (zones 1241/3431), else 2.0
_StoreGuidSpawnEvidence ~9421012 Stores per-GUID kill evidence; calls NormalizeCoordPair
_MergeSpawnEvidence ~10141140 Groups evidence → promotes top groups to npcDataOverrides

Debug Log

Re-enable this block (_StoreGuidSpawnEvidence, lines ~963964) to verify normalized coordinates during gameplay:

Questie:Debug(Questie.DEBUG_LEARNER,
    "[QuestieLearner] _StoreGuidSpawnEvidence: spawnUID=", spawnUID,
    "zoneId=", zoneId, "nx=", nx, "ny=", ny)

Expected log output after /reload:

entry.x=58.68 entry.y=43.19  (not "5868,4319")

Files Modified

  • Modules/QuestieLearner.lua — lines 958959, 1114 (already patched prior to this handoff)
  • Tests/QuestieLearner_spec.lua — (unchanged; legacy reference)