Commit Graph

91 Commits

Author SHA1 Message Date
Xurkon 0ebfb51ded fix(learner): capture spawn coords via HBD so learner pins persist
GetPlayerCoords used raw GetPlayerMapPosition('player'), which returns
0,0 when the world map isn't on the player's zone (the usual case) and
mis-reports on Ascension subzones like Sunstrider. Learn events captured
no position, so NPCs were saved spawnSource='fallback' with no [7]
spawns and their learner-only pins never persisted -- showing briefly
after a live kill then vanishing. Read from HBD:GetPlayerZonePosition()
(robust SetMapToCurrentZone/Sunstrider-corrected, cached), falling back
to the old API only if HBD is unavailable.
2026-06-10 21:04:01 -05:00
Xurkon aa50404484 fix(learner): robust safety fallbacks for all learner types
Hardens the learner data-ingestion paths against malformed/partial data
across NPC/object/item/quest types:

- _ValidateLearnedSpawnData now validates object spawn coordinates (key 4)
  in addition to NPC spawns (key 7); object coords were previously
  unvalidated. Extracted a shared _ValidateCoordTable helper.
- _ApplyIncomingNetworkMerge coordinate merge skips malformed zone keys and
  coordinates (non-number / out-of-range) per entry instead of erroring,
  and guards the item drop-list merge against non-number NPC ids.
- The live comms-merge flush isolates each broadcast in a pcall so one
  malformed entry can't abort the batch or break the live-update loop;
  the post-merge InjectLearnedData is also guarded.

Live Learn* entry points already validate id/type. selene 0 errors;
busted 145 successes / same 7 pre-existing failures.
2026-06-10 05:16:51 -05:00
Xurkon dfdad2cbc3 fix(quest/learner): draw turn-in '?' for in-log quests; learn turn-in NPC
Reverts the previous approach of stripping char.complete (which mutated
completed-quest data). Correct rule: a quest in the player's log is active
and should show its turn-in location regardless of the completed flag.

- AddFinisher now trusts the live quest log: if the quest is in
  currentQuestlog and not failed, the '?' finisher draws regardless of the
  (possibly stale, e.g. prior-prestige) char.complete flag. No completion
  data is modified. Reverts the AcceptQuest and QUEST_QUERY_COMPLETE strips.

- Learner: OnTargetChanged now learns quest-giver/turn-in NPC spawns
  (it previously only cached the GUID), so targeting a turn-in NPC records
  its location. OnQuestComplete/OnQuestTurnedIn fall back to the 'target'
  unit when the 'npc' gossip unit is already cleared, so the finisher NPC
  is reliably learned on turn-in.

selene 0 errors; busted 145 successes / same 7 pre-existing failures.
2026-06-10 05:05:28 -05:00
Xurkon 4827a3131e fix(tooltip): copy ElvUI's exact tooltip border (pixel-perfect, even)
The previous ElvUI-style border was too thick and uneven (thicker at the
top): it used Interface\ChatFrame\ChatFrameBackground with edgeSize = 1 UI
*unit*, which renders several physical pixels thick at the user's UI scale,
and a 1x1 texture that samples unevenly along edges.

Now copies ElvUI/Core/Toolkit.lua SetTemplate exactly: the blank texture
E.media.blankTex (Interface\Buttons\WHITE8X8) for bg + edge, and edgeSize =
E.mult (one physical pixel = (768 / screenHeight) / uiScale) so the border
is a true even 1px. Colors unchanged (ElvUI defaults the user runs):
backdropfadecolor {0.06,0.06,0.06} @ colorAlpha 0.8, bordercolor black.

Factored into QuestieTooltips:ApplyElvUISkin so the secondary learner frame
and the default tooltips share one implementation.
2026-06-09 22:06:46 -05:00
Xurkon 86e37857c0 fix(learner): don't purge NPCs with name/zone/kills/quests but no spawns
The InjectLearnedData purge loop was deleting entire NPC entries from
Questie.dbLearner.global.npcs whenever data[7] (spawns) was empty,
even if the entry still had a name, home zone, recorded kills, or
quest references. This caused learner data to silently disappear on
/reload for NPCs that had been learned but never killed in a position
the learner could record (e.g. party-kill position attribution fix
now passes nil coords for uncredited kills).

