38 Commits

Author SHA1 Message Date
Narcasung b4e0894c3f fix(map): remove redundant scale-mismatched icon cull on world map
The manual overflow cull in HandleWorldMapPin compared icon:GetCenter()
against WorldMapScrollFrame's bounds without normalizing effective scale.
Magnify's zoom drags the icon's effective scale via WorldMapDetailFrame,
while the scroll frame's stays constant, so at high zoom ratios the
comparison failed for every icon and hid the whole map. Native
WorldMapScrollFrame:SetScrollChild() clipping (now reachable on all 4
edges since SetDrawOrder correctly detects bundled Magnify) already
handles this without the buggy manual math.
2026-07-15 17:34:38 +02:00
Narcasung 75bebafaa9 fix(quest-tag): prefer live quest log tag over static QuestTag.lua data
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.
2026-07-15 16:20:51 +02:00
Narcasung c09d30b832 Apply local fixes on top of upstream: tracker desync/drag/title, map icon zoom offset
- Compat/HBD.lua: fix world map pin offset math to account for zoom addons
  (e.g. Magnify) rescaling an ancestor frame instead of WorldMapButton itself;
  cull pins that fall outside the scroll frame's viewport when zoomed
- Compat/Compat.lua: add a short TTL to the chat-parsed objective progress
  cache so a stale entry can't be reapplied to an unrelated quest
- Modules/QuestieLearner.lua: re-point QuestiePlayer.currentQuestlog at the
  rebuilt quest table after invalidating QuestieDB's quest cache, fixing
  Tracker freezing on stale objective progress
- Modules/Tracker/QuestieTracker.lua: fall back to a formatted quest name
  when QuestieDB has no title for a quest (e.g. custom server quests)
- Modules/Tracker/TrackerBaseFrame.lua: force baseFrame movability on drag
  start instead of trusting the async-refreshed IsMovable() state
- Modules/Tracker/TrackerHeaderFrame.lua: wire up drag on the tracker icon
- Modules/Quest/QuestEventHandler.lua: force a full quest log reconciliation
  when the native quest log is opened

