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
This commit is contained in:
+7
-2
@@ -193,7 +193,7 @@
|
||||
<li><strong>Root Cause (Player Position)</strong>: <code>HBD:GetPlayerWorldPosition()</code> returns a non-nil value on Sunstrider Isle, but those coords are Eastern Kingdoms world position (wrong), not Sunstrider's actual position. Because a non-nil value is returned, the fallback chain never fires. The arrow then calculates distance using wrong player coords vs correct target coords, giving a wildly incorrect distance.</li>
|
||||
<li><strong>Root Cause (Ghost Map Player Position)</strong>: <code>C_Map.GetPlayerMapPosition(946, "player")</code> where <code>946</code> is Ascension's ghost/cosmic map for Sunstrider Isle returns <code>(0, 0)</code> because the ghost map has no valid coordinate data. The correct map for player position on Sunstrider is <code>1941</code> (Eversong Woods parent), which shares the same world coordinate space and returns valid zone coords.</li>
|
||||
<li><strong>Root Cause (OnUpdate same-map check)</strong>: <code>OnUpdate</code> was using <code>_ResolveArrowUiMapId(_arrow_playerUiMapId)</code> (which resolves 1241→1941) for the player-side uiMapId, making it equal to <code>target.uiMapId</code> (also 1941). This caused the same-map branch to fire, which then called <code>C_Map.GetPlayerMapPosition(_arrow_playerUiMapId)</code> with 946, getting <code>(0, 0)</code> and computing wrong distance.</li>
|
||||
<li><strong>Fix — QuestieArrow.lua UpdateNearestTargets</strong>: Added Sunstrider detection (<code>zoneId == 3430</code>) <em>before</em> calling <code>HBD:GetPlayerWorldPosition()</code> to force the C_Map fallback path. The fallback now calls <code>C_Map.GetPlayerMapPosition(1241, "player")</code> to get Sunstrider map-space coords, then converts through <code>HBD:GetWorldCoordinatesFromZone(..., 1941)</code> using Eversong Woods bounds — which share Sunstrider's world coordinate space.</li>
|
||||
<li><strong>Fix — QuestieArrow.lua UpdateNearestTargets</strong>: Added Sunstrider detection (<code>zoneId == 3430 OR 3431 OR uiMapId == 1241</code>) <em>before</em> calling <code>HBD:GetPlayerWorldPosition()</code> to force the C_Map fallback path. All 4 Sunstrider detection checks in QuestieArrow.lua now accept zoneId 3430 OR 3431 OR uiMapId 1241 (lines 354, 395, 747, 782), since <code>GetCurrentZoneId()</code> can return either 3430 or 3431 when the player is physically on uiMap 1241. The fallback now calls <code>C_Map.GetPlayerMapPosition(1241, "player")</code> to get Sunstrider map-space coords, then converts through <code>HBD:GetWorldCoordinatesFromZone(..., 1941)</code> using Eversong Woods bounds — which share Sunstrider's world coordinate space.</li>
|
||||
<li><strong>Fix — QuestieArrow.lua OnUpdate same-map branch</strong>: Changed <code>C_Map.GetPlayerMapPosition(1941, "player")</code> for player zone coords (not <code>_arrow_playerUiMapId</code> which is 946). Normalizes both <code>playerUiMapId</code> and <code>targetUiMapId</code> through <code>_ResolveArrowUiMapId()</code> before same-map comparison. Uses <code>zoneScale = 13.53</code> yards/zone-unit for distance. Declares <code>worldPlayerX/Y</code> before the if-else to prevent nil in debug prints.</li>
|
||||
<li><strong>Debug Output</strong>: Added debug prints showing UnitPosition vs HBD player coords comparison, raw vs resolved uiMapIds, branch selection, and per-frame distance calculation inputs.</li>
|
||||
</ul>
|
||||
@@ -203,9 +203,14 @@
|
||||
<li><strong>Root Cause</strong>: <code>HBDPins:HandlePin</code> (<code>HereBeDragons-Pins-2.0:424</code>) has an early-return guard: <code>if not HBD.mapData[uiMapID] then return end</code>. When the player zooms into Sunstrider Isle, <code>uiMapID</code> is 1241, but <code>HBD.mapData[1241]</code> is nil — no mapData entry existed for Sunstrider's custom child map. The icon was silently dropped before any coordinate conversion occurred.</li>
|
||||
<li><strong>Fix — Compat/HBD.lua</strong>: Added <code>mapData[1241] = mapData[1941]</code> alias and <code>mapData[946] = mapData[1941]</code> alias. Sunstrider Isle (1241) and its ghost map (946) share Eversong Woods' (1941) world coordinate space for these conversions.</li>
|
||||
<li><strong>Fix — HBD fallback loading</strong>: Added a lazy fallback to the real HBD library's <code>mapData</code> for maps not present in Questie's compat table, so custom/private-server maps can still resolve world and zone coordinates when <code>QuestieCompat</code> lacks a local entry.</li>
|
||||
<li><strong>Fix — Modules/Map/QuestieMap.lua</strong>: Added <code>_ResolveMapUiMapId()</code> helper (1241→1941) applied across <code>FadeLogic</code>, <code>FindClosestStarter</code>, <code>GetNearestSpawn</code>, and <code>GetNearestQuestSpawn</code>. <code>DrawWorldIcon</code> and <code>DrawManualIcon</code> now also store and render Sunstrider map icons against the resolved parent map coordinate space.</li>
|
||||
<li><strong>Fix — Modules/Map/QuestieMap.lua</strong>: Originally added <code>_ResolveMapUiMapId()</code> helper (1241→1941) to redirect Sunstrider pins to Eversong's coordinate space. This redirect was later <strong>removed</strong> so pins on 1241 render natively using Ascension-calibrated bounds. Added <code>areaIdToUiMapId[1241] = 1241</code> mapping in zoneDB.lua so <code>DrawWorldIcon</code> can place pins directly on the Sunstrider sub-map. HBD's ZONE_REDIRECT visibility (<code>ResolveZone(1241)=1941</code>) ensures pins on 1241 are also visible on the Eversong map.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><strong>[Fix — Sunstrider zoneId 3431 Detection]</strong> <code>GetCurrentZoneId()</code> returns 3431 (Eversong Woods) when the player is physically on uiMap 1241 (Sunstrider Isle), not 3430 as previously assumed. All 4 Sunstrider detection checks in QuestieArrow.lua now accept zoneId 3430 OR 3431 OR uiMapId 1241 (lines 354, 395, 747, 782). Without this fix, NONE of the Sunstrider coordinate overrides triggered, causing the arrow to compute player and target positions in different coordinate spaces (858 yard offset).</li>
|
||||
<li><strong>[Fix — Arrow Rotation Direction]</strong> WoW's <code>Texture:SetRotation(r)</code> rotates CW for positive r, NOT CCW as the code comment claimed. Changed <code>rotAngle = -relative</code> to <code>rotAngle = relative</code> (line 441). The arrow was rotating in the opposite direction of the target, pointing away instead of toward it.</li>
|
||||
<li><strong>[Fix — Collection Function Distance Mismatch]</strong> <code>_CollectFinisherSpawns</code> and <code>_CollectObjective</code> converted targets through 1941 (Eversong) bounds while player coordinates were in 1241 (Sunstrider) bounds. Added <code>sunOverride = (pMap == 1241)</code> variable and forced target conversion through 1241 bounds at all 4 conversion sites in both functions. Without this fix, sortedTargets showed dist=1261 instead of the correct ~48 yards.</li>
|
||||
<li><strong>[Fix — NPC Spawn Zone for Sunstrider]</strong> NPC 15281 (Lanthan Perilon) spawn data changed from zone 3430 to zone 1241. Coordinates gathered via <code>GetPlayerMapPosition</code> on uiMap 1241 are in 1241's normalized space, NOT 1941's. Using zone 3430 (→1941) produced world coordinates outside 1241's 0-1 range, making map pins invisible on the Sunstrider sub-map.</li>
|
||||
<li><strong>[Fix — Sunstrider Map Pin System]</strong> Removed the 1241→1941 redirect in <code>_ResolveMapUiMapId()</code>. Pins on 1241 now render natively using Ascension-calibrated bounds instead of being forced to 1941's coordinate space. Added <code>areaIdToUiMapId[1241] = 1241</code> mapping in zoneDB.lua so <code>DrawWorldIcon</code> can place pins directly on the Sunstrider sub-map.</li>
|
||||
<li><strong>[Fix — Northshire Valley UiMapData Registration]</strong> Added explicit <code>QuestieCompat.UiMapData[1238]</code> for Northshire Valley so custom/private-server zone lookups have concrete geometry for the child map instead of relying on incomplete parent fallbacks.</li>
|
||||
<li><strong>[Fix — QuestieLearner Icon Preservation]</strong> Preserved the learned objective icon when registering with the tooltip system so nameplates can render the correct learned slay/loot/talk marker. Previously the icon was always nil on fresh registration.</li>
|
||||
<li><strong>[Notes — Failed Approaches Documented]</strong> The unreleased notes now explicitly capture the Sunstrider approaches that did <em>not</em> work:
|
||||
|
||||
+6
-6
@@ -224,8 +224,8 @@
|
||||
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
<h4>Sunstrider Coordinate Normalization</h4>
|
||||
<p>Arrow and world-map code now normalize Sunstrider's child map <code>1241</code>, ghost map <code>946</code>, and parent Eversong map <code>1941</code> into a consistent coordinate path so distance, direction, and icon placement all use the same world space.</p>
|
||||
<h4>Sunstrider Coordinate Normalization (Final)</h4>
|
||||
<p>Arrow and world-map code now normalize Sunstrider's child map <code>1241</code>, ghost map <code>946</code>, and parent Eversong map <code>1941</code> into a consistent coordinate path. <code>GetCurrentZoneId()</code> can return 3430 <em>or</em> 3431 on Sunstrider — all 4 detection checks now accept both values plus uiMapId 1241. The 1241→1941 redirect in <code>_ResolveMapUiMapId()</code> was removed; pins render natively on 1241 via <code>areaIdToUiMapId[1241] = 1241</code>.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h4>Learned Tooltip Schema Fix</h4>
|
||||
@@ -235,12 +235,12 @@
|
||||
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
<h4>Custom Map Data Aliases</h4>
|
||||
<p><code>Compat/HBD.lua</code> now aliases Sunstrider map data (<code>1241</code> and <code>946</code>) to Eversong (<code>1941</code>) and can fall back to the real HBD library's <code>mapData</code> for maps not present in Questie's local compat table.</p>
|
||||
<h4>Arrow Rotation & Collection Fixes</h4>
|
||||
<p>Fixed arrow rotation direction (<code>SetRotation</code> is CW-positive, not CCW) and collection function distance mismatch where targets were converted through 1941 bounds while player coords were in 1241 bounds, causing 1261-yard errors instead of ~48 yards.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h4>QuestieLearner Icon Preservation</h4>
|
||||
<p>Learned objectives now preserve the resolved quest-log icon during immediate tooltip registration so nameplates can render the correct learned slay/loot/talk marker instead of a missing icon state.</p>
|
||||
<h4>NPC Spawn Zone & Native Map Pins</h4>
|
||||
<p>NPC 15281 (Lanthan Perilon) spawn zone corrected from 3430 to 1241 so coords land in Sunstrider's 0-1 space. Pins on 1241 now render natively using Ascension-calibrated bounds with <code>areaIdToUiMapId[1241] = 1241</code> instead of redirecting to 1941.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ NPC spawn data: zone 3430 (Eversong) → GetUiMapIdByAreaId(3430) → uiMapId 19
|
||||
| Lookup | From | To | Purpose |
|
||||
|--------|------|----|---------|
|
||||
| `GetUiMapIdByAreaId(3430)` | areaId 3430 | uiMapId 1941 | Pin placement on Eversong map |
|
||||
| `GetAreaIdByUiMapId(1241)` | uiMapId 1241 | areaId 3430 | Zone ID for spawn data keys |
|
||||
| `GetUiMapIdByAreaId(3431)` | areaId 3431 | uiMapId 1941 | Pin placement on Eversong map (Sunstrider subzone) |
|
||||
| `GetAreaIdByUiMapId(1241)` | uiMapId 1241 | areaId 3431 | Zone ID for spawn data keys (Sunstrider subzone) |
|
||||
| `_ResolveMapUiMapId(1241)` | uiMapId 1241 | uiMapId 1941 | Normalize pin rendering |
|
||||
| `_ResolveArrowUiMapId(1241)` | uiMapId 1241 | uiMapId 1941 | Arrow math normalization |
|
||||
| `ZONE_REDIRECT[1241]` | uiMapId 1241 | uiMapId 1941 | Cross-visibility |
|
||||
@@ -32,7 +33,7 @@ percentages (e.g., NPC 15278 at 38.02%, 21.01%). These render correctly on
|
||||
the Eversong map (1941). Mapping 3430→1241 would place Eversong-wide
|
||||
coordinates on the Sunstrider sub-map, producing wrong positions.
|
||||
|
||||
Pins from zone 3430 render on uiMapId 1941 (Eversong) and appear on uiMapId
|
||||
Pins from zones 3430 and 3431 render on uiMapId 1941 (Eversong) and appear on uiMapId
|
||||
1241 (Sunstrider) via ZONE_REDIRECT visibility, which works because
|
||||
`ResolveZone(1241) == ResolveZone(1941) == 1941`.
|
||||
|
||||
@@ -54,6 +55,7 @@ Pins from zone 3430 render on uiMapId 1941 (Eversong) and appear on uiMapId
|
||||
- `_ResolveArrowUiMapId(1241)` → 1941
|
||||
- `_ResolveArrowUiMapId(946)` → 1941
|
||||
- Comment updated to match new approach
|
||||
- **Arrow rendering**: Replaced sprite sheet (108-frame) with single-frame texture + `SetRotation(-angle)` for infinite angular resolution and zero jitter. Arrow texture is now X-PLORE's `XPArrow4.tga` (256×256 RGBA, arrow pointing UP centered at 128,128). Removed all `ARROW_SHEET_*`, `ARROW_CELL_*`, UV math, and `SetTexCoord` cell selection logic. Arrow uses `ARROW_DISPLAY_SIZE=96` for on-screen pixel size and `SetPoint("CENTER")` anchor for clean rotation pivot. `SetVertexColor(1,1,1)` preserves original blue color.
|
||||
|
||||
### Modules/QuestieLearner.lua
|
||||
- `GetZoneId()`: Returns areaId via `ZoneDB:GetAreaIdByUiMapId(uiMapId)` with fallback
|
||||
@@ -233,4 +235,72 @@ Expected: `ResolveZone(1241)= 1941 ResolveZone(946)= 1941`
|
||||
- [ ] Kill 1 NPC on Sunstrider, check learned data shows zone=3430 (not 1241)
|
||||
- [ ] After 1+ kill, verify learned pin auto-appears at correct position
|
||||
- [ ] Verify Eversong Woods NPCs NOT on Sunstrider show correctly on Eversong map
|
||||
- [ ] Check no regressions on other zones
|
||||
- [ ] Check no regressions on other zones
|
||||
- [ ] **Complete-abandon-reaccept cycle**: Complete a quest's objectives → abandon → re-accept → verify pins appear for fresh 0/X objectives
|
||||
- [ ] **Arrow rendering**: Verify arrow shows a single blue arrow (not sprite sheet), smooth rotation with no visible frame transitions, correct direction toward quest objectives, and correct display size
|
||||
- [ ] **Learner data in arrow**: Verify arrow targets point to QuestieLearner-injected NPC spawn locations correctly
|
||||
- [ ] **QUEST_TURNED_IN auto-complete**: Verify quests that auto-complete on turn-in clean up state properly (no orphan pins)
|
||||
|
||||
## Complete-Abandon-Reaccept Pin Lifecycle Fix (Session 2026-05-17)
|
||||
|
||||
### Bug Chain
|
||||
|
||||
Four interacting bugs prevented map pins and GPS arrow from reappearing after
|
||||
completing quest objectives, abandoning the quest, and re-accepting it:
|
||||
|
||||
1. **MarkQuestAsAbandoned `objectivesWereComplete` path** — called `CompleteQuest`
|
||||
without clearing `quest.Objectives`, `quest.WasComplete`, or `quest.isComplete`.
|
||||
Stale `Completed=true` + `isUpdated=true` flags caused `PopulateObjectiveNotes`
|
||||
to skip drawing pins on re-accept.
|
||||
|
||||
2. **CompleteQuest** — did not clear `quest.Objectives` (unlike `AbandonedQuest`
|
||||
which does). Now adds `quest.Objectives = {}` with type guard as defense-in-depth.
|
||||
|
||||
3. **QUEST_TURNED_IN dead code** — `questLog[questId] = {}` wiped state before the
|
||||
QUEST_TURNED_IN state check could read it, making auto-complete cleanup unreachable.
|
||||
Moved the check before the wipe.
|
||||
|
||||
4. **AcceptQuest reset** — added `SetObjectivesDirty(questId)` in the re-accept block
|
||||
to ensure `isUpdated` flags are reset even if stale objectives survive.
|
||||
|
||||
5. **Arrow spawnList gap** — `_CollectObjective` silently skipped objectives with
|
||||
nil/empty `spawnList`. After quest re-accept, `PopulateQuestLogInfo` creates
|
||||
objectives without `spawnList`; `PopulateObjectiveNotes` builds it later in the
|
||||
TaskQueue. Added `QuestieQuest:BuildObjectiveSpawnList(objective, objectiveData)`
|
||||
public API that lazily builds `spawnList` from `objectiveSpawnListCallTable` handlers.
|
||||
The arrow now calls this when `spawnList` is missing.
|
||||
|
||||
### Files Changed
|
||||
|
||||
- **QuestEventHandler.lua** (~line 443-461): MarkQuestAsAbandoned — clear stale
|
||||
objectives/flags + SetObjectivesDirty before CompleteQuest
|
||||
- **QuestEventHandler.lua** (~line 233): QUEST_TURNED_IN — moved state check before
|
||||
questLog[questId] = {} wipe
|
||||
- **QuestieQuest.lua** (~line 492): AcceptQuest reset — added SetObjectivesDirty(questId)
|
||||
- **QuestieQuest.lua** (~line 583): CompleteQuest — added `quest.Objectives = {}`
|
||||
- **QuestieQuest.lua** (~line 1996-2018): New `BuildObjectiveSpawnList` public API
|
||||
- **QuestieArrow.lua** (~line 726-760): _CollectObjective — lazy spawnList building
|
||||
via `QuestieQuest:BuildObjectiveSpawnList()`
|
||||
## UpdateQuest Pin Refresher Fallback (Session 2026-05-17)
|
||||
|
||||
### Problem
|
||||
After reload or abandon-reaccept, incomplete quests sometimes have no objective pins
|
||||
on the map even though they are in the quest log. This happens when:
|
||||
1. `PopulateQuestLogInfo` hits a cache miss and leaves `quest.Objectives` empty.
|
||||
2. `UnloadQuestFrames` removes map frames but `AlreadySpawned` is not cleared,
|
||||
so `_DetermineIconsToDraw` skips recreating icons on the next refresh.
|
||||
|
||||
### Fix
|
||||
Added a robustness fallback in `QuestieQuest:UpdateQuest()` (incomplete branch):
|
||||
- If `quest.Objectives` is empty → re-call `PopulateQuestLogInfo()`, then
|
||||
`PopulateObjectiveNotes()` if objectives were created.
|
||||
- If objectives exist but `QuestieMap.questIdFrames[questId]` is nil → clear
|
||||
`objective.AlreadySpawned = {}` for all objectives, then re-call
|
||||
`PopulateObjectiveNotes()` to force icon recreation.
|
||||
|
||||
This ensures that ANY incomplete quest in the log gets its pins re-added on the
|
||||
next periodic refresh (30s) or `QUEST_LOG_UPDATE` if they were lost.
|
||||
|
||||
### Files Changed
|
||||
- **QuestieQuest.lua** (~line 833): Added `hasObjectives` / `hasFrames` fallback
|
||||
in the `isComplete == 0` branch of `UpdateQuest`.
|
||||
|
||||
Reference in New Issue
Block a user