Now only purges when ALL of name, zone, kills, and quest references
are missing. Entries with other useful state get data[7] set to nil
instead so the row stays.
2026-06-09 22:02:39 -05:00
Xurkon fa37ab8eb5 feat(tooltip): ElvUI style without ElvUI; source in secondary only; fix learner source label
- ElvUI tooltip style: new 'ElvUI tooltip style' option (General tab, on by
  default) skins GameTooltip/WorldMapTooltip/ItemRefTooltip/shopping tooltips
  and the secondary learner frame with ElvUI's transparent flat look (dark bg
  + thin 1px border) when ElvUI is not installed. Corrected the secondary
  frame fallback that used the chunky WoW border. No-op when ElvUI is loaded.

- Source attribution now shows ONLY inside the secondary learner tooltip when
  'Use secondary learner tooltip' is enabled; removed from the main NPC/object/
  item tooltip and gated off entirely when the secondary tooltip is disabled
  (map-pin source gated the same way).

- Fixed learner-learned pins mislabelled 'AscensionDB': GetPinDataSource is now
  mode-aware and returns 'Learner' in learner mode when the entity has a learner
  record, even if AscensionDB also curates it (curated coords are discarded by
  GetNPC/GetObject in learner mode anyway).

Test-neutral (145 successes / same 7 pre-existing failures + 1 error).
2026-06-09 21:52:55 -05:00
Xurkon 08b266d7ba fix(tooltip): never add learner spawn data to the main tooltip
The 'Use secondary learner tooltip' option's off-path appended learner
spawn/kill lines directly to the main GameTooltip. The toggle now gates
the data entirely: on = shown in the separate secondary frame, off = not
shown anywhere. Learner spawn/kill data is never inline in the main NPC
tooltip under any setting.

Removed the now-unused _AddTooltipSeparator helper and updated the option
description.
2026-06-09 18:20:39 -05:00
Xurkon 1629352eb6 fix(learner): don't record other players' kill positions
On PARTY_KILL and unengaged kills, the learner was recording the local
player's position (GetCurrentPlayerPosition) as the spawn location.
This polluted the learner's spawn map with the wrong coords. Now only
records position for credited kills (your own kills or mobs you damaged
within the last 60 seconds).
2026-06-08 21:51:40 -05:00
Xurkon edbb64fb3d fix(learner): learner-only mode shows only learner data
Three-mode spawn-merge semantics:
- Learner: discard npcDataOverrides (which AscensionDB's _Asc_MergeInto
  populates with curated coords). GetNPC returns learnerRecord only.
  _ApplyNpcLiveUpdate and object-spawn injection use IsAscensionProtected
  (mode-dependent) so learner coords pass through in learner mode.
- Auto: static DB primary, learner fills gaps. Curated spawns protected.
- Static: base DB only.

Also removes the allowSpawnMerge bypass that was the original hole
letting learner coords leak into curated spawns in auto mode.
2026-06-08 21:48:02 -05:00
Xurkon 6a4f715b76 fix(learner): guard HasQuestReferences against flat-number entries on Area 52
Some Area 52 quest records store qData[2][3] as a flat number instead of
a table-of-tables. The inner loop's entry[1] index then crashes with
'attempt to index local entry (a number value)'. Normalize with a
type check before comparing.
2026-06-08 21:36:10 -05:00
Xurkon 011cdb58a9 fix(learner): defer to AscensionDB curated spawns for owned NPCs
Mana Wyrm 15274 (quest 8325) pins rendered in the NE corner because the
learner's Sunstrider spawns leaked into the curated AscensionDB coords.
Root causes:
- In learner mode GetNPC uses rawdata = learner record, and _MergeOverride
  deep-merges spawn tables, so the learner's bad zone (1445 @ 54,12)
  survived since AscensionDB had no entry to displace it.
- The injection guards used IsAscensionProtected(), which returns false in
  learner mode, so the learner overrode AscensionDB-owned spawns. Commit
  0f20ea8 had also added a (not learnerLiveMode) bypass to the
  _MergeSpawnEvidence Sunstrider guard, re-enabling the e80a008 regression.

