Update custom DB quests and bump version to 9.8.5

This commit is contained in:
Xurkon
2026-02-24 20:52:12 -06:00
parent 174c397cf2
commit 8616765eed
27 changed files with 54322 additions and 10 deletions
+153
View File
@@ -0,0 +1,153 @@
# Changelog
## v9.8.2
### Fixes
- **[Quest]** Updated the objective tooltip for "Forging an Alliance" (12924) at King Jokkum to explicitly instruct players to pick up the breadcrumb quest "You Can't Miss Him" (12966).
## v9.8.1
### Fixes
- **[Quest]** Fixed QuestieArrow direction for "Forging an Alliance" (12924). Added an extra objective to speak with King Jokkum, ensuring the arrow points toward the breadcrumb quest start at the beginning of the quest.
## v9.8.0
### Fixes
- **[Quest]** Modified `BAG_UPDATE_DELAYED` to trigger a quest log update and instantly refresh the tracker when items are deposited directly into bags by autoloot bots that bypass standard item events.
- **[Map]** Fixed an issue where "Special Objectives" (e.g., source item drops) failed to check player bag contents upon completion, causing their map icons to linger indefinitely until the main quest was turned in.
## v9.7.12
### Fixes
- **[Quest]** Fixed an issue where tracking icons for dynamically updated custom quests like Peak Predators would prematurely disappear due to sync delays on WotLK servers.
- **[Map]** Resolved a frame pool leak that prevented the yellow Finisher icon from appearing immediately on the map after turning in or completing a quest.
## v9.7.11
### Fixes
- **[Quest]** Fixed an issue where quest objective icons and waypoints failed to clear from the map after a quest was completed or abandoned.
- **[Tracker]** Prevented quests from falsely flagging as complete and wiping tracking data when the World of Warcraft server drops its objective arrays. Fixes "Peak Predators" icons disappearing randomly.
- **[Database]** Corrected an error that improperly identified Item Finishers as GameObject Finishers on custom servers, causing map pinpointing errors (e.g. `[QuestieDB:GetObject] rawdata is nil for objectID:`).
- **[Database]** Appended correct fallback spawn data for the "Thorim" listen bunny (`NPC 30514`) so Sibling Rivalry's turn in/listen point functions correctly on WotLK clients.
## v9.7.10
### Fixes
- **[Arrow]** Refactored Arrow logic to drastically improve target distance calculations and prioritize targets correctly based on the player's current zone.
- **[Arrow]** Fixed a bug where the Arrow would mistakenly point to previously completed objective locations instead of the Quest Finisher's exact location.
- **[Tracker]** Fixed `QuestieDB.IsComplete` edge case returning incomplete incorrectly; now verifies `numFulfilled == numRequired` to immediately acknowledge completed quests while awaiting the server flag.
- **[Tracker]** Resolved false-positive "broken quest log" errors spamming chat on WotLK servers by correctly handling API responses for trackable objectives.
- **[Tracker]** Demoted harmless WotLK objective cache count mismatches from Error to Debug visibility level to eliminate chat spam on login.
- **[Quest]** Fixed quest arrow pointing to the key-drop NPC after using all consumable quest keys (e.g. Cold Iron Key for "They Took Our Men!" quest 12843). When a quest uses a key item that is consumed on interaction, it leaves the bag and `CheckQuestSourceItem` returns false, incorrectly triggering a quest reset that re-drew the key source NPC on the map. Now checks if all tracked objectives are already `Completed=true` before applying the reset, preventing the spurious icon.
## v9.7.9
### Fixes
- **[Quest]** Fixed tracker objective count staying stale (e.g. stuck at 14/16 when quest is complete) when an autoloot bot bypasses the standard loot frame. Registered `BAG_UPDATE_DELAYED` event to force a full quest log scan on bag changes, catching progress updates that `QUEST_WATCH_UPDATE` would normally fire for manual looting.
## v9.7.8
### Fixes
- **[Quest]** Fixed "There was an error populating objectives" error in chat for `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone"). `_RegisterObjectiveTooltips` now silently returns for `event`-type objectives with no `spawnList` — these have nothing to register a tooltip for.
## v9.7.7
### Fixes
- **[Quest]** Fixed "Missing event data for Objective" error appearing in chat for all `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone" types). Nil coordinates are valid for server-tracked objectives with no pin — the handler now returns silently instead of logging a visible error.
## v9.7.6
### Fixes
- **[Database]** Fixed "Missing objective data" error for all "complete N quests in zone" quest types (IDs 50151, 50145, 50098, 50100, 50149, 50099, 50108, 50111, 50150). Added `triggerEnd` (`[9]`) field so Questie correctly registers the server-tracked objective without drawing map pins.
## v9.7.5
### Fixes
- **[Quest]** Fixed objective pins/icons persisting on the map after a quest is completed or abandoned. Added `CleanupRemovedQuestsFallback` which diffs Questie's quest log against the game's actual quest log on every `QUEST_LOG_UPDATE` and correctly calls `CompleteQuest` or `AbandonedQuest` for any quest that silently disappeared, ensuring map icons are removed.
- **[Quest]** Fixed re-accepted repeatable custom quests (e.g., Stormforged Scales) not showing objective icons on the map after being accepted a second time.
### New Quests
- **[Database]** Added **Storm Peak Orders** (ID 50150) - *The Storm Peaks*
- Objective: Complete any 6 quests in The Storm Peaks.
- **[Database]** Added **Wild Basin** (ID 50094) - *Sholazar Basin*
- Objective: Kill 75 Beasts. Includes 29 Beast NPC types with full spawn coordinates.
- NPCs: King Krush, Shardhorn Rhino, Aotona, Pitch, Serfex the Reaver, Dreadsaber, Hardknuckle Matriarch, Shango, Venomtip, Bushwhacker, Hardknuckle Charger, Ravenous Mangal Crocolisk, Farunn, Zeptek the Destroyer, Goretalon Matriarch, Sapphire Hive Wasp, Emperor Cobra, Sapphire Hive Drone, Shattertusk Bull, Siltslither Eel, Spirit of Atha, Stranded Thresher, Mangal Crocolisk, Spirit of Koosu, Longneck Grazer, Goretalon Roc, Sapphire Hive Queen, Spirit of Ha-Khalan, Bittertide Hydra
## v9.7.4
### Fixes
- **[Tooltips]** Fixed "attempt to concatenate local 'name' (a nil value)" error when quest starters/finishers have missing names in the database.
- **[Database]** Added missing spawn coordinates for Quest 50031 "Stormbound" elementals in Storm Peaks (zone 67).
- **[Database]** Fixed "Unknown Zone" issue for custom quests by correcting Zone ID index usage (swapped `[6]` RequiredRaces for `[17]` ZoneID).
- **[Database]** Corrected Dragonblight Zone ID in custom quest definitions.
### New Quests
- **[Database]** Added **Morogh Missions** (ID 50098) - *Dun Morogh*
- Objective: Complete any 6 quests in Dun Morogh. Auto-completes upon reaching the objective.
- **[Database]** Added **Azuremyst Aid** (ID 50100) - *Azuremyst Isle*
- Objective: Complete any 6 quests in Azuremyst Isle. Auto-completes upon reaching the objective.
- **[Database]** Added **Stormforged Scales** (ID 50066) - *The Storm Peaks*
- Objective: Kill 30 Dragonkin. Includes 8 Dragonkin NPC types with full spawn coordinates.
- **[Database]** Added **Peak Predators** (ID 50095) - *The Storm Peaks*
- Objective: Kill 75 Beasts. Includes 24 Beast NPC types with full spawn coordinates.
- **[Database]** Added **Peak Predators** (ID 50096) - *Icecrown*
- Objective: Kill 75 Beasts. Includes 12 Beast NPC types with full spawn coordinates.
- **[Database]** Added **Icecrown Advance** (ID 50151) - *Icecrown*
- Objective: Complete any 6 quests in Icecrown. Auto-completes upon reaching the objective.
- **[Database]** Added **Storm Peaks Trophy** (ID 50205) - *The Storm Peaks*
- Objective: Kill 1 Rare in The Storm Peaks. Includes 4 Rare NPC types (Skoll, Time-Lost Proto-Drake, Vyragosa, Dirkee) with full spawn coordinates.
## v9.7.3
### New Features
- **[Database]** Implemented **Ebonhold Database Module**.
- Created dedicated `Database/Ebonhold/` structure for custom server data.
- Added `EbonholdLoader` to inject custom Quests, NPCs, Objects, and Items as overrides.
- **Note:** This structure preserves custom data during upstream Questie updates.
- **[Objectives]** Implemented **Automated Text Retrieval**.
- Questie now attempts to fetch quest text from the server at runtime for custom quests that are missing from the database.
- Added "Objectives Board" (ID 600600) as a global quest starter.
### Quests (Custom Content)
- **[New]** Added **Heart of the Dragonflights** (ID 50064) - *Dragonblight*
- Objective: Kill 30 Dragonkin. Includes 49 Dragonkin NPC types.
- **[New]** Added **Skies of Blade's Edge** (ID 50060) - *Blade's Edge Mountains*
- Objective: Kill 75 Dragonkin. Includes 17 Dragonkin NPC types.
- **[New]** Added **Shadowed Beasts** (ID 50087) - *Shadowmoon Valley*
- Objective: Kill 75 Beasts. Includes 25 Beast NPC types.
- **[New]** Added **Forest Stalkers** (ID 50083) - *Terokkar Forest*
- Objective: Kill 75 Beasts. Includes 53 Beast NPC types.
- **[New]** Added **Savage Heights** (ID 50085) - *Blade's Edge Mountains*
- Objective: Kill 75 Beasts. Includes 47 Beast NPC types.
- **[New]** Added **Unstable Fauna** (ID 50086) - *Netherstorm*
- Objective: Kill 75 Beasts. Includes 18 Beast NPC types.
- **[New]** Added **Elemental Balance** (ID 50026) - *Nagrand*
- Objective: Kill 30 Elementals. Includes 12 Elemental NPC types.
- **[New]** Added **Redridge Trophy** (ID 50160) and **Zangarmarsh Trophy** (ID 50192).
### New Ascension Quests
- **Westfall**: Agria's Medicine, Seven Years of Bad Luck, Worm-Eaten Apple, Goldshire's Generosity, Bookworm, Knowledge Corrupts, The Ruins of Northshire, Accursed Sisterhood, Words That Shepherd Madness, Oracular Idol, A Betrayal Within, The Maid I Left Behind, The Saddest Among Us, The Threat Swept Downstream, Stay a While, Defias Disruption.
- **Dun Morogh**: A Small Mistake, We Found Her!, The Scout's Favor, Old Mirsinth, Smoke on the Wind, A Promising Path, A Fitting Disguise, His Radiant Majesty, Deciphering Radiation, Soaking the Masses, Sever the Right Hand, A Growing Business, Thunderbrew's Hop, Stay a While, Live-Fire Demo, Bots on Strike, A Brother's Betrayal, The True Story, Timber for the Coldhewn, Icehide the Unbroken.
- **Teldrassil**: The Carrion Road, The Sister Who Never Returned, Finding the Good Meat, Transsubstantiating the Flesh, Communion Banquet, A Trail of Petals, Restless entrails, A Dark Warning, The Aid of Theren-Dion, No Place for Scavengers, Termites in Teldrassil, Stay a While, Elydna's Heirloom.
- **Durotar**: To Find a Cure, A Dangerous Sample, Knowledge of the Centaurs, Those Who Fell, The Way is Shut, The Sinister Triad, So That He May Hear Again, A Sinister Ritual, Innocents for Sinners, Unease Makes Tongues Wag, A Door Left Ajar, Esgramor's Master, Shinies!, Echoes of Hirsutta, Auction the Past, Stay a While, Durotar's Dire Drought, The Queen's Decree, Avianna's Rose, The Last Piece, Reversion.
- **Tirisfal Glades**: Rude Awakening, Marla's Last Wish, Monsters With Noble Intentions, Restless Family Members, An Unspeakable Secret, A Noble Heritage, The True Heir of the Cains, The Friends We Make Along the Way, I'm Home, Apothecary Flemer, The Nature of Freedom, Spotless Standing, Stay a While, More Than the Sum of its Parts, Scarlet Correspondence, A Humble Duty, The Balnirs' Rest, Brewing Disarray, This Is Justice.
- **Mulgore**: Death and Tribute, Death and Exile, Death and Dishonor, Death and Justice, Death by Laughter, To Whom I Devote, Fighting Over Carrion, Smoke on the Horizon, Amphora of Sacred Water, Stay a While, Exile of Embers, The Smoke that Remembers, The Circles Rite.
### New Ebonhold Quests
- **Outland**: Elemental Balance, Savage Heights, Unstable Fauna, Forest Stalkers, Marsh Predators, Skies of Blade's Edge, Shadowed Beasts, Zangarmarsh Trophy.
- **Northrend**: Tundra Turbulence, Stormbound, Dragonblight Trophy, Heart of the Dragonflights, Peak Predators, Icecrown Advance, Storm Peaks Trophy, Stormforged Scales, Fjord Front, Wild Basin, Grizzly Trophy, Zul'Drak Trophy, Basin Expeditions.
- **Azeroth**: Redridge Trophy, Morogh Missions, Azuremyst Aid, Shadow of Teldrassil, Trials of Durotar, Song of the Woods, Morogh Trophy, Tirisfal Trophy.
### Fixes
- **[Tracker]** **Combat Update Fix**: Tracker now updates objectives immediately during combat without causing Lua errors or taint.
- **[Tracker]** **Bag Update Fix**: Quest progress now updates immediately when looting items (fixes delay with loot bots).
- **[Arrow]** **Refined Visibility Logic**:
- **Auto Nearby**: Arrow correctly defaults to showing the nearest quest when no quests are tracked.
- **Zone Filter**: In "Auto Mode", the arrow hides if the nearest quest is in a different zone.
- **Instance Filter**: Arrow explicitly hides if the target is in a different instance.
- **[Map]** Fixed an issue where completed quest icons would persist on the map (`RequestMapUpdate` logic).
- **[Database]** Updated `wotlkNpcDB.lua` with scraped spawn data for 12 key beast NPCs in Terokkar Forest to ensure accuracy.
- **[Arrow]** Fixed a nil function error for `_CollectObjective` when processing incomplete quests.
- **[Arrow]** Fixed syntax issues that prevented `QuestieArrow` module from initializing correctly.
- **[Database]** Fixed a runtime crash in `ZoneDB` when encountering maps with no AreaId mapping (e.g., Kalimdor).
+166
View File
@@ -0,0 +1,166 @@
# Changelog
## v9.8.3
### Fixes
- **[Quest]** Extended `HideCondition` support to regular monster, object, and item objectives in the database.
- **[Quest]** Added `hideIfQuestActive` conditions to quest 13010 objectives to resolve icon overlap at King Jokkum.
- **[Database]** Corrected the finisher for "You Can't Miss Him" (12966) to NPC 30127, properly moving the arrow to Fjorn's Anvil.
- **[Arrow]** Implemented immediate arrow refreshing upon quest acceptance to provide seamless transitions between objective phases.
## v9.8.2
### Fixes
- **[Quest]** Updated the objective tooltip for "Forging an Alliance" (12924) at King Jokkum to explicitly instruct players to pick up the breadcrumb quest "You Can't Miss Him" (12966).
## v9.8.1
### Fixes
- **[Quest]** Fixed QuestieArrow direction for "Forging an Alliance" (12924). Added an extra objective to speak with King Jokkum, ensuring the arrow points toward the breadcrumb quest start at the beginning of the quest.
## v9.8.0
### Fixes
- **[Quest]** Modified `BAG_UPDATE_DELAYED` to trigger a quest log update and instantly refresh the tracker when items are deposited directly into bags by autoloot bots that bypass standard item events.
- **[Map]** Fixed an issue where "Special Objectives" (e.g., source item drops) failed to check player bag contents upon completion, causing their map icons to linger indefinitely until the main quest was turned in.
## v9.7.12
### Fixes
- **[Quest]** Fixed an issue where tracking icons for dynamically updated custom quests like Peak Predators would prematurely disappear due to sync delays on WotLK servers.
- **[Map]** Resolved a frame pool leak that prevented the yellow Finisher icon from appearing immediately on the map after turning in or completing a quest.
### Completion State Evaluation (`QuestieDB.IsComplete`)
* **Server vs Client State:** The `finished` flag on quest objectives is governed by server `GetQuestLogTitle` packets. Because quests consuming items (e.g. freeing prisoners with keys) update numeric counts instantly but delay the `finished` flag until turn-in time, Questie manually evaluates completeness.
* **Logical Evaluation Bug**: When implementing loops iterating numerical objectives, never use inline ternary operators like `(object[1] and 0)` right at the start, as Lua will evaluate existency strings as truthy and short-circuit return 0 regardless of actually finishing the `numFulfilled == numRequired` checks. Iterate the full list and verify `allDone` instead.
- **[Database]** Corrected an error that improperly identified Item Finishers as GameObject Finishers on custom servers, causing map pinpointing errors (e.g. `[QuestieDB:GetObject] rawdata is nil for objectID:`).
- **[Database]** Appended correct fallback spawn data for the "Thorim" listen bunny (`NPC 30514`) so Sibling Rivalry's turn in/listen point functions correctly on WotLK clients.
## v9.7.11
### Fixes
- **[Quest]** Fixed an issue where quest objective icons and waypoints failed to clear from the map after a quest was completed or abandoned.
- **[Tracker]** Prevented quests from falsely flagging as complete and wiping tracking data when the World of Warcraft server drops its objective arrays. Fixes "Peak Predators" icons disappearing randomly.
- **[Database]** Corrected an error that improperly identified Item Finishers as GameObject Finishers on custom servers, causing map pinpointing errors (e.g. `[QuestieDB:GetObject] rawdata is nil for objectID:`).
- **[Database]** Appended correct fallback spawn data for the "Thorim" listen bunny (`NPC 30514`) so Sibling Rivalry's turn in/listen point functions correctly on WotLK clients.
## v9.7.10
### Fixes
- **[Arrow]** Refactored Arrow logic to drastically improve target distance calculations and prioritize targets correctly based on the player's current zone.
- **[Arrow]** Fixed a bug where the Arrow would mistakenly point to previously completed objective locations instead of the Quest Finisher's exact location.
- **[Tracker]** Fixed `QuestieDB.IsComplete` edge case returning incomplete incorrectly; now verifies `numFulfilled == numRequired` to immediately acknowledge completed quests while awaiting the server flag.
- **[Tracker]** Resolved false-positive "broken quest log" errors spamming chat on WotLK servers by correctly handling API responses for trackable objectives.
- **[Tracker]** Demoted harmless WotLK objective cache count mismatches from Error to Debug visibility level to eliminate chat spam on login.
- **[Quest]** Fixed quest arrow pointing to the key-drop NPC after using all consumable quest keys (e.g. Cold Iron Key for "They Took Our Men!" quest 12843). When a quest uses a key item that is consumed on interaction, it leaves the bag and `CheckQuestSourceItem` returns false, incorrectly triggering a quest reset that re-drew the key source NPC on the map. Now checks if all tracked objectives are already `Completed=true` before applying the reset, preventing the spurious icon.
## v9.7.9
### Fixes
- **[Quest]** Fixed tracker objective count staying stale (e.g. stuck at 14/16 when quest is complete) when an autoloot bot bypasses the standard loot frame. Registered `BAG_UPDATE_DELAYED` event to force a full quest log scan on bag changes, catching progress updates that `QUEST_WATCH_UPDATE` would normally fire for manual looting.
## v9.7.8
### Fixes
- **[Quest]** Fixed "There was an error populating objectives" error in chat for `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone"). `_RegisterObjectiveTooltips` now silently returns for `event`-type objectives with no `spawnList` — these have nothing to register a tooltip for.
## v9.7.7
### Fixes
- **[Quest]** Fixed "Missing event data for Objective" error appearing in chat for all `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone" types). Nil coordinates are valid for server-tracked objectives with no pin — the handler now returns silently instead of logging a visible error.
## v9.7.6
### Fixes
- **[Database]** Fixed "Missing objective data" error for all "complete N quests in zone" quest types (IDs 50151, 50145, 50098, 50100, 50149, 50099, 50108, 50111, 50150). Added `triggerEnd` (`[9]`) field so Questie correctly registers the server-tracked objective without drawing map pins.
## v9.7.5
### Fixes
- **[Quest]** Fixed objective pins/icons persisting on the map after a quest is completed or abandoned. Added `CleanupRemovedQuestsFallback` which diffs Questie's quest log against the game's actual quest log on every `QUEST_LOG_UPDATE` and correctly calls `CompleteQuest` or `AbandonedQuest` for any quest that silently disappeared, ensuring map icons are removed.
- **[Quest]** Fixed re-accepted repeatable custom quests (e.g., Stormforged Scales) not showing objective icons on the map after being accepted a second time.
### New Quests
- **[Database]** Added **Storm Peak Orders** (ID 50150) - *The Storm Peaks*
- Objective: Complete any 6 quests in The Storm Peaks.
- **[Database]** Added **Wild Basin** (ID 50094) - *Sholazar Basin*
- Objective: Kill 75 Beasts. Includes 29 Beast NPC types with full spawn coordinates.
- NPCs: King Krush, Shardhorn Rhino, Aotona, Pitch, Serfex the Reaver, Dreadsaber, Hardknuckle Matriarch, Shango, Venomtip, Bushwhacker, Hardknuckle Charger, Ravenous Mangal Crocolisk, Farunn, Zeptek the Destroyer, Goretalon Matriarch, Sapphire Hive Wasp, Emperor Cobra, Sapphire Hive Drone, Shattertusk Bull, Siltslither Eel, Spirit of Atha, Stranded Thresher, Mangal Crocolisk, Spirit of Koosu, Longneck Grazer, Goretalon Roc, Sapphire Hive Queen, Spirit of Ha-Khalan, Bittertide Hydra
## v9.7.4
### Fixes
- **[Tooltips]** Fixed "attempt to concatenate local 'name' (a nil value)" error when quest starters/finishers have missing names in the database.
- **[Database]** Added missing spawn coordinates for Quest 50031 "Stormbound" elementals in Storm Peaks (zone 67).
- **[Database]** Fixed "Unknown Zone" issue for custom quests by correcting Zone ID index usage (swapped `[6]` RequiredRaces for `[17]` ZoneID).
- **[Database]** Corrected Dragonblight Zone ID in custom quest definitions.
### New Quests
- **[Database]** Added **Morogh Missions** (ID 50098) - *Dun Morogh*
- Objective: Complete any 6 quests in Dun Morogh. Auto-completes upon reaching the objective.
- **[Database]** Added **Azuremyst Aid** (ID 50100) - *Azuremyst Isle*
- Objective: Complete any 6 quests in Azuremyst Isle. Auto-completes upon reaching the objective.
- **[Database]** Added **Stormforged Scales** (ID 50066) - *The Storm Peaks*
- Objective: Kill 30 Dragonkin. Includes 8 Dragonkin NPC types with full spawn coordinates.
- **[Database]** Added **Peak Predators** (ID 50095) - *The Storm Peaks*
- Objective: Kill 75 Beasts. Includes 24 Beast NPC types with full spawn coordinates.
- **[Database]** Added **Peak Predators** (ID 50096) - *Icecrown*
- Objective: Kill 75 Beasts. Includes 12 Beast NPC types with full spawn coordinates.
- **[Database]** Added **Icecrown Advance** (ID 50151) - *Icecrown*
- Objective: Complete any 6 quests in Icecrown. Auto-completes upon reaching the objective.
- **[Database]** Added **Storm Peaks Trophy** (ID 50205) - *The Storm Peaks*
- Objective: Kill 1 Rare in The Storm Peaks. Includes 4 Rare NPC types (Skoll, Time-Lost Proto-Drake, Vyragosa, Dirkee) with full spawn coordinates.
## v9.7.3
### New Features
- **[Database]** Implemented **Ebonhold Database Module**.
- Created dedicated `Database/Ebonhold/` structure for custom server data.
- Added `EbonholdLoader` to inject custom Quests, NPCs, Objects, and Items as overrides.
- **Note:** This structure preserves custom data during upstream Questie updates.
- **[Objectives]** Implemented **Automated Text Retrieval**.
- Questie now attempts to fetch quest text from the server at runtime for custom quests that are missing from the database.
- Added "Objectives Board" (ID 600600) as a global quest starter.
### Quests (Custom Content)
- **[New]** Added **Heart of the Dragonflights** (ID 50064) - *Dragonblight*
- Objective: Kill 30 Dragonkin. Includes 49 Dragonkin NPC types.
- **[New]** Added **Skies of Blade's Edge** (ID 50060) - *Blade's Edge Mountains*
- Objective: Kill 75 Dragonkin. Includes 17 Dragonkin NPC types.
- **[New]** Added **Shadowed Beasts** (ID 50087) - *Shadowmoon Valley*
- Objective: Kill 75 Beasts. Includes 25 Beast NPC types.
- **[New]** Added **Forest Stalkers** (ID 50083) - *Terokkar Forest*
- Objective: Kill 75 Beasts. Includes 53 Beast NPC types.
- **[New]** Added **Savage Heights** (ID 50085) - *Blade's Edge Mountains*
- Objective: Kill 75 Beasts. Includes 47 Beast NPC types.
- **[New]** Added **Unstable Fauna** (ID 50086) - *Netherstorm*
- Objective: Kill 75 Beasts. Includes 18 Beast NPC types.
- **[New]** Added **Elemental Balance** (ID 50026) - *Nagrand*
- Objective: Kill 30 Elementals. Includes 12 Elemental NPC types.
- **[New]** Added **Redridge Trophy** (ID 50160) and **Zangarmarsh Trophy** (ID 50192).
### New Ascension Quests
- **Westfall**: Agria's Medicine, Seven Years of Bad Luck, Worm-Eaten Apple, Goldshire's Generosity, Bookworm, Knowledge Corrupts, The Ruins of Northshire, Accursed Sisterhood, Words That Shepherd Madness, Oracular Idol, A Betrayal Within, The Maid I Left Behind, The Saddest Among Us, The Threat Swept Downstream, Stay a While, Defias Disruption.
- **Dun Morogh**: A Small Mistake, We Found Her!, The Scout's Favor, Old Mirsinth, Smoke on the Wind, A Promising Path, A Fitting Disguise, His Radiant Majesty, Deciphering Radiation, Soaking the Masses, Sever the Right Hand, A Growing Business, Thunderbrew's Hop, Stay a While, Live-Fire Demo, Bots on Strike, A Brother's Betrayal, The True Story, Timber for the Coldhewn, Icehide the Unbroken.
- **Teldrassil**: The Carrion Road, The Sister Who Never Returned, Finding the Good Meat, Transsubstantiating the Flesh, Communion Banquet, A Trail of Petals, Restless entrails, A Dark Warning, The Aid of Theren-Dion, No Place for Scavengers, Termites in Teldrassil, Stay a While, Elydna's Heirloom.
- **Durotar**: To Find a Cure, A Dangerous Sample, Knowledge of the Centaurs, Those Who Fell, The Way is Shut, The Sinister Triad, So That He May Hear Again, A Sinister Ritual, Innocents for Sinners, Unease Makes Tongues Wag, A Door Left Ajar, Esgramor's Master, Shinies!, Echoes of Hirsutta, Auction the Past, Stay a While, Durotar's Dire Drought, The Queen's Decree, Avianna's Rose, The Last Piece, Reversion.
- **Tirisfal Glades**: Rude Awakening, Marla's Last Wish, Monsters With Noble Intentions, Restless Family Members, An Unspeakable Secret, A Noble Heritage, The True Heir of the Cains, The Friends We Make Along the Way, I'm Home, Apothecary Flemer, The Nature of Freedom, Spotless Standing, Stay a While, More Than the Sum of its Parts, Scarlet Correspondence, A Humble Duty, The Balnirs' Rest, Brewing Disarray, This Is Justice.
- **Mulgore**: Death and Tribute, Death and Exile, Death and Dishonor, Death and Justice, Death by Laughter, To Whom I Devote, Fighting Over Carrion, Smoke on the Horizon, Amphora of Sacred Water, Stay a While, Exile of Embers, The Smoke that Remembers, The Circles Rite.
### New Ebonhold Quests
- **Outland**: Elemental Balance, Savage Heights, Unstable Fauna, Forest Stalkers, Marsh Predators, Skies of Blade's Edge, Shadowed Beasts, Zangarmarsh Trophy.
- **Northrend**: Tundra Turbulence, Stormbound, Dragonblight Trophy, Heart of the Dragonflights, Peak Predators, Icecrown Advance, Storm Peaks Trophy, Stormforged Scales, Fjord Front, Wild Basin, Grizzly Trophy, Zul'Drak Trophy, Basin Expeditions.
- **Azeroth**: Redridge Trophy, Morogh Missions, Azuremyst Aid, Shadow of Teldrassil, Trials of Durotar, Song of the Woods, Morogh Trophy, Tirisfal Trophy.
### Fixes
- **[Tracker]** **Combat Update Fix**: Tracker now updates objectives immediately during combat without causing Lua errors or taint.
- **[Tracker]** **Bag Update Fix**: Quest progress now updates immediately when looting items (fixes delay with loot bots).
- **[Arrow]** **Refined Visibility Logic**:
- **Auto Nearby**: Arrow correctly defaults to showing the nearest quest when no quests are tracked.
- **Zone Filter**: In "Auto Mode", the arrow hides if the nearest quest is in a different zone.
- **Instance Filter**: Arrow explicitly hides if the target is in a different instance.
- **[Map]** Fixed an issue where completed quest icons would persist on the map (`RequestMapUpdate` logic).
- **[Database]** Updated `wotlkNpcDB.lua` with scraped spawn data for 12 key beast NPCs in Terokkar Forest to ensure accuracy.
- **[Arrow]** Fixed a nil function error for `_CollectObjective` when processing incomplete quests.
- **[Arrow]** Fixed syntax issues that prevented `QuestieArrow` module from initializing correctly.
- **[Database]** Fixed a runtime crash in `ZoneDB` when encountering maps with no AreaId mapping (e.g., Kalimdor).
+164
View File
@@ -0,0 +1,164 @@
# Changelog
## v9.8.3
### Fixes
- **[Quest]** Extended `HideCondition` support to regular monster, object, and item objectives in the database.
- **[Quest]** Added `hideIfQuestActive` conditions to quest 13010 objectives to resolve icon overlap at King Jokkum.
- **[Database]** Corrected the finisher for "You Can't Miss Him" (12966) to NPC 30127, properly moving the arrow to Fjorn's Anvil.
- **[Arrow]** Implemented immediate arrow refreshing upon quest acceptance to provide seamless transitions between objective phases.
## v9.8.2
### Fixes
- **[Quest]** Updated the objective tooltip for "Forging an Alliance" (12924) at King Jokkum to explicitly instruct players to pick up the breadcrumb quest "You Can't Miss Him" (12966).
## v9.8.1
### Fixes
- **[Quest]** Fixed QuestieArrow direction for "Forging an Alliance" (12924). Added an extra objective to speak with King Jokkum, ensuring the arrow points toward the breadcrumb quest start at the beginning of the quest.
## v9.8.0
### Fixes
- **[Quest]** Modified `BAG_UPDATE_DELAYED` to trigger a quest log update and instantly refresh the tracker when items are deposited directly into bags by autoloot bots that bypass standard item events.
- **[Map]** Fixed an issue where "Special Objectives" (e.g., source item drops) failed to check player bag contents upon completion, causing their map icons to linger indefinitely until the main quest was turned in.
## v9.7.12
### Fixes
- **[Quest]** Fixed an issue where tracking icons for dynamically updated custom quests like Peak Predators would prematurely disappear due to sync delays on WotLK servers.
- **[Map]** Resolved a frame pool leak that prevented the yellow Finisher icon from appearing immediately on the map after turning in or completing a quest.
- **[Database]** Corrected an error that improperly identified Item Finishers as GameObject Finishers on custom servers, causing map pinpointing errors (e.g. `[QuestieDB:GetObject] rawdata is nil for objectID:`).
- **[Database]** Appended correct fallback spawn data for the "Thorim" listen bunny (`NPC 30514`) so Sibling Rivalry's turn in/listen point functions correctly on WotLK clients.
## v9.7.11
### Fixes
- **[Quest]** Fixed an issue where quest objective icons and waypoints failed to clear from the map after a quest was completed or abandoned.
- **[Tracker]** Prevented quests from falsely flagging as complete and wiping tracking data when the World of Warcraft server drops its objective arrays. Fixes "Peak Predators" icons disappearing randomly.
- **[Database]** Corrected an error that improperly identified Item Finishers as GameObject Finishers on custom servers, causing map pinpointing errors (e.g. `[QuestieDB:GetObject] rawdata is nil for objectID:`).
- **[Database]** Appended correct fallback spawn data for the "Thorim" listen bunny (`NPC 30514`) so Sibling Rivalry's turn in/listen point functions correctly on WotLK clients.
## v9.7.10
### Fixes
- **[Arrow]** Refactored Arrow logic to drastically improve target distance calculations and prioritize targets correctly based on the player's current zone.
- **[Arrow]** Fixed a bug where the Arrow would mistakenly point to previously completed objective locations instead of the Quest Finisher's exact location.
- **[Tracker]** Fixed `QuestieDB.IsComplete` edge case returning incomplete incorrectly; now verifies `numFulfilled == numRequired` to immediately acknowledge completed quests while awaiting the server flag.
- **[Tracker]** Resolved false-positive "broken quest log" errors spamming chat on WotLK servers by correctly handling API responses for trackable objectives.
- **[Tracker]** Demoted harmless WotLK objective cache count mismatches from Error to Debug visibility level to eliminate chat spam on login.
- **[Quest]** Fixed quest arrow pointing to the key-drop NPC after using all consumable quest keys (e.g. Cold Iron Key for "They Took Our Men!" quest 12843). When a quest uses a key item that is consumed on interaction, it leaves the bag and `CheckQuestSourceItem` returns false, incorrectly triggering a quest reset that re-drew the key source NPC on the map. Now checks if all tracked objectives are already `Completed=true` before applying the reset, preventing the spurious icon.
## v9.7.9
### Fixes
- **[Quest]** Fixed tracker objective count staying stale (e.g. stuck at 14/16 when quest is complete) when an autoloot bot bypasses the standard loot frame. Registered `BAG_UPDATE_DELAYED` event to force a full quest log scan on bag changes, catching progress updates that `QUEST_WATCH_UPDATE` would normally fire for manual looting.
## v9.7.8
### Fixes
- **[Quest]** Fixed "There was an error populating objectives" error in chat for `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone"). `_RegisterObjectiveTooltips` now silently returns for `event`-type objectives with no `spawnList` — these have nothing to register a tooltip for.
## v9.7.7
### Fixes
- **[Quest]** Fixed "Missing event data for Objective" error appearing in chat for all `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone" types). Nil coordinates are valid for server-tracked objectives with no pin — the handler now returns silently instead of logging a visible error.
## v9.7.6
### Fixes
- **[Database]** Fixed "Missing objective data" error for all "complete N quests in zone" quest types (IDs 50151, 50145, 50098, 50100, 50149, 50099, 50108, 50111, 50150). Added `triggerEnd` (`[9]`) field so Questie correctly registers the server-tracked objective without drawing map pins.
## v9.7.5
### Fixes
- **[Quest]** Fixed objective pins/icons persisting on the map after a quest is completed or abandoned. Added `CleanupRemovedQuestsFallback` which diffs Questie's quest log against the game's actual quest log on every `QUEST_LOG_UPDATE` and correctly calls `CompleteQuest` or `AbandonedQuest` for any quest that silently disappeared, ensuring map icons are removed.
- **[Quest]** Fixed re-accepted repeatable custom quests (e.g., Stormforged Scales) not showing objective icons on the map after being accepted a second time.
### New Quests
- **[Database]** Added **Storm Peak Orders** (ID 50150) - *The Storm Peaks*
- Objective: Complete any 6 quests in The Storm Peaks.
- **[Database]** Added **Wild Basin** (ID 50094) - *Sholazar Basin*
- Objective: Kill 75 Beasts. Includes 29 Beast NPC types with full spawn coordinates.
- NPCs: King Krush, Shardhorn Rhino, Aotona, Pitch, Serfex the Reaver, Dreadsaber, Hardknuckle Matriarch, Shango, Venomtip, Bushwhacker, Hardknuckle Charger, Ravenous Mangal Crocolisk, Farunn, Zeptek the Destroyer, Goretalon Matriarch, Sapphire Hive Wasp, Emperor Cobra, Sapphire Hive Drone, Shattertusk Bull, Siltslither Eel, Spirit of Atha, Stranded Thresher, Mangal Crocolisk, Spirit of Koosu, Longneck Grazer, Goretalon Roc, Sapphire Hive Queen, Spirit of Ha-Khalan, Bittertide Hydra
## v9.7.4
### Fixes
- **[Tooltips]** Fixed "attempt to concatenate local 'name' (a nil value)" error when quest starters/finishers have missing names in the database.
- **[Database]** Added missing spawn coordinates for Quest 50031 "Stormbound" elementals in Storm Peaks (zone 67).
- **[Database]** Fixed "Unknown Zone" issue for custom quests by correcting Zone ID index usage (swapped `[6]` RequiredRaces for `[17]` ZoneID).
- **[Database]** Corrected Dragonblight Zone ID in custom quest definitions.
### New Quests
- **[Database]** Added **Morogh Missions** (ID 50098) - *Dun Morogh*
- Objective: Complete any 6 quests in Dun Morogh. Auto-completes upon reaching the objective.
- **[Database]** Added **Azuremyst Aid** (ID 50100) - *Azuremyst Isle*
- Objective: Complete any 6 quests in Azuremyst Isle. Auto-completes upon reaching the objective.
- **[Database]** Added **Stormforged Scales** (ID 50066) - *The Storm Peaks*
- Objective: Kill 30 Dragonkin. Includes 8 Dragonkin NPC types with full spawn coordinates.
- **[Database]** Added **Peak Predators** (ID 50095) - *The Storm Peaks*
- Objective: Kill 75 Beasts. Includes 24 Beast NPC types with full spawn coordinates.
- **[Database]** Added **Peak Predators** (ID 50096) - *Icecrown*
- Objective: Kill 75 Beasts. Includes 12 Beast NPC types with full spawn coordinates.
- **[Database]** Added **Icecrown Advance** (ID 50151) - *Icecrown*
- Objective: Complete any 6 quests in Icecrown. Auto-completes upon reaching the objective.
- **[Database]** Added **Storm Peaks Trophy** (ID 50205) - *The Storm Peaks*
- Objective: Kill 1 Rare in The Storm Peaks. Includes 4 Rare NPC types (Skoll, Time-Lost Proto-Drake, Vyragosa, Dirkee) with full spawn coordinates.
## v9.7.3
### New Features
- **[Database]** Implemented **Ebonhold Database Module**.
- Created dedicated `Database/Ebonhold/` structure for custom server data.
- Added `EbonholdLoader` to inject custom Quests, NPCs, Objects, and Items as overrides.
- **Note:** This structure preserves custom data during upstream Questie updates.
- **[Objectives]** Implemented **Automated Text Retrieval**.
- Questie now attempts to fetch quest text from the server at runtime for custom quests that are missing from the database.
- Added "Objectives Board" (ID 600600) as a global quest starter.
### Quests (Custom Content)
- **[New]** Added **Heart of the Dragonflights** (ID 50064) - *Dragonblight*
- Objective: Kill 30 Dragonkin. Includes 49 Dragonkin NPC types.
- **[New]** Added **Skies of Blade's Edge** (ID 50060) - *Blade's Edge Mountains*
- Objective: Kill 75 Dragonkin. Includes 17 Dragonkin NPC types.
- **[New]** Added **Shadowed Beasts** (ID 50087) - *Shadowmoon Valley*
- Objective: Kill 75 Beasts. Includes 25 Beast NPC types.
- **[New]** Added **Forest Stalkers** (ID 50083) - *Terokkar Forest*
- Objective: Kill 75 Beasts. Includes 53 Beast NPC types.
- **[New]** Added **Savage Heights** (ID 50085) - *Blade's Edge Mountains*
- Objective: Kill 75 Beasts. Includes 47 Beast NPC types.
- **[New]** Added **Unstable Fauna** (ID 50086) - *Netherstorm*
- Objective: Kill 75 Beasts. Includes 18 Beast NPC types.
- **[New]** Added **Elemental Balance** (ID 50026) - *Nagrand*
- Objective: Kill 30 Elementals. Includes 12 Elemental NPC types.
- **[New]** Added **Redridge Trophy** (ID 50160) and **Zangarmarsh Trophy** (ID 50192).
### New Ascension Quests
- **Westfall**: Agria's Medicine, Seven Years of Bad Luck, Worm-Eaten Apple, Goldshire's Generosity, Bookworm, Knowledge Corrupts, The Ruins of Northshire, Accursed Sisterhood, Words That Shepherd Madness, Oracular Idol, A Betrayal Within, The Maid I Left Behind, The Saddest Among Us, The Threat Swept Downstream, Stay a While, Defias Disruption.
- **Dun Morogh**: A Small Mistake, We Found Her!, The Scout's Favor, Old Mirsinth, Smoke on the Wind, A Promising Path, A Fitting Disguise, His Radiant Majesty, Deciphering Radiation, Soaking the Masses, Sever the Right Hand, A Growing Business, Thunderbrew's Hop, Stay a While, Live-Fire Demo, Bots on Strike, A Brother's Betrayal, The True Story, Timber for the Coldhewn, Icehide the Unbroken.
- **Teldrassil**: The Carrion Road, The Sister Who Never Returned, Finding the Good Meat, Transsubstantiating the Flesh, Communion Banquet, A Trail of Petals, Restless entrails, A Dark Warning, The Aid of Theren-Dion, No Place for Scavengers, Termites in Teldrassil, Stay a While, Elydna's Heirloom.
- **Durotar**: To Find a Cure, A Dangerous Sample, Knowledge of the Centaurs, Those Who Fell, The Way is Shut, The Sinister Triad, So That He May Hear Again, A Sinister Ritual, Innocents for Sinners, Unease Makes Tongues Wag, A Door Left Ajar, Esgramor's Master, Shinies!, Echoes of Hirsutta, Auction the Past, Stay a While, Durotar's Dire Drought, The Queen's Decree, Avianna's Rose, The Last Piece, Reversion.
- **Tirisfal Glades**: Rude Awakening, Marla's Last Wish, Monsters With Noble Intentions, Restless Family Members, An Unspeakable Secret, A Noble Heritage, The True Heir of the Cains, The Friends We Make Along the Way, I'm Home, Apothecary Flemer, The Nature of Freedom, Spotless Standing, Stay a While, More Than the Sum of its Parts, Scarlet Correspondence, A Humble Duty, The Balnirs' Rest, Brewing Disarray, This Is Justice.
- **Mulgore**: Death and Tribute, Death and Exile, Death and Dishonor, Death and Justice, Death by Laughter, To Whom I Devote, Fighting Over Carrion, Smoke on the Horizon, Amphora of Sacred Water, Stay a While, Exile of Embers, The Smoke that Remembers, The Circles Rite.
### New Ebonhold Quests
- **Outland**: Elemental Balance, Savage Heights, Unstable Fauna, Forest Stalkers, Marsh Predators, Skies of Blade's Edge, Shadowed Beasts, Zangarmarsh Trophy.
- **Northrend**: Tundra Turbulence, Stormbound, Dragonblight Trophy, Heart of the Dragonflights, Peak Predators, Icecrown Advance, Storm Peaks Trophy, Stormforged Scales, Fjord Front, Wild Basin, Grizzly Trophy, Zul'Drak Trophy, Basin Expeditions.
- **Azeroth**: Redridge Trophy, Morogh Missions, Azuremyst Aid, Shadow of Teldrassil, Trials of Durotar, Song of the Woods, Morogh Trophy, Tirisfal Trophy.
### Fixes
- **[Tracker]** **Combat Update Fix**: Tracker now updates objectives immediately during combat without causing Lua errors or taint.
- **[Tracker]** **Bag Update Fix**: Quest progress now updates immediately when looting items (fixes delay with loot bots).
- **[Arrow]** **Refined Visibility Logic**:
- **Auto Nearby**: Arrow correctly defaults to showing the nearest quest when no quests are tracked.
- **Zone Filter**: In "Auto Mode", the arrow hides if the nearest quest is in a different zone.
- **Instance Filter**: Arrow explicitly hides if the target is in a different instance.
- **[Map]** Fixed an issue where completed quest icons would persist on the map (`RequestMapUpdate` logic).
- **[Database]** Updated `wotlkNpcDB.lua` with scraped spawn data for 12 key beast NPCs in Terokkar Forest to ensure accuracy.
- **[Arrow]** Fixed a nil function error for `_CollectObjective` when processing incomplete quests.
- **[Arrow]** Fixed syntax issues that prevented `QuestieArrow` module from initializing correctly.
- **[Database]** Fixed a runtime crash in `ZoneDB` when encountering maps with no AreaId mapping (e.g., Kalimdor).
+169
View File
@@ -0,0 +1,169 @@
# Changelog
## v9.8.4
### Fixes
- **[Quest]** Fixed a Lua crash ("attempt to index global 'QuestiePlayer'") occurring during chat message processing for auto-completing quests, by explicitly requiring the `QuestiePlayer` module in `QuestEventHandler`.
## v9.8.3
### Fixes
- **[Quest]** Extended `HideCondition` support to regular monster, object, and item objectives in the database.
- **[Quest]** Added `hideIfQuestActive` conditions to quest 13010 objectives to resolve icon overlap at King Jokkum.
- **[Database]** Corrected the finisher for "You Can't Miss Him" (12966) to NPC 30127, properly moving the arrow to Fjorn's Anvil.
- **[Arrow]** Implemented immediate arrow refreshing upon quest acceptance to provide seamless transitions between objective phases.
## v9.8.2
### Fixes
- **[Quest]** Updated the objective tooltip for "Forging an Alliance" (12924) at King Jokkum to explicitly instruct players to pick up the breadcrumb quest "You Can't Miss Him" (12966).
## v9.8.1
### Fixes
- **[Quest]** Fixed QuestieArrow direction for "Forging an Alliance" (12924). Added an extra objective to speak with King Jokkum, ensuring the arrow points toward the breadcrumb quest start at the beginning of the quest.
## v9.8.0
### Fixes
- **[Quest]** Modified `BAG_UPDATE_DELAYED` to trigger a quest log update and instantly refresh the tracker when items are deposited directly into bags by autoloot bots that bypass standard item events.
- **[Map]** Fixed an issue where "Special Objectives" (e.g., source item drops) failed to check player bag contents upon completion, causing their map icons to linger indefinitely until the main quest was turned in.
## v9.7.12
### Fixes
- **[Quest]** Fixed an issue where tracking icons for dynamically updated custom quests like Peak Predators would prematurely disappear due to sync delays on WotLK servers.
- **[Map]** Resolved a frame pool leak that prevented the yellow Finisher icon from appearing immediately on the map after turning in or completing a quest.
- **[Database]** Corrected an error that improperly identified Item Finishers as GameObject Finishers on custom servers, causing map pinpointing errors (e.g. `[QuestieDB:GetObject] rawdata is nil for objectID:`).
- **[Database]** Appended correct fallback spawn data for the "Thorim" listen bunny (`NPC 30514`) so Sibling Rivalry's turn in/listen point functions correctly on WotLK clients.
## v9.7.11
### Fixes
- **[Quest]** Fixed an issue where quest objective icons and waypoints failed to clear from the map after a quest was completed or abandoned.
- **[Tracker]** Prevented quests from falsely flagging as complete and wiping tracking data when the World of Warcraft server drops its objective arrays. Fixes "Peak Predators" icons disappearing randomly.
- **[Database]** Corrected an error that improperly identified Item Finishers as GameObject Finishers on custom servers, causing map pinpointing errors (e.g. `[QuestieDB:GetObject] rawdata is nil for objectID:`).
- **[Database]** Appended correct fallback spawn data for the "Thorim" listen bunny (`NPC 30514`) so Sibling Rivalry's turn in/listen point functions correctly on WotLK clients.
## v9.7.10
### Fixes
- **[Arrow]** Refactored Arrow logic to drastically improve target distance calculations and prioritize targets correctly based on the player's current zone.
- **[Arrow]** Fixed a bug where the Arrow would mistakenly point to previously completed objective locations instead of the Quest Finisher's exact location.
- **[Tracker]** Fixed `QuestieDB.IsComplete` edge case returning incomplete incorrectly; now verifies `numFulfilled == numRequired` to immediately acknowledge completed quests while awaiting the server flag.
- **[Tracker]** Resolved false-positive "broken quest log" errors spamming chat on WotLK servers by correctly handling API responses for trackable objectives.
- **[Tracker]** Demoted harmless WotLK objective cache count mismatches from Error to Debug visibility level to eliminate chat spam on login.
- **[Quest]** Fixed quest arrow pointing to the key-drop NPC after using all consumable quest keys (e.g. Cold Iron Key for "They Took Our Men!" quest 12843). When a quest uses a key item that is consumed on interaction, it leaves the bag and `CheckQuestSourceItem` returns false, incorrectly triggering a quest reset that re-drew the key source NPC on the map. Now checks if all tracked objectives are already `Completed=true` before applying the reset, preventing the spurious icon.
## v9.7.9
### Fixes
- **[Quest]** Fixed tracker objective count staying stale (e.g. stuck at 14/16 when quest is complete) when an autoloot bot bypasses the standard loot frame. Registered `BAG_UPDATE_DELAYED` event to force a full quest log scan on bag changes, catching progress updates that `QUEST_WATCH_UPDATE` would normally fire for manual looting.
## v9.7.8
### Fixes
- **[Quest]** Fixed "There was an error populating objectives" error in chat for `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone"). `_RegisterObjectiveTooltips` now silently returns for `event`-type objectives with no `spawnList` — these have nothing to register a tooltip for.
## v9.7.7
### Fixes
- **[Quest]** Fixed "Missing event data for Objective" error appearing in chat for all `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone" types). Nil coordinates are valid for server-tracked objectives with no pin — the handler now returns silently instead of logging a visible error.
## v9.7.6
### Fixes
- **[Database]** Fixed "Missing objective data" error for all "complete N quests in zone" quest types (IDs 50151, 50145, 50098, 50100, 50149, 50099, 50108, 50111, 50150). Added `triggerEnd` (`[9]`) field so Questie correctly registers the server-tracked objective without drawing map pins.
## v9.7.5
### Fixes
- **[Quest]** Fixed objective pins/icons persisting on the map after a quest is completed or abandoned. Added `CleanupRemovedQuestsFallback` which diffs Questie's quest log against the game's actual quest log on every `QUEST_LOG_UPDATE` and correctly calls `CompleteQuest` or `AbandonedQuest` for any quest that silently disappeared, ensuring map icons are removed.
- **[Quest]** Fixed re-accepted repeatable custom quests (e.g., Stormforged Scales) not showing objective icons on the map after being accepted a second time.
### New Quests
- **[Database]** Added **Storm Peak Orders** (ID 50150) - *The Storm Peaks*
- Objective: Complete any 6 quests in The Storm Peaks.
- **[Database]** Added **Wild Basin** (ID 50094) - *Sholazar Basin*
- Objective: Kill 75 Beasts. Includes 29 Beast NPC types with full spawn coordinates.
- NPCs: King Krush, Shardhorn Rhino, Aotona, Pitch, Serfex the Reaver, Dreadsaber, Hardknuckle Matriarch, Shango, Venomtip, Bushwhacker, Hardknuckle Charger, Ravenous Mangal Crocolisk, Farunn, Zeptek the Destroyer, Goretalon Matriarch, Sapphire Hive Wasp, Emperor Cobra, Sapphire Hive Drone, Shattertusk Bull, Siltslither Eel, Spirit of Atha, Stranded Thresher, Mangal Crocolisk, Spirit of Koosu, Longneck Grazer, Goretalon Roc, Sapphire Hive Queen, Spirit of Ha-Khalan, Bittertide Hydra
## v9.7.4
### Fixes
- **[Tooltips]** Fixed "attempt to concatenate local 'name' (a nil value)" error when quest starters/finishers have missing names in the database.
- **[Database]** Added missing spawn coordinates for Quest 50031 "Stormbound" elementals in Storm Peaks (zone 67).
- **[Database]** Fixed "Unknown Zone" issue for custom quests by correcting Zone ID index usage (swapped `[6]` RequiredRaces for `[17]` ZoneID).
- **[Database]** Corrected Dragonblight Zone ID in custom quest definitions.
### New Quests
- **[Database]** Added **Morogh Missions** (ID 50098) - *Dun Morogh*
- Objective: Complete any 6 quests in Dun Morogh. Auto-completes upon reaching the objective.
- **[Database]** Added **Azuremyst Aid** (ID 50100) - *Azuremyst Isle*
- Objective: Complete any 6 quests in Azuremyst Isle. Auto-completes upon reaching the objective.
- **[Database]** Added **Stormforged Scales** (ID 50066) - *The Storm Peaks*
- Objective: Kill 30 Dragonkin. Includes 8 Dragonkin NPC types with full spawn coordinates.
- **[Database]** Added **Peak Predators** (ID 50095) - *The Storm Peaks*
- Objective: Kill 75 Beasts. Includes 24 Beast NPC types with full spawn coordinates.
- **[Database]** Added **Peak Predators** (ID 50096) - *Icecrown*
- Objective: Kill 75 Beasts. Includes 12 Beast NPC types with full spawn coordinates.
- **[Database]** Added **Icecrown Advance** (ID 50151) - *Icecrown*
- Objective: Complete any 6 quests in Icecrown. Auto-completes upon reaching the objective.
- **[Database]** Added **Storm Peaks Trophy** (ID 50205) - *The Storm Peaks*
- Objective: Kill 1 Rare in The Storm Peaks. Includes 4 Rare NPC types (Skoll, Time-Lost Proto-Drake, Vyragosa, Dirkee) with full spawn coordinates.
## v9.7.3
### New Features
- **[Database]** Implemented **Ebonhold Database Module**.
- Created dedicated `Database/Ebonhold/` structure for custom server data.
- Added `EbonholdLoader` to inject custom Quests, NPCs, Objects, and Items as overrides.
- **Note:** This structure preserves custom data during upstream Questie updates.
- **[Objectives]** Implemented **Automated Text Retrieval**.
- Questie now attempts to fetch quest text from the server at runtime for custom quests that are missing from the database.
- Added "Objectives Board" (ID 600600) as a global quest starter.
### Quests (Custom Content)
- **[New]** Added **Heart of the Dragonflights** (ID 50064) - *Dragonblight*
- Objective: Kill 30 Dragonkin. Includes 49 Dragonkin NPC types.
- **[New]** Added **Skies of Blade's Edge** (ID 50060) - *Blade's Edge Mountains*
- Objective: Kill 75 Dragonkin. Includes 17 Dragonkin NPC types.
- **[New]** Added **Shadowed Beasts** (ID 50087) - *Shadowmoon Valley*
- Objective: Kill 75 Beasts. Includes 25 Beast NPC types.
- **[New]** Added **Forest Stalkers** (ID 50083) - *Terokkar Forest*
- Objective: Kill 75 Beasts. Includes 53 Beast NPC types.
- **[New]** Added **Savage Heights** (ID 50085) - *Blade's Edge Mountains*
- Objective: Kill 75 Beasts. Includes 47 Beast NPC types.
- **[New]** Added **Unstable Fauna** (ID 50086) - *Netherstorm*
- Objective: Kill 75 Beasts. Includes 18 Beast NPC types.
- **[New]** Added **Elemental Balance** (ID 50026) - *Nagrand*
- Objective: Kill 30 Elementals. Includes 12 Elemental NPC types.
- **[New]** Added **Redridge Trophy** (ID 50160) and **Zangarmarsh Trophy** (ID 50192).
### New Ascension Quests
- **Westfall**: Agria's Medicine, Seven Years of Bad Luck, Worm-Eaten Apple, Goldshire's Generosity, Bookworm, Knowledge Corrupts, The Ruins of Northshire, Accursed Sisterhood, Words That Shepherd Madness, Oracular Idol, A Betrayal Within, The Maid I Left Behind, The Saddest Among Us, The Threat Swept Downstream, Stay a While, Defias Disruption.
- **Dun Morogh**: A Small Mistake, We Found Her!, The Scout's Favor, Old Mirsinth, Smoke on the Wind, A Promising Path, A Fitting Disguise, His Radiant Majesty, Deciphering Radiation, Soaking the Masses, Sever the Right Hand, A Growing Business, Thunderbrew's Hop, Stay a While, Live-Fire Demo, Bots on Strike, A Brother's Betrayal, The True Story, Timber for the Coldhewn, Icehide the Unbroken.
- **Teldrassil**: The Carrion Road, The Sister Who Never Returned, Finding the Good Meat, Transsubstantiating the Flesh, Communion Banquet, A Trail of Petals, Restless entrails, A Dark Warning, The Aid of Theren-Dion, No Place for Scavengers, Termites in Teldrassil, Stay a While, Elydna's Heirloom.
- **Durotar**: To Find a Cure, A Dangerous Sample, Knowledge of the Centaurs, Those Who Fell, The Way is Shut, The Sinister Triad, So That He May Hear Again, A Sinister Ritual, Innocents for Sinners, Unease Makes Tongues Wag, A Door Left Ajar, Esgramor's Master, Shinies!, Echoes of Hirsutta, Auction the Past, Stay a While, Durotar's Dire Drought, The Queen's Decree, Avianna's Rose, The Last Piece, Reversion.
- **Tirisfal Glades**: Rude Awakening, Marla's Last Wish, Monsters With Noble Intentions, Restless Family Members, An Unspeakable Secret, A Noble Heritage, The True Heir of the Cains, The Friends We Make Along the Way, I'm Home, Apothecary Flemer, The Nature of Freedom, Spotless Standing, Stay a While, More Than the Sum of its Parts, Scarlet Correspondence, A Humble Duty, The Balnirs' Rest, Brewing Disarray, This Is Justice.
- **Mulgore**: Death and Tribute, Death and Exile, Death and Dishonor, Death and Justice, Death by Laughter, To Whom I Devote, Fighting Over Carrion, Smoke on the Horizon, Amphora of Sacred Water, Stay a While, Exile of Embers, The Smoke that Remembers, The Circles Rite.
### New Ebonhold Quests
- **Outland**: Elemental Balance, Savage Heights, Unstable Fauna, Forest Stalkers, Marsh Predators, Skies of Blade's Edge, Shadowed Beasts, Zangarmarsh Trophy.
- **Northrend**: Tundra Turbulence, Stormbound, Dragonblight Trophy, Heart of the Dragonflights, Peak Predators, Icecrown Advance, Storm Peaks Trophy, Stormforged Scales, Fjord Front, Wild Basin, Grizzly Trophy, Zul'Drak Trophy, Basin Expeditions.
- **Azeroth**: Redridge Trophy, Morogh Missions, Azuremyst Aid, Shadow of Teldrassil, Trials of Durotar, Song of the Woods, Morogh Trophy, Tirisfal Trophy.
### Fixes
- **[Tracker]** **Combat Update Fix**: Tracker now updates objectives immediately during combat without causing Lua errors or taint.
- **[Tracker]** **Bag Update Fix**: Quest progress now updates immediately when looting items (fixes delay with loot bots).
- **[Arrow]** **Refined Visibility Logic**:
- **Auto Nearby**: Arrow correctly defaults to showing the nearest quest when no quests are tracked.
- **Zone Filter**: In "Auto Mode", the arrow hides if the nearest quest is in a different zone.
- **Instance Filter**: Arrow explicitly hides if the target is in a different instance.
- **[Map]** Fixed an issue where completed quest icons would persist on the map (`RequestMapUpdate` logic).
- **[Database]** Updated `wotlkNpcDB.lua` with scraped spawn data for 12 key beast NPCs in Terokkar Forest to ensure accuracy.
- **[Arrow]** Fixed a nil function error for `_CollectObjective` when processing incomplete quests.
- **[Arrow]** Fixed syntax issues that prevented `QuestieArrow` module from initializing correctly.
- **[Database]** Fixed a runtime crash in `ZoneDB` when encountering maps with no AreaId mapping (e.g., Kalimdor).
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,765 @@
---@class QuestieArrow
local QuestieArrow = QuestieLoader:CreateModule("QuestieArrow")
---@type ZoneDB
local ZoneDB = QuestieLoader:ImportModule("ZoneDB")
---@type QuestieLib
local QuestieLib = QuestieLoader:ImportModule("QuestieLib")
---@type QuestieMap
local QuestieMap = QuestieLoader:ImportModule("QuestieMap")
---@type QuestieTracker
local QuestieTracker = QuestieLoader:ImportModule("QuestieTracker")
---@type QuestieDB
local QuestieDB = QuestieLoader:ImportModule("QuestieDB")
---@type QuestiePlayer
local QuestiePlayer = QuestieLoader:ImportModule("QuestiePlayer")
---@type QuestieQuest
local QuestieQuest = QuestieLoader:ImportModule("QuestieQuest")
local HBD = QuestieCompat.HBD or LibStub("HereBeDragonsQuestie-2.0")
local atan2 = math.atan2
local pi = math.pi
local floor = math.floor
local abs = math.abs
local max = math.max
local min = math.min
local ARROW_SHEET_SIZE = 512
local ARROW_CELL_W = 56
local ARROW_CELL_H = 42
local ARROW_SHEET_COLS = 9
local ARROW_SHEET_ROWS = 12
local ARROW_TOTAL_CELLS = ARROW_SHEET_COLS * ARROW_SHEET_ROWS
local UPDATE_THROTTLE_SECONDS = 0.05
local RECALC_NEAREST_SECONDS = 1.0
local TRACKER_REFRESH_THROTTLE_SECONDS = 0.5
---@type Frame?
local arrowFrame = nil
---@type Frame?
local driverFrame = nil
-- Current auto-tracked targets sorted by distance
local sortedTargets = {}
local hasManualTarget = false
local lastPopulateByQuestId = {}
local function _IsArrowEnabled()
if not Questie or not Questie.db or not Questie.db.profile then
return true
end
return Questie.db.profile.arrowEnabled ~= false
end
local function _GetArrowScale()
if not Questie or not Questie.db or not Questie.db.profile then
return 1
end
return Questie.db.profile.arrowScale or 1
end
local function _SetArrowScale(scale)
if not Questie or not Questie.db or not Questie.db.profile then
return
end
Questie.db.profile.arrowScale = scale
end
local function _GetProfilePosition()
if not Questie or not Questie.db or not Questie.db.profile then
return nil
end
return Questie.db.profile.arrowPosition
end
local function _SaveProfilePosition(point, relativePoint, x, y)
if not Questie or not Questie.db or not Questie.db.profile then
return
end
Questie.db.profile.arrowPosition = {
point = point,
relativePoint = relativePoint,
x = x,
y = y,
}
end
local function modulo(val, by)
return val - floor(val / by) * by
end
local function GetColorGradient(perc)
if perc <= 0.5 then
return 1, perc * 2, 0
else
return 2 - perc * 2, 1, 0
end
end
local function ResolveIconTexture(icon)
if not icon then
return nil
end
if type(icon) == "string" then
return icon
end
if type(icon) == "number" then
if Questie and Questie.usedIcons then
return Questie.usedIcons[icon]
end
return nil
end
return nil
end
local function _ApplyOutline(fontString)
if not fontString or not fontString.GetFont or not fontString.SetFont then
return
end
local font, size, flags = fontString:GetFont()
if not font then
return
end
flags = flags or ""
if not string.find(flags, "OUTLINE", 1, true) then
if flags ~= "" then
flags = flags .. ",OUTLINE"
else
flags = "OUTLINE"
end
end
fontString:SetFont(font, size, flags)
end
local function EnsureArrowFrame()
if arrowFrame then
return
end
arrowFrame = CreateFrame("Frame", "QuestieArrowFrame", UIParent)
local pos = _GetProfilePosition()
if pos and pos.point and pos.relativePoint and pos.x and pos.y then
arrowFrame:SetPoint(pos.point, UIParent, pos.relativePoint, pos.x, pos.y)
else
arrowFrame:SetPoint("CENTER", 0, -100)
end
-- Make room for the objective icon below the arrow (no overlap)
arrowFrame:SetWidth(56)
arrowFrame:SetHeight(64)
arrowFrame:SetScale(_GetArrowScale())
arrowFrame:SetClampedToScreen(true)
arrowFrame:SetMovable(true)
arrowFrame:EnableMouse(true)
arrowFrame:EnableMouseWheel(true)
arrowFrame:RegisterForDrag("LeftButton")
arrowFrame:SetScript("OnDragStart", function(self)
if IsShiftKeyDown() then
self:StartMoving()
end
end)
arrowFrame:SetScript("OnDragStop", function(self)
self:StopMovingOrSizing()
local point, _, relativePoint, x, y = self:GetPoint(1)
if point and relativePoint and x and y then
_SaveProfilePosition(point, relativePoint, x, y)
end
end)
arrowFrame:SetScript("OnMouseWheel", function(self, delta)
if not IsShiftKeyDown() then
return
end
local scale = _GetArrowScale() or 1
local step = 0.05
if delta and delta > 0 then
scale = scale + step
else
scale = scale - step
end
if scale < 0.5 then scale = 0.5 end
if scale > 2.0 then scale = 2.0 end
_SetArrowScale(scale)
self:SetScale(scale)
end)
-- Arrow sprite sheet texture (108 cells: 9 columns, 12 rows)
arrowFrame.arrow = arrowFrame:CreateTexture(nil, "MEDIUM")
arrowFrame.arrow:SetTexture(QuestieLib.AddonPath .. "Icons\\arrow.tga")
-- Render at native cell size; use frame scaling if you want it larger.
arrowFrame.arrow:SetWidth(ARROW_CELL_W)
arrowFrame.arrow:SetHeight(ARROW_CELL_H)
arrowFrame.arrow:SetPoint("TOP", arrowFrame, "TOP", 0, 0)
arrowFrame.arrow:SetTexCoord(0, 0.109375, 0, 0.08203125) -- First cell
-- Quest icon texture at bottom (pfQuest style)
arrowFrame.icon = arrowFrame:CreateTexture(nil, "OVERLAY")
arrowFrame.icon:SetWidth(28)
arrowFrame.icon:SetHeight(28)
arrowFrame.icon:SetPoint("BOTTOM", arrowFrame.arrow, "BOTTOM", 0, -20)
arrowFrame.title = arrowFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
arrowFrame.title:SetPoint("TOP", arrowFrame.icon, "BOTTOM", 0, -2)
arrowFrame.title:SetJustifyH("CENTER")
_ApplyOutline(arrowFrame.title)
arrowFrame.distance = arrowFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
arrowFrame.distance:SetPoint("TOP", arrowFrame.title, "BOTTOM", 0, -2)
arrowFrame.distance:SetJustifyH("CENTER")
arrowFrame.distance:SetTextColor(1, 1, 1, 1)
_ApplyOutline(arrowFrame.distance)
arrowFrame._lastUpdate = 0
arrowFrame._lastRecalc = 0
arrowFrame._lastTarget = nil
-- Right-click to clear manual target and resume auto-tracking
arrowFrame:EnableMouse(true)
arrowFrame:SetScript("OnMouseUp", function(self, button)
if button == "RightButton" then
hasManualTarget = false
sortedTargets = {}
QuestieArrow:Refresh()
end
end)
arrowFrame:SetScript("OnUpdate", function(self)
local now = GetTime()
local target = sortedTargets[1]
if not target then
self:Hide()
return
end
if not self:IsShown() then
self:Show()
end
if (self._lastUpdate or 0) + UPDATE_THROTTLE_SECONDS > now then
return
end
self._lastUpdate = now
local playerX, playerY, playerInstance = HBD:GetPlayerWorldPosition()
if not playerX or not playerY or not playerInstance then
self.distance:SetText("Distance: --")
return
end
local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(target.x / 100.0, target.y / 100.0,
target.uiMapId)
if not targetX or not targetY or not targetInstance then
self.distance:SetText("Distance: --")
return
end
if targetInstance ~= playerInstance then
self:Hide()
return
end
-- Calculate arrow direction using pfQuest's method, but in world coordinates
-- (map coordinates break when the target is in a different zone)
local xDelta = (playerX - targetX) * 1.5
local yDelta = (playerY - targetY)
local angle = atan2(xDelta, -(yDelta))
angle = angle > 0 and (pi * 2) - angle or -angle
if angle < 0 then angle = angle + (pi * 2) end
local player = GetPlayerFacing and GetPlayerFacing() or 0
angle = angle - player
-- Calculate color gradient based on direction
local perc = abs(((pi - abs(angle)) / pi))
local r, g, b = GetColorGradient(perc)
-- Select sprite sheet cell
local cell = modulo(floor(angle / (pi * 2) * ARROW_TOTAL_CELLS + 0.5), ARROW_TOTAL_CELLS)
local column = modulo(cell, ARROW_SHEET_COLS)
local row = floor(cell / ARROW_SHEET_COLS)
local xstart = (column * ARROW_CELL_W) / ARROW_SHEET_SIZE
local ystart = (row * ARROW_CELL_H) / ARROW_SHEET_SIZE
local xend = ((column + 1) * ARROW_CELL_W) / ARROW_SHEET_SIZE
local yend = ((row + 1) * ARROW_CELL_H) / ARROW_SHEET_SIZE
-- Avoid bleeding from neighboring cells when texture filtering is enabled.
local padX = 0.5 / ARROW_SHEET_SIZE
local padY = 0.5 / ARROW_SHEET_SIZE
xstart = xstart + padX
ystart = ystart + padY
xend = xend - padX
yend = yend - padY
-- Calculate distance and alpha
local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
if dist then
local area = 1
local alpha = dist - area
alpha = alpha > 1 and 1 or alpha
alpha = alpha < 0.5 and 0.5 or alpha
local texalpha = (1 - alpha) * 2
texalpha = texalpha > 1 and 1 or texalpha
texalpha = texalpha < 0 and 0 or texalpha
r, g, b = r + texalpha, g + texalpha, b + texalpha
self.arrow:SetTexCoord(xstart, xend, ystart, yend)
self.arrow:SetVertexColor(r, g, b)
self.arrow:SetAlpha(alpha)
local distText = string.format("%.1f", dist)
self.distance:SetText("Distance: " .. distText)
end
-- Update title and icon when target changes
if target ~= self._lastTarget then
self._lastTarget = target
local title = target.title or ""
if target.questLevel then
title = "[" .. target.questLevel .. "] " .. title
end
self.title:SetText(Questie:Colorize(title, "gold"))
if target.iconPath then
self.icon:SetTexture(target.iconPath)
self.icon:Show()
else
self.icon:Hide()
end
end
end)
arrowFrame:Hide()
end
local function EnsureDriverFrame()
if driverFrame then
return
end
driverFrame = CreateFrame("Frame", "QuestieArrowDriverFrame", UIParent)
driverFrame:Show()
driverFrame._lastRecalc = 0
driverFrame:SetScript("OnUpdate", function(self)
local now = GetTime()
if (self._lastRecalc or 0) + RECALC_NEAREST_SECONDS < now then
self._lastRecalc = now
if not _IsArrowEnabled() then
if arrowFrame then
arrowFrame:Hide()
end
return
end
QuestieArrow:Refresh()
end
end)
end
-- Gather all objectives from tracked quests and sort by distance
function QuestieArrow:UpdateNearestTargets()
-- Don't override manual targets with auto-updates
if hasManualTarget then
return
end
sortedTargets = {}
if not Questie.db or not Questie.db.char then
return
end
local playerX, playerY, playerInstance = HBD:GetPlayerWorldPosition()
if not playerX or not playerY or not playerInstance then
return
end
local tracked = Questie.db.char.TrackedQuests or {}
local hasTracked = next(tracked) ~= nil
-- Auto mode logic: If autoTrack is on OR NOTHING is tracked
local usingAutoLogic = Questie.db.profile.autoTrackQuests or not hasTracked
local playerZoneId = QuestiePlayer:GetCurrentZoneId()
local function _CollectQuestTargets(quest)
if not quest then
return
end
-- Avoid spamming QuestieQuest:PopulateQuestLogInfo (it can trigger marker rebuilds and flicker).
-- Only populate when objective completion flags are missing, and throttle per quest id.
if QuestieQuest and QuestieQuest.PopulateQuestLogInfo and quest.Id then
local needsPopulate = false
if not quest.Objectives and not quest.SpecialObjectives then
needsPopulate = true
else
local function _HasMissingCompletedFlag(list)
if not list then return false end
for _, obj in pairs(list) do
if obj and obj.Completed == nil then
return true
end
end
return false
end
if _HasMissingCompletedFlag(quest.Objectives) or _HasMissingCompletedFlag(quest.SpecialObjectives) then
needsPopulate = true
end
end
if needsPopulate then
local now = GetTime()
local last = lastPopulateByQuestId[quest.Id] or 0
if (last + 2.0) < now then
lastPopulateByQuestId[quest.Id] = now
QuestieQuest:PopulateQuestLogInfo(quest)
end
end
end
local isComplete = quest.isComplete or (QuestieDB.IsComplete(quest.Id) == 1)
if isComplete then
quest.isComplete = true
end
local function _GetCompleteIconType()
local iconType = Questie.ICON_TYPE_COMPLETE
if QuestieDB and QuestieDB.IsActiveEventQuest and QuestieDB.IsActiveEventQuest(quest.Id) then
iconType = Questie.ICON_TYPE_EVENTQUEST_COMPLETE
elseif QuestieDB and QuestieDB.IsPvPQuest and QuestieDB.IsPvPQuest(quest.Id) then
iconType = Questie.ICON_TYPE_PVPQUEST_COMPLETE
elseif quest.IsRepeatable then
iconType = Questie.ICON_TYPE_REPEATABLE_COMPLETE
end
return iconType
end
local function _CollectFinisherSpawns(finisher)
if not finisher then
return
end
local iconPath = ResolveIconTexture(_GetCompleteIconType())
if finisher.spawns then
for finisherZone, spawns in pairs(finisher.spawns) do
if finisherZone and spawns then
for _, coords in ipairs(spawns) do
if coords and coords[1] and coords[2] then
if coords[1] == -1 or coords[2] == -1 then
local dungeonLocation = ZoneDB:GetDungeonLocation(finisherZone)
if dungeonLocation then
for _, value in ipairs(dungeonLocation) do
local zone = value[1]
local x = value[2]
local y = value[3]
-- Auto Logic: Hide distant quests (different zone)
if not (usingAutoLogic and zone ~= playerZoneId) then
local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone)
if uiMapId and x and y then
local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId)
if targetX and targetY and targetInstance then
local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
if dist then
if targetInstance ~= playerInstance then
dist = 500000 + dist * 100
end
table.insert(sortedTargets, {
x = x, y = y, uiMapId = uiMapId, title = quest.name, questLevel = quest.level, iconPath = iconPath, distance = dist,
})
end
end
end
end
end
end
else
-- Auto Logic: Hide distant quests (different zone)
if not (usingAutoLogic and finisherZone ~= playerZoneId) then
local x = coords[1]
local y = coords[2]
local uiMapId = ZoneDB:GetUiMapIdByAreaId(finisherZone)
if uiMapId then
local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId)
if targetX and targetY and targetInstance then
local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
if dist then
if targetInstance ~= playerInstance then
dist = 500000 + dist * 100
end
table.insert(sortedTargets, {
x = x, y = y, uiMapId = uiMapId, title = quest.name, questLevel = quest.level, iconPath = iconPath, distance = dist,
})
end
end
end
end
end
end
end
end
end
end
if finisher.waypoints then
for zone, waypoints in pairs(finisher.waypoints) do
-- Auto Logic: Hide distant quests (different zone)
if not (usingAutoLogic and zone ~= playerZoneId) then
if waypoints and waypoints[1] and waypoints[1][1] and waypoints[1][1][1] then
local x = waypoints[1][1][1]
local y = waypoints[1][1][2]
local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone)
if uiMapId and x and y then
local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(x / 100.0, y / 100.0, uiMapId)
if targetX and targetY and targetInstance then
local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
if dist then
if targetInstance ~= playerInstance then
dist = 500000 + dist * 100
end
table.insert(sortedTargets, {
x = x, y = y, uiMapId = uiMapId, title = quest.name, questLevel = quest.level, iconPath = iconPath, distance = dist,
})
end
end
end
end
end
end
end
end
local function _CollectObjective(objective)
if not objective or not objective.spawnList then
return
end
if QuestieQuest.ShouldHideObjective(objective) then
return
end
if objective.Completed == true or objective.Completed == 1 then
return
end
-- If the objective is numerically fulfilled but the server hasn't sent the Completed flag yet
if objective.Needed and objective.Collected and type(objective.Needed) == "number" and type(objective.Collected) == "number" then
if objective.Collected >= objective.Needed then
return
end
end
for _, spawnData in pairs(objective.spawnList) do
if spawnData and spawnData.Spawns then
for zone, spawns in pairs(spawnData.Spawns) do
-- Auto Logic: Hide distant quests (different zone)
if not (usingAutoLogic and zone ~= playerZoneId) then
for _, spawn in pairs(spawns) do
local uiMapId = ZoneDB:GetUiMapIdByAreaId(zone)
if uiMapId then
local targetX, targetY, targetInstance = HBD:GetWorldCoordinatesFromZone(spawn[1] / 100.0, spawn[2] / 100.0, uiMapId)
if targetX and targetY and targetInstance then
local dist = HBD:GetWorldDistance(targetInstance, playerX, playerY, targetX, targetY)
if dist then
if targetInstance ~= playerInstance then
dist = 500000 + dist * 100
end
table.insert(sortedTargets, {
x = spawn[1], y = spawn[2], uiMapId = uiMapId, title = quest.name, questLevel = quest.level,
iconPath = ResolveIconTexture(objective.Icon) or ResolveIconTexture(spawnData and spawnData.Icon), distance = dist,
})
end
end
end
end
end
end
end
end
end
-- Main Logic Route for this quest target
if isComplete then
if quest.Finisher and quest.Finisher.Id and quest.Finisher.Type then
local finisher
if quest.Finisher.Type == "monster" and QuestieDB and QuestieDB.GetNPC then
finisher = QuestieDB:GetNPC(quest.Finisher.Id)
elseif quest.Finisher.Type == "object" and QuestieDB and QuestieDB.GetObject then
finisher = QuestieDB:GetObject(quest.Finisher.Id)
end
_CollectFinisherSpawns(finisher)
end
-- If the quest is complete, do not add normal objectives to the arrow!
return
end
if quest.Objectives then
for _, objective in pairs(quest.Objectives) do
_CollectObjective(objective)
end
end
if quest.SpecialObjectives then
for _, objective in pairs(quest.SpecialObjectives) do
_CollectObjective(objective)
end
end
end
if QuestiePlayer and QuestiePlayer.currentQuestlog then
for questId, quest in pairs(QuestiePlayer.currentQuestlog) do
if type(quest) == "table" then
local shouldTrack = false
if usingAutoLogic then
-- If using auto logic (implicit or explicit), verify not explicitly hidden
if not Questie.db.char.AutoUntrackedQuests[questId] then
shouldTrack = true
end
else
-- Strict manual tracking
if Questie.db.char.TrackedQuests[questId] then
shouldTrack = true
end
end
if shouldTrack then
_CollectQuestTargets(quest)
end
end
end
end
-- Sort by distance
table.sort(sortedTargets, function(a, b) return a.distance < b.distance end)
end
function QuestieArrow:Refresh()
if not _IsArrowEnabled() then
if arrowFrame then
arrowFrame:Hide()
end
return
end
if hasManualTarget then
EnsureArrowFrame()
arrowFrame:Show()
return
end
QuestieArrow:UpdateNearestTargets()
EnsureArrowFrame()
if sortedTargets[1] then
arrowFrame:Show()
else
arrowFrame:Hide()
end
end
-- Manual target setting (called from tracker TomTom bind)
---@param title string
---@param zoneOrUiMapId number
---@param x number
---@param y number
function QuestieArrow:SetTarget(title, zoneOrUiMapId, x, y)
if not _IsArrowEnabled() then
return
end
-- For manual targets, insert at front of sorted list
local uiMapId = ZoneDB:GetUiMapIdByAreaId(zoneOrUiMapId) or zoneOrUiMapId
hasManualTarget = true
sortedTargets = { {
x = x,
y = y,
uiMapId = uiMapId,
title = title,
distance = 0, -- Manual targets always go first
} }
EnsureArrowFrame()
arrowFrame:Show()
end
function QuestieArrow:ClearTarget()
hasManualTarget = false
sortedTargets = {}
if arrowFrame then
arrowFrame:Hide()
end
end
function QuestieArrow:Initialize()
EnsureArrowFrame()
EnsureDriverFrame()
-- Refresh immediately on tracker updates (quest progress, objective completion, etc.)
if QuestieTracker and QuestieTracker.Update and hooksecurefunc then
local lastTrackerRefresh = 0
hooksecurefunc(QuestieTracker, "Update", function()
if hasManualTarget or not _IsArrowEnabled() then
return
end
local now = GetTime()
if (lastTrackerRefresh + TRACKER_REFRESH_THROTTLE_SECONDS) > now then
return
end
lastTrackerRefresh = now
QuestieArrow:Refresh()
end)
end
QuestieArrow:Refresh()
end
-- Debug function to show current arrow target coordinates
function QuestieArrow:PrintTargetCoords()
if not sortedTargets or not sortedTargets[1] then
print("Questie Arrow: No target currently set!")
return
end
local target = sortedTargets[1]
print("Questie Arrow Target:")
print(" Quest: " .. tostring(target.title))
print(" Level: " .. tostring(target.questLevel))
print(" Zone Coords: " .. string.format("%.1f, %.1f", target.x, target.y))
print(" UI Map ID: " .. tostring(target.uiMapId))
print(" Distance: " .. string.format("%.0f", target.distance))
end
-- Also expose sortedTargets for external access
function QuestieArrow:GetTargets()
return sortedTargets
end
-- Hook into Refresh to show debug info when arrow updates
local _OriginalRefresh = QuestieArrow.Refresh
QuestieArrow.Refresh = function(self, ...)
_OriginalRefresh(self, ...)
-- You can uncomment the line below to see debug output every refresh:
-- QuestieArrow:PrintTargetCoords()
end
@@ -0,0 +1,718 @@
---@class QuestEventHandler
local QuestEventHandler = QuestieLoader:CreateModule("QuestEventHandler")
---@class QuestEventHandlerPrivate
local _QuestEventHandler = QuestEventHandler.private
local _QuestLogUpdateQueue = {} -- Helper module
local questLogUpdateQueue = {} -- The actual queue
---@type QuestEventHandlerPrivate
QuestEventHandler.private = QuestEventHandler.private or {}
---@type QuestLogCache
local QuestLogCache = QuestieLoader:ImportModule("QuestLogCache")
---@type QuestieQuest
local QuestieQuest = QuestieLoader:ImportModule("QuestieQuest")
---@type QuestieJourney
local QuestieJourney = QuestieLoader:ImportModule("QuestieJourney")
---@type QuestieNameplate
local QuestieNameplate = QuestieLoader:ImportModule("QuestieNameplate")
---@type QuestieLib
local QuestieLib = QuestieLoader:ImportModule("QuestieLib")
---@type QuestieDB
local QuestieDB = QuestieLoader:ImportModule("QuestieDB")
---@type QuestieAnnounce
local QuestieAnnounce = QuestieLoader:ImportModule("QuestieAnnounce")
---@type IsleOfQuelDanas
local IsleOfQuelDanas = QuestieLoader:ImportModule("IsleOfQuelDanas")
---@type QuestieCombatQueue
local QuestieCombatQueue = QuestieLoader:ImportModule("QuestieCombatQueue")
---@type QuestieTracker
local QuestieTracker = QuestieLoader:ImportModule("QuestieTracker")
---@type l10n
local l10n = QuestieLoader:ImportModule("l10n")
---@type QuestiePlayer
local QuestiePlayer = QuestieLoader:ImportModule("QuestiePlayer")
--- COMPATIBILITY ---
local C_Timer = QuestieCompat.C_Timer
local GetQuestLogTitle = QuestieCompat.GetQuestLogTitle
local GetItemInfo = QuestieCompat.GetItemInfo
local tableRemove = table.remove
local QUEST_LOG_STATES = {
QUEST_ACCEPTED = "QUEST_ACCEPTED",
QUEST_TURNED_IN = "QUEST_TURNED_IN",
QUEST_REMOVED = "QUEST_REMOVED",
QUEST_ABANDONED = "QUEST_ABANDONED"
}
local eventFrame = CreateFrame("Frame", "QuestieQuestEventFrame")
local questLog = {}
local questLogUpdateQueueSize = 1
local skipNextUQLCEvent = false
local doFullQuestLogScan = false
local deletedQuestItem = false
--- Registers all events that are required for questing (accepting, removing, objective updates, ...)
function QuestEventHandler:RegisterEvents()
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] RegisterEvents")
eventFrame:RegisterEvent("QUEST_ACCEPTED")
eventFrame:RegisterEvent("QUEST_TURNED_IN")
eventFrame:RegisterEvent("QUEST_REMOVED")
eventFrame:RegisterEvent("QUEST_LOG_UPDATE")
eventFrame:RegisterEvent("QUEST_WATCH_UPDATE")
eventFrame:RegisterEvent("UNIT_QUEST_LOG_CHANGED")
eventFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
eventFrame:RegisterEvent("NEW_RECIPE_LEARNED") -- Spell objectives; Runes in SoD count as recipes because "Engraving" is a profession?
--eventFrame:RegisterEvent("SPELLS_CHANGED") -- Spell objectives
eventFrame:RegisterEvent("BAG_UPDATE_DELAYED") -- Catch quest item loots that bypass QUEST_WATCH_UPDATE (e.g. autoloot bots)
eventFrame:RegisterEvent("PLAYER_INTERACTION_MANAGER_FRAME_HIDE")
eventFrame:RegisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE")
eventFrame:SetScript("OnEvent", _QuestEventHandler.OnEvent)
-- StaticPopup dialog hooks. Deleteing Quest items do not always trigger a Quest Log Update.
hooksecurefunc("StaticPopup_Show", function(...)
-- Hook StaticPopup_Show. If we find the "DELETE_ITEM" dialog, check for Quest Items and notify the player.
local which, text_arg1 = ...
if which == "DELETE_ITEM" then
local quest
local questName
local foundQuestItem = false
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieQuest] StaticPopup_Show: Item Name: ", text_arg1)
if deletedQuestItem == true then
deletedQuestItem = false
end
for questLogIndex = 1, 75 do
local title, _, _, isHeader, _, _, _, questId = GetQuestLogTitle(questLogIndex)
if (not title) then
break
end
if (not isHeader) then
quest = QuestieDB.GetQuest(questId)
if quest then
local info = StaticPopupDialogs[which]
local sourceItemId, soureItemName, sourceItemType, soureClassID
local reqSourceItemId, reqSoureItemName, reqSourceItemType, reqSoureClassID
if quest.sourceItemId then
sourceItemId = quest.sourceItemId
if sourceItemId then
soureItemName, _, _, _, _, sourceItemType, _, _, _, _, _, soureClassID = GetItemInfo(sourceItemId)
end
end
if quest.requiredSourceItems then
reqSourceItemId = quest.requiredSourceItems[1]
if reqSourceItemId then
reqSoureItemName, _, _, _, _, reqSourceItemType, _, _, _, _, _, reqSoureClassID = GetItemInfo(reqSourceItemId)
end
end
if sourceItemId and soureItemName and sourceItemType and soureClassID and (sourceItemType == "Quest" or soureClassID == 12) and QuestieDB.QueryItemSingle(sourceItemId, "class") == 12 and text_arg1 == soureItemName then
questName = quest.name
foundQuestItem = true
break
elseif reqSourceItemId and reqSoureItemName and reqSourceItemType and reqSoureClassID and (reqSourceItemType == "Quest" or reqSoureClassID == 12) and QuestieDB.QueryItemSingle(reqSourceItemId, "class") == 12 and text_arg1 == reqSoureItemName then
questName = quest.name
foundQuestItem = true
break
else
if quest.Objectives and #quest.Objectives > 0 then
for _, objective in pairs(quest.Objectives) do
if text_arg1 == objective.Description then
questName = quest.name
foundQuestItem = true
break
end
end
end
end
end
end
end
if foundQuestItem and quest and questName then
local frame, text
for i = 1, STATICPOPUP_NUMDIALOGS do
frame = _G["StaticPopup" .. i]
if (frame:IsShown()) and ((frame.text.text_arg1 == text_arg1) or (string.find(frame.text:GetText(), text_arg1))) then
text = _G[frame:GetName() .. "Text"]
break
end
end
if frame ~= nil and text ~= nil then
local updateText = l10n("Quest Item %%s might be needed for the quest %%s. \n\nAre you sure you want to delete this?")
text:SetFormattedText(updateText, text_arg1, questName)
text.text_arg1 = updateText
StaticPopup_Resize(frame, which)
deletedQuestItem = true
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieQuest] StaticPopup_Show: Quest Item Detected. Updating Static Popup.")
end
end
end
end)
hooksecurefunc("DeleteCursorItem", function()
-- Hook DeleteCursorItem so we know when the player clicks the Accept button
if deletedQuestItem then
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieQuest] DeleteCursorItem: Quest Item deleted. Update all quests.")
C_Timer.After(0.25, function()
_QuestEventHandler:UpdateAllQuests()
deletedQuestItem = false
end)
end
end)
_QuestEventHandler:InitQuestLog()
end
--- On Login mark all quests in the quest log with QUEST_ACCEPTED state
function _QuestEventHandler:InitQuestLog()
-- Fill the QuestLogCache for first time
local cacheMiss, changes = QuestLogCache.CheckForChanges(nil)
-- if cacheMiss then
-- TODO actually can happen in rare edge case if player accepts new quest during questie init. *cough*
-- or if someone managed to overflow game cache already at this point.
--Questie:Error("Did you accept a quest during InitQuestLog? Please report on Github or Discord. Game's quest log cache is not ok. This shouldn't happen. Questie may malfunction.")
-- end
for questId, _ in pairs(changes) do
questLog[questId] = {
state = QUEST_LOG_STATES.QUEST_ACCEPTED
}
QuestieLib:CacheItemNames(questId)
end
end
--- Fires when a quest is accepted in anyway.
---@param questLogIndex number
---@param questId number
function _QuestEventHandler:QuestAccepted(questLogIndex, questId)
questId = questId or select(8, GetQuestLogTitle(questLogIndex))
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_ACCEPTED", questLogIndex, questId)
if questLog[questId] and questLog[questId].timer then
-- We had a QUEST_REMOVED event which started this timer and now it was accepted again.
-- So the quest was abandoned before, because QUEST_TURNED_IN would have run before QUEST_ACCEPTED.
questLog[questId].timer:Cancel()
questLog[questId].timer = nil
QuestieCombatQueue:Queue(function()
_QuestEventHandler:MarkQuestAsAbandoned(questId)
end)
end
questLog[questId] = {}
-- Timed quests do not need a full Quest Log Update.
-- TODO: Add achievement timers later.
local questTimers = GetQuestTimers(questId)
if type(questTimers) == "number" then
skipNextUQLCEvent = false
else
skipNextUQLCEvent = true
end
QuestieCombatQueue:Queue(function()
QuestieLib:CacheItemNames(questId)
_QuestEventHandler:HandleQuestAccepted(questId)
QuestieTracker:Update()
end)
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_ACCEPTED - skipNextUQLCEvent - ", skipNextUQLCEvent)
end
---@param questId number
---@return boolean true @if the function was successful, false otherwise
function _QuestEventHandler:HandleQuestAccepted(questId)
local idx = QuestieCompat.GetQuestLogIndexByID(questId)
if not idx then
_QuestLogUpdateQueue:Insert(function()
return _QuestEventHandler:HandleQuestAccepted(questId)
end)
return false
end
-- We first check the quest objectives and retry in the next QLU event if they are not correct yet
local cacheMiss, changes = QuestLogCache.CheckForChanges({ [questId] = true })
if cacheMiss then
-- if cacheMiss, no need to check changes as only 1 questId
Questie:Debug(Questie.DEBUG_INFO, "Objectives are not cached yet")
_QuestLogUpdateQueue:Insert(function()
return _QuestEventHandler:HandleQuestAccepted(questId)
end)
return false
end
Questie:Debug(Questie.DEBUG_INFO, "Objectives are correct. Calling accept logic. quest:", questId)
questLog[questId].state = QUEST_LOG_STATES.QUEST_ACCEPTED
QuestieQuest:SetObjectivesDirty(questId)
QuestieJourney:AcceptQuest(questId)
QuestieAnnounce:AcceptedQuest(questId)
local isLastIslePhase = Questie.db.global.isleOfQuelDanasPhase == IsleOfQuelDanas.MAX_ISLE_OF_QUEL_DANAS_PHASES
if Questie.IsWotlk and (not isLastIslePhase) and IsleOfQuelDanas.CheckForActivePhase(questId) then
QuestieQuest:SmoothReset()
else
QuestieQuest:AcceptQuest(questId)
end
QuestieCompat.C_Timer.After(0.2, function()
QuestieTracker:Update()
end)
return true
end
--- Fires when a quest is turned in
---@param questId number
---@param xpReward number
---@param moneyReward number
function _QuestEventHandler:QuestTurnedIn(questId, xpReward, moneyReward)
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_TURNED_IN", xpReward, moneyReward, questId)
-- Block UpdateQuest from redrawing objective pins while completion is in-flight
QuestiePlayer.pendingCompleteQuestIds[questId] = true
if questLog[questId] and questLog[questId].timer then
-- Cancel the timer so the quest is not marked as abandoned
questLog[questId].timer:Cancel()
questLog[questId].timer = nil
end
Questie:Debug(Questie.DEBUG_INFO, "Quest:", questId, "was turned in and is completed")
if questLog[questId] then
-- There are quests which you just turn in so there is no preceding QUEST_ACCEPTED event and questLog[questId]
-- is empty
questLog[questId].state = QUEST_LOG_STATES.QUEST_TURNED_IN
elseif QuestieCompat.Is335 then
questLog[questId] = {state = QUEST_LOG_STATES.QUEST_TURNED_IN}
end
local parentQuest = QuestieDB.QueryQuestSingle(questId, "parentQuest")
if parentQuest and parentQuest > 0 then
-- Quests like "The Warsong Reports" have child quests which are just turned in. These child quests only
-- fire QUEST_TURNED_IN + QUEST_LOG_UPDATE
Questie:Debug(Questie.DEBUG_DEVELOP, "Quest:", questId, "Has a Parent Quest - do a full Quest Log check")
doFullQuestLogScan = true
end
local itemName, _, _, quality, _, itemID = GetQuestLogRewardInfo(GetNumQuestLogRewards(questId), questId)
if (itemID ~= nil or itemName ~= nil) and quality == 1 then
Questie:Debug(Questie.DEBUG_DEVELOP, "Quest:", questId, "Recieved a possible Quest Item - do a full Quest Log check")
doFullQuestLogScan = true
skipNextUQLCEvent = false
else
skipNextUQLCEvent = true
end
QuestLogCache.RemoveQuest(questId)
QuestieQuest:SetObjectivesDirty(questId) -- is this necessary? should whole quest.Objectives be cleared at some point of quest removal?
-- Don't immediately mark as complete, wait for QUEST_REMOVED to confirm it was actually turned in
-- This prevents completed quests from being saved as turned in when abandoned
-- QuestieQuest:CompleteQuest(questId)
-- QuestieJourney:CompleteQuest(questId)
-- QuestieAnnounce:CompletedQuest(questId)
-- questLog[questId] = nil
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
end
--- Fires when a quest is removed from the quest log. This includes turning it in and abandoning it.
---@param questId number
function _QuestEventHandler:QuestRemoved(questId)
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_REMOVED", questId)
doFullQuestLogScan = false
if (not questLog[questId]) then
questLog[questId] = {}
end
-- The party members don't care whether a quest was turned in or abandoned, so we can just broadcast here
Questie:SendMessage("QC_ID_BROADCAST_QUEST_REMOVE", questId)
-- QUEST_TURNED_IN was called before QUEST_REMOVED --> quest was turned in
if questLog[questId].state == QUEST_LOG_STATES.QUEST_TURNED_IN then
Questie:Debug(Questie.DEBUG_INFO, "Quest:", questId, "was turned in before. Completing quest.")
-- Ensure the guard is set in case QUEST_REMOVED fires before the combat queue drains
QuestiePlayer.pendingCompleteQuestIds[questId] = true
-- Now that we confirmed the quest was actually turned in (not abandoned), mark it as complete
QuestieQuest:CompleteQuest(questId)
QuestieJourney:CompleteQuest(questId)
QuestieAnnounce:CompletedQuest(questId)
questLog[questId] = nil
return
end
-- QUEST_REMOVED can fire before QUEST_TURNED_IN. If QUEST_TURNED_IN is not called after X seconds the quest
-- was abandoned
questLog[questId] = {
state = QUEST_LOG_STATES.QUEST_REMOVED,
timer = C_Timer.NewTicker(1, function()
_QuestEventHandler:MarkQuestAsAbandoned(questId)
end, 1)
}
skipNextUQLCEvent = true
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_REMOVED - skipNextUQLCEvent - ", skipNextUQLCEvent)
end
---@param questId number
function _QuestEventHandler:MarkQuestAsAbandoned(questId)
Questie:Debug(Questie.DEBUG_DEVELOP, "QuestEventHandler:MarkQuestAsAbandoned")
local questEntry = questLog[questId]
-- so we don't attempt to index a nil value.
if (not questEntry) then
Questie:Debug(Questie.DEBUG_DEVELOP, "QuestEventHandler:MarkQuestAsAbandoned - questLog entry missing for", questId)
return
end
if questEntry.state == QUEST_LOG_STATES.QUEST_REMOVED then
-- Check if objectives were completed before the quest was removed.
-- This handles auto-complete quests that disappear from the log without firing QUEST_TURNED_IN properly.
-- If objectives were complete, treat it as a completion (not abandonment) so objective pins get hidden.
local objectivesWereComplete = false
local quest = QuestieDB.GetQuest(questId)
if quest then
local isComplete = QuestieDB.IsComplete(questId)
objectivesWereComplete = (isComplete == 1)
-- Check for Ebonhold auto-complete quests which might be removed before IsComplete returns 1
local desc = quest.Description
if type(desc) == "table" then desc = desc[1] end
if (not objectivesWereComplete) and desc and type(desc) == "string" then
if string.find(desc, "automatically rewarded") then
Questie:Debug(Questie.DEBUG_INFO, "Quest:", questId, "detected as auto-complete by description")
objectivesWereComplete = true
end
end
end
if objectivesWereComplete then
-- Objectives were complete, so this was likely an auto-complete quest.
-- Mark as complete instead of abandoned so objective pins get hidden.
Questie:Debug(Questie.DEBUG_INFO, "Quest:", questId, "objectives were complete - treating as completed (auto-complete quest)")
questEntry.state = QUEST_LOG_STATES.QUEST_TURNED_IN
QuestLogCache.RemoveQuest(questId)
QuestieQuest:CompleteQuest(questId)
QuestieJourney:CompleteQuest(questId)
QuestieAnnounce:CompletedQuest(questId)
questLog[questId] = nil
else
Questie:Debug(Questie.DEBUG_INFO, "Quest:", questId, "was abandoned")
questEntry.state = QUEST_LOG_STATES.QUEST_ABANDONED
QuestLogCache.RemoveQuest(questId)
QuestieQuest:SetObjectivesDirty(questId) -- is this necessary? should whole quest.Objectives be cleared at some point of quest removal?
QuestieQuest:AbandonedQuest(questId)
QuestieJourney:AbandonQuest(questId)
QuestieAnnounce:AbandonedQuest(questId)
questLog[questId] = nil
end
end
end
---Fires when the quest log changed in any way. This event fires very often!
function _QuestEventHandler:QuestLogUpdate()
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_LOG_UPDATE")
local continueQueuing = true
-- Some of the other quest event didn't have the required information and ordered to wait for the next QLU.
-- We are now calling the function which the event added.
while continueQueuing and next(questLogUpdateQueue) do
continueQueuing = _QuestLogUpdateQueue:GetFirst()()
end
if doFullQuestLogScan then
doFullQuestLogScan = false
-- Function call updates doFullQuestLogScan. Order matters.
_QuestEventHandler:UpdateAllQuests()
else
_QuestEventHandler:CleanupRemovedQuestsFallback()
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
end
end
--- Fires whenever a quest objective progressed
---@param questId number
function _QuestEventHandler:QuestWatchUpdate(questId)
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_WATCH_UPDATE", questId)
-- We do a full scan even though we have the questId because many QUEST_WATCH_UPDATE can fire before
-- a QUEST_LOG_UPDATE. Also not every QUEST_WATCH_UPDATE gets a single QUEST_LOG_UPDATE and doing a full
-- scan is less error prone
doFullQuestLogScan = true
end
local _UnitQuestLogChangedCallback = function()
-- We also check in here because UNIT_QUEST_LOG_CHANGED is fired before the relevant events
-- (Accept, removed, ...)
if (not skipNextUQLCEvent) then
doFullQuestLogScan = true
else
doFullQuestLogScan = false
skipNextUQLCEvent = false
Questie:Debug(Questie.DEBUG_INFO, "Skipping UnitQuestLogChanged")
end
return true
end
--- Fires when an objective changed in the quest log of the unitTarget. The required data is not available yet though
---@param unitTarget string
function _QuestEventHandler:UnitQuestLogChanged(unitTarget)
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] UNIT_QUEST_LOG_CHANGED", unitTarget)
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] UNIT_QUEST_LOG_CHANGED - skipNextUQLCEvent - ", skipNextUQLCEvent)
-- There seem to be quests which don't trigger a QUEST_WATCH_UPDATE.
-- We don't add a full check to the queue if skipNextUQLCEvent == true (from QUEST_WATCH_UPDATE or QUEST_TURNED_IN)
if (not skipNextUQLCEvent) then
doFullQuestLogScan = true
_QuestLogUpdateQueue:Insert(_UnitQuestLogChangedCallback)
else
Questie:Debug(Questie.DEBUG_INFO, "Skipping UnitQuestLogChanged")
end
skipNextUQLCEvent = false
end
-- Fallback cleanup: some servers remove quests without firing QUEST_REMOVED reliably.
-- This compares Questie's currentQuestlog vs the game's quest log and removes stale quests.
function _QuestEventHandler:CleanupRemovedQuestsFallback()
local gameQuestIds = {}
local numEntries = select(1, GetNumQuestLogEntries()) or 0
for questLogIndex = 1, numEntries do
local title, _, _, isHeader, _, _, _, qid = GetQuestLogTitle(questLogIndex)
if title and qid and qid > 0 and (not isHeader) then
gameQuestIds[qid] = true
end
end
if QuestiePlayer and QuestiePlayer.currentQuestlog then
local removedQuestIds = {}
for questId in pairs(QuestiePlayer.currentQuestlog) do
if questId and questId > 0 and (not gameQuestIds[questId]) then
removedQuestIds[#removedQuestIds + 1] = questId
end
end
for i = 1, #removedQuestIds do
local questId = removedQuestIds[i]
-- Quest disappeared from log (abandoned or auto-turned-in)
-- Check if this quest was confirmed as turned in (not just objectives complete)
local wasTurnedIn = questLog[questId] and questLog[questId].state == QUEST_LOG_STATES.QUEST_TURNED_IN
local wasAlreadyComplete = Questie.db.char.complete and Questie.db.char.complete[questId]
QuestLogCache.RemoveQuest(questId)
QuestieQuest:SetObjectivesDirty(questId)
-- Only mark as complete if it was actually turned in OR already marked complete from previous session
-- Don't use quest.WasComplete because that's set when objectives complete, not when quest is turned in
if wasTurnedIn or wasAlreadyComplete then
QuestieQuest:CompleteQuest(questId)
else
QuestieQuest:AbandonedQuest(questId)
QuestieJourney:AbandonQuest(questId)
QuestieAnnounce:AbandonedQuest(questId)
end
questLog[questId] = nil
end
if #removedQuestIds > 0 then
QuestieNameplate:UpdateNameplate()
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
end
end
end
--- Does a full scan of the quest log and updates every quest that is in the QUEST_ACCEPTED state and which hash changed
--- since the last check
function _QuestEventHandler:UpdateAllQuests()
Questie:Debug(Questie.DEBUG_INFO, "Running full questlog check")
local questIdsToCheck = {}
-- TODO replace with a ready table so no need to generate at each call
for questId, data in pairs(questLog) do
if data.state == QUEST_LOG_STATES.QUEST_ACCEPTED then
questIdsToCheck[questId] = true
end
end
local cacheMiss, changes = QuestLogCache.CheckForChanges(questIdsToCheck)
if next(changes) then
for questId, objIds in pairs(changes) do
--Questie:Debug(Questie.DEBUG_INFO, "Quest:", questId, "objectives:", table.concat(objIds, ","), "will be updated")
Questie:Debug(Questie.DEBUG_INFO, "Quest:", questId, "will be updated")
QuestieQuest:SetObjectivesDirty(questId)
QuestieNameplate:UpdateNameplate()
QuestieQuest:UpdateQuest(questId)
end
QuestieCombatQueue:Queue(function()
C_Timer.After(1.0, function()
QuestieTracker:Update()
end)
end)
else
Questie:Debug(Questie.DEBUG_INFO, "Nothing to update")
end
_QuestEventHandler:CleanupRemovedQuestsFallback()
-- Do UpdateAllQuests() again at next QUEST_LOG_UPDATE if there was "cacheMiss" (game's cache and addon's cache didn't have all required data yet)
doFullQuestLogScan = doFullQuestLogScan or cacheMiss
end
local lastTimeQuestRelatedFrameClosedEvent = -1
--- Blizzard does not fire any event when quest items are received or retrieved from sources other than looting.
--- So we hook events which fires once or twice after closing certain frames and do a full quest log check.
function _QuestEventHandler:QuestRelatedFrameClosed(event)
local now = math.floor(GetTime())
-- Don't do update if event fired twice
if lastTimeQuestRelatedFrameClosedEvent ~= now then
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event]", event)
lastTimeQuestRelatedFrameClosedEvent = now
_QuestEventHandler:UpdateAllQuests()
QuestieTracker:Update()
end
end
function _QuestEventHandler:ReputationChange()
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] CHAT_MSG_COMBAT_FACTION_CHANGE")
-- Reputational quest progression doesn't fire UNIT_QUEST_LOG_CHANGED event, only QUEST_LOG_UPDATE event.
doFullQuestLogScan = true
end
--- Helper function to insert a callback to the questLogUpdateQueue and increase the index
function _QuestLogUpdateQueue:Insert(callback)
questLogUpdateQueue[questLogUpdateQueueSize] = callback
questLogUpdateQueueSize = questLogUpdateQueueSize + 1
end
--- Helper function to retrieve the first element of questLogUpdateQueue
---@return function @The callback that was inserted first into questLogUpdateQueue
function _QuestLogUpdateQueue:GetFirst()
questLogUpdateQueueSize = questLogUpdateQueueSize - 1
return tableRemove(questLogUpdateQueue, 1)
end
local trackerMinimizedByDungeon = false
function _QuestEventHandler:ZoneChangedNewArea()
Questie:Debug(Questie.DEBUG_DEVELOP, "[EVENT] ZONE_CHANGED_NEW_AREA")
-- By my tests it takes a full 6-7 seconds for the world to load. There are a lot of
-- backend Questie updates that occur when a player zones in/out of an instance. This
-- is necessary to get everything back into it's "normal" state after all the updates.
local isInInstance, instanceType = IsInInstance()
if isInInstance then
C_Timer.After(8, function()
Questie:Debug(Questie.DEBUG_DEVELOP, "[EVENT] ZONE_CHANGED_NEW_AREA: Entering Instance")
if Questie.db.profile.hideTrackerInDungeons then
trackerMinimizedByDungeon = true
QuestieCombatQueue:Queue(function()
QuestieTracker:Collapse()
end)
end
end)
-- We only want this to fire outside of an instance if the player isn't dead and we need to reset the Tracker
elseif (not Questie.db.char.isTrackerExpanded and not UnitIsGhost("player")) and trackerMinimizedByDungeon == true then
C_Timer.After(8, function()
Questie:Debug(Questie.DEBUG_DEVELOP, "[EVENT] ZONE_CHANGED_NEW_AREA: Exiting Instance")
if Questie.db.profile.hideTrackerInDungeons then
trackerMinimizedByDungeon = false
QuestieCombatQueue:Queue(function()
QuestieTracker:Expand()
end)
end
end)
end
end
--- Is executed whenever an event is fired and triggers relevant event handling.
---@param event string
function _QuestEventHandler:OnEvent(event, ...)
if event == "QUEST_ACCEPTED" then
_QuestEventHandler:QuestAccepted(...)
elseif event == "QUEST_TURNED_IN" then
_QuestEventHandler:QuestTurnedIn(...)
elseif event == "QUEST_REMOVED" then
_QuestEventHandler:QuestRemoved(...)
elseif event == "QUEST_LOG_UPDATE" then
_QuestEventHandler:QuestLogUpdate()
elseif event == "QUEST_WATCH_UPDATE" then
_QuestEventHandler:QuestWatchUpdate(...)
elseif event == "UNIT_QUEST_LOG_CHANGED" and select(1, ...) == "player" then
_QuestEventHandler:UnitQuestLogChanged(...)
elseif event == "ZONE_CHANGED_NEW_AREA" then
_QuestEventHandler:ZoneChangedNewArea()
elseif event == "NEW_RECIPE_LEARNED" then
Questie:Debug(Questie.DEBUG_DEVELOP, "[EVENT] NEW_RECIPE_LEARNED (QuestEventHandler)")
doFullQuestLogScan = true -- If this event is related to a spell objective, a QUEST_LOG_UPDATE will be fired afterwards
elseif event == "BAG_UPDATE_DELAYED" then
-- Autoloot bots can bypass the standard loot frame, skipping QUEST_WATCH_UPDATE for the last items looted.
-- Flag a full scan and trigger the update immediately so the tracker refreshes.
doFullQuestLogScan = true
_QuestEventHandler:QuestLogUpdate()
elseif event == "PLAYER_INTERACTION_MANAGER_FRAME_HIDE" then
local eventType = select(1, ...)
if eventType == 1 then
event = "TRADE_CLOSED"
elseif eventType == 5 then
event = "MERCHANT_CLOSED"
elseif eventType == 8 then
event = "BANKFRAME_CLOSED"
elseif eventType == 10 then
event = "GUILDBANKFRAME_CLOSED"
elseif eventType == 12 then
event = "VENDOR_CLOSED"
elseif eventType == 17 then
event = "MAIL_CLOSED"
elseif eventType == 21 then
event = "AUCTION_HOUSE_CLOSED"
else
-- Unknown event which we will simply ignore
return
end
_QuestEventHandler:QuestRelatedFrameClosed(event)
elseif event == "CHAT_MSG_COMBAT_FACTION_CHANGE" then
_QuestEventHandler:ReputationChange()
end
end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+250
View File
@@ -0,0 +1,250 @@
## Interface: 30300
## Title: Questie - Ebonhold
## Author: Questie Team
## Notes: A standalone Classic QuestHelper
## Notes-esMX: Ayundante de misión
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
## Version: 9.8.2
## RequiredDeps:
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig
## SavedVariablesPerCharacter: QuestieConfigCharacter
## X-Curse-Project-ID: 334372
## X-Wago-ID: qv634BKb
## X-WOW_PROJECT_ID: 11
# Loader module
Modules\Libs\QuestieLoader.lua
# COMPATIBILITY
Modules\QuestieCompat.lua
Compat\embeds.xml
Modules\VersionCheck.lua
# Thread Manager
Modules\Libs\ThreadLib.lua
#Message Handler
Modules\Libs\MessageHandler.lua
#Quest XP
Database\QuestXP\QuestieXP.lua
Database\QuestXP\DB\xpDB-wotlk.lua
# stream module (used by DB)
Modules\QuestieStream.lua
# Zones
Database\Zones\zoneTables.lua
# Ascension Custom Zones
Database\Ascension\Zones\AscensionZoneTables.lua
Database\Ascension\Zones\AscensionUiMapData.lua
# Ebonhold Custom Zones
Database\Ebonhold\Zones\EbonholdZoneTables.lua
Database\Ebonhold\Zones\EbonholdUiMapData.lua
Database\Zones\zoneDB.lua
# Databases
Database\Wotlk\wotlkItemDB.lua
Database\Wotlk\wotlkNpcDB.lua
Database\Wotlk\wotlkObjectDB.lua
Database\Wotlk\wotlkQuestDB.lua
Database\QuestieDB.lua
Database\questDB.lua
Database\objectDB.lua
Database\npcDB.lua
Database\itemDB.lua
Database\Constants.lua
Database\MeetingStones.lua
# Ascension Custom Database
Database\Ascension\Bronzebeard\AscensionNpcDB.lua
Database\Ascension\Bronzebeard\AscensionObjectDB.lua
Database\Ascension\Bronzebeard\AscensionItemDB.lua
Database\Ascension\Bronzebeard\AscensionQuestDB.lua
Database\Ascension\AscensionLoader.lua
# Ebonhold Custom Database
Database\Ebonhold\Ebonhold\EbonholdNpcDB.lua
Database\Ebonhold\Ebonhold\EbonholdObjectDB.lua
Database\Ebonhold\Ebonhold\EbonholdItemDB.lua
Database\Ebonhold\Ebonhold\EbonholdQuestDB.lua
Database\Ebonhold\EbonholdLoader.lua
# Corrections
Database\Corrections\AutoTableUpdates.lua
Database\Corrections\QuestieCorrections.lua
Database\Corrections\QuestieItemBlacklist.lua
Database\Corrections\QuestieNPCBlacklist.lua
Database\Corrections\QuestieQuestBlacklist.lua
#Database\Corrections\SoMPhases.lua
Database\Corrections\QuestieEvent.lua
# Automatic General Corrections
Database\Corrections\Automatic\itemStartFixes.lua
Database\Corrections\Automatic\classicQuestReputationFixes.lua
# Classic Corrections
Database\Corrections\classicQuestFixes.lua
Database\Corrections\classicNPCFixes.lua
Database\Corrections\classicItemFixes.lua
Database\Corrections\classicObjectFixes.lua
# TBC Corrections
Database\Corrections\tbcQuestFixes.lua
Database\Corrections\tbcNPCFixes.lua
Database\Corrections\tbcItemFixes.lua
Database\Corrections\tbcObjectFixes.lua
# Wotlk Corrections
Database\Corrections\wotlkQuestFixes.lua
Database\Corrections\wotlkNPCFixes.lua
Database\Corrections\wotlkItemFixes.lua
Database\Corrections\wotlkObjectFixes.lua
# Compiler
Database\compiler.lua
# Localization
Localization\l10n.lua
Localization\Translations\Translations.xml
Localization\lookups\lookupQuestCategories.lua
Localization\lookups\lookupZones.lua
Localization\lookups\Wotlk\lookupItems\lookupItems.xml
Localization\lookups\Wotlk\lookupNpcs\lookupNpcs.xml
Localization\lookups\Wotlk\lookupObjects\lookupObjects.xml
Localization\lookups\Wotlk\lookupQuests\lookupQuests.xml
# Libs
Modules\Libs\QuestieLib.lua
Modules\Libs\QuestieSerializer.lua
Modules\Libs\QuestieCombatQueue.lua
Modules\Libs\RamerDouglasPeucker.lua
# Modules
Modules\QuestieValidateGameCache.lua
Modules\Arrow\QuestieArrow.lua
Modules\QuestieInit.lua
Modules\MinimapIcon.lua
Modules\QuestieProfessions.lua
Modules\QuestieReputation.lua
Modules\QuestieEventHandler.lua
Modules\QuestieLearner.lua
Modules\Migration.lua
Modules\QuestieMenu\Townsfolk.lua
Modules\QuestieMenu\ClassTrainers.lua
Modules\QuestieMenu\Mailboxes.lua
Modules\QuestieMenu\MeetingStones.lua
Modules\QuestieMenu\ProfessionTrainers.lua
Modules\QuestieMenu\QuestieMenu.lua
Modules\QuestieAnnounce.lua
Modules\QuestieShutUp.lua
Modules\Sounds.lua
Modules\TaskQueue.lua
Modules\QuestiePlayer.lua
#Modules\QuestieDebugOffer.lua
Modules\WorldMapButton\WorldMapButton.lua
#Modules\WorldMapButton\QuestieWorldMapButtonTemplate.xml
# QuestLinks
Modules\QuestLinks\ChatFilter.lua
Modules\QuestLinks\Hooks.lua
Modules\QuestLinks\Link.lua
# Tooltips
Modules\Tooltips\Tooltip.lua
Modules\Tooltips\MapIconTooltip.lua
Modules\Tooltips\TooltipHandler.lua
# Auto
Modules\Auto\QuestieAuto.lua
Modules\Auto\Privates.lua
Modules\Auto\DisallowedIDs.lua
# FramePool
Modules\FramePool\QuestieFramePool.lua
Modules\FramePool\QuestieFrame.lua
# Map
Modules\Map\QuestieMap.lua
Modules\Map\QuestieMapUtils.lua
#Modules\Map\HBDHooks.lua
Modules\Map\WeaponMasterSkills.lua
# Quest
Modules\Quest\AvailableQuests.lua
Modules\Quest\QuestLogCache.lua
Modules\Quest\DailyQuests.lua
Modules\Quest\IsleOfQuelDanas.lua
Modules\Quest\QuestEventHandler.lua
Modules\Quest\QuestgiverFrame.lua
Modules\Quest\QuestieQuest.lua
Modules\Quest\QuestieQuestPrivates.lua
Modules\QuestieNameplate.lua
Modules\QuestieCoordinates.lua
# Network
Modules\Network\QuestieComms.lua
Modules\Network\QuestieCommsData.lua
# Journey
Modules\Journey\QuestieJourney.lua
Modules\Journey\QuestieJourneyPrivates.lua
Modules\Journey\QuestieJourneyUtils.lua
Modules\Journey\History.lua
Modules\Journey\QuestDetailsFrame.lua
Modules\Journey\tabs\MyJourney\Note.lua
Modules\Journey\tabs\MyJourney\MyJourney.lua
Modules\Journey\tabs\MyJourney\MyJourneyTab.lua
Modules\Journey\tabs\QuestsByZone\QuestsByZone.lua
Modules\Journey\tabs\QuestsByZone\QuestsByZoneTab.lua
#Modules\Journey\tabs\Search\Search.lua
#Modules\Journey\tabs\Search\SearchTab.lua
Modules\Journey\QuestieSearch.lua
Modules\Journey\QuestieSearchResults.lua
# Tracker
Modules\Tracker\QuestieTracker.lua
Modules\Tracker\TrackerUtils.lua
Modules\Tracker\TrackerMenu.lua
Modules\Tracker\TrackerFadeTicker.lua
Modules\Tracker\TrackerBaseFrame.lua
Modules\Tracker\TrackerHeaderFrame.lua
Modules\Tracker\TrackerQuestFrame.lua
Modules\Tracker\TrackerQuestTimers.lua
Modules\Tracker\TrackerLinePool.lua
# Tutorial
Modules\Tutorial\ChooseObjectiveType.lua
Modules\Tutorial\Tutorial.lua
#Modules\QuestieDBMIntegration.lua
Modules\QuestieSlash.lua
# Options
Modules\Options\QuestieOptions.lua
Modules\Options\QuestieOptionsDefaults.lua
Modules\Options\QuestieOptionsUtils.lua
Modules\Options\AdvancedTab\QuestieOptionsAdvanced.lua
Modules\Options\AutoTab\QuestieOptionsAuto.lua
Modules\Options\DBMTab\QuestieOptionsDBM.lua
Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
Modules\QuestieProfiler.lua
# Main
Questie.lua
+250
View File
@@ -0,0 +1,250 @@
## Interface: 30300
## Title: Questie - Ebonhold
## Author: Questie Team
## Notes: A standalone Classic QuestHelper
## Notes-esMX: Ayundante de misión
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
## Version: 9.8.4
## RequiredDeps:
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig
## SavedVariablesPerCharacter: QuestieConfigCharacter
## X-Curse-Project-ID: 334372
## X-Wago-ID: qv634BKb
## X-WOW_PROJECT_ID: 11
# Loader module
Modules\Libs\QuestieLoader.lua
# COMPATIBILITY
Modules\QuestieCompat.lua
Compat\embeds.xml
Modules\VersionCheck.lua
# Thread Manager
Modules\Libs\ThreadLib.lua
#Message Handler
Modules\Libs\MessageHandler.lua
#Quest XP
Database\QuestXP\QuestieXP.lua
Database\QuestXP\DB\xpDB-wotlk.lua
# stream module (used by DB)
Modules\QuestieStream.lua
# Zones
Database\Zones\zoneTables.lua
# Ascension Custom Zones
Database\Ascension\Zones\AscensionZoneTables.lua
Database\Ascension\Zones\AscensionUiMapData.lua
# Ebonhold Custom Zones
Database\Ebonhold\Zones\EbonholdZoneTables.lua
Database\Ebonhold\Zones\EbonholdUiMapData.lua
Database\Zones\zoneDB.lua
# Databases
Database\Wotlk\wotlkItemDB.lua
Database\Wotlk\wotlkNpcDB.lua
Database\Wotlk\wotlkObjectDB.lua
Database\Wotlk\wotlkQuestDB.lua
Database\QuestieDB.lua
Database\questDB.lua
Database\objectDB.lua
Database\npcDB.lua
Database\itemDB.lua
Database\Constants.lua
Database\MeetingStones.lua
# Ascension Custom Database
Database\Ascension\Bronzebeard\AscensionNpcDB.lua
Database\Ascension\Bronzebeard\AscensionObjectDB.lua
Database\Ascension\Bronzebeard\AscensionItemDB.lua
Database\Ascension\Bronzebeard\AscensionQuestDB.lua
Database\Ascension\AscensionLoader.lua
# Ebonhold Custom Database
Database\Ebonhold\Ebonhold\EbonholdNpcDB.lua
Database\Ebonhold\Ebonhold\EbonholdObjectDB.lua
Database\Ebonhold\Ebonhold\EbonholdItemDB.lua
Database\Ebonhold\Ebonhold\EbonholdQuestDB.lua
Database\Ebonhold\EbonholdLoader.lua
# Corrections
Database\Corrections\AutoTableUpdates.lua
Database\Corrections\QuestieCorrections.lua
Database\Corrections\QuestieItemBlacklist.lua
Database\Corrections\QuestieNPCBlacklist.lua
Database\Corrections\QuestieQuestBlacklist.lua
#Database\Corrections\SoMPhases.lua
Database\Corrections\QuestieEvent.lua
# Automatic General Corrections
Database\Corrections\Automatic\itemStartFixes.lua
Database\Corrections\Automatic\classicQuestReputationFixes.lua
# Classic Corrections
Database\Corrections\classicQuestFixes.lua
Database\Corrections\classicNPCFixes.lua
Database\Corrections\classicItemFixes.lua
Database\Corrections\classicObjectFixes.lua
# TBC Corrections
Database\Corrections\tbcQuestFixes.lua
Database\Corrections\tbcNPCFixes.lua
Database\Corrections\tbcItemFixes.lua
Database\Corrections\tbcObjectFixes.lua
# Wotlk Corrections
Database\Corrections\wotlkQuestFixes.lua
Database\Corrections\wotlkNPCFixes.lua
Database\Corrections\wotlkItemFixes.lua
Database\Corrections\wotlkObjectFixes.lua
# Compiler
Database\compiler.lua
# Localization
Localization\l10n.lua
Localization\Translations\Translations.xml
Localization\lookups\lookupQuestCategories.lua
Localization\lookups\lookupZones.lua
Localization\lookups\Wotlk\lookupItems\lookupItems.xml
Localization\lookups\Wotlk\lookupNpcs\lookupNpcs.xml
Localization\lookups\Wotlk\lookupObjects\lookupObjects.xml
Localization\lookups\Wotlk\lookupQuests\lookupQuests.xml
# Libs
Modules\Libs\QuestieLib.lua
Modules\Libs\QuestieSerializer.lua
Modules\Libs\QuestieCombatQueue.lua
Modules\Libs\RamerDouglasPeucker.lua
# Modules
Modules\QuestieValidateGameCache.lua
Modules\Arrow\QuestieArrow.lua
Modules\QuestieInit.lua
Modules\MinimapIcon.lua
Modules\QuestieProfessions.lua
Modules\QuestieReputation.lua
Modules\QuestieEventHandler.lua
Modules\QuestieLearner.lua
Modules\Migration.lua
Modules\QuestieMenu\Townsfolk.lua
Modules\QuestieMenu\ClassTrainers.lua
Modules\QuestieMenu\Mailboxes.lua
Modules\QuestieMenu\MeetingStones.lua
Modules\QuestieMenu\ProfessionTrainers.lua
Modules\QuestieMenu\QuestieMenu.lua
Modules\QuestieAnnounce.lua
Modules\QuestieShutUp.lua
Modules\Sounds.lua
Modules\TaskQueue.lua
Modules\QuestiePlayer.lua
#Modules\QuestieDebugOffer.lua
Modules\WorldMapButton\WorldMapButton.lua
#Modules\WorldMapButton\QuestieWorldMapButtonTemplate.xml
# QuestLinks
Modules\QuestLinks\ChatFilter.lua
Modules\QuestLinks\Hooks.lua
Modules\QuestLinks\Link.lua
# Tooltips
Modules\Tooltips\Tooltip.lua
Modules\Tooltips\MapIconTooltip.lua
Modules\Tooltips\TooltipHandler.lua
# Auto
Modules\Auto\QuestieAuto.lua
Modules\Auto\Privates.lua
Modules\Auto\DisallowedIDs.lua
# FramePool
Modules\FramePool\QuestieFramePool.lua
Modules\FramePool\QuestieFrame.lua
# Map
Modules\Map\QuestieMap.lua
Modules\Map\QuestieMapUtils.lua
#Modules\Map\HBDHooks.lua
Modules\Map\WeaponMasterSkills.lua
# Quest
Modules\Quest\AvailableQuests.lua
Modules\Quest\QuestLogCache.lua
Modules\Quest\DailyQuests.lua
Modules\Quest\IsleOfQuelDanas.lua
Modules\Quest\QuestEventHandler.lua
Modules\Quest\QuestgiverFrame.lua
Modules\Quest\QuestieQuest.lua
Modules\Quest\QuestieQuestPrivates.lua
Modules\QuestieNameplate.lua
Modules\QuestieCoordinates.lua
# Network
Modules\Network\QuestieComms.lua
Modules\Network\QuestieCommsData.lua
# Journey
Modules\Journey\QuestieJourney.lua
Modules\Journey\QuestieJourneyPrivates.lua
Modules\Journey\QuestieJourneyUtils.lua
Modules\Journey\History.lua
Modules\Journey\QuestDetailsFrame.lua
Modules\Journey\tabs\MyJourney\Note.lua
Modules\Journey\tabs\MyJourney\MyJourney.lua
Modules\Journey\tabs\MyJourney\MyJourneyTab.lua
Modules\Journey\tabs\QuestsByZone\QuestsByZone.lua
Modules\Journey\tabs\QuestsByZone\QuestsByZoneTab.lua
#Modules\Journey\tabs\Search\Search.lua
#Modules\Journey\tabs\Search\SearchTab.lua
Modules\Journey\QuestieSearch.lua
Modules\Journey\QuestieSearchResults.lua
# Tracker
Modules\Tracker\QuestieTracker.lua
Modules\Tracker\TrackerUtils.lua
Modules\Tracker\TrackerMenu.lua
Modules\Tracker\TrackerFadeTicker.lua
Modules\Tracker\TrackerBaseFrame.lua
Modules\Tracker\TrackerHeaderFrame.lua
Modules\Tracker\TrackerQuestFrame.lua
Modules\Tracker\TrackerQuestTimers.lua
Modules\Tracker\TrackerLinePool.lua
# Tutorial
Modules\Tutorial\ChooseObjectiveType.lua
Modules\Tutorial\Tutorial.lua
#Modules\QuestieDBMIntegration.lua
Modules\QuestieSlash.lua
# Options
Modules\Options\QuestieOptions.lua
Modules\Options\QuestieOptionsDefaults.lua
Modules\Options\QuestieOptionsUtils.lua
Modules\Options\AdvancedTab\QuestieOptionsAdvanced.lua
Modules\Options\AutoTab\QuestieOptionsAuto.lua
Modules\Options\DBMTab\QuestieOptionsDBM.lua
Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
Modules\Options\IconsTab\QuestieOptionsIcons.lua
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
# Cleanup
Modules\QuestieCleanup.lua
# Profiler
Modules\QuestieProfiler.lua
# Main
Questie.lua
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## v9.8.5
### New Ebonhold Quests
- **Outland**: Blade's Edge Trophy (includes missing Blade's Edge Mountains spawn tracking data for Morcrush, Hemathion, Speaker Mar'grom).
- **Azeroth**: Arathi Trophy (includes missing Arathi Highlands spawn tracking data for Darbel Montrose, Singer, Foulbelly, Ruul Onestone, Kovork, Molok the Crusher, Zalas Witherbark, Nimar the Slayer, Geomancer Flintdagger, Prince Nazjak).
## v9.8.4
### Fixes
+3 -2
View File
@@ -2724,7 +2724,7 @@ function QuestieWotlkQuestFixes:Load()
[12924] = {
[questKeys.objectives] = {{{30099,"Fjorn's Anvil Brought to Dun Niffelem"}}},
[questKeys.extraObjectives] = {
{nil, Questie.ICON_TYPE_TALK, l10n("Ask King Jokkum to allow Thorim's armor to be reforged"), 0, {{"monster", 30105}}},
{nil, Questie.ICON_TYPE_TALK, l10n("Pick up 'You Can't Miss Him' (12966)"), 0, {{"monster", 30105}}, {["hideIfQuestActive"] = 12966}},
},
},
[12925] = {
@@ -2828,6 +2828,7 @@ function QuestieWotlkQuestFixes:Load()
[12966] = {
[questKeys.preQuestGroup] = {12915,12956},
[questKeys.requiredMinRep] = {1119,0},
[questKeys.finishedBy] = {{30127}},
},
[12967] = {
[questKeys.objectives] = {{{30120}}},
@@ -2916,7 +2917,7 @@ function QuestieWotlkQuestFixes:Load()
[questKeys.objectives] = {nil,nil,nil,nil,{{{30273,30268,30274},30273,}}},
},
[13010] = {
[questKeys.objectives] = {{{30105}},nil,nil,{1119,3000}},
[questKeys.objectives] = {{{30105, nil, {["hideIfQuestActive"] = 12966}}},nil,nil,{1119,3000}},
},
[13011] = {
[questKeys.name] = "Culling Jorcuttar",
+16 -1
View File
@@ -143,7 +143,22 @@ EbonholdDB.npcData = EbonholdDB.npcData or {
[1911] = {'Deeb',12600,12600,13,13,4,{[85] = {{57.2,28.2},{57.4,29.2},{57.6,28.2},{57.6,29},{58,25},{58,26.4},{58.2,26.6},{58.6,27.6},{58.6,28.6},{58.8,27.2},{59.6,27},{59.6,28.6},{60,30},{61.4,29.8},{62,28.4},{62.2,29.6},{62.4,26.6},{62.4,29},{62.6,28.6},{62.8,29.6},{63.2,27.4},{63.2,27.6},{63.2,31},{63.6,28},{63.8,26.8},{63.8,29.4}}},nil,85,nil,nil,16,nil,"",0},
[1910] = {'Muad',12600,12600,12,12,4,{[85] = {{33.4,42.8},{33.4,43.8},{33.6,43},{34,43.8},{34.2,41.6},{34.2,44.6},{34.4,41.2},{34.6,41},{34.6,42},{34.8,44.2},{34.8,44.8},{34.8,45.8},{35,39.8},{35.2,43.4},{35.8,46.4},{36.2,38},{36.2,42.4},{36.2,44.2},{36.2,44.6},{36.4,39.4},{36.4,40.2},{36.4,41.2},{36.4,42.8},{36.6,38},{36.6,42},{36.6,43.4},{36.6,43.6},{36.8,39},{36.8,40},{36.8,40.8},{36.8,44.6},{37.6,39.2},{37.6,40.4},{37.6,41.2},{37.6,41.6},{37.8,43.4}}},nil,85,nil,nil,16,nil,"",0},
[10358] = {'Fellicent\'s Shade',12600,12600,11,11,4,{[85] = {{71.4,61.6},{73.4,60},{74.2,60.4},{74.2,63.2},{74.4,59.4},{74.4,60.8},{74.4,61.6},{74.6,63.8},{74.8,60.6},{75,59.4},{75,59.8},{75.2,58.4},{75.2,61.8},{75.4,63},{75.6,59.4},{75.8,58.4},{75.8,63.6},{76.2,59.6},{76.4,57.4},{76.4,61.4},{76.4,61.8},{76.4,62.6},{76.6,59.4},{76.6,61.8},{76.6,62.6},{76.8,60.2},{76.8,61.2},{77,64.2},{77.6,60.8},{77.6,61.6},{77.8,63.2},{78.2,65.4}}},nil,85,nil,nil,16,nil,"",0},
[1533] = {'Tormented Spirit',12600,12600,10,10,4,{[85] = {{43,34.8},{43.4,31.2},{43.4,32.4},{43.4,32.6},{43.4,34.2},{43.8,31.4},{43.8,32},{44,32.6},{44,34.6},{44,36.2},{44.2,36.6},{44.4,28.6},{44.4,34.2},{44.6,29.6},{44.6,31.4},{44.6,31.6},{44.6,33.2},{44.8,34.4},{45,37.6},{45.2,36.6},{45.4,35.4},{45.4,36.4},{45.6,31.6},{45.6,33.8},{46,35.4},{46,36.6},{46,37.6},{46.2,29.4},{46.4,30},{46.4,30.8},{46.4,36.2},{46.6,30.4},{46.6,37},{46.8,35.4},{47,31.4},{47,32},{47,37.8},{47.4,32.8},{47.4,35.6},{47.6,31.4},{47.6,31.8},{47.6,32.6},{47.8,35.2},{47.8,36.6},{48,34.4},{48.2,35.8},{48.4,40.2},{48.6,31.8},{48.6,34.2},{48.6,34.8},{49,37},{49.6,39}}},nil,85,nil,nil,16,nil,"",0},
-- Quest 50176 Arathi Trophy: Rare NPCs in Arathi Highlands (zone 45)
[2598] = {'Darbel Montrose',12600,12600,29,30,4,{[45] = {{25.2,66.2},{25.8,59.2},{25.8,66.2},{26.4,62.4},{27,65.2},{27.2,66},{27.4,62.8},{27.4,63.8},{27.6,61},{27.6,63.6},{27.6,66.2},{27.8,60.2},{27.8,62.4},{28,62.8},{28.4,64.8},{28.6,61.8},{28.6,64},{28.6,64.8},{29.2,60.2},{29.4,60.8},{29.6,60.6},{29.8,60.2},{29.8,62.4},{29.8,62.8},{29.8,64}}},nil,45,nil,nil,16,nil,"",0},
[2600] = {'Singer',12600,12600,28,29,4,{[45] = {{30.2,26.2},{30.2,28.8},{31,27.8},{31.2,26.2},{31.2,26.6},{31.8,31.8},{32,28},{32.4,26.4},{32.4,26.6},{32.4,29.6},{32.4,30.8},{32.6,30.2},{32.6,31.2},{33.4,26.2},{33.4,27.4},{33.4,27.6},{33.4,29.4},{33.4,31.6},{33.6,27.4},{33.6,27.8},{33.6,30.2},{34.6,32},{34.8,31.4},{35,30},{35.4,35.2},{36.2,28.4}}},nil,45,nil,nil,16,nil,"",0},
[2601] = {'Foulbelly',12600,12600,28,29,4,{[45] = {{18,66.2},{18.8,66},{18.8,67.6},{19.4,64.4},{19.4,65.2},{19.8,65.2},{19.8,65.6},{20,64.4},{20,66.6},{20.2,67.6},{20.6,67.4},{21.4,66.2},{21.6,65.4},{21.6,66.8}}},nil,45,nil,nil,16,nil,"",0},
[2602] = {'Ruul Onestone',12600,12600,31,31,4,{[45] = {{17.4,68.4},{17.4,68.6},{18.2,68.4},{18.2,68.6}}},nil,45,nil,nil,16,nil,"",0},
[2603] = {'Kovork',12600,12600,31,31,4,{[45] = {{31.4,45.8},{31.6,45.8},{32.6,46}}},nil,45,nil,nil,16,nil,"",0},
[2604] = {'Molok the Crusher',12600,12600,31,31,4,{[45] = {{53.4,79.4},{53.4,79.8},{53.6,79.8},{53.8,79.4},{54,77.6},{54.4,77.4},{54.6,78.2},{54.6,79},{54.8,80.2}}},nil,45,nil,nil,16,nil,"",0},
[2605] = {'Zalas Witherbark',12600,12600,31,32,4,{[45] = {{66,82},{67.4,80.4},{67.4,81.2},{67.4,81.6},{67.6,80.2},{67.6,80.6},{68.2,82},{68.6,80.8},{69,82.6},{69.2,79.4},{69.2,79.6},{69.2,81.8},{69.6,79.6},{69.6,81.2},{69.6,82.2},{69.8,79}}},nil,45,nil,nil,16,nil,"",0},
[2606] = {'Nimar the Slayer',12600,12600,28,29,4,{[45] = {{60.2,71.8},{60.2,73.2},{60.4,73.8},{60.6,75.2},{61,73.6},{61.2,71.8},{61.2,72.6},{61.4,71.2},{61.6,74},{61.8,72.6},{62.4,71.4},{62.4,71.6},{62.6,67.6},{62.6,71.8},{63,68.6},{63,74},{63.2,66.2},{63.4,67.2},{63.6,67.4},{63.8,63.6},{63.8,64.8},{63.8,67.8},{63.8,69},{64.2,73},{64.2,74.4},{64.4,63.4},{64.4,66.2},{64.4,74.6},{64.6,66.2},{64.6,69},{64.6,74.6},{64.8,63},{65,73.4},{65,73.8},{65.2,61.2},{65.4,56.6},{65.6,57.6},{65.8,62.2},{65.8,74.8},{66,60.2},{66.2,64},{66.4,62.6},{66.4,64.8},{66.6,62.4},{66.6,62.6},{67,63.8},{67.2,61.2},{67.6,62.4},{68.4,59.8},{68.6,61.2},{69.4,54.6},{69.8,52.8},{70.2,64},{70.2,66.2},{71,59},{71.2,62.6},{71.2,63.6},{71.2,64.8},{71.2,66.6},{71.4,65.8},{71.8,63},{72,65.8},{72,66.6},{72.2,61.2},{72.4,64.2},{72.4,64.8},{72.6,65.8},{72.8,64.2},{72.8,65},{73.2,67},{73.6,63.8}}},nil,45,nil,nil,16,nil,"",0},
[2609] = {'Geomancer Flintdagger',12600,12600,28,29,4,{[45] = {{82.8,32.2},{82.8,32.6},{83.6,31.4},{83.6,34.6},{84.2,32.8},{84.4,28.4},{84.4,28.6},{84.4,32.2},{84.6,28.4},{84.6,28.6},{84.8,29.6},{85.2,31.4},{85.4,31.6},{85.6,31.4},{85.6,31.6}}},nil,45,nil,nil,16,nil,"",0},
[2779] = {'Prince Nazjak',12600,12600,32,32,4,{[45] = {{19.8,88.8},{20.2,82.4},{20.6,83.4},{20.8,84},{21.2,84.6},{21.2,89.2},{21.2,89.6},{21.6,82.8},{21.6,86},{21.6,89},{21.8,83.6},{21.8,84.8},{22.4,89.6},{22.8,84.4},{23,84.8},{23,86.2},{23,88},{23.2,82.2},{23.2,83.2},{23.4,89},{23.6,83.8},{23.6,89.4},{23.6,89.8},{24,88.4}}},nil,45,nil,nil,16,nil,"",0},
-- Quest 50195 Blade's Edge Trophy: Rare NPCs in Blade's Edge Mountains (zone 3522)
[18690] = {'Morcrush',12600,12600,69,69,4,{[3522] = {{59.2,23},{59.2,24.4},{59.4,20.2},{59.4,25.2},{59.6,20.4},{59.6,24.4},{59.6,25.4},{60,20.6},{60.2,23.2},{60.8,24.8},{61,20.8},{61,23},{61.2,23.8},{61.4,18.8},{61.4,21.8},{61.4,54.6},{61.8,21},{61.8,22.6},{61.8,54.4},{62,19.4},{62,19.6},{62.6,51},{62.6,52.4},{62.6,53.2},{63.8,51},{65,49.2},{65,53.4},{65.2,47.2},{65.2,50.4},{66.6,65},{66.8,48.4},{67,49},{67.2,68.2},{67.4,46.8},{67.4,66.2},{67.4,70.2},{67.6,47.2},{67.6,48.2},{67.6,65.6},{67.8,64.4},{67.8,65.4},{67.8,70.2},{67.8,73.4},{68,33.6},{68,67.4},{68,74.4},{68.2,67.6},{68.2,68.6},{68.2,75.6},{68.4,32.4},{68.4,33.2},{68.4,71.6},{68.6,64.4},{68.6,65.8},{68.6,68},{68.6,71.8},{68.6,74.8},{68.8,31.8},{68.8,64.6},{68.8,73},{69,29.8},{69.2,45},{69.4,33.8},{69.4,73.8},{69.6,32.8},{69.6,45},{70,28.6},{70,44.2},{70.2,34.2},{70.8,41.8},{71,41.4},{71.2,29.4},{71.6,30.2},{71.6,33.4},{73.2,29.8},{73.4,29.2},{73.6,24.6},{74,23.8},{74,29},{74.2,27.4},{74.4,23.4},{74.8,23.4},{76.8,23.8},{77.8,24.4},{77.8,28.8},{77.8,30},{78.4,26.8},{78.4,28}}},nil,3522,nil,nil,16,nil,"",0},
[18692] = {'Hemathion',12600,12600,68,69,4,{[3522] = {{27.4,54.4},{27.6,72},{27.8,67.6},{28,65.6},{28.2,65},{28.4,63.2},{28.4,67.2},{28.4,69.8},{28.6,64.4},{29,43.8},{29.2,44.6},{29.2,49.6},{29.2,50.8},{29.4,47.6},{29.4,49.4},{29.4,68},{29.4,68.6},{29.4,70.2},{29.4,70.8},{29.6,50.4},{29.6,63.6},{29.6,66.6},{29.6,68.2},{29.6,70.2},{29.6,71},{29.8,43.6},{29.8,51.2},{29.8,68.6},{30,43.2},{30,44.8},{30,48.6},{30,71.6},{30.2,45.8},{30.2,48.2},{30.2,53.6},{30.2,63.4},{30.2,64.8},{30.4,46.6},{30.4,51.6},{30.4,66.2},{30.6,44.6},{30.6,46.8},{30.6,51.4},{30.6,67},{30.6,68.8},{30.6,72.4},{30.6,72.6},{30.8,44},{30.8,68.2},{30.8,70.8},{31,45.6},{31.2,50.4},{31.2,52},{31.2,70},{31.4,52.6},{31.4,55.6},{31.6,55},{31.6,55.8},{32,53},{32.2,51.4},{32.2,52},{32.2,53.8},{32.6,52.6},{32.8,51.6},{32.8,54.6}}},nil,3522,nil,nil,16,nil,"",0},
[18693] = {'Speaker Mar\'grom',12600,12600,68,68,4,{[3522] = {{39.8,56},{40.2,56.6},{40.8,55.8},{41,49.2},{41,55},{41.2,49.6},{41.2,50.6},{41.4,48},{41.6,54},{41.8,51},{41.8,53.2},{42,55.6},{42.2,82},{42.4,50},{42.6,49.6},{42.8,49.2},{42.8,81.2},{43.4,80.4},{43.6,80.8},{43.8,79},{44.4,78},{44.6,75.4},{45,76.8},{45.8,76.8},{45.8,79.6},{46.2,78.8},{46.4,78.2},{46.6,78.2},{46.6,79.6},{46.8,76.2},{47,75.4},{47,76.8},{55.4,36.2},{55.8,25.4},{55.8,36},{56,26.4},{56.2,24.4},{56.2,26.8},{56.2,34.8},{56.6,27.4},{56.6,33.8},{57.2,28.2},{57.4,29.4},{57.4,33.4},{57.6,30},{57.6,30.6},{57.6,33.4},{57.8,32},{64.2,19.2},{64.4,19.6},{65,20.2},{65.2,21.2},{65.2,21.6},{65.6,22.4},{66,23.4},{66.2,23.6},{66.2,24.8},{66.2,26.2},{66.4,26.6},{67,26.8},{67.6,24.2}}},nil,3522,nil,nil,16,nil,"",0},
}
+58 -2
View File
@@ -782,6 +782,36 @@ EbonholdDB.questData = EbonholdDB.questData or {
[30] = 1, -- Kill count (only 1 rare needed)
},
-- Quest 50176: Arathi Trophy
-- Kill 1 rare in Arathi Highlands
[50176] = {
[1] = "Arathi Trophy", -- Quest name
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
[4] = 25, -- Quest level
[5] = 20, -- Min level
[17] = 45, -- Zone (Arathi Highlands)
[8] = {
"This is a custom objective. Upon completion, you will automatically receive the assigned reward. If you die, the quest will be removed from your quest log. This quest is automatically rewarded upon completion.",
"Kill 1 Rare in Arathi Highlands"
},
[10] = {
nil, -- [1] creatureObjective (not used)
nil, -- [2] objectObjective (not used)
nil, -- [3] itemObjective (not used)
nil, -- [4] reputationObjective (not used)
{ -- [5] killCreditObjective
{
-- 10 rare NPCs in Arathi Highlands
{ 2598, 2603, 2600, 2604, 2606, 2779, 2605, 2609, 2602, 2601 },
2606, -- RootId: Nimar the Slayer (representative rare)
"Rare slain"
}
}
},
[30] = 1, -- Kill count (only 1 rare needed)
},
[50150] = {
[1] = "Storm Peak Orders",
[2] = { nil, { 600600 } },
@@ -795,9 +825,35 @@ EbonholdDB.questData = EbonholdDB.questData or {
[9] = { "Complete 6 Quests", nil },
},
-- Quest 50195: Blade's Edge Trophy
-- Kill 1 rare in Blade's Edge Mountains
[50195] = {
[1] = "Blade's Edge Trophy", -- Quest name
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
[4] = 70, -- Quest level
[5] = 67, -- Min level
[17] = 3522, -- Zone (Blade's Edge Mountains)
[8] = {
"This is a custom objective. Upon completion, you will automatically receive the assigned reward. If you die, the quest will be removed from your quest log. This quest is automatically rewarded upon completion.",
"Kill 1 Rare in Blade's Edge Mountains"
},
[10] = {
nil, -- [1] creatureObjective (not used)
nil, -- [2] objectObjective (not used)
nil, -- [3] itemObjective (not used)
nil, -- [4] reputationObjective (not used)
{ -- [5] killCreditObjective
{
-- 3 rare NPCs in Blade's Edge Mountains
{ 18690, 18692, 18693 },
18692, -- RootId: Hemathion (representative rare)
"Rare slain"
}
}
},
[30] = 1, -- Kill count (only 1 rare needed)
},
}
+7 -3
View File
@@ -1275,7 +1275,8 @@ function QuestieDB.GetQuest(questId) -- /dump QuestieDB.GetQuest(867)
QO.ObjectiveData[#QO.ObjectiveData+1] = {
Type = "monster",
Id = creatureObjective[1],
Text = creatureObjective[2]
Text = creatureObjective[2],
HideCondition = creatureObjective[3],
}
end
end
@@ -1287,7 +1288,8 @@ function QuestieDB.GetQuest(questId) -- /dump QuestieDB.GetQuest(867)
QO.ObjectiveData[#QO.ObjectiveData+1] = {
Type = "object",
Id = objectObjective[1],
Text = objectObjective[2]
Text = objectObjective[2],
HideCondition = objectObjective[3],
}
end
end
@@ -1299,7 +1301,8 @@ function QuestieDB.GetQuest(questId) -- /dump QuestieDB.GetQuest(867)
QO.ObjectiveData[#QO.ObjectiveData+1] = {
Type = "item",
Id = itemObjective[1],
Text = itemObjective[2]
Text = itemObjective[2],
HideCondition = itemObjective[3],
}
end
end
@@ -1410,6 +1413,7 @@ function QuestieDB.GetQuest(questId) -- /dump QuestieDB.GetQuest(867)
Icon = o[2],
Description = o[3],
RealObjectiveIndex = o[4],
HideCondition = o[6],
}
if o[1] then -- custom spawn
specialObjective.spawnList = {{
+4
View File
@@ -553,6 +553,10 @@ function QuestieArrow:UpdateNearestTargets()
return
end
if QuestieQuest.ShouldHideObjective(objective) then
return
end
if objective.Completed == true or objective.Completed == 1 then
return
end
+37 -1
View File
@@ -482,6 +482,11 @@ function QuestieQuest:AcceptQuest(questId)
QuestieCombatQueue:Queue(function()
QuestieTracker:Update()
end)
end,
function()
if QuestieArrow and QuestieArrow.Refresh then
QuestieArrow:Refresh()
end
end
)
else
@@ -1213,6 +1218,30 @@ function QuestieQuest:AddFinisher(quest)
end
end
---@param objective any
function QuestieQuest.ShouldHideObjective(objective)
local hideCondition = objective.HideCondition
if not hideCondition then
return false
end
if hideCondition.hideIfQuestActive then
local questId = hideCondition.hideIfQuestActive
if QuestiePlayer.currentQuestlog[questId] or (Questie.db and Questie.db.char and Questie.db.char.complete and Questie.db.char.complete[questId]) then
return true
end
end
if hideCondition.hideIfQuestComplete then
local questId = hideCondition.hideIfQuestComplete
if Questie.db and Questie.db.char and Questie.db.char.complete and Questie.db.char.complete[questId] then
return true
end
end
return false
end
---@param quest Quest
---@param objectiveIndex ObjectiveIndex
---@param objective QuestObjective
@@ -1226,6 +1255,12 @@ function QuestieQuest:PopulateObjective(quest, objectiveIndex, objective, blockI
end
objective:Update()
if QuestieQuest.ShouldHideObjective(objective) then
_UnloadAlreadySpawnedIcons(objective)
return
end
local completed = objective.Completed
local objectiveData = quest.ObjectiveData[objective.Index] or
objective -- the reason for "or objective" is to handle "SpecialObjectives" aka non-listed objectives (demonic runestones for closing the portal)
@@ -1621,7 +1656,8 @@ function QuestieQuest:PopulateQuestLogInfo(quest)
AlreadySpawned = {},
Update = _QuestieQuest.ObjectiveUpdate,
Coordinates = quest.ObjectiveData[objectiveIndex].Coordinates, -- Only for type "event"
RequiredRepValue = quest.ObjectiveData[objectiveIndex].RequiredRepValue
RequiredRepValue = quest.ObjectiveData[objectiveIndex].RequiredRepValue,
HideCondition = quest.ObjectiveData[objectiveIndex].HideCondition
}
end
+1 -1
View File
@@ -6,7 +6,7 @@
## Notes-esES: Ayundante de misión
## Notes-ptBR: Ajudante de missão
## Notes-frFR: Assistant de quête
## Version: 9.8.4
## Version: 9.8.5
## RequiredDeps:
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
## SavedVariables: QuestieConfig