Squashed from prior commit-by-commit history to rebuild this working copy
on a clean fork of aron-w/Questie-X (restores the native GitHub fork link).
Per-fix rationale is preserved in project memory
(project_tracker_fixes.md, project_map_icon_offset.md).
2026-07-15 01:02:15 +02:00
Xurkon 8898dcf96a fix: harden quest poi filtering and objective refresh 2026-06-13 08:30:41 -05:00
Xurkon 70a99346e6 fix: suppress duplicate native quest POIs 2026-06-12 22:32:24 -05:00
Xurkon 71e172c4d0 fix: sync native objective POIs with Questie icons 2026-06-12 22:20:09 -05:00
Xurkon 9fa0164318 fix: clear quest completion cache on refresh 2026-06-12 21:40:23 -05:00
Xurkon e755416f8a fix(map): align minimap pins at non-1 UI scales 2026-06-11 06:49:51 -05:00
Xurkon cee005fc63 fix(map): pixel-snap minimap icons to align with native blips at fractional scales (#6)
At fractional UI scales (e.g. 0.71 game scale + Windows display scaling)
the raw fractional pin offset landed icons between physical pixels,
rendering blurry and offset from the engine-drawn native quest blips.
Snap the offset to a whole physical pixel via the minimap's effective
scale so Questie's icons sit on the same grid as native markers.
2026-06-10 20:34:20 -05:00
Xurkon 1c0a891efd fix(map): minimap range cutoff no longer clips visible icons (#17)
The cutoff hid icons beyond its yard value before checking the minimap's
visible radius, so the default 100 hid icons that were clearly on the
minimap (view radius is 133-466 yd by zoom). Now it only clips icons
outside the visible circle: HBD's pin renderer gates the cutoff on
dist > 1, and QuestieMap FadeLogic raises the effective cutoff to at
least the current minimap view radius via new HBDPins:GetMinimapRadius().
2026-06-10 19:24:39 -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 f9ff77c088 fix(quest): clear stale char.complete for re-accepted (prestige) quests
A quest completed in a prior Ascension prestige stays in char.complete.
On re-accept it is active in the log again, but the stale completion flag
was never cleared — and AddFinisher only draws the turn-in '?' when
not char.complete[questId]. So the finisher was suppressed and the quest
showed '(Complete)' with stale objective text while standing at the
turn-in NPC (e.g. Aggression 8334 at Lanthan Perilon 15281).

An active in-log quest is now kept out of char.complete:
- QuestieQuest:AcceptQuest clears char.complete[questId] on accept.
- The async QUEST_QUERY_COMPLETE handler also strips any quest currently
  in QuestiePlayer.currentQuestlog, so the server's completed list can't
  re-flag a re-accepted quest.

Restores the turn-in '?' and normal objective tracking. selene 0 errors;
busted 145 successes / same 7 pre-existing failures.
2026-06-10 04:58:44 -05:00
Xurkon ab560d5711 fix(map): completed/accepted/repeatable available-quest pins (#7 #9 #10)
#7: Completed quests kept showing as available '!'. The server completed-
quest list arrives async via QUEST_QUERY_COMPLETE, often after available
quests were first drawn. Recalculate available quests once char.complete is
populated by that event so completed quests are removed (also clears the
already-completed subset of #8).

#9: An accepted quest's available '!' could linger on the minimap until
/reload. UnloadQuestFramesByDataType unloaded the frame but left its name in
questIdFrames and _G; it now removes those references so the icon is torn
down immediately on both map and minimap.

#10: Added 'Hide repeatable quests below level 60' (Icons tab, off by
default) to hide repeatable available quests (e.g. the Ascension Callboard)
from map/minimap until level 60. Enforced in _DrawQuestIfAvailable and
ShouldBeHidden so existing minimap pins are removed too; reappear at 60.

Lint: selene 0 errors. Tests: 145 successes / same 7 pre-existing failures.
2026-06-09 23:18:38 -05:00
Xurkon 4b7c295210 fix: stabilize minimap range cutoff and update release docs 2026-06-03 06:05:55 -05:00
Xurkon 5a112d731b fix(minimap): use live Minimap:GetViewRadius() API + corrected pixel math
- Use 3.3.5a-native Minimap:GetViewRadius() (instance method) instead of
  C_Minimap.GetViewRadius (nil on 3.3.5a) with C_Minimap fallback. Returns
  116.67 at zoom 5 instead of the hardcoded 125 from the broken lookup table.
- Replace minimapWidth = (GetWidth()/2) * (mapRadius/155.52) with
  minimapWidth = GetWidth() * GetScale() / 2. The new formula yields the
  actual half-width of the visible minimap in screen pixels, the correct
  multiplier for diffX*minimapWidth when diffX is normalized by mapRadius.
- Comment out (do not delete) all QDMATH / UPDATE entering / ICON debug
  blocks as --[[ DEBUG: ... --]] for future regression investigation.
- Remove loaded debug scripts from Questie-X.toc and add to .gitignore
  (drift_test, radius_debug, spawn_calibration, etc.). Scripts preserved
  in tests/ for reference.
- Add .gitignore entries for tests/ lowercase variant (case-sensitive
  on Linux/macOS) and additional debug script patterns.
- Update CHANGELOG.md and docs/changelog.html with fix entry.
- Refresh handoff.md to reflect RESOLVED status and iteration 4 history.

Verified: pins now stay anchored to world positions across all zoom levels
on both Stock UI and ElvUI. Per-frame diffX ~0.35 yards during walking
translates to ~0.21 pixels of pin movement (correct for 1 yard of world
movement).
2026-06-01 18:35:39 -05:00
Xurkon 0c034d0ff4 debug(minimap): trace zone->world roundtrip for all pins including 1241 2026-06-01 18:35:39 -05:00
Xurkon 039bdf3627 fix(minimap): remove 1241 special-case overlay from drawMinimapPin
The uiMapID==1241 branch in drawMinimapPin was an experimental overlay
that ran BEFORE the standard minimap projection and rotation transforms.
It duplicated the projection math while bypassing the rotation matrix,
used a different edge-clamp path, and is the primary suspect for why
pins visually follow the player on Sunstrider Isle.

The standard minimap path (handle rotation -> adapt delta to mapRadius
-> apply shape mask -> float-on-edge or clamp) already handles all
pins uniformly regardless of zone. Removing this experimental branch
lets 1241 pins use the same proven path as every other zone.

Also cleaned up:
- stale lastInstanceId reference in throttled PIN debug trace
- unnecessary data.uiMapID guard in QuestieDebugMinimapPin gate
- Sunstrider-specific minimap debug block in UpdateMinimapPins
2026-06-01 18:35:39 -05:00
Xurkon 72b924c514 wip: preserve Sunstrider minimap debugging state 2026-06-01 18:35:39 -05:00
Xurkon 1311ee6fd3 debug(minimap): add /qdrift slash command and throttled PIN debug for drift diagnosis
- /qdrift: one-shot diagnostic that traces the full player-position chain
  (GetCurrentPlayerPosition -> GetWorldCoordinatesFromZone), checks
  mapIdToUiMapId entries, shows pin world coords vs player world coords,
  and verifies zone center bounds
- Throttled [QD] PIN debug in drawMinimapPin (1/sec) showing pinWorld,
  playerWorld, distance, mapRadius, and diff values
- Enhanced [QD] CONV/CONV2 debug in GetCurrentPlayerPosition showing
  raw coords, world coords after conversion, and zone coords after
  back-conversion

Purpose: diagnose why minimap pins follow the player after the areaId fix
2026-06-01 18:35:39 -05:00
Xurkon 4336166d95 fix(minimap): add Ascension areaId mappings to mapIdToUiMapId
Root cause of minimap pin drift on Sunstrider Isle: on Ascension,
GetCurrentMapAreaID() returns 3430 for Eversong, but mapIdToUiMapId only
had the WotLK mapping (463→1941). This meant actualUiMapId was nil in
GetCurrentPlayerPosition(), causing the parent→child zone conversion to
be skipped entirely. Eversong-zone coords passed through tagged as
uiMapID 1241, producing wrong world positions and pin drift.

Fix: add Ascension areaId→uiMapId mappings (3430→1941, 3431→1241) to
mapIdToUiMapId after UiMapData init. Now the conversion path triggers
correctly: Eversong coords → world coords (via 1941 bounds) →
Sunstrider zone coords (via 1241 bounds).

One-line fix in Compat.lua. No changes to HBD.lua or projection logic.
2026-06-01 18:35:20 -05:00
Xurkon efbc0da736 Revert "fix(minimap): zone-space projection for child-map pins (Sunstrider 1241)"
This reverts commit cd65e77af5cafd1ca03fdb4efbafb983dc6d919c.
2026-06-01 18:35:04 -05:00
Xurkon e5d7d42201 fix(minimap): zone-space projection for child-map pins (Sunstrider 1241)
Adds _ComputeZoneSpaceDiff to HBD.lua that computes minimap pin
projection in the parent zone's coordinate space (Eversong 1941) instead
of using the world-coordinate delta. On Ascension, GetPlayerMapPosition
returns Eversong-relative coords for players on Sunstrider, but
GetWorldCoordinatesFromZone(1241) treats them as Sunstrider-relative,
producing a wrong player world position and causing pins to drift or
move opposite to the player.

Fix: (1) Store original zone coords on minimap pins at registration
(AddMinimapIconMap). (2) In drawMinimapPin, recover player's actual
Eversong zone coords by reversing the 1241-bounds conversion. (3)
Convert pin's 1241 zone coord to Eversong zone coord via 1241-world.
(4) Delta in Eversong zone-space, scale to pixels using parent-width/mapRadius.

Falls back to existing world-space math for pins without zone coords.
2026-06-01 18:34:28 -05:00
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
Xurkon 415b924199 fix(Sunstrider): correct map pins, override check, nil guards
- zoneDB: remap areaId 3431 → uiMapId 1241 (Sunstrider Isle) so quest 8335
  pins render on correct map instead of Eversong Woods (1941)
- compat/HBD: remove 1241→1941 redirect (Sunstrider pins now handled by zoneDB)
- compiler: QuerySingle override check skips empty tables (next() guard) so
  spawn data overrides don't fall through to nil base DB values
- MapIconTooltip: nil guards for minLevel/maxLevel to prevent crashes
- Map/QuestieMap: remove stale 1241→1941 redirect comment
2026-05-22 19:31:47 -05:00
Xurkon 24ed0f48b3 fix(arrow): Sunstrider zoneId 3431, rotation CW, collection distance, native map pins
- zoneId detection: accept 3430 OR 3431 OR uiMapId 1241 (4 locations)
- SetRotation is CW-positive: rotAngle=relative (was -relative)
- Collection functions: override target->1241 when player on Sunstrider
- NPC 15281: spawn zone 1241 (not 3430) for correct coord space
- _ResolveMapUiMapId: removed 1241->1941 redirect
- zoneDB: added areaIdToUiMapId[1241]=1241
- Updated CHANGELOG, README, docs
2026-05-21 19:22:40 -05:00
Xurkon bf6ecaedbe v1.6.3-unreleased: Sunstrider zone fixes, QuestieLearner icon preservation, migration, and Busted test suite
Code changes (13 files, +916/-171):
- ZoneDB integration: GetZoneId() converts uiMapId→areaId via ZoneDB reverse lookup
- MIN_CONFIDENCE_PINS reduced to 1 for Ascension (incomplete NPC DBs)
- QuestieLearner icon preservation: objective Icon passed to RegisterObjectiveTooltip
- InjectLearnedData zone migration: converts old uiMapId spawn keys to areaId
- areaId passed through all LearnNPC call sites (OnMouseoverUnit, OnQuestDetail,
  OnQuestComplete, OnQuestAccepted, OnQuestTurnedIn, OnGossipShow)
- Compat/Compat.lua: C_Map.GetPlayerMapPosition UiMapData support
- Compat/HBD.lua: Sunstrider mapData aliases and fallback loading
- Sunstrider arrow fix (QuestieArrow.lua), resolved pin rendering (QuestieMap.lua)
- _MergeOverride helper for string/numeric key compatibility
- Northshire Valley UiMapData registration

Testing infrastructure:
- .busted config pointing to tests/ directory
- Tests/wow_api_mock.lua: WoW API mocks (ZoneDB, C_Map, QuestLogCache, etc.)
- Tests/QuestieLearner_spec.lua: 12 tests covering coordinate scaling, spell cast
  learning, zone migration (NPC/objects), icon preservation, settings defaults,
  and LearnNPC spawn zone tracking
- selene.toml + wow_classic.yml: linter configuration

Documentation:
- Makefile with test/lint/ci targets
- sunstrider-coordinate-collection.md: coordinate data reference
- sunstrider-pin-fix.md: root cause analysis and fix documentation
2026-05-16 07:32:47 -05:00
Xurkon 05ea31bc53 perf: reduce CPU hotspots identified in profiler
- HBD.lua: Cache GetPlayerWorldPosition/GetPlayerZonePosition at 50ms
  intervals instead of hammering GetPlayerMapPosition() every frame.
  Invalidate cache on PLAYER_ENTERING_WORLD and ZONE_CHANGED_* events.
  Expected ~97% reduction in C API position calls (45,570 -> ~1,200 / 10min).

- zoneDB.lua: Replace O(n) linear scan in GetAreaIdByUiMapId with an
  O(1) reverse lookup cache (uiMapIdToAreaIdCache) built at Initialize().
  Cache is kept in sync by ApplyCustomZones and name-match fallback now
  caches its result so subsequent calls are also O(1).

- Tooltip.lua: Throttle GameTooltip OnUpdate hook to 100ms intervals
  (was firing every frame at 60-144 Hz). Added _tooltipLastText cache
  to avoid redundant GetText() + CountTooltip() calls when nothing changed.

- QuestieArrow.lua: Hoist _HasMissingCompletedFlag, _GetCompleteIconType,
  _CollectFinisherSpawns, and _CollectObjective out of _CollectQuestTargets
  to module-level functions. These were re-created as closures on every
  UpdateNearestTargets call (1 Hz). Shared per-cycle context is published
  via _arrow_* module upvalues to avoid closure capture overhead.

- QuestieLearnerComms.lua: Four micro-optimizations:
  (1) Reduce ProcessQueues ticker 0.2s -> 0.5s (still 7x faster than
      minChatInterval of 3.5s).
  (2) Cache hidden channel ID at init; lazy refresh on disconnect.
  (3) Drop LibDeflate compress level 9 -> 1 (fraction of CPU cost).
  (4) O(1) messageCacheCount counter replaces O(n) pairs() size scan.
2026-03-29 16:42:43 -05:00
Xurkon 17dd969793 Fix: Prevent nil index error in QuestieTooltips_RegisterObjectiveTooltip 2026-03-29 11:49:57 -05:00
Xurkon 3af73e9b00 fix: check QuestieCompat.UiMapData directly for custom zones in GetCurrentUiMapID 2026-03-28 22:50:16 -05:00
Xurkon 1fc9727fee v1.4.9: Validation fixes, Profiler fix, Quest link duplicate fix, Ascension fixes 2026-03-26 06:47:54 -05:00
Xurkon 6e34cebead feat: release v1.4.6 - Fix SavedVariables persistence and red textures for MafWow/3.3.5a 2026-03-22 08:30:20 -05:00
Xurkon 2df8a7b96d fix: v1.4.4 - AceGUI pool fixes, event handling nil checks, QuestieLearner serialization, l10n format fixes 2026-03-20 21:16:58 -05:00
Xurkon 5d94cf8f67 feat: v1.4.0 - Code review fixes and taint resolution
- C_Timer OnUpdate uses elapsed param
- IsAchievementCompletion checks completion boolean
- C_Map.GetPlayerMapPosition fixes
- QuestieLearner GUID function forward declarations
- Taint guards on secure hooks (InCombatLockdown + pcall)

Fixes ADDON_ACTION_BLOCKED: UseAction() errors
2026-03-19 19:24:24 -05:00
Xurkon c5c3897421 feat: idempotent quest tracking and robustness improvements v1.3.7 2026-03-19 00:22:26 -05:00
Xurkon 28fc4d5095 chore: release v1.3.5 - Comprehensive Taint & Architecture Fixes 2026-03-18 21:27:48 -05:00
Xurkon c4d003e58f feat: Questie-X v1.1.4 - plugin architecture, monorepo, rebranding
- Repoint remote to Xurkon/Questie-X
- Add QuestiePluginAPI, QuestieServer, QuestieLearnerComms modules
- Add Questie-X.toc, Questie-X-Classic.toc, Questie-X-TBC.toc, Questie-X-Turtle.toc
- Remove embedded Database/Ascension and Database/Ebonhold (migrated to plugins)
- Add Plugins/ directory with NTFS junctions for Questie-X-AscensionDB and Questie-X-EbonholdDB
- Add LibDeflate, XXH_Lua_Lib, LibDBIcon-1.0, LibDataBroker-1.1
- Update README: Questie-X branding, logo, plugin install guide, plugin API docs
- Update CHANGELOG: v1.1.4 entry documenting all architectural changes
- Update .gitignore: exclude plugin junctions, __pycache__, .agents, debug files
- Various module updates: corrections, map, tracker, tooltips, quest, options
2026-03-14 06:10:17 -05:00
Xurkon b13833935a v9.8.9: Badlands Trophy quest, 7:XT NPC data, fix AreaId CRITICAL spam 2026-03-02 21:11:30 -06:00
Xurkon 6ef85d4e2d v9.7.2: Ebonhold Database integration and core logic refinements 2026-02-14 21:13:44 -06:00