Fixes:
- QuestieDB.GetNPC: for AscensionDB-owned NPC spawns (direct
  ascensionOverrideKeys check), use ONLY the curated override spawns and
  discard the merged learner zones.
- New mode-independent AscensionOwnsNpcSpawns() helper; used by the
  InjectLearnedData spawn restore and the _MergeSpawnEvidence guard
  (removed the (not learnerLiveMode) bypass).

Regression test asserts GetNPC returns only the curated 1241 coords and
drops the learner 1445 zone.
2026-06-08 17:53:16 -05:00
Xurkon a525813f12 fix(learner): restore learned spawns under native uiMapId, not areaId
Follow-up to da5546f: the previous restore read the POST-migration data[7]
keys and ran them through NormalizeSpawnZoneKey. On Sunstrider that round-
tripped uiMapId 1241 -> parent areaId 3430 -> Eversong map 1941, placing
learner pins in the wrong (NE) corner of the map.

Now snapshot each NPC's [7] spawns in their NATIVE uiMapId space BEFORE the
uiMapId->areaId migration runs, and restore from that snapshot with no key
conversion. This keys the override exactly like the live _MergeSpawnEvidence
kill path (e.g. 1241 for Sunstrider), so pins render on the correct map and
HBD isSameZoneSpace handles Eversong<->Sunstrider visibility. Still gated by
IsAscensionProtected. Regression test extended to assert spawns land on 1241
and NOT 1941/3430/3431.
2026-06-08 17:36:35 -05:00
Xurkon 6634074096 docs(learner): add regression-guard note at NPC spawn [7] strip
Document why stripping [7] in InjectLearnedData is only safe because the
guarded restore block below re-merges saved spawns (normalized to uiMapId).
Prevents re-introducing bug 7ce0cdc (learner quests losing pins on /reload
until the mob is re-killed).
2026-06-08 16:56:50 -05:00
Xurkon da5546fde0 fix(learner): restore persisted NPC spawns into override on load
InjectLearnedData stripped each learned NPC's spawn field [7] when injecting
into npcDataOverrides (CopyWithoutField(data,7) / k~=7), deferring to
_MergeSpawnEvidence. That promoter only runs on live kill evidence, so spawns
learned in a prior session never returned to the queryable DB on /reload, and
a freshly accepted quest (8325 -> Mana Wyrm 15274 on Sunstrider) had no pins
until the mob was re-killed.

