Update custom DB quests and bump version to 9.8.5
This commit is contained in:
@@ -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 Circle’s 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).
|
||||
@@ -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 Circle’s 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).
|
||||
@@ -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 Circle’s 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).
|
||||
@@ -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 Circle’s 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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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},
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = {{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user