Ascension sometimes reuses a Blizzard questId for custom content whose
group/tag status differs from the original (e.g. 253 "Bride of the
Embalmer" is a real group quest here but zeroed by QuestTag.lua for
TBC+/WotLK clients). Once a quest is accepted, QuestieDB.GetQuestTagInfo
now checks the live questLog entry's questTag before falling back to
questTagCorrections and the static QuestTag.lua table. Compat.lua gains
QuestTagNameToId, a reverse lookup built from questTagToName.
Lua 5.0 (Vanilla 1.12) has no % operator outside string formatting; it is a
parse error. Route the 9 arithmetic modulo sites through the existing math.mod
shim (Compat/Compat.lua) so the addon parses on 5.0 through Retail.
Sites: QuestieDB daily/weekly flag tests, QuestieEvent DMF cycle math,
QuestieLearner GUID/flag math, QuestiePlayer race/class flag tests.
Brings the still-needed changes from questie-phase1perf that main lacked.
Main already had the Lua 5.0 shims (QuestieLoader bit/strsplit, QuestieStream
and QuestieSerializer math.mod sweep), so those are omitted.
- QuestieNameplate: skip missing entries instead of return-aborting the whole
activeGUIDs loop (one bad unit no longer stalls every nameplate update)
- QuestieQuest.ClearAllNotes: skip DB-missing quests instead of aborting, so
remaining quests' notes still get cleared
- QuestieOptionsTracker: fix fadeTickerValue:Cancel -> fadeTicker:Cancel (3x);
fadeTickerValue is a number, the ticker handle is fadeTicker
- QuestieCommsData: nil-guard GetNPC/GetObject before reading .name
- QuestieAnnounce: bound the alreadySentBandaid dedup cache (reset at 1000)
- QuestieDB.IsComplete: hoist GetQuest into expectedQuest (one call, not two)
- QuestieFramePool/QuestieFrame: drop the dead BaseOnUpdate ticker branch
(BaseOnUpdate was never defined; behavior was always OnUpdate=nil)
- QuestieLib: document unused questId arg on Ascension_IsScalingEnabled
- Database/Corrections x3: strip stray UTF-8 BOM
- Questie-X.toc: remove duplicate QuestieSlash.lua load line
Ascension board bounties (e.g. NPC 24 'Outlaw's Contract Board') aren't
reliably flagged repeatable, so IsRepeatable missed them and their ! kept
showing below 60. Add QuestieDB.IsBoardQuest (detects starter NPC/object
names containing 'board', cached per quest); the hide-below-60 option now
hides repeatable OR board quests in both the draw path and ShouldBeHidden.
- 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).
In learner-only mode the map/minimap drew curated AscensionDB (and static)
spawns for every quest NPC/object the player had not personally recorded.
GetNPC/GetObject fall back to the npcDataOverrides/objectDataOverrides
entry for metadata when there is no learner record, and that entry's
spawns (AscensionDB-curated for un-recorded entities) were drawn as pins.
Both now track whether a real learner record exists and, in learner mode,
strip spawns when it does not -- so learner-only shows exclusively what the
learner recorded (metadata fallback for names/tooltips kept). GetObject
also now nils the override in learner mode to match GetNPC. Recorded
entities still show their learner spawns; auto/static/none unchanged.
Verified test-neutral on the full suite (144 successes / same 7 pre-existing
failures) with a local regression test that passes with the fix and fails
without it.
Re-adds the 'Show data source' tooltip option (General tab, default off),
but accurate this time. The previous version was removed because it
guessed the source from the global data-source mode (showing Learner when
data was AscensionDB, etc.). This tags each pin with its real provenance
at creation and reads that tag.
- QuestieDB.GetPinDataSource(entityType, id, spawnData): resolves
Learner (per-spawn isLearned or learner record), AscensionDB (curated
ascensionOverrideKeys override), or base Questie DB. Never guesses.
- Objective pins tagged per-spawn in _DetermineIconsToDraw; available/
finisher pins defaulted by quest in DrawWorldIcon; manual notes tagged
Townsfolk in DrawManualIcon.
- World-map pins read the per-pin tag (MapIconTooltip); unit/object/item
hovers derive per-id at the render layer (TooltipHandler via
QuestieTooltips:GetDataSourceLine). Comms appended via KeyExists.
- No line shown when source is genuinely unknown (never misleading).
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.
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.
In 'auto' data-source mode, QuestieDB.GetQuest now overlays the
SavedVariables learner record on top of the static DB quest, filling only
nil fields and deep-merging objectives/objIndex. Fixes quests like 8325
where the shipped DB has only a stub record but QuestieLearner holds the
real objective mapping that the stub was blocking. Learner data never
overwrites a present static value, so it strictly enriches.
- Add CopySpawnTable and MergeSpawnTables helpers to deep-merge spawn
coordinate lists (zoneId -> {{x,y}, ...}) instead of replacing them
wholesale. Previously an override containing spawns would clobber the
base list, reducing visible pins for any NPC with partial overrides
(Sunstrider Isle calibration, Ascension area-specific fixes, etc.).
- _MergeOverride now special-cases the 'spawns' key to call the merger
with the base spawn table as a fallback when override is empty.
- GetSuppressedNPCs/Objects now check ld.settings.enabled alongside
prioritizeMyData. When the learner is fully disabled, the suppression
pass is skipped entirely (additive and AND-only).
- 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.
Two fixes for QuestieLearner real-time pin rendering:
1. _MergeOverride now skips empty tables (IsEmptyTable guard).
QuestieLearner stores spawns={} before any coords are captured.
Previously _MergeOverride treated {} as valid data and replaced the
base DB's real spawn coordinates with an empty table, breaking pins
for all NPCs that had been seen but not killed (mouseovers, etc.).
2. _InvalidateSpawnListsForNPC triggers after LearnNPC adds new spawn data.
The quest objective system caches spawnList once per objective.
When a kill adds new coordinates, the cached list is stale.
The new helper:
- Scans all active quest objectives for references to the NPC
- Clears objective.spawnList and objective.AlreadySpawned
- Calls QuestieQuest:UpdateQuest to rebuild pins with fresh data
This makes learned pins appear in real-time without /reload.
In Lua, 0 evaluates as truthy. The check
'if questLogEntry.isComplete then return questLogEntry.isComplete end'
was completely bypassing our fallback completion logic because
GetQuestLogTitle sets isComplete = 0 when a quest is incomplete.
This caused the arrow to still point to requiredSourceItems (like
the Cold Iron Key drops) because the quest was never being flagged
as 'isComplete=true' internally.
Fixed by explicitly checking for isComplete == 1 or isComplete == -1
before returning.
The finished flag in QuestLogCache is only set to true when the server
sends isComplete=1 via GetQuestLogTitle. For quest 12843 ('They Took
Our Men!'), after using all Cold Iron Keys the objectives numerically
complete (5/5) but isComplete=1 may not fire until the player visits
the turn-in NPC.
Use numFulfilled == numRequired as the completion check instead, which
updates from GetQuestLogLeaderBoard immediately when each objective
fills. Added numRequired > 0 guard to avoid trivially matching
zero-required objectives.
The inline ternary short-circuited to 0 as soon as objectives[1]
existed, regardless of whether all objectives were done. This caused
quests using consumable key items (e.g. Cold Iron Key for quest 12843)
to incorrectly return IsComplete=0 after using the key, since the key
is no longer in the bag (CheckQuestSourceItem=false) and
questLogEntry.isComplete is not set by the server until after
explicit turn-in.
Now iterates questLogEntry.objectives and returns 1 if all are
finished, so PopulateObjectiveNotes routes to AddFinisher correctly.