Re-merge the saved [7] spawns into the override at injection time, normalized
to the canonical uiMapId via NormalizeSpawnZoneKey (so an areaId left by the
uiMapId->areaId migration, e.g. 3431/3430, maps back to 1241 for the renderer/
HBD), deep-merged with InsertIfNewBucket, and gated by IsAscensionProtected so
curated AscensionDB coords are never overwritten (always restored in learner
mode; in auto mode only non-curated NPCs). Regression from 7ce0cdc.
2026-06-08 16:51:58 -05:00
Xurkon d92ae93870 fix(learner): seed objective pins on accept; handle monster objectives
OnQuestAccepted now seeds objective pins directly from the SavedVariables
learner payload (objIndex) on accept in learner mode, instead of waiting
for quest-log text sync — so quests like 8325 spawn pins immediately when
the objective mapping already exists. The accept-time ID lookup is widened
from killcredit to also cover monster objectives, and falls back to
objData.Id when no IdList is present.
2026-06-08 08:00:15 -05:00
Xurkon 5b576911d7 fix: tooltip flicker, learner quest field mapping, secondary tooltip style
- QuestieLib.GetColoredQuestName now nil-guards QuestieDB.GetQuest() before reading .isComplete
- TooltipHandler.AddItemDataToTooltip re-keyed on itemId only (was firing on every ElvUI refresh)
- Removed unconditional ResizeTooltip call from item tooltip path (caused first-hover pop)
- OnQuestDetail no longer writes objectives text to data[6] or quest body to data[17] or zoneId to data[8]
- OnQuestAccepted documents why requiredLevel/requiredRaces/requiredClasses are intentionally not captured
- Reused logIdx from data build pass instead of redeclaring it for the objective scan
- Secondary learner tooltip now matches GameTooltip style with or without ElvUI (defers to ElvUI when loaded, replicates its Transparent template otherwise)
- Combined-tooltip learner stats now framed by invisible spacer lines for visual separation
2026-06-07 08:38:12 -05:00
Xurkon 1ca426ee9f feat: expand learner tooltip controls 2026-06-06 14:30:07 -05:00
Xurkon 1f3de0e02e feat: add learner tooltip controls 2026-06-06 13:59:31 -05:00
Xurkon 84fefc1c20 fix: validate quest turn in learning 2026-06-06 13:16:51 -05:00
Xurkon a1c6a181fc fix: refresh learner settings live 2026-06-06 12:19:23 -05:00
Xurkon 287751a071 fix: let learner turn-ins drive arrow spawns 2026-06-06 11:48:11 -05:00
Xurkon 4e95418594 fix: gate object learning to quest-related data 2026-06-06 10:35:46 -05:00
Xurkon ccdfa525cf fix: gate learner item learning to quest items 2026-06-06 10:21:36 -05:00
Xurkon ada40add8b fix: invalidate caches after learner updates 2026-06-06 10:07:28 -05:00
Xurkon b0f2088ab7 fix: prefer loot source for item drops 2026-06-06 09:44:51 -05:00
Xurkon 36668338f5 fix: restore learner questgiver and item drop learning 2026-06-06 07:56:29 -05:00
Xurkon cccfa1e81b fix: preserve explicit learner spawn data 2026-06-06 07:44:17 -05:00
Xurkon adb99c68c1 feat: heal learned npc coordinates from repeated kills 2026-06-06 07:21:03 -05:00
Xurkon 85d4a7a1e4 fix: suppress duplicate combat log npc learns 2026-06-06 07:15:05 -05:00
Xurkon 3f105e5782 fix: harden learner compatibility shims 2026-06-06 07:03:16 -05:00
Xurkon bed1e31a2f fix: quiet learner debug and harden vanilla guids 2026-06-06 07:00:30 -05:00
Xurkon 8c593a1cfd fix: correct learner npc and item learning ids 2026-06-06 06:53:38 -05:00
Xurkon 82b5aa86dd fix: harden learner quest accept resolution 2026-06-06 06:38:47 -05:00
Xurkon 6597d20b7d feat: refine learner data source and pin rendering 2026-06-06 00:04:50 -05:00
Xurkon 5e3d1b4fd3 fix: learn object quest objectives 2026-06-05 21:32:10 -05:00
Xurkon 0f20ea8aad fix: learn more combat kills 2026-06-05 21:22:14 -05:00
Xurkon 11b78cf3ce fix: route learner diagnostics to learner debug 2026-06-05 21:12:13 -05:00
Xurkon 15023b4a3a fix: learn credited unit died kills 2026-06-05 21:01:56 -05:00
Xurkon 64d5fb2f10 fix: keep learner mode live 2026-06-05 20:51:42 -05:00
Xurkon 9d02c8a231 fix: fully clear learned data buckets 2026-06-05 20:37:34 -05:00
Xurkon 3eda8d01ed fix: force learner on when base db is missing 2026-06-05 20:23:29 -05:00
Xurkon a0409eef8c feat: add learner/static data source mode 2026-06-05 20:15:26 -05:00
Xurkon 3f87e04c75 fix: learn gameobjects from used events 2026-06-05 19:19:11 -05:00
Xurkon fa8b204a8f fix: trace loot source gameobjects 2026-06-05 19:13:16 -05:00
Xurkon ad8f85bf63 fix: trace learner object captures 2026-06-05 19:06:13 -05:00
Xurkon cd01a537f3 Merge branch 'tooltip-ascensiondb-precedence' into questie-learner-comms-improvements 2026-06-05 18:22:12 -05:00
Xurkon 9fcb1988da fix: preserve learner party kill updates 2026-06-05 14:19:42 -05:00
Xurkon 1f6b6b14dc perf: align learner debounce defaults 2026-06-05 14:10:58 -05:00
Xurkon d1f79fd73e fix: prefer ascension tooltip data 2026-06-04 22:36:42 -05:00
Xurkon 5e3ac7cdd1 fix: synchronize learner performance options 2026-06-04 16:59:37 -05:00