v9.8.9: Badlands Trophy quest, 7:XT NPC data, fix AreaId CRITICAL spam
This commit is contained in:
+114
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
||||
"Lua.runtime.version": "Lua 5.1",
|
||||
"Lua.diagnostics.globals": [
|
||||
"QuestieLoader",
|
||||
"QuestieCompat",
|
||||
"Questie",
|
||||
"MAX_QUEST_LOG_INDEX",
|
||||
"GetNumQuestLogEntries",
|
||||
"GetQuestLogTitle",
|
||||
"GetQuestLogQuestText",
|
||||
"GetQuestObjectives",
|
||||
"GetNumQuestLeaderBoards",
|
||||
"GetQuestIndexForWatch",
|
||||
"IsQuestWatched",
|
||||
"QuestWatch_Update",
|
||||
"WatchFrame_Update",
|
||||
"HaveQuestData",
|
||||
"GetTitleText",
|
||||
"GetObjectiveText",
|
||||
"GetQuestID",
|
||||
"GetItemInfoFromHyperlink",
|
||||
"GetQuestLink",
|
||||
"GetQuestIndexByID",
|
||||
"ChatEdit_GetActiveWindow",
|
||||
"ChatEdit_InsertLink",
|
||||
"QuestLog_SetSelection",
|
||||
"QuestLog_Update",
|
||||
"QuestLogTitleButton_OnClick",
|
||||
"QuestLogListScrollFrame",
|
||||
"FauxScrollFrame_GetOffset",
|
||||
"QuestLogExFrame",
|
||||
"ClassicQuestLog",
|
||||
"QuestLogEx",
|
||||
"StaticPopupDialogs",
|
||||
"StaticPopup_Show",
|
||||
"STATICPOPUP_NUMDIALOGS",
|
||||
"QUEST_WATCH_NO_EXPIRE",
|
||||
"RemoveQuestWatch",
|
||||
"AddQuestWatch",
|
||||
"GetNumLootItems",
|
||||
"GetLootSlotInfo",
|
||||
"GetLootSlotLink",
|
||||
"GetBestMapForUnit",
|
||||
"GetPlayerMapPosition",
|
||||
"GetRealZoneText",
|
||||
"GetInstanceInfo",
|
||||
"GetUnitName",
|
||||
"UnitGUID",
|
||||
"UnitName",
|
||||
"UnitLevel",
|
||||
"UnitExists",
|
||||
"UnitIsPlayer",
|
||||
"UnitIsVisible",
|
||||
"UnitClass",
|
||||
"UnitReaction",
|
||||
"UnitFactionGroup",
|
||||
"GetFactionInfoByID",
|
||||
"GetQuestLogRewardMoney",
|
||||
"GetCoinTextureString",
|
||||
"GetClassColor",
|
||||
"IsModifiedClick",
|
||||
"GetTime",
|
||||
"IsShiftKeyDown",
|
||||
"Minimap",
|
||||
"GetCVar",
|
||||
"GameTooltip",
|
||||
"LibStub",
|
||||
"Questie_BaseFrame",
|
||||
"VoiceOver",
|
||||
"format",
|
||||
"strsplit",
|
||||
"tinsert",
|
||||
"tremove",
|
||||
"wipe",
|
||||
"hooksecurefunc",
|
||||
"WorldMapFrame",
|
||||
"C_Map",
|
||||
"CreateFrame",
|
||||
"InterfaceOptionsFrame",
|
||||
"GetAddOnMetadata",
|
||||
"GetBuildInfo",
|
||||
"IsInInstance",
|
||||
"UnitIsPVP",
|
||||
"GetNumPartyMembers",
|
||||
"GetNumRaidMembers",
|
||||
"GetPartyMember",
|
||||
"GetRaidRosterInfo",
|
||||
"GetSpellInfo",
|
||||
"GetSpellLink",
|
||||
"GetContainerNumSlots",
|
||||
"GetContainerItemInfo",
|
||||
"GetContainerItemLink",
|
||||
"PickupContainerItem",
|
||||
"DeleteCursorItem",
|
||||
"GetItemInfo",
|
||||
"GetItemCount",
|
||||
"IsEquippedItem",
|
||||
"GetInventoryItemID",
|
||||
"GetItemQualityColor",
|
||||
"geterrorhandler",
|
||||
"seterrorhandler",
|
||||
"GetFramerate",
|
||||
"GetLatency"
|
||||
],
|
||||
"Lua.diagnostics.disable": [
|
||||
"duplicate-set-field",
|
||||
"undefined-field"
|
||||
],
|
||||
"Lua.workspace.ignoreDir": [
|
||||
"docs",
|
||||
"workflow"
|
||||
]
|
||||
}
|
||||
+78
-26
@@ -1,8 +1,40 @@
|
||||
# Changelog
|
||||
|
||||
## v9.8.9
|
||||
|
||||
### New Ebonhold Quests
|
||||
|
||||
- **Azeroth**: Badlands Trophy (50178) — Kill 1 Rare in Badlands. Includes tracking data for 10 Badlands rares: Broken Tooth, Zaricotl, 7:XT, Anathemus, Barnabus, Rumbler, Siege Golem, Digmaster Shovelphlange, Shadowforge Commander, War Golem.
|
||||
|
||||
### NPC Data
|
||||
|
||||
- **classicNPCFixes.lua**: Injected spawn coordinates for NPC 14224 (7:XT \<Long Distance Recovery Unit\>, Badlands). The native `wotlkNpcDB` entry for ID 14224 is a different NPC (Gnomeregan's Instance Recovery Unit) and `classicNpcDB` had no entry — all 74 Wowhead patrol coordinates for zone 3 (Badlands) were injected.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **[UI]** Fixed spammy `[CRITICAL] No AreaId found for UiMapId` errors appearing in chat when entering Ascension hub cities (Stormwind, Darnassus, Shattrath, etc.). On Ascension, `C_Map.GetBestMapForUnit("player")` returns a continent-level UiMapId for certain cities (e.g. `1415` = Eastern Kingdoms, `1414` = Kalimdor, `1945` = Outland) — Questie logged a CRITICAL error since these have no AreaId mapping, even though the `nil` return was already handled gracefully by callers. Downgraded from `DEBUG_CRITICAL` to `DEBUG_DEVELOP` in `zoneDB.lua`.
|
||||
|
||||
## v9.8.8
|
||||
|
||||
### New Ebonhold Quests
|
||||
|
||||
- **Azeroth**: Alterac Trophy (includes missing Alterac Mountains spawn tracking data for Narillasanz, Cranky Benj, Gravis Slipknot, Araga, Lo'Grosh, Stone Fury, Jimmy the Bleeder, Skhowl). Northern Jungle Trophy (verified Stranglethorn Vale spawn tracking data). Southern Jungle Trophy (verified Stranglethorn Vale spawn tracking data for 4 rares).
|
||||
- **Kalimdor**: Ashen Corruption (includes missing Ashenvale spawn tracking data for Demon NPCs), Spires of Chaos (includes missing Thousand Needles spawn tracking data for Elemental NPCs).
|
||||
- **Outland**: Shadowmoon Trophy (verified Shadowmoon Valley spawn tracking data for Collidus the Warp-Watcher, Ambassador Jerrikar, Kraator). Demon's at the Edge (verified Blade's Edge Mountains spawn tracking data for 37 demons).
|
||||
- **Northrend**: Fjord Trophy (includes missing Howling Fjord spawn tracking data for King Ping, Perobas the Bloodthirster, Vigdis the War Maiden). Frostbound Brood (verified Borean Tundra spawn tracking data for 16 dragonkin).
|
||||
|
||||
## v9.8.7
|
||||
|
||||
### Fixes
|
||||
|
||||
- **[Quest]** Corrected `GetQuestLogTitle` return value indices across multiple modules to match the WoW 3.3.5 client API. The 3.3.5 client returns `suggestedGroup` at index 4, shifting `isHeader` to index 5 and `questId` to index 9. Affected modules previously used indices 4 and 8 (or `select(8, ...)`) and would misidentify quest headers as regular quests and incorrectly assign `isDaily` as `questId`.
|
||||
- **[Quest]** Removed premature `break` on nil `title` in quest log iteration loops. On this server, quest log slots can be non-contiguous, causing early loop termination to silently skip valid quests. Loops now use a `if title and (not isHeader) then` guard to safely skip empty slots without aborting iteration.
|
||||
- **Affected modules:** `QuestieValidateGameCache`, `QuestEventHandler`, `QuestLogCache`, `TooltipHandler`, `TrackerUtils`, `QuestieTracker`, `QuestieLearner`.
|
||||
|
||||
## v9.8.6
|
||||
|
||||
### New Ebonhold Quests
|
||||
|
||||
- **Outland**: Blade's Edge Trophy (includes missing Blade's Edge Mountains spawn tracking data for Morcrush, Hemathion, Speaker Mar'grom). Fel Scars of Nagrand (includes missing Nagrand spawn tracking data for Voidwalker Minions, etc). Netherstorm Trophy (includes missing Netherstorm spawn tracking data for Nuramoc, Ever-Core the Punisher, Chief Engineer Lorthander).
|
||||
- **Northrend**: Borean Trophy (includes missing Borean Tundra spawn tracking data for Fumblub Gearwind, Icehorn, Old Crystalbark).
|
||||
- **Kalimdor**: Teldrassil Trophy (includes missing Teldrassil spawn tracking data for Threggil, Blackmoss the Fetid, Duskstalker, Uruson, Fury Shelda, Grimmaw). Darkshore Defense (complete 6 quests in Darkshore). Bloodmyst Recovery (complete 6 quests in Bloodmyst Isle).
|
||||
@@ -11,11 +43,13 @@
|
||||
## 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.
|
||||
@@ -24,32 +58,36 @@
|
||||
## 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:`).
|
||||
@@ -58,6 +96,7 @@
|
||||
## 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.
|
||||
@@ -68,89 +107,100 @@
|
||||
## 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.
|
||||
- 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
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
@@ -159,17 +209,19 @@
|
||||
- **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.
|
||||
- **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.
|
||||
|
||||
+418
-393
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+1821
-1360
File diff suppressed because one or more lines are too long
@@ -1,206 +1,9 @@
|
||||
---@type table
|
||||
local EbonholdDB = QuestieLoader:CreateModule("EbonholdDB")
|
||||
|
||||
-- Generated by Ebonhold
|
||||
EbonholdDB = EbonholdDB or {}
|
||||
EbonholdDB.npcData = EbonholdDB.npcData or {
|
||||
-- Quest 11420/11426/11427/11436: The Path to Payback - Update Guard Captain Zorek coordinates
|
||||
[23728] = {'Guard Captain Zorek',29820,29820,73,73,1,{[495]={{60.1,62.4}}},nil,495,nil,nil,1892,"A","",3},
|
||||
-- Quest 50030 Corrections: Full Spawn Data for Borean Tundra Elementals
|
||||
-- Overrides existing sparse data in WotLK DB
|
||||
[24601] = {'Steam Rager',9291,9291,70,71,0,{[3537] = {{67,25.4},{67.4,22},{67.4,26.4},{67.4,26.8},{68,26},{68,27},{68.2,23},{68.2,23.6},{68.4,22.4},{68.4,25},{68.4,28.2},{68.8,24.8},{68.8,31.2},{69.2,23.8},{69.2,26.8},{69.2,27.8},{69.4,22.2},{69.4,22.8},{69.4,26.4},{69.4,29},{69.4,30},{69.6,22.4},{69.6,24.4},{69.6,28.2},{69.8,22.8},{69.8,32},{70,29.4},{70.2,36.6},{70.4,25.4},{70.4,25.6},{70.4,26.6},{70.4,29.8},{70.4,30.8},{70.4,36},{70.6,29.4},{70.8,36.4},{71,22.2},{71,22.6},{71,24.4},{71,25.8},{71,28.2},{71,36.6},{71.2,38.4},{71.4,25.4},{71.4,27.2},{71.4,30.4},{71.4,31.2},{71.4,32.4},{71.4,33.2},{71.4,34},{71.4,35},{71.4,39.4},{71.4,39.6},{71.6,22},{71.6,29.6},{71.6,31},{71.6,39.4},{71.8,25.8},{71.8,27.2},{71.8,33.6},{71.8,42.2},{72,24.6},{72,28.6},{72,32.6},{72,37.6},{72.2,24.2},{72.2,28.4},{72.2,32.4},{72.2,35.2},{72.2,35.8},{72.2,36.6},{72.4,21},{72.4,23.4},{72.4,40.4},{72.4,41.2},{72.6,24.4},{72.6,27.2},{72.6,30.2},{72.6,31.4},{72.6,32.4},{72.6,33.4},{72.6,33.6},{72.6,35.4},{72.6,36.4},{72.6,36.6},{72.8,25.4},{72.8,41.6},{73,23.4},{73,26.2},{73,28.2},{73.2,38.2},{73.2,39.4},{73.2,40.2},{73.2,40.6},{73.4,28.6},{73.6,24.4},{73.6,26},{73.6,27.2},{73.6,40.4},{73.6,40.6},{73.8,25.2},{73.8,28},{73.8,29.2},{73.8,38.6},{74.2,30.2},{74.2,30.6},{74.2,37.4},{74.2,37.8},{74.4,31.6},{74.4,33.4},{74.4,34.2},{74.4,35},{74.4,35.8},{74.6,29.4},{74.6,30},{74.6,31.8},{74.6,36.8},{74.6,38.4},{74.6,39.4},{74.6,39.8},{74.8,30.8},{74.8,33.6},{74.8,34.6},{74.8,35.6},{75.4,33.4},{75.6,29},{75.6,33.4},{75.6,33.8},{75.6,34.6},{75.6,35.8},{75.8,38.2},{76.4,32.4},{76.4,37.4},{76.6,32},{76.8,36},{77,37.8},{77.4,37},{77.6,37}}},nil,3537,nil,nil,91,nil,"",0},
|
||||
[25226] = {'Scalder',9291,9291,71,71,0,{[3537] = {{42.4,15.4},{42.4,15.6},{42.6,15.4},{42.6,16.4},{42.6,16.6},{42.8,17.6}}},nil,3537,nil,nil,14,nil,"",0},
|
||||
[25376] = {'Imperean',9291,9291,72,72,0,{[3537] = {{46.4,9.4},{46.6,9.4}}},nil,3537,nil,nil,190,nil,"",0},
|
||||
[25415] = {'Enraged Tempest',9291,9291,70,71,0,{[3537] = {{42,8},{42.2,9.4},{42.2,13.4},{42.4,10.2},{42.4,10.6},{42.6,10.4},{42.8,9},{42.8,10.6},{43,7.4},{43.2,8},{43.4,13.8},{43.6,7.8},{43.6,9},{43.6,13.4},{43.8,7.4},{43.8,10.6},{44,13.6},{44.2,11.6},{44.4,10},{44.6,7.4},{44.6,7.6},{44.6,11.6},{44.8,10.8},{45,9.2},{45.4,6.4},{45.4,9.8},{45.6,6.4},{45.6,9.8},{45.8,9.4},{45.8,12.4},{46,7.4},{46,7.6},{46,10.6},{46,13.2},{46.6,7.8},{46.6,9.2},{46.6,10.4},{46.6,11.2},{47.2,11.6},{48.2,7.4}}},nil,3537,nil,nil,834,nil,"",0},
|
||||
[25416] = {'Simmer',9291,9291,72,72,0,{[3537] = {{50.4,15.2},{50.8,15.2}}},nil,3537,nil,nil,1983,nil,"",0},
|
||||
[25417] = {'Raging Boiler',9291,9291,69,70,0,{[3537] = {{46,14.6},{46.2,13.2},{46.2,13.8},{46.8,14.4},{47,9.8},{47,12.4},{47,12.8},{47.2,14.6},{47.2,16.8},{47.4,11.2},{47.4,15.6},{47.8,12.4},{47.8,15.4},{48,11.4},{48,15.8},{48,21.2},{48.2,12.8},{48.2,16.6},{48.2,19.8},{48.4,14.2},{48.4,18.2},{48.4,19.4},{48.6,12.4},{48.6,16.2},{48.6,19.4},{48.8,13.4},{48.8,13.6},{49,16.8},{49.2,17.6},{49.4,10.2},{49.4,10.6},{49.4,15},{49.6,10.8},{49.6,13.4},{49.6,14.4},{49.6,17},{50.2,15},{50.4,15.6},{50.4,17.8},{50.6,15.6},{50.8,15.2}}},nil,3537,nil,nil,1983,nil,"",0},
|
||||
[25418] = {'Churn',9291,9291,71,71,0,{[3537] = {{45.4,12.4},{45.8,12.2},{45.8,12.8},{45.8,13.6}}},nil,3537,nil,nil,1984,nil,"",0},
|
||||
[25419] = {'Boiling Spirit',9291,9291,69,70,0,{[3537] = {{43.4,13.8},{44.4,9},{44.6,9.8},{44.6,15.6},{45.2,12.4},{45.2,12.6},{45.2,16.8},{45.4,11.4},{45.4,15.4},{45.8,9.8},{45.8,12.2},{45.8,13},{45.8,13.6},{46,14.8},{46,16.8},{46,19},{46.2,11.4},{46.2,15.6},{46.4,9.4},{46.6,9.6},{46.8,9.2},{46.8,15},{46.8,16.8},{47,11.2},{47,12.6},{47.2,12.4},{47.2,16},{47.2,18.4},{47.4,14.2},{47.6,11.4},{47.6,12.4},{47.6,15.4},{47.8,16.8},{47.8,17.8},{48,15.8},{48.2,13.4},{48.2,14},{48.6,16},{48.8,12.2},{48.8,13.4},{49,16.8},{49.2,14.8},{49.4,10.6},{49.4,13.8},{50,10.8},{50.2,15.2},{51,15.2}}},nil,3537,nil,nil,1984,nil,"",0},
|
||||
[25514] = {'Rocknar',9291,9291,71,71,0,{[3537] = {{81.4,42.4},{81.4,42.6},{81.6,42.6}}},nil,3537,nil,nil,14,nil,"",0},
|
||||
[25707] = {'Magic-bound Ancient',9291,9291,71,72,0,{[3537] = {{22.4,23.4},{22.4,24},{22.8,24},{23,25.4},{23.4,30.2},{23.4,33.6},{23.6,27.8},{23.8,25.8},{23.8,34.2},{24,29.4},{24,29.8},{24.2,21.4},{24.4,22.4},{24.4,22.6},{24.4,23.6},{24.4,30.8},{24.4,31.6},{24.4,35},{24.6,22.4},{24.6,23},{24.6,23.6},{24.6,28.8},{24.6,30.4},{25,31.4},{25.2,20.4},{25.2,25},{25.2,31.6},{25.4,28.4},{25.4,34.4},{25.4,34.8},{25.4,35.6},{25.4,36.6},{25.6,34.6},{25.6,37},{25.8,21.4},{25.8,34.2},{25.8,35.6},{26,21.8},{26,23.4},{26,29.4},{26,31.4},{26,31.8},{26.4,32.6},{26.6,35},{27,20.4},{27,32.6},{27,33.8},{27.2,31},{27.4,20.6},{27.4,21.8},{27.4,30.4},{27.4,32},{27.6,33.6},{27.8,32.2},{27.8,32.6},{28.2,28.8},{28.2,29.8},{28.2,31.4},{28.2,35.8},{28.4,20.4},{28.4,21.4},{28.4,21.8},{28.4,28},{28.6,32.6},{28.6,34.2},{28.8,21.4},{28.8,21.6},{28.8,28.4},{28.8,32.4},{29,20.4},{29.2,27.4},{29.4,29},{29.4,30},{29.4,30.6},{29.6,20.2},{29.6,20.6},{29.6,22.8},{29.6,30.4},{29.8,22},{29.8,24.4},{29.8,25.8},{29.8,30.8},{29.8,31.8},{30,29.4},{30,33.2},{30.4,24.6},{30.6,29.2},{30.6,29.8},{30.8,31.2},{31,22.4},{31,26.6},{31.2,23.4},{31.2,25.6},{31.4,20.2},{31.4,21.2},{31.4,24.4},{31.4,24.8},{31.4,27.8},{31.6,20.4},{31.6,22.4},{31.6,24.2},{31.6,24.8},{31.6,25.6},{31.6,26.6},{31.6,30.8},{31.8,20.6},{31.8,23.4},{32,30},{32.4,27.6},{32.4,28.6},{32.4,33.8},{32.6,27.8},{32.6,30.6},{32.8,23.4},{33.2,24.6},{33.2,34.4},{33.4,24.2},{33.4,25.6},{33.4,29.4},{33.6,23.4},{33.6,24.4},{33.6,24.6},{33.8,25.6},{33.8,26.8},{34.4,28.4},{34.4,29.2},{34.4,29.8},{34.6,25.6},{34.8,29},{35,27},{35,29.6},{35.2,28.4},{35.4,30.6},{35.6,28},{35.6,29},{35.6,29.6},{35.6,30.6}}},nil,3537,nil,nil,16,nil,"",0},
|
||||
[25709] = {'Glacial Ancient',9291,9291,71,72,0,{[3537] = {{20.4,27},{20.4,28.2},{20.8,28.2},{21,25.8},{21,29.2},{21.2,29.6},{21.4,27},{21.4,31.4},{21.4,31.6},{21.4,32.6},{21.6,29.2},{21.6,30.4},{21.6,31},{21.6,32},{21.8,27.6},{22.2,33.2},{22.4,26.4},{22.4,27.2},{22.4,33.6},{22.4,34.6},{22.6,33.4},{22.8,27.2},{22.8,28.8},{23,32.4},{23,33.6},{23.2,27.8},{23.2,34.6},{23.4,25.2},{23.4,26},{23.4,35.6},{23.4,36.6},{23.6,25},{23.6,28.6},{23.6,33.4},{23.6,34.8},{23.6,35.8},{23.8,26.4},{23.8,27.8},{23.8,32.4},{23.8,36.6},{24,26.6},{24.2,34.2},{24.6,26},{24.6,27.8},{24.6,36.8},{24.8,27.2},{25,34.2},{25.2,19.4},{25.4,33.4},{25.4,34.6},{25.4,35.6},{25.6,33.4},{25.6,35},{25.6,35.6},{25.6,36.6},{25.8,34.2},{26.4,17.4},{26.4,18.2},{26.4,19.2},{26.4,20},{26.4,20.6},{26.6,18.4},{26.6,18.6},{26.6,19.6},{26.6,20.6},{27.2,33.8},{27.8,18},{29.4,30.2},{29.4,32.2},{29.4,32.8},{30.4,23.4},{30.4,23.8},{30.4,24.8},{30.4,29},{30.4,30.4},{30.4,31.4},{30.4,32.4},{30.4,32.6},{30.6,29.2},{30.6,30.4},{30.6,30.6},{30.6,32.2},{30.6,32.6},{31,28.4},{31.2,25.6},{31.4,22},{31.4,22.8},{31.4,23.6},{31.4,24.8},{31.6,22.4},{31.6,23.6},{31.6,24.6},{31.6,25.8},{31.6,31},{31.8,23.2},{32.6,23},{32.6,23.8},{32.6,26.4},{34.4,25.4},{34.4,26.4},{34.4,26.8},{34.4,28.2},{34.4,28.6},{34.8,26.4},{34.8,26.6},{35,28.6},{35.2,27.8},{35.4,25.4},{35.6,26.4},{35.6,27.2},{35.6,27.6},{35.6,28.6}}},nil,3537,nil,nil,7,nil,"",0},
|
||||
[25715] = {'Frozen Elemental',9291,9291,70,71,0,{[65]={{11.28,62.69},{11.05,61.25},{9.43,61.9},{10.2,60.22},{10.21,62.04},{9.29,60.28},{8.68,62.04},{9.07,59.02},{7.78,62.99},{8.79,54.22},{9.63,56.48},{11.56,54.92},{11.53,57.32},{11.05,56.14},{8.94,55.86},{10.33,55.94},{10.23,57.3},{7.8,61.25},{13.09,60.42},{8.24,60.06},{12.21,58.61},{11.52,59.08},{11.71,53.34},{7.88,58.82},{8.55,58.35},{6.81,62.17},{11.85,60.86}},[3537] = {{82.8,48.8},{83.2,45.6},{83.4,44.4},{83.4,45},{83.4,47.2},{83.4,47.6},{83.6,44.4},{83.6,47.2},{83.8,44.8},{84.2,46.4},{84.2,47.6},{84.6,47.2},{85,46.4},{85,48.8},{85.2,48},{85.4,43.8},{85.4,44.8},{85.6,43.4},{85.8,44.2},{85.8,47.4},{85.8,47.6},{86,45.8},{86.2,45.4},{86.8,47.6},{87.2,43.4},{87.2,43.6},{87.2,45},{87.4,42.4},{87.4,46.4},{87.4,46.6},{87.6,45.4},{87.6,45.8},{87.8,42.8},{88.4,42.4},{88.4,44.2},{88.4,46.8},{88.6,44.2},{88.6,45.8},{88.6,46.8},{88.8,41.4},{88.8,42.2},{88.8,45.4},{89,42.6},{89.8,42.6},{90.2,40.8},{90.2,41.8},{91,43},{91.2,40.4},{91.2,41.6},{91.4,41.4},{91.6,41.2},{91.6,41.6},{92,42.6},{92.4,37.8},{92.4,39.4},{92.4,39.6},{92.6,39.2},{92.6,39.6},{92.8,43.6},{93,36.4},{93,37.4},{93,38},{93.4,35.4}}},nil,3537,nil,nil,14,nil,"",0},
|
||||
[26045] = {'Storm Tempest',9291,9291,71,71,0,{[3537] = {{77,38.6}}},nil,3537,nil,nil,834,nil,"",0},
|
||||
-- Quest 50162 Wetlands Trophy: Rare NPCs in Wetlands (zone 11)
|
||||
[1037] = {'Dragonmaw Battlemaster',684,734,24,25,4,{[11] = {{42.2,40.8},{42.2,44.6},{42.4,42.8},{42.4,44.4},{42.8,42.6},{42.8,43.8},{43,40.6},{43,42.4},{44.2,43.2},{44.2,44},{44.4,44.8},{44.6,42.8},{44.6,43.8},{45.4,44.6},{45.8,43.8},{46.4,45},{47,43},{47,44.2},{47,46},{47.4,45.4},{47.4,46.6},{47.6,46},{48,44.2},{48.2,45.2},{48.4,46.6},{48.4,47.6},{48.4,48.8},{48.6,47.4},{48.8,45.8},{48.8,48.4},{49,45.2},{49,49.4},{49.2,42},{49.2,49.6},{50,48.2},{50,49.4},{50.2,52.2},{50.4,50},{50.4,51.2},{50.8,49.4},{51,51},{51.2,51.8},{51.4,50},{51.4,52.6},{51.6,48.8},{51.6,52.4},{51.6,52.6},{52.4,53.6},{52.6,49.4},{52.8,53.2},{53,53.6}}},nil,11,nil,nil,62,nil,"",0},
|
||||
[1140] = {'Razormaw Matriarch',1106,1106,31,31,4,{[11] = {{67.2,29.2},{67.4,28.4},{67.4,30.2},{67.4,30.8},{67.4,31.6},{67.6,30.6},{67.6,32},{67.8,27.8},{69,28.4},{69.2,28.8},{69.6,29.8},{69.8,29},{70,31.8},{70.2,31.4},{70.6,30.8},{70.8,30.4}}},nil,11,nil,nil,48,nil,"",0},
|
||||
[2108] = {'Garneg Charskull',812,812,29,29,4,{[11] = {{30.6,39.4},{31.4,41.2},{37,44},{37,46.4},{37,47},{37,47.8},{38.2,45.4},{38.4,46},{38.6,46.2},{39.2,46.6},{39.2,47.6},{39.2,49},{39.4,37.2},{39.8,46.6},{40,46.4},{40.6,37.4},{40.8,46.8},{41.2,46},{41.4,45.4},{41.6,45.4},{41.6,45.6},{41.8,42.6},{42.4,44.2},{42.6,40.2},{43.2,43},{43.2,44.2},{44,42.6},{44.4,44.2},{44.8,45.4},{45.4,44.4},{46,43.8},{46.2,44.8},{46.8,43.4},{46.8,44.2},{47,48.6},{47.2,46.2},{47.6,49},{48,45.2},{48,46.4},{48,47.6}}},nil,11,nil,nil,62,nil,"",0},
|
||||
[14425] = {'Gnawbone',664,664,24,24,4,{[11] = {{30,30.6},{30.2,29},{30.2,30},{30.4,33},{30.6,30},{30.6,31.2},{32,34.2},{32.2,31.4},{32.4,32.8},{32.8,29},{32.8,29.8},{33,32.6},{33.4,31.2},{33.4,34},{33.6,29.8},{33.8,31.4},{34.2,34.2},{34.4,36},{34.8,30.2},{35,35},{35.2,34.4},{35.4,31.6},{35.4,37.2},{35.6,35},{35.8,29.6},{36,37.4},{36.8,29.4},{36.8,34.4},{37,35.2},{37.6,29.2},{37.8,34.6},{38,33.4},{38.4,29.8},{38.4,36.4},{38.8,29.6},{39,29},{39,30.6}}},nil,11,nil,nil,61,nil,"",0},
|
||||
[14433] = {'Sludginn',974,974,30,30,4,{[11] = {{10.8,69.4},{11.2,71.4},{11.4,69.6},{11.8,69.4},{11.8,69.6},{12,70.6},{13.2,68},{13.6,68.4},{13.8,68.6},{14.2,66.4},{14.2,66.6},{14.6,67.2}}},nil,11,nil,nil,14,nil,"",0},
|
||||
[2090] = {'Ma\'ruk Wyrmscale',617,617,23,23,4,{[11] = {{47.2,74},{47.4,74.6},{47.4,75.8},{47.8,74.6},{47.8,75.6},{47.8,77},{48,74.2},{48.2,73.4},{48.4,78.6},{48.6,75},{48.8,78.8},{49.4,74.2},{49.4,76},{49.8,73.6},{50,72.4}}},nil,11,nil,nil,62,nil,"Dragonmaw Warlord",0},
|
||||
[1112] = {'Leech Widow',664,664,24,24,4,{[11] = {{45.6,63.4},{45.6,63.8},{46,62.2},{46.2,64.8},{46.6,64},{46.6,65.4},{46.6,65.6},{46.8,61.4},{46.8,62.8},{47,61.6}}},nil,11,nil,nil,22,nil,"",0},
|
||||
[14424] = {'Mirelow',734,734,25,25,4,{[11] = {{17.2,28.6},{17.4,26.8},{17.4,28},{18,26.2},{18,26.8},{18.2,27.6},{18.4,29.2},{18.4,30.6},{18.6,27.4},{18.6,29.4},{18.8,31},{19,27.6},{19,30.4},{19.6,31.6},{19.6,32.8},{20,30.6},{20.2,27.8},{20.2,28.8},{20.4,27.4},{20.4,30},{20.6,30.6},{20.8,28.4},{20.8,32},{20.8,32.8},{21,29.2},{21,33.6},{21.2,29.8},{21.2,35.6},{21.4,35.2},{21.6,30.8},{21.8,29.2},{22,35.4},{22.2,21.4},{22.4,21.6},{22.4,22.6},{22.4,23.8},{22.4,29.6},{22.4,35.8},{22.4,36.8},{22.6,28.2},{22.8,22.4},{22.8,22.6},{22.8,24.2},{22.8,24.6},{22.8,31.4},{23,21.4},{23.2,34.4},{23.4,29},{23.4,30.2},{23.4,35.8},{23.4,37},{23.6,25.2},{23.6,34.8},{23.8,30.8},{23.8,36.2},{24,24.4},{24,29.6},{24.2,26.2},{24.2,27.6},{24.2,36.6},{24.4,26.6},{24.6,25.2},{24.6,25.6},{24.6,37},{24.8,35.6},{25,38},{25.2,27.2},{25.2,30.4},{25.2,30.6},{25.2,32.2},{25.4,28},{25.4,38.6},{25.6,27.8},{25.8,32},{26,29.2},{26,33.8},{26.4,31.2},{26.4,33.4},{26.6,29.4},{26.6,30},{26.6,33.6},{27,30.8},{27,33.2},{27.4,31.8},{27.6,32},{27.6,32.8},{28.2,31.4}}},nil,11,nil,nil,14,nil,"",0},
|
||||
-- Quest 50199 Borean Trophy: Rare NPCs in Borean Tundra (zone 3537)
|
||||
[32358] = {'Fumblub Gearwind',13936,13936,71,71,2,{[3537] = {{59.2,21.8},{59.6,19.4},{59.8,26.2},{60,17},{60.4,23.6},{60.4,28.4},{60.6,25},{60.8,15.2},{61,21.6},{61.2,22.8},{61.2,24.2},{61.4,30},{61.6,22.6},{61.8,20},{61.8,21.4},{62.4,19.2},{62.8,29},{62.8,34.6},{63,19.4},{63,32.4},{63.2,25.4},{63.2,25.6},{63.4,16.4},{63.4,17},{63.8,17.6},{64.2,16.8},{64.4,16},{64.4,32.4},{64.4,33},{64.6,35},{65,17.2},{65.2,17.8},{65.4,19.2},{65.4,33.6},{65.8,20},{66,17},{66,36.4},{66.2,18},{66.2,18.6},{66.4,20.6},{66.6,36.8},{67,20.8},{67.2,19.8},{67.2,35},{67.8,23.4},{67.8,26.4},{67.8,36.8},{68,25.4},{68.2,28.6},{68.4,19.2},{68.4,27},{69,29.4},{69.2,38},{69.4,37},{69.6,32},{69.6,37.2},{70.2,38},{70.4,34.6},{71,34},{71,36.2},{71.6,28.4},{71.8,34.4},{71.8,36.4},{73,34.2},{73.2,35.2},{74,30.2}}},nil,3537,nil,nil,16,nil,"",0},
|
||||
[32361] = {'Icehorn',13936,13936,71,71,2,{[3537] = {{80.2,45.8},{80.6,31.8},{80.6,45.8},{81.4,31.4},{81.6,30.8},{84.4,46.8},{84.6,45.8},{84.6,46.6},{85.2,34.2},{85.6,34.4},{85.6,35},{88.2,39.2},{88.2,39.6},{88.6,40.2},{88.6,40.6},{89.8,43.4},{91.2,32.2},{91.2,33.8},{91.4,32.6},{91.6,32.4},{91.8,32.6},{92,31.4}}},nil,3537,nil,nil,14,nil,"",0},
|
||||
[32357] = {'Old Crystalbark',9291,9291,71,72,0,{[3537] = {{20.6,27.8},{20.8,27},{21.2,28.6},{21.2,29.8},{21.6,30.8},{21.8,27},{21.8,34.6},{22,33.8},{22.2,35.8},{22.4,33.4},{22.6,33},{23,33.8},{23.6,35.8},{24.4,34.4},{24.4,34.6},{25,34.2},{25,34.8},{25.6,34.6},{27,35.6},{29.6,33.2},{30,32},{30.8,30.6},{31.2,30.2},{31.6,30.2},{32,31.4},{33,31.8},{33.2,24.4},{33.2,34},{33.4,31},{33.6,31.2},{34.2,23.6},{34.4,25.4},{34.6,27.4},{35.2,28.4},{35.4,30},{35.6,30.8},{35.6,31.6},{36,28.2},{36.2,29.2},{36.2,30.2},{37.2,29}}},nil,3537,nil,nil,14,nil,"",0},
|
||||
-- Quest 50154 Teldrassil Trophy: Rare NPCs in Teldrassil (zone 141)
|
||||
[14432] = {'Threggil',115,115,6,6,4,{[141] = {{51.2,50.4},{51.2,50.6},{51.6,50.4},{52,50.6},{52,52},{52.6,52.4}}},nil,141,nil,nil,90,nil,"",0},
|
||||
[3535] = {'Blackmoss the Fetid',273,273,13,13,4,{[141] = {{39.8,38.2},{40.8,26.6},{40.8,33},{40.8,39.6},{41,26.4},{41.4,28.4},{41.4,38.6},{42,37.2},{42,38.6},{42.2,25.6},{42.2,28},{42.2,38},{42.2,40},{42.4,25.2},{42.4,29},{42.4,32},{42.6,25.4},{42.6,26.4},{42.6,37.6},{42.8,28.4},{42.8,28.6},{42.8,37.2},{42.8,38.6},{43,27},{43,31},{43,39.6},{43.2,36.4},{43.4,30},{43.4,32.2},{43.4,32.6},{43.6,27.4},{43.6,30.6},{43.6,32},{43.6,36.6},{43.6,39.4},{43.8,28.8},{43.8,29.8},{43.8,33.2},{44,28.2},{44,39.6},{44.2,26.4},{44.6,27.4},{44.6,27.6},{44.6,29.2},{44.8,30.2},{45,31.2},{45.6,29.2},{45.6,29.6},{45.6,32.8}}},nil,141,nil,nil,14,nil,"",0},
|
||||
[14430] = {'Duskstalker',176,176,9,9,4,{[141] = {{50.2,76.6},{51.2,77},{51.2,77.8},{51.6,76.2},{51.8,77.4},{52.4,77.6},{52.6,77.6},{53.4,76.2},{53.4,77.2},{53.8,76.8},{54,77.6},{54.2,75.4},{54.4,76},{54.6,76},{54.6,77},{57.4,76},{57.4,76.6},{58,75},{58,76.4},{58.4,76.8},{58.6,76.2},{58.8,76.6},{60,75.6},{60.2,73.8},{60.2,75.4},{60.6,75.4},{60.6,75.8},{61,74.4}}},nil,141,nil,nil,66,nil,"",0},
|
||||
[14428] = {'Uruson',137,137,7,7,4,{[141] = {{62.6,56.2},{62.8,57},{63.4,57.6},{63.8,57.2},{64.4,55.8},{64.6,62.2},{65.2,60.4},{65.4,57.4},{65.4,58},{65.4,61.2},{65.6,53.8},{66.2,58.6},{66.2,60.6},{66.4,56.4},{66.4,57.2},{66.4,58.2},{66.4,59.8},{66.6,54.8},{66.8,56},{66.8,58.4},{66.8,58.6},{67,56.8},{67.2,54},{67.2,61.2},{67.4,59.6},{67.4,61.8},{67.6,56.4},{67.6,58.4},{67.6,59.4},{67.6,59.6},{67.8,57},{67.8,61},{68,62.2},{68.4,53.6},{69.2,61.4},{69.6,62},{70.2,57.8}}},nil,141,nil,nil,82,nil,"",0},
|
||||
[14431] = {'Fury Shelda',156,156,8,8,4,{[141] = {{34.4,34.4},{34.4,35.2},{34.8,32.4},{34.8,33},{34.8,34.4},{35.2,35},{35.4,36.2},{35.4,36.6},{35.4,37.6},{35.4,38.6},{35.6,35.4},{35.6,35.6},{35.6,37.2},{36,38},{36.4,33.8},{36.4,38.8},{36.4,39.6},{36.4,42.4},{36.6,35.4},{36.6,38.2},{36.6,39.4},{36.8,36.4},{37,40.8},{37.2,40.2},{37.2,41.6},{37.4,36.6},{37.4,42.6},{37.4,43.6},{37.6,40.4},{37.6,40.6},{37.6,42.4},{37.8,37},{37.8,42.6},{38,39},{38,44},{38.2,34.8},{39,41.4},{39.8,44.2}}},nil,141,nil,nil,514,nil,"",0},
|
||||
[14429] = {'Grimmaw',222,222,11,11,4,{[141] = {{39.2,79.4},{39.4,79.6},{39.4,80.8},{40.2,80.6},{40.4,79.4},{40.4,79.6},{40.6,79.6},{41,78.4},{41,78.8},{41.4,74.6},{41.4,77.4},{41.6,76},{41.6,78.4},{41.6,78.6},{41.8,77},{41.8,79.6},{42.6,75.8},{42.6,77.6},{42.6,79.6},{43,75.4},{43,79.2},{43.2,74.4},{43.6,76.4},{43.8,77.8},{43.8,79.6},{47.8,73.8}}},nil,141,nil,nil,82,nil,"",0},
|
||||
-- Quest 50156 Westfall Trophy: Rare NPCs in Westfall (zone 40)
|
||||
[573] = {'Foe Reaper 4000',484,484,20,20,4,{[40] = {{33.8,52},{34.6,51.6},{35.2,50.4},{35.4,49.4},{36.2,50},{36.2,50.6},{36.4,52.4},{36.6,53.6},{37,48.2},{37,49.2},{37.2,47.4},{37.2,52},{37.2,52.6},{37.4,50.2},{37.4,51.4},{37.6,51.4},{37.6,53.2},{37.8,47.8},{38,46},{38,49},{38,51.8},{38.2,54.2},{38.4,49.8},{38.6,45.8},{38.6,50},{38.6,51},{38.8,51.6},{39,49.4},{39.2,47},{39.6,52},{40,50.4},{40.2,46.6},{42,34.2},{42.4,36.4},{42.4,37},{42.4,37.8},{42.4,39.4},{42.6,34.6},{43.2,32.8},{43.2,54.2},{43.4,35.8},{43.4,36.8},{43.4,38.6},{43.6,32.6},{44,32},{44,34.2},{44,35.6},{44,40.4},{44.2,38.2},{44.2,39.4},{44.4,35.2},{44.4,37},{44.6,32.8},{44.6,38.2},{44.6,39},{44.6,40.6},{44.8,31.4},{44.8,34.4},{44.8,35.6},{44.8,37},{45,31.6},{45.2,35.2},{45.8,31.8},{46,32.6},{46,35.2},{46.2,36},{46.8,33.6},{46.8,49.2},{47,19.2},{47.4,22},{48.4,23.2},{48.4,23.8},{48.6,22.8},{48.8,24},{49,64.2},{49.2,25.4},{49.4,22.2},{49.4,25.6},{49.6,23.4},{49.6,64.4},{50,22.2},{50,23.8},{50,25},{50.2,25.8},{50.2,26.8},{50.2,65},{50.4,21.4},{50.4,66.8},{50.6,27.2},{50.8,21.2},{50.8,21.8},{50.8,22.8},{50.8,24},{50.8,26},{50.8,67.2},{50.8,69},{51,27.6},{51,66.2},{51.4,24.6},{51.4,67.6},{51.6,20.4},{51.6,23.2},{51.6,23.8},{51.6,67.4},{51.6,67.8},{51.8,21.2},{51.8,25.4},{51.8,69},{52,21.6},{52,26.2},{52,69.8},{52.2,64.6},{52.6,26.2},{52.6,66.8},{52.6,67.8},{52.8,64.6},{53,64.4},{53.2,21.6},{53.2,68.6},{53.4,23},{54.4,19},{54.6,67.8},{57.8,32.8},{61.4,64.2},{61.8,60.2},{62.2,63.8},{62.2,65.2},{62.4,61.4},{62.4,61.6},{62.4,62.6},{62.6,62},{62.8,60.4},{62.8,61.4},{62.8,62.6},{63,59.4},{63.6,59.4},{63.6,60},{63.6,60.6},{63.6,63},{63.8,62.2}}},nil,40,nil,nil,14,nil,"",0},
|
||||
[599] = {'Marisa du\'Paige',531,531,18,18,4,{[40] = {{39.8,78.2}}},nil,40,nil,nil,17,nil,"",0},
|
||||
[462] = {'Vultros',788,788,26,26,4,{[40] = {{34,68.2},{35,67},{35.2,70},{35.4,67.8},{35.4,68.8},{35.6,67.4},{35.6,67.8},{35.6,68.6},{36.2,71},{36.6,66.4},{36.6,67.8},{43.2,59.2},{43.4,60.4},{44,60.2},{44.2,59},{44.2,61.6},{44.6,59},{44.8,59.6},{45.4,58.2},{45.6,57.4},{45.6,58.6},{45.6,60.2},{45.8,58},{46,56.4},{46.4,45},{46.8,44.4},{47,44.6},{47.2,42.6},{47.4,40.8},{47.4,41.8},{47.4,45.6},{47.6,44.4},{47.8,41.4},{47.8,45.6},{48,42.4},{48,43.4},{48.4,44.6},{48.6,45},{48.8,42.4},{49,43.8},{49.2,43.4},{49.6,23.4},{50,25},{50.2,24},{50.2,28.2},{50.4,47.8},{50.6,27.8},{51,20.6},{51,22.2},{51,24},{51.2,22.8},{51.4,24.6},{51.4,25.6},{51.6,23.2},{51.6,23.6},{51.8,26},{52,20.8},{52,22},{52.2,20.4},{52.2,25.2},{52.6,23.2},{52.6,24.8},{52.8,24.4},{52.8,26.4},{52.8,26.6},{54,21.4},{58.2,34.4},{62.6,73},{63,74.4},{63,74.8},{63.2,54.8},{63.8,58},{64,73.8},{64.4,55.2},{64.4,56},{64.4,57},{64.6,57.6},{64.8,56.2},{65,56.6},{65.6,73.8}}},nil,40,nil,nil,73,nil,"",0},
|
||||
[520] = {'Brack',449,449,19,19,4,{[40] = {{25.4,64.6},{25.6,64.4},{26,53},{26,56},{26,58.8},{26,61},{26,63},{26.2,61.8},{26.4,47.4},{26.4,48},{26.4,48.8},{26.4,51},{26.4,52},{26.4,57.2},{26.4,58.4},{26.4,60},{26.4,65.2},{26.4,65.6},{26.4,66.8},{26.4,69.4},{26.6,41},{26.6,47.8},{26.6,51.6},{26.6,60},{26.6,61.6},{26.6,66},{26.8,49.2},{26.8,50},{26.8,54},{26.8,58.6},{27,41.6},{27,43.2},{27,44.8},{27,46.2},{27,46.6},{27,52.6},{27,60.8},{27,67.4},{27.2,38.8},{27.2,44},{27.2,56},{27.2,58},{27.2,62.8},{27.2,68},{27.2,68.8},{27.2,69.8},{27.4,38},{27.4,50.8},{27.4,55.2},{27.4,57},{27.4,70.6},{27.6,44.8},{27.6,46.2},{27.6,48.4},{27.6,49.4},{27.6,51.2},{27.6,54.2},{27.6,66.6},{27.6,71.6},{27.8,39.6},{27.8,40.8},{27.8,43.4},{27.8,44.4},{27.8,54.8},{28,49.6},{28,69},{28,71.4},{28,73.2},{28.2,33.6},{28.2,37.4},{28.2,42},{28.2,56},{28.2,56.8},{28.2,74.2},{28.4,36},{28.4,37.8},{28.4,38.8},{28.4,70.4},{28.4,74.8},{28.4,76.6},{28.6,34.6},{28.6,37.2},{28.6,38.6},{28.6,40},{28.6,71.6},{28.8,33.4},{28.8,37.6},{28.8,45.6},{28.8,71},{29,32.2},{29,34.4},{29,41.2},{29,72.8},{29,74.2},{29.2,30.4},{29.2,76.4},{29.2,76.6},{29.2,77.8},{29.4,46.6},{29.4,75},{29.4,79.4},{29.6,31.4},{29.6,35.2},{29.6,39.8},{29.6,76.4},{29.8,30.2},{29.8,31.6},{29.8,34},{29.8,71.4},{29.8,78},{29.8,78.6},{30,75.2},{30.2,29},{30.2,77.2},{30.2,80},{30.2,81.6},{30.4,80.6},{30.4,82.8},{30.6,81},{30.8,27.8},{30.8,29.4},{30.8,75.2},{30.8,79.4},{30.8,81.8},{31,25.2},{31,26.2},{31.2,30.4},{31.2,31.2},{31.4,27.4},{31.4,83},{31.4,83.6},{31.6,27.4},{31.6,28.2},{31.6,81.4},{31.6,82.4},{32.2,23.6},{32.2,26.4},{32.2,84},{32.4,22.6},{32.4,25},{32.4,83},{32.6,24.6},{33,23.8},{33.2,82.4},{33.2,83.4},{33.2,83.6},{33.4,19.4},{33.4,21.8},{33.4,22.6},{33.6,22.4},{33.6,23.2},{33.6,23.8},{33.8,81.8},{34,20.2},{34,83.4},{34,84},{34,84.8},{34.2,20.8},{34.6,20.4},{34.6,84},{34.6,84.6},{34.8,20.6},{34.8,85.8},{35.2,83.2},{35.6,20},{35.6,21.6},{36.4,19},{36.8,16.4},{36.8,18},{36.8,19},{36.8,19.8},{37.6,17.6},{38,17.2},{38.4,16},{38.6,15.4},{38.8,17.2},{39,13.4},{39,18},{39.2,14.2},{39.2,15.8},{39.6,12.8},{39.6,13.6},{39.6,15.8},{40.2,17},{40.4,10.4},{40.4,11.4},{40.4,12.4},{40.4,18.4},{40.6,12.6},{41,11.2},{41,11.8},{41.6,11.6},{42,9.6},{42,11.2},{42.8,10.4},{42.8,11.6},{43.4,11.4},{43.6,9.4},{43.8,10.2},{44.2,10.6},{44.2,12.4},{45,8.4},{45.2,10},{45.4,9.4},{46,10.8},{46.2,10.4},{46.4,12.2},{46.6,8.8},{46.6,12.4},{47,10.4},{47,10.6},{47.8,10.6},{48.4,9.8},{48.6,11.2},{49.2,10.2},{49.2,11.6},{49.4,14},{49.6,14.8},{49.8,10.4},{49.8,13.2},{50.2,11},{50.2,11.8},{50.6,10.4},{51.2,11.6},{51.4,8.8},{51.4,10.8},{51.8,11.4},{51.8,11.6},{52,8.8},{52.4,10.4},{52.6,9},{52.6,11},{52.8,10.4},{53,11.8},{53.6,10.6},{53.8,10.4},{54.2,12.6},{54.4,9},{54.4,12},{54.4,13.8},{54.6,13.2},{54.8,10.8},{54.8,16},{55,14.6},{55.2,9.4},{55.2,9.6},{55.2,14.2},{55.4,12},{55.6,9.2},{55.8,10.2},{55.8,10.8},{57.2,10.2},{57.2,11}}},nil,40,nil,nil,18,nil,"",0},
|
||||
[596] = {'Brainwashed Noble',531,531,18,18,4,{[40] = {{42.4,76.6}}},nil,40,nil,nil,17,nil,"",0},
|
||||
[572] = {'Leprithus',404,404,19,19,4,{[40] = {{39.4,26.2},{39.4,26.6},{39.6,35.6},{40.2,27.2},{40.4,29.4},{40.8,32.6},{40.8,35.8},{41.2,27.6},{41.2,32.4},{41.4,29},{41.4,29.6},{41.4,31},{41.6,29.2},{41.8,25.6},{41.8,29.6},{42.4,28.4},{42.4,30.8},{42.6,25.8},{42.6,29.6},{42.6,33.8},{42.8,29},{43.2,28.4},{43.2,31.4},{43.2,31.6},{43.6,28.2},{43.6,30},{43.8,28.6},{44,41.8},{45,27.8},{45.6,28.2},{46.2,31.2},{47.8,29.8},{48,29.2},{49,29},{56.4,80.6},{56.6,79.4},{56.6,80.6},{56.8,80.4},{58,79.2},{58,80.2},{59.4,77},{59.8,77.2},{60,77.6},{60.2,72.8},{61,76.4},{61.2,72.2},{61.2,76.6},{61.4,73.2},{61.4,73.8},{61.4,74.8},{61.6,72},{61.8,68.4},{61.8,69.6},{61.8,72.8},{62,67.2},{62,74},{62.2,68.8},{62.8,65.8},{63,65},{63.4,66.6},{63.8,64.6},{64,63.8},{64.2,68.6},{64.4,66.2},{64.4,67.4},{64.4,68.4},{64.6,61.2},{64.6,63.6},{64.6,69},{64.8,64.6},{64.8,66.8},{64.8,67.6},{65.2,62.4},{65.2,63.2},{65.4,65.8},{65.6,66.6},{66.4,62.4},{66.4,63},{66.6,62.8},{66.8,65.6},{67.6,62.8}}},nil,40,nil,nil,21,nil,"",0},
|
||||
[1424] = {'Master Digger',328,328,15,15,4,{[40] = {{44.6,19.6},{44.8,20.6},{45.2,18.6},{45.4,18.2},{45.8,18.2},{46.2,18.8},{46.6,19.4},{46.6,19.6}}},nil,40,nil,nil,26,nil,"",0},
|
||||
[506] = {'Sergeant Brashclaw',417,417,18,18,4,{[40] = {{32.2,38.8},{32.6,34.8},{33.4,29.6},{33.4,32.4},{33.6,33.8},{34,32.6},{34.4,32.4},{34.4,36.4},{34.6,30.4},{34.8,31},{35,29.4},{35,33.8},{35,36.8},{35.2,32.4},{35.4,32.6},{35.6,33.8},{36.2,29},{36.2,31},{36.2,31.8},{36.4,27.2},{36.4,28.4},{36.4,30.4},{36.4,32.8},{36.4,35},{36.6,38.4},{36.8,29.4},{36.8,35.2},{37,27.6},{37,31.4},{37,31.8},{37,35.6},{37.2,30.4},{37.2,33},{37.4,33.8},{37.6,31.4},{37.6,32.8},{37.6,36.2},{37.6,37.4},{37.8,30.4},{38,29.4},{38,33.6},{38,37.8},{38.2,34.6},{38.4,32},{38.4,40},{38.6,31.6},{38.6,33.4},{38.8,29.6},{38.8,33.8},{39,27},{39,35},{39.2,27.8},{39.2,30.8},{39.4,29.4},{39.6,29.2},{39.6,29.6},{39.6,31.2},{39.6,34},{39.8,27.2},{40,36.8},{40,43},{40.2,35},{40.2,36},{40.4,33.2},{40.6,26.6},{40.6,30.6},{40.8,31.8},{41.2,38},{41.6,31.8},{43.4,27},{44,41},{46.4,28},{46.6,28.8}}},nil,40,nil,nil,20,nil,"",0},
|
||||
[519] = {'Slark',328,328,15,15,4,{[40] = {{25.6,63},{25.8,56.4},{26.2,59},{26.2,64.4},{26.2,65.6},{26.4,47},{26.4,48},{26.4,48.6},{26.4,49.8},{26.4,52.4},{26.4,52.6},{26.4,54.4},{26.4,55.2},{26.4,61.4},{26.4,62.2},{26.4,65.2},{26.4,66.8},{26.4,67.8},{26.6,53},{26.6,56.4},{26.6,59.8},{26.6,65.2},{26.8,47.6},{26.8,52.2},{26.8,66.4},{27,39.2},{27,46.4},{27,49},{27,57.6},{27,66.6},{27,69.4},{27.2,35.2},{27.2,35.6},{27.2,44.2},{27.2,45},{27.2,46.6},{27.2,49.8},{27.2,54.8},{27.2,56.6},{27.2,62.8},{27.2,68.2},{27.4,34},{27.4,36.8},{27.4,38},{27.4,39.8},{27.4,41},{27.4,42.2},{27.4,51.4},{27.4,54},{27.4,70},{27.4,71},{27.4,72.6},{27.6,34},{27.6,34.6},{27.6,42},{27.6,43.4},{27.6,49.6},{27.6,51.4},{27.6,52.4},{27.6,53.2},{27.6,54.4},{27.6,56.6},{27.6,69.8},{27.8,45.2},{27.8,72.2},{28,46.2},{28,70.6},{28.2,36.4},{28.2,36.6},{28.2,37.6},{28.2,41.2},{28.2,63.4},{28.2,73},{28.2,74},{28.4,38.8},{28.4,39.6},{28.4,55.6},{28.4,57.6},{28.4,75.6},{28.4,77},{28.6,35.8},{28.6,39.8},{28.6,56},{28.6,71.4},{28.8,32},{28.8,34.2},{28.8,70.2},{29,34.6},{29,36.8},{29,55.2},{29,73},{29,74},{29,74.8},{29.2,38},{29.2,72.4},{29.2,79.6},{29.4,31.2},{29.4,33},{29.4,76.2},{29.4,77.2},{29.4,77.8},{29.4,79.2},{29.6,32},{29.6,33},{29.6,34.4},{29.6,34.6},{29.6,70.8},{29.6,77.4},{29.6,78.8},{29.8,31.2},{29.8,80.4},{30.2,29},{30.2,36.2},{30.4,29.8},{30.4,80.6},{30.4,82},{30.6,31.2},{30.6,80.2},{30.6,81.2},{30.6,81.6},{30.6,85.2},{30.8,27.8},{31,26.4},{31,27.2},{31.2,29.4},{31.2,83},{31.4,25},{31.4,30},{31.6,25.6},{31.6,27.2},{31.6,27.8},{31.8,81.2},{32.2,82.4},{32.2,83.6},{32.2,84.8},{32.4,21.8},{32.4,23.4},{32.4,23.8},{32.4,24.8},{32.4,83},{32.6,25.2},{32.8,82.8},{33,83.6},{33.2,81.8},{33.2,84.6},{33.4,21.8},{33.4,23.2},{33.4,23.8},{33.6,23.6},{33.6,83.2},{33.8,84.8},{34,21.6},{34,84},{34.2,81.8},{34.4,19.8},{34.4,20.6},{34.4,22.6},{34.8,23},{34.8,82.6},{34.8,87.2},{35,20.6},{35,85.6},{35.2,19.4},{35.2,20.2},{35.4,84.2},{35.4,84.6},{35.8,84.4},{35.8,85},{36,19.2},{36,20.2},{36,86},{36.2,18.4},{36.4,86.6},{37.2,15.6},{37.2,16.8},{37.2,18.2},{37.2,87.8},{37.6,15.6},{37.6,18},{38,15.4},{38,16.6},{38.6,14},{38.8,12},{38.8,16.2},{39,15},{39.4,17},{39.6,13.4},{39.6,14.4},{39.6,14.8},{39.6,15.8},{39.8,10.8},{40.4,12.2},{41.2,12.8},{41.4,12.4},{41.6,12.4},{41.8,12.6},{42.2,11.4},{42.4,10.4},{42.8,11.4},{43,10},{43.2,9.4},{43.2,12.8},{43.6,11.2},{43.6,12.6},{44.2,10},{44.4,9.4},{44.8,9.4},{45.2,10.2},{45.6,8.2},{46.2,10.2},{46.4,11},{46.6,8.2},{46.8,11.6},{47.2,11},{47.4,10.2},{47.8,10.8},{48.4,10.4},{49.2,9.6},{49.4,11},{49.4,12.2},{49.4,12.6},{50,10.4},{50.2,10.8},{50.4,12},{50.4,13.6},{50.8,9},{51,11.6},{51.2,11.4},{51.4,9.6},{51.8,8.8},{52.2,10.6},{52.4,10},{53,11.6},{53.2,10.6},{53.4,9.4},{53.4,10.2},{54.2,10.4},{54.4,11},{54.4,12},{54.4,12.8},{54.6,10.4},{54.8,13.6},{55,10.6},{55.2,12.4},{55.2,13.4},{55.6,14.6},{55.8,9.4},{55.8,10.8},{55.8,11.6},{56.2,10},{56.8,10.6}}},nil,40,nil,nil,18,nil,"",0},
|
||||
-- Quest 50157 Modan Trophy: Rare NPCs in Loch Modan (zone 38)
|
||||
[1425] = {'Grizlak',301,301,15,15,4,{[38] = {{34.2,26.8},{34.8,27.2},{35.4,27.8},{35.6,27.8},{36.2,26.6},{36.4,26}}},nil,38,nil,nil,26,nil,"",0},
|
||||
[1399] = {'Magosh',473,473,21,21,4,{[38] = {{64.6,67.4},{65.2,65.6},{66.4,69},{67.2,63.2},{67.4,68.4},{67.4,68.6},{68,68.6},{68.4,68.4},{68.6,63.2},{68.8,68.4},{69.2,66},{69.2,66.8},{69.6,60.2},{69.6,67.6},{70,65.4},{70,66.2},{70.2,62},{70.4,61.4},{70.4,62.8},{70.4,64.2},{70.4,67.2},{70.6,64.2},{70.6,65.2},{70.6,67},{70.8,65.8},{70.8,68.4},{71.6,68.2},{72.4,67},{72.4,68.6},{72.8,61.8},{72.8,63.6}}},nil,38,nil,nil,59,nil,"Stonesplinter Tribal Shaman",0},
|
||||
[2476] = {'Large Loch Crocolisk',573,573,22,22,4,{[38] = {{53.2,30.8},{55.8,17.6},{56,19.4},{56,32},{56.8,30.2},{57,20.6},{57.4,29.4},{57.4,30.8},{57.8,22},{57.8,31.4},{58,29.2},{58,32.2},{58,32.6},{58,33.6},{58.2,27.4},{58.4,26.4},{58.4,28},{58.4,29.8},{58.4,35},{58.4,36.8},{58.6,25.2},{58.6,26},{58.6,28.4},{58.6,30.4},{58.6,34.2},{58.6,34.8},{58.6,35.8},{58.8,29.4},{58.8,30.8},{58.8,31.6},{58.8,37.4},{59.2,22.2},{59.2,32.6},{59.2,39},{59.2,39.8},{59.4,38},{59.4,40.8},{59.6,29.2},{59.6,30.2},{59.6,31.2},{59.6,34.8},{59.6,38},{59.8,26.2},{59.8,31.8},{59.8,35.6},{59.8,36.6},{59.8,39.6},{60,33.2},{60,34.4},{60,39.4},{60.2,41},{60.4,27},{60.4,41.8},{60.6,29},{60.6,34.2},{60.8,26.2},{60.8,36.4},{60.8,37.2},{60.8,38.2},{60.8,39},{60.8,39.8},{61,43},{61.2,42},{61.4,40.8},{61.6,41.2},{61.6,41.6},{61.8,34.2},{61.8,36.4},{61.8,42.6},{61.8,44},{62,39},{62.4,45.6},{62.6,35.2},{62.8,42},{63.4,47.6},{63.4,48.6},{64,42.2},{64.4,51.6}}},nil,38,nil,nil,14,nil,"",0},
|
||||
[14266] = {'Shanda the Spinner',449,449,19,19,4,{[38] = {{75.8,53.4},{76.2,47.2},{76.4,54.2},{76.6,49.8},{76.6,55},{77,51.2},{77.2,53},{77.4,52.2},{77.4,53.8},{77.8,52.2},{77.8,52.6},{77.8,53.6},{78.6,52.6},{79,51.4},{79.2,51.6},{79.8,51.8}}},nil,38,nil,nil,22,nil,"",0},
|
||||
[14268] = {'Lord Condar',328,356,15,16,4,{[38] = {{57,77},{60.4,77.8},{61.4,77.6},{62.2,78},{62.4,77.4},{62.4,78.6},{62.4,79.6},{62.8,78.2},{63.4,77.4},{63.6,77.8},{64,77},{64.4,76.4},{74.2,67.8},{74.4,64},{74.4,65},{74.4,65.8},{74.4,66.6},{74.4,68.6},{74.6,65.4},{74.6,66},{74.8,67.2},{75.2,67.8},{75.4,69},{75.6,66.4},{75.6,68},{76,67.2},{76.2,73.4},{76.4,73.8},{76.4,75},{76.8,66.2},{77,72.4},{77.4,73.4},{77.4,74},{77.4,74.8},{77.6,72.4},{77.8,74.2},{77.8,74.6},{78,73},{78.4,76.4},{78.6,71.4},{79,75.2},{79.6,72}}},nil,38,nil,nil,73,nil,"",0},
|
||||
[14267] = {'Emogg the Crusher',1347,1347,19,19,2,{[38] = {{61.6,20},{61.8,24},{62.2,17},{62.4,19.4},{62.8,22.8},{63,23.8},{63.4,19},{63.8,19.4},{64.4,20},{64.4,20.6},{65,21},{65.2,19.4},{65.4,19.8},{66.2,21},{66.2,22.4},{66.2,22.8},{66.4,20.4},{66.6,21},{67.2,21.6},{67.2,30},{67.2,31.4},{67.4,23},{67.6,22.6},{67.8,20.4},{67.8,20.6},{67.8,26.6},{68.4,21.6},{68.4,24},{68.4,26.4},{68.4,27.8},{68.4,28.8},{68.6,24.4},{68.6,26.2},{68.6,29.2},{68.8,21.2},{68.8,24.8},{69.2,23.4},{69.2,27.6},{69.4,22.2},{69.4,27.2},{69.4,29.6},{69.6,21.8},{69.6,23.2},{69.6,25.6},{69.6,28.8},{69.8,21.4},{69.8,24.2},{69.8,24.6},{69.8,26.8},{69.8,27.6},{70,20.4},{70.6,20.4},{70.8,21},{70.8,23.6},{70.8,26},{71.4,22.4},{71.4,23.2},{71.4,24.6},{71.6,19.6},{71.6,21},{72,23.8},{72.2,23.2},{72.2,24.8},{72.2,25.8},{72.4,21.8},{72.4,27},{72.6,20.2},{72.6,27.6},{72.8,19.2},{72.8,21.2},{72.8,22},{72.8,24.4},{72.8,25},{73,27},{73,28.6},{73.2,23.2},{73.4,26},{73.6,23},{73.6,26},{73.6,30},{74,28.6},{74.2,28.4},{74.2,31},{74.8,32},{75.2,24.8},{75.4,34.4}}},nil,38,nil,nil,45,nil,"",0},
|
||||
[1398] = {'Boss Galgosh',573,573,22,22,4,{[38] = {{59.6,65.2},{62.6,61.8},{62.8,62.8},{64,62.2},{64,66.8},{64.4,65.8},{64.6,64.2},{65,65.4},{65.2,67.4},{65.4,68.4},{65.8,68},{66,66},{66.2,65.2},{66.4,68.6},{66.8,68.2},{67,63.2},{67,66},{67,68.8},{67.4,64.8},{67.8,68.8},{68.4,66},{68.4,68.2},{68.8,66},{68.8,68.6},{69,68.2},{69.2,66.6},{69.6,67.4},{69.8,65.8},{70,65.2},{70.4,63.8},{70.4,67.6},{70.6,66.8},{70.6,68.6},{70.8,65},{70.8,66.4},{70.8,67.8},{71.6,68.6},{71.8,64.2},{72.4,67.6},{72.6,69}}},nil,38,nil,nil,59,nil,"Stonesplinter Chieftain",0},
|
||||
-- Quest 50031 Stormbound: Storm Peaks (zone 67) elementals
|
||||
-- All 11 elementals scraped from Storm Peaks filter page
|
||||
[30120] = {'Seething Revenant',12600,12600,80,80,0,{[67] = {{76.4,63},{76.8,63},{77,62.2},{77.6,62.4},{77.6,62.6}}},nil,67,nil,nil,834,nil,"",0},
|
||||
[30053] = {'Icebound Revenant',12600,12600,78,80,0,{[67] = {{41.8,65.8},{42,63.4},{42,65},{42.4,63.8},{42.4,66.8},{42.6,63.8},{42.6,66.4},{42.8,65},{43,67.4},{43.2,67.6},{43.6,67.6},{43.8,67},{44,66.4}}},nil,67,nil,nil,16,nil,"",0},
|
||||
-- Additional Storm Peaks elementals for Quest 50031 (scraped from filter page)
|
||||
[29504] = {'Seething Revenant',12600,12600,80,80,0,{[67] = {{68,63.6},{68.2,63.2},{69,57.4},{69,57.6},{69.2,62.4},{69.4,59.4},{69.4,60.4},{69.4,60.6},{69.4,62.6},{69.6,60.6},{69.6,62.6},{69.8,59.4},{70,57},{70,59.6},{70.2,56.4},{70.4,57.6},{70.4,61.8},{70.6,57.8},{70.6,60.4},{70.6,61.8},{70.6,62.6},{71,56},{71,56.6},{71.4,59},{71.4,60.6},{71.6,59},{71.6,60.4},{71.6,60.8},{72.4,62},{72.6,62.2},{73.4,63},{73.8,63},{74.2,62.4},{75,63.2},{76.4,63},{76.4,63.8},{76.6,62.8},{76.6,63.6},{77,61.4},{77,62},{77.6,62.4},{77.6,62.8}}},nil,67,nil,nil,834,nil,"",0},
|
||||
[30450] = {'Wailing Winds',12600,12600,79,80,0,{[67] = {{61.4,38.4},{61.4,39},{61.4,39.6},{61.6,38.2},{61.6,39.2},{61.8,40},{62.2,40.8},{62.4,41.6},{62.6,40.4}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30184] = {'Scion of Storm',12600,12600,80,80,0,{[67] = {{64,42.8},{64.2,39.4},{64.2,42.2},{64.4,40.4},{64.4,41.2},{64.4,44.4},{64.4,44.6},{64.6,40.6},{64.6,44.2},{64.8,39},{65,44.6},{65.2,42.4},{65.2,42.6},{65.4,39.6},{65.6,38.4},{65.6,40.4},{65.6,42.8},{65.6,43.8},{65.8,39.4},{65.8,41.2},{66.2,41.8},{66.4,44.8},{66.6,39.4},{66.6,40.6},{66.6,42.2},{66.6,42.6},{67,44.6},{67,45.6},{67.2,40},{67.4,43.8},{67.6,43.8},{67.6,44.6},{67.8,39.6},{67.8,41},{68.2,43.4},{68.4,39.4},{68.4,42.4},{68.6,40.2},{68.6,40.8},{68.6,43.8},{69,42.6},{69.4,41.6},{69.6,40.4},{69.6,41},{69.6,41.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29844] = {'Icebound Revenant',12600,12600,78,80,0,{[67] = {{40.4,62.4},{40.4,63},{40.8,62.8},{40.8,63.6},{41.2,62.4},{41.4,61},{41.4,65},{41.4,66.2},{41.6,62.4},{41.8,60.4},{41.8,62.8},{41.8,65.8},{42,61.4},{42,65.2},{42.4,63.8},{42.6,66.2},{42.8,67},{43,64.4},{43,64.8},{43.2,67.6},{43.6,67.6},{43.8,67},{44,66},{44.4,64.4},{44.4,64.6},{44.6,64.4},{44.6,65.4},{44.6,65.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30387] = {'Seething Revenant',12600,12600,80,80,0,{[67] = {{73.4,62.8},{73.8,62.4},{74,62.8},{74.6,62.4},{75,62.6},{75.2,63.6},{75.6,63},{75.8,63.6},{75.8,64.6},{76.6,64},{76.8,63},{77.2,62.2},{77.6,62.4},{77.6,62.6}}},nil,67,nil,nil,834,nil,"",0},
|
||||
[30160] = {'Brittle Revenant',12600,12600,80,80,0,{[67] = {{69,59.4},{69.2,57.4},{69.2,59.6},{69.4,58.2},{69.4,61},{69.4,61.8},{69.6,59.8},{70,57},{70,58.2},{70,59.4},{70.2,61},{70.2,62},{70.2,62.6},{70.6,56.8},{70.6,60.4},{70.6,61.4},{70.8,57.8},{70.8,58.8},{70.8,61.6},{71.2,56},{71.4,62.6},{71.6,62.4},{71.8,62.6}}},nil,67,nil,nil,834,nil,"",0},
|
||||
[29624] = {'Stormrider',12600,12600,80,80,0,{[67] = {{23.2,36.2},{23.4,37.4},{23.4,37.6},{23.8,37.4},{23.8,37.6},{24.4,39.4},{24.4,40.2},{24.4,40.6},{24.6,39.8},{25,43},{25.2,38.6},{25.4,37.4},{25.4,37.8},{25.4,40.8},{25.6,37.4},{25.6,37.8},{26,39.2},{26.2,39.6},{26.2,40.8},{26.2,44},{26.4,41.8},{26.4,42.8},{26.4,44.6},{26.4,50.6},{26.6,41.8},{27,43.6},{27.2,38.4},{27.2,40.4},{27.2,40.6},{27.2,48.8},{27.4,39.2},{27.4,42.8},{27.4,45.4},{27.4,45.8},{27.4,47},{27.4,48.4},{27.4,49.6},{27.6,39.2},{27.6,39.8},{27.6,41.4},{27.6,42},{27.6,44.4},{27.6,44.6},{27.6,45.8},{27.6,47.6},{27.8,47.4},{28,42.8},{28.2,37.4},{28.4,49.4},{28.4,49.8},{28.4,51.2},{28.4,51.6},{28.6,43},{28.6,51},{28.6,51.6},{28.8,47.4},{28.8,48.4},{29,46.2},{29,49.6},{29.2,49.4},{29.6,47.4},{29.6,50.6},{30,49.4},{30,49.6},{30.2,48.4},{30.6,48.2},{31.2,49.2},{31.2,49.6},{31.6,49.6},{32,47.2},{32.4,48.2},{32.4,48.6},{32.6,48.6},{32.8,47.8},{33.4,47.2},{33.6,47.2},{33.6,47.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30001] = {'Blackmaw',12600,12600,78,80,0,{[67] = {{30.4,36.8},{30.6,37}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30474] = {'The North Wind',12600,12600,80,80,0,{[67] = {{64.2,47.6},{64.4,47.2},{64.6,47.2},{64.6,47.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
-- Quest 50095 Peak Predators: Storm Peaks (zone 67) beasts
|
||||
-- All hostile beasts scraped from Storm Peaks filter page
|
||||
[29411] = {'Crystalweb Weaver',12600,12600,77,78,0,{[67] = {{40.2,74.4},{40.2,74.6},{40.2,76.4},{40.2,76.6},{41.2,76},{41.4,74},{41.4,74.8},{41.6,75},{41.6,75.6},{42,74.4},{42.6,74.4},{42.6,74.6},{43.4,76.2},{43.6,74.2},{43.8,75.4},{44,76},{44.6,73.4},{45,73.8},{45.6,73.8},{47.2,72.4},{47.2,72.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29590] = {'Blighted Proto-Drake',12600,12600,80,80,0,{[67] = {{21.4,57.4},{21.4,58},{21.4,58.6},{21.6,57.2},{22,59.8},{22.2,58.6},{22.4,58.4},{22.6,58.6},{23,57.4},{23,59.6},{23.2,58.2},{24,57.8},{24,58.6},{24.4,57.4},{24.6,57.2},{24.6,57.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30148] = {'Infesting Jormungar',12600,12600,80,80,0,{[67] = {{46.4,55.4},{46.4,55.6},{46.6,57.4},{46.8,55.6},{47.2,54.4},{47.2,54.6},{47.4,48.4},{47.4,48.6},{47.4,49.6},{47.4,50.6},{47.6,48.4},{47.6,48.6},{47.6,50},{47.8,46.6},{47.8,50.8},{47.8,54.6},{48.4,46.4},{48.4,51.6},{48.4,53},{48.4,54.2},{48.6,46.4},{48.6,47.4},{48.6,48.6},{48.6,51.8},{48.6,54.2},{48.8,47.8},{49,52.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[32475] = {'Terror Spinner',12600,12600,76,76,0,{[67] = {{72,75}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29958] = {'Tundra Ram',12600,12600,79,80,0,{[67] = {{67.2,64.2},{67.6,64.6},{68.2,63.2},{68.4,63.6},{68.6,63.4},{68.6,63.6},{69.2,62},{69.4,55.2},{69.4,55.8},{69.6,55.2},{69.6,55.6},{70.2,54},{70.2,58.8},{70.2,59.8},{70.4,56.8},{70.6,54.4},{71.2,55.2},{71.2,55.6},{71.4,56.8},{71.4,58.2},{71.4,59.2},{71.4,60.4},{71.4,60.6},{71.6,56.4},{71.6,56.6},{71.6,57.8},{71.6,60.6},{71.8,59},{71.8,60.4},{72,61.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29358] = {'Frostworg',12600,12600,79,80,0,{[67] = {{59.4,40.6},{59.6,41.4},{59.6,42.6},{60,40.8},{60.2,41},{60.4,40.4},{60.4,40.6},{60.6,42.2},{61,41},{61.2,40.2},{61.4,42.6},{61.6,41.2},{62,41.8},{62.2,41.2},{62.4,41},{62.4,42.6},{62.6,41.4},{62.6,42.6},{62.8,41.6},{63,41},{63.2,42.4},{63.4,41},{63.6,42.2},{64,42.6},{64.2,41.6},{64.4,42.2},{64.6,42.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29469] = {'Ice Steppe Rhino',12600,12600,78,79,0,{[67] = {{59.2,52.6},{59.4,51.8},{59.6,52.6},{60,53},{60.2,52},{60.2,53.4},{60.4,53},{60.6,51.4},{60.6,52},{60.8,53.6},{61,52},{61.2,52.6},{61.4,53.4},{61.6,52.8},{61.8,53},{62,52.8},{62.2,52.2},{62.4,51.8},{62.4,53.6},{62.6,52.2},{62.8,52.6},{63,52},{63.2,53},{63.4,52},{63.6,53.2},{63.8,52.6},{64,52.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30422] = {'Roaming Jormungar',12600,12600,79,80,0,{[67] = {{57.2,57.6},{57.4,58},{57.6,57.6},{57.6,58.4},{57.8,57},{58,57.4},{58,58.2},{58.2,58},{58.4,57.4},{58.4,58.2},{58.6,57.8},{58.8,57.4},{58.8,58.2},{59,57.6},{59,58.4},{59.2,58},{59.4,57.4},{59.4,58.6},{59.6,58.4},{59.8,57.8},{60,58.2},{60.2,58.6},{60.4,58},{60.6,57.4}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30445] = {'Ice Steppe Bull',12600,12600,78,79,0,{[67] = {{60.4,59.4},{60.6,59},{60.8,58.4},{61,58.6},{61.2,59.4},{61.4,58.8},{61.6,59.2},{61.8,58.6},{62,59},{62.2,58.4},{62.4,59},{62.6,58.6},{62.8,59.2},{63,58.8},{63.2,59.4},{63.4,58.6},{63.6,59},{63.8,58.4},{64,59.2},{64.2,58.6},{64.4,59},{64.6,58.8},{64.8,59.4},{65,58.6},{65.2,59}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30291] = {'Ravenous Jormungar',12600,12600,79,80,0,{[67] = {{53.4,62},{53.6,62.2},{54,61.4},{54.4,60.4},{54.4,63.2},{54.4,63.6},{54.6,63.2},{54.6,63.6},{55,60.4},{55.2,60.8},{55.4,62},{55.6,61.4},{55.6,61.6},{55.6,63.4},{55.8,63.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29412] = {'Crystalweb Spitter',12600,12600,77,78,0,{[67] = {{40.2,75.4},{40.2,76},{40.4,77.2},{40.4,77.6},{40.6,77.2},{41.2,74},{41.2,75.4},{41.4,76},{41.6,76},{42.2,74.4},{42.2,74.6},{42.6,74.4},{43.4,75},{43.6,74.8},{44,74.4},{44,75.6},{44.8,73.8},{45.8,73.8},{46.4,73.4},{46.6,73.4},{46.6,73.6},{47.2,72.4},{47.6,72.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30448] = {'Plains Mammoth',12600,12600,77,78,0,{[67] = {{61.2,42},{61.6,42},{62.2,43.4},{62.2,43.6},{62.4,44.8},{62.6,44.4},{62.6,44.8},{62.6,45.6},{63,47.2},{63,47.8},{63.4,42.2},{63.4,42.6},{63.4,48.6},{63.6,42.8},{63.6,48.4},{63.8,47.2},{63.8,48.6},{64,43.8},{64.4,41.4},{64.4,42},{64.4,44.8},{64.4,45.8},{64.6,41.2},{64.6,42.2},{64.8,46.2},{65,45},{65.2,43.2},{65.4,43.8},{65.4,48.6},{65.6,41.8},{65.6,43.4},{66,45.6},{66,48.2},{66,48.6},{66.2,44.4},{66.4,45.4},{66.4,47.2},{66.6,45.2},{66.6,47.6},{66.8,47.2},{67.4,46.4},{67.6,46.4},{67.6,46.6},{67.6,47.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29461] = {'Icetip Crawler',12600,12600,78,78,0,{[67] = {{47,72},{47.2,71.4},{47.2,72.6},{47.4,70},{47.6,70.4},{48,71.8},{48.2,71.2},{48.6,71.4},{48.6,71.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29605] = {'Ravenous Jormungar',12600,12600,79,80,0,{[67] = {{53.4,62},{53.6,62.2},{53.8,62.8},{54.2,61},{54.6,63.6},{55.2,60.4},{55.2,60.6},{55.4,62},{55.4,63.2},{55.6,61.4},{55.6,62},{55.6,63.4},{55.8,64.2}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30447] = {'Romping Rhino',12600,12600,78,79,0,{[67] = {{61.2,41.8},{61.6,43},{62.2,44.4},{62.4,42},{62.4,44.6},{62.6,42.8},{63,42.4},{63,45},{63.2,44.4},{63.6,43.6},{64,42.6},{64.2,42},{64.6,41.8},{64.6,43.2},{64.8,43.6},{65,44.6},{65.4,48.8},{65.6,42.4},{65.6,42.6},{65.6,43.6},{65.8,45},{66.4,46},{66.4,47.4},{66.4,47.6},{66.8,45.8},{66.8,47.6},{67.4,46.6},{67.6,47.6},{67.8,46.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29319] = {'Icepaw Bear',12600,12600,76,77,0,{[67] = {{68.4,73.6},{68.6,73.4},{68.8,73.8},{69.4,74.8},{69.6,72.8},{69.8,74.4},{69.8,74.6},{70.2,71.4},{70.2,71.6},{70.6,73.2},{71.4,72.4},{71.4,74.4},{71.4,74.8},{71.6,72.4},{71.6,74.4},{72.2,73.4},{72.4,75},{72.6,72.4},{72.6,73.8},{72.8,75},{73,73.4},{74.2,74.2},{74.8,74.2},{75.4,74.6},{75.6,73.6},{75.6,74.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29390] = {'Snowdrift Jormungar',12600,12600,79,80,0,{[67] = {{23.4,36.2},{23.4,36.8},{23.4,38.4},{23.8,37.8},{23.8,39.2},{24,36.4},{24,40},{24.4,40.8},{24.8,36.4},{24.8,36.8},{24.8,43},{25.8,44.8},{26.2,42.4},{26.2,43},{26.4,43.6},{26.4,50},{26.6,42.4},{26.8,41},{27,42.6},{27,44.8},{27.2,40.4},{27.2,46.2},{27.4,44.2},{27.4,46.6},{27.4,47.6},{27.4,49.6},{27.4,54.4},{27.4,54.8},{27.6,46},{27.6,46.6},{27.6,47.6},{27.6,49.4},{27.6,54},{27.8,40.2},{27.8,41.2},{27.8,43.2},{27.8,52.8},{28,41.6},{28,44.4},{28,44.6},{28,52.4},{28.2,50.4},{28.2,50.6},{28.8,42.2},{29,47.2},{29.4,48.2},{29.4,49.4},{29.4,50.4},{29.4,50.6},{29.6,48.2},{29.8,48.8},{29.8,50.6},{30,49.8},{30.8,50},{31.6,50},{32,47},{32.4,47.6},{32.6,47.2},{32.6,47.6},{32.6,48.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29562] = {'Icemaw Bear',12600,12600,79,80,0,{[67] = {{54.2,63},{54.6,63.4},{54.6,63.6},{55.6,61.4},{55.6,62},{55.6,63.4},{55.8,64}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30340] = {'Jorcuttar',12600,12600,80,80,0,{[67] = {{54.6,60.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30292] = {'Dead Icemaw Bear',12600,12600,79,80,0,{[67] = {{53.6,61.8},{54.2,61.4},{54.4,60.4},{54.4,63.2},{54.8,60.4},{55,61.8},{55.4,60.8},{55.4,63.2},{55.6,61.4},{55.6,62.2},{55.6,63.2},{55.8,64}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29808] = {'Stormcrest Hatchling',12600,12600,77,77,0,{[67] = {{26,72},{26,72.6},{26.6,72.4},{27.4,71.4},{27.8,71},{28.2,68},{28.2,68.8},{28.2,70},{28.6,67.4},{28.6,68},{28.6,68.6},{29,65.2},{29.4,63.8},{29.8,66.8},{30,66.4},{30.4,64.6},{30.8,65.4},{31,66},{31,66.6},{31.6,66.2},{33,66.6},{33.2,66},{34.4,65.8},{34.8,65.8},{35.8,66.4},{35.8,69.4},{35.8,75},{36.2,67.2},{36.2,69.8},{36.4,67.8},{36.4,71},{36.4,74.4},{36.6,68.2},{36.6,68.6},{36.6,69.6},{36.6,71.4},{36.6,72},{36.8,72.8},{37.2,73.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30174] = {'Hyldsmeet Warbear',12600,12600,80,80,0,{[67] = {{49.4,67.4},{49.4,67.8},{49.4,68.8},{49.6,68.2},{49.6,68.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[34920] = {'Deep Jormungar',12600,12600,80,80,0,{[67] = {{37.4,56},{37.6,56},{37.6,59.8},{38,57},{38,58.8},{38.2,54.4},{38.2,62},{38.4,55},{38.4,58.4},{38.4,60.6},{38.6,58.4},{38.8,54.6},{38.8,59.4},{38.8,59.6},{39.2,61.4},{39.2,61.6},{39.4,53.8},{39.8,61.2},{40,52.4},{40,52.6},{40,60.2},{40,61.8},{40.4,62.8},{40.6,53.2},{40.6,60.6},{40.6,62.8},{40.8,52},{41.4,53.6},{41.4,60},{41.6,52.2},{42,53.2},{42.2,60},{42.4,53.8},{42.4,55},{42.6,58.4},{42.8,54},{42.8,56.8},{42.8,58.6},{43.2,54.8},{43.2,56},{43.2,59.6},{43.4,60.6},{43.6,58.6},{43.8,56.4},{43.8,56.6},{43.8,61.8},{44.2,58.4},{44.2,61},{44.6,59.4},{44.6,61.8},{45,55.6},{45,56.8},{45,60.8},{45.4,60},{45.6,55.6},{45.6,57},{45.8,57.6},{46,61.2},{46,63.4},{46.4,59.2},{46.4,62.4},{46.4,64},{46.6,60.6},{46.6,64},{46.8,63},{47,60},{47.2,62.4},{47.6,61.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
-- Quest 50096 Peak Predators: Icecrown (zone 210) beasts
|
||||
-- All hostile beasts scraped from Icecrown filter page
|
||||
[29392] = {'Ravenous Jaws',12600,12600,79,80,0,{[210] = {{2.4,42.2},{2.6,42.2},{2.8,42.6},{3.2,40.4},{3.2,44.2},{3.2,44.6},{3.4,37.4},{3.4,37.8},{3.4,40.6},{3.4,47.2},{3.6,38},{3.6,43.8},{4,42.4},{4,42.6},{4,44.6},{4.2,36.2},{4.2,36.6},{4.2,39.2},{4.2,46.4},{4.2,46.6},{4.4,34.4},{4.4,34.8},{4.4,40.4},{4.4,41.2},{4.6,34.4},{4.6,36.6},{4.6,39.2},{4.6,40.4},{4.6,40.8},{4.6,42.6},{4.8,38.2},{5,41.6},{5,46.2},{5.2,47.6},{5.4,35.4},{5.4,35.6},{5.4,47.4},{5.6,35.4},{5.8,46},{6.2,42.4},{6.2,42.6},{6.2,43.8},{6.4,34.2},{6.4,36.2},{6.4,36.6},{6.4,45},{6.4,46.8},{6.4,47.8},{6.6,36.4},{6.6,36.6},{6.6,42.4},{6.6,46.4},{6.6,47.6},{6.8,33.8},{6.8,44.4},{6.8,44.6},{6.8,47.4},{7.4,35.4},{7.4,43},{7.6,35.4},{7.6,35.6},{7.6,43},{8.2,34.4},{8.4,39.4},{8.4,39.6},{8.4,41.4},{8.4,41.6},{8.6,32.2},{8.6,41.4},{8.8,33},{8.8,39.4},{8.8,39.6},{8.8,42},{9.4,34.4},{9.4,34.6},{9.4,35.6},{9.6,34.4},{10.2,33.4},{10.2,35.6},{10.2,41.8},{10.4,35.2},{10.4,39.4},{10.4,40.4},{10.4,40.6},{10.6,33.4},{10.6,35.4},{10.6,40},{11.2,34.2},{11.4,36.2},{11.4,36.6},{11.4,41.4},{11.4,41.6},{11.6,34.8},{11.6,41.6},{11.8,36.6},{11.8,41.4},{12,34.4},{12,36},{12.2,42.6},{12.2,46.4},{12.4,37.8},{12.4,38.6},{12.4,47},{12.4,47.8},{12.6,35.4},{12.6,35.6},{12.6,37.8},{12.6,47.2},{12.6,47.6},{12.8,46.4},{13.2,41.4},{13.2,42},{13.2,43.4},{13.2,44.6},{13.4,36.8},{13.4,39.4},{13.4,39.8},{13.4,43.8},{13.4,48.6},{13.6,36.8},{13.6,39.4},{13.6,39.8},{13.6,42},{13.6,42.6},{13.6,43.8},{13.6,48.4},{13.6,48.6},{14.2,38.2},{14.4,40.8},{14.4,45.4},{14.4,46.2},{14.4,46.6},{14.6,38.2},{14.6,40.8},{14.6,44},{14.6,46},{14.6,46.8},{15.4,39.2},{15.4,39.6},{15.4,42.2},{15.4,42.8},{15.4,45.4},{15.6,39.2},{15.6,39.8},{15.6,42.6},{15.6,45.4},{15.6,45.6},{15.8,42.2}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[30206] = {'Carrion Fleshstripper',12600,12600,76,77,0,{[210] = {{83,72.4},{83.2,72.6},{83.2,77.4},{83.2,77.6},{83.4,74.2},{83.4,75.4},{83.4,76},{84,73.6},{84,80},{84.2,76.2},{84.4,72.4},{84.4,72.8},{84.4,74.8},{84.4,77.4},{84.4,77.6},{84.4,78.6},{84.6,72.4},{84.6,72.8},{84.6,74.6},{84.6,77.4},{84.6,78.6},{84.8,73.8},{84.8,78.4},{84.8,80.4},{85,75.6},{85,80.8},{85.8,73.4},{85.8,73.6},{85.8,78.8}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[30330] = {'Jotunheim Proto-Drake',12600,12600,80,80,0,{[210] = {{28,38.4},{29.2,24.8},{29.2,35.2},{29.6,32.8},{30,33.6},{30.2,25},{30.2,34.6},{31.2,25.6},{32.2,26.4},{32.8,24},{33.2,25},{33.6,27.8}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[30430] = {'Sentry Worg',12600,12600,77,78,0,{[210] = {{15.2,58.2},{15.2,58.8},{19.6,56.2},{19.8,55.4},{20,57},{20.6,54.2},{20.8,53.2},{22,54},{22.4,59.2},{23,54.2},{23.4,54.6},{23.4,57.8},{23.6,54.8},{23.6,58.4},{23.6,58.6},{23.8,54.2},{23.8,56.4},{23.8,57},{27.2,40.2},{27.2,42.8},{27.4,39.4},{27.6,37.2},{28,39.4},{28,40},{28.2,40.6},{28.2,44.2},{28.2,45.4},{28.4,38.2},{28.4,41.8},{28.4,42.6},{28.4,46.4},{28.4,46.8},{28.6,38.2},{28.6,40.2},{28.8,40.6},{28.8,41.8},{28.8,46.4},{29,26.4},{29,29.2},{29,31.4},{29.2,27.2},{29.2,28.2},{29.2,35},{29.2,36.2},{29.2,37.4},{29.2,39.2},{29.4,30.2},{29.4,43.2},{29.4,44.4},{29.4,44.6},{29.4,47.4},{29.4,48.2},{29.6,27.8},{29.6,36.2},{29.8,34},{29.8,34.8},{29.8,47},{30,36.6},{30.2,26.6},{30.2,32.6},{30.2,38.4},{30.4,26.4},{30.4,31.4},{30.4,31.6},{30.4,38.6},{30.4,43.4},{30.4,43.8},{30.4,47.6},{30.6,31.6},{30.6,33.8},{30.6,34.6},{30.8,31.4},{30.8,43.6},{30.8,47.6},{31,33.2},{31,37.2},{31,38.4},{31,43.2},{31.2,26.4},{31.2,26.8},{31.2,39.4},{31.2,47.4},{31.4,39.6},{31.4,40.6},{31.6,26.4},{31.6,39.4},{31.6,40.8},{31.6,47.6},{31.8,32.2},{31.8,40.4},{32,32.6},{32,42.2},{32,47.4},{32.2,27.4},{32.2,27.8},{32.4,28.6},{32.4,31},{32.4,42.8},{32.6,31},{32.6,43},{32.8,28.2},{33.2,30},{33.4,27},{33.4,28.8},{33.6,28.8},{34.4,27.2},{34.4,27.6},{34.6,27.4},{34.6,27.6},{35.8,28.8},{36.4,24.6},{36.4,26.4},{36.4,26.6},{36.6,25.8},{36.6,26.6},{36.8,24.2},{36.8,25.4}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[31265] = {'Savage Proto-Drake',12600,12600,80,80,0,{[210] = {{52.8,52},{53,52.6},{53.2,53.6},{53.8,52.6},{54,52.4},{54.8,51.4},{55,51.8},{55.4,52.8},{55.8,51},{56,57.4},{56,57.8},{56.4,52.4},{56.4,52.6},{56.6,52.2},{56.6,52.8},{56.8,55},{56.8,57.4},{57.4,55.8},{57.6,56.8},{57.8,56},{58,55},{58.2,54.4},{59,56.2},{59,56.6},{59,62.4},{59.4,62.8},{59.6,62.8},{59.8,55.2},{59.8,62.4},{60.2,64}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[31747] = {'Necrotic Webspinner',12600,12600,79,80,0,{[210] = {{44.4,66.8},{45,67.2},{45.2,67.8},{46,67.4},{46,68},{48.2,65.2},{48.4,64},{48.6,66},{49,64.8},{49.2,64},{51,75.6},{51.2,75.2},{51.6,75.4},{51.6,76},{52.8,76.2},{53.2,77.4},{53.4,74},{53.4,75.4},{53.4,77.6},{53.6,75},{53.6,75.6},{53.6,77.8},{54,77},{54.4,80},{54.6,79.4},{54.6,79.8},{54.8,81.4},{55,81.6},{55.2,82.6}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[32484] = {'Bone Spider',12600,12600,80,80,0,{[210] = {{30,28.4},{30.4,29.4},{30.4,29.8},{30.6,28.4},{31,30.8},{31.2,29},{31.4,29.6},{31.6,28.4},{31.6,29.4},{31.8,29.8}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[35060] = {'North Sea Thresher',12600,12600,79,80,0,{[210] = {{65.8,8.6},{66.4,7.4},{66.4,8},{66.4,9.8},{66.8,7.4},{66.8,7.6},{66.8,9},{67.2,6.4},{67.6,8.4},{72,6.2},{73,9.4},{73.4,9.8},{74,7.8},{74,10.4},{74.2,9},{74.2,10.6},{74.6,8.4},{74.6,9.4},{74.6,9.6}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[35061] = {'North Sea Blue Shark',12600,12600,79,80,0,{[210] = {{66,9},{66.4,7.4},{66.4,8},{66.4,10},{66.8,7.4},{66.8,7.6},{66.8,9},{67.6,8.4},{68.8,5.6},{72,6.2},{73,9.6},{73.2,10.6},{73.4,9.2},{74.2,9},{74.2,10.4},{74.2,10.6},{74.6,9.6},{74.8,9.2}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[35071] = {'North Sea Mako',12600,12600,79,80,0,{[210] = {{65.8,8.6},{66.4,8},{66.8,7.4},{66.8,7.6},{66.8,9},{67,9.6},{67.6,8.4},{68.8,5.6},{72,5.6},{73.4,9.8},{73.8,7.8},{74,10.6},{74.2,9},{74.2,10.4},{74.6,9.6},{74.8,9.4}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[35470] = {'Icehowl',12600,12600,80,80,0,{[210] = {{72.4,25},{72.6,25}}},nil,210,nil,nil,16,nil,"",0},
|
||||
[35482] = {'Hungry Jormungar',12600,12600,83,83,0,{[210] = {{70.4,23.8},{23.8}}},nil,210,nil,nil,16,nil,"",0},
|
||||
|
||||
-- Quest 50205 Storm Peaks Trophy: Rare NPCs in The Storm Peaks (zone 67)
|
||||
[35189] = {'Skoll',12600,12600,80,80,0,{[67] = {{27.8,47.6},{27.8,50.8},{28,50.4},{30,64.6},{30.2,64.4},{46.2,64.4},{46.2,65.6},{46.4,64.8},{46.6,64.2},{48,63}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[32491] = {'Time-Lost Proto-Drake',12600,12600,80,80,0,{[67] = {{31.4,69.8},{32,65.6},{35,76.6},{36,76},{36.8,74.4},{37,71.4},{38.2,60.8},{41.2,61.4},{43.8,30.6},{45,59},{49.6,30.2},{50.8,71.2},{52.2,33.4},{52.2,34.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[32630] = {'Vyragosa',12600,12600,80,80,0,{[67] = {{26.2,42.2},{26.2,43.4},{26.2,74.2},{26.4,58.4},{26.8,44.2},{27,42},{27.2,55},{27.2,63.8},{27.2,70.6},{27.4,44.8},{27.4,67.6},{27.8,38.6},{27.8,62.2},{28,64.2},{28.4,51.2},{28.4,69},{29,50.6},{29,66},{29,67.2},{29.6,65.8},{29.8,38},{30.2,68},{31,69.4},{31.4,65.8},{31.6,64.4},{31.6,66},{31.6,69.4},{33.2,36.6},{33.4,35.4},{33.8,64.8},{33.8,66},{34.6,66.4},{35,65.2},{35.2,66.6},{35.6,74},{35.8,77.8},{36,64.2},{36,65},{36.4,62.6},{36.4,68.4},{36.4,76},{36.6,73},{36.8,62.8},{36.8,69},{36.8,74.8},{37,69.6},{37,72},{37,74.2},{38.2,61.2},{38.2,74},{38.4,75.2},{38.8,61.4},{39,59.4},{39.2,73},{40,65.2},{40.2,29.6},{40.4,63.4},{40.4,71.8},{40.8,55.2},{40.8,70.8},{40.8,84},{41.2,30.6},{41.2,60},{41.8,60.4},{42.8,30.6},{43.6,30.4},{43.8,30.6},{44.6,58.6},{45.6,82.4},{46,62},{46.2,30},{46.4,31.4},{46.6,62.6},{46.8,31.4},{47.4,63.8},{47.4,65.2},{47.6,64.6},{47.8,30.6},{48.4,67.8},{48.6,66.4},{48.8,67},{49,29.6},{49,67.6},{49,74.8},{49.2,31},{49.2,46.8},{49.6,30.4},{50,69},{50.2,69.8},{51,71},{51.8,34},{52,32.2},{52,33.2},{52.2,34.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[32500] = {'Dirkee',12600,12600,80,80,0,{[67] = {{37.4,58.4},{37.4,58.6},{37.4,60.4},{37.6,57},{37.6,58.2},{37.6,59.2},{37.8,59.8},{40.4,39.6},{41.2,39.8},{41.2,51.4},{41.2,52},{41.4,41},{41.6,40.6},{41.8,40.2},{42.6,38.2},{67.2,47.6},{68,47.4},{68.2,47.8}}},nil,67,nil,nil,16,nil,"",0},
|
||||
|
||||
-- Quest 50066 Stormforged Scales: Dragonkin NPCs in The Storm Peaks (zone 67)
|
||||
[29753] = {'Stormpeak Wyrm',12600,12600,80,80,0,{[67] = {{43.4,64.2},{43.8,64.6},{44,61.4},{44,64.4},{44.6,61},{45,58},{45.8,62.4},{45.8,62.6},{46.2,67.4},{46.2,67.6},{47,55},{47.4,57.4},{48.8,55.2},{49,60},{49.2,62.2},{50.8,71.2},{51.8,74.4},{52,74.6},{53,73.4}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29755] = {'Stormpeak Hatchling',12600,12600,80,80,0,{[67] = {{45.2,66.4},{45.2,66.8},{45.6,67.2},{52,73.6},{52.2,72.4},{52.4,73.2},{52.4,75.2},{52.6,73.4},{52.6,73.6},{52.6,75.2}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[29460] = {'Frigid Proto-Drake',12600,12600,80,80,0,{[67] = {{53.6,66},{54.4,65.4},{54.8,65.2},{55.2,67},{55.2,67.6},{55.6,65.8},{56,64.2},{56,64.6},{56.8,64.4},{57,64.6},{57,65.6},{57.2,63.2},{57.8,63.8},{58.2,61.6},{58.4,63},{58.6,62.6},{58.8,62.2},{59.6,57.6},{59.6,58.6},{59.8,61.6},{60.2,60.8},{60.6,60.4},{60.8,60.8},{63.4,62.4},{64,61.8},{64.6,60.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30275] = {'Wild Wyrm',12600,12600,80,80,0,{[67] = {{51.2,64.4},{53.2,66.6},{54,64.4},{54.2,66.6},{54.6,66.6},{55,65.8},{55.4,65.2},{56,64.6},{56,66.6},{56.2,66.4},{56.4,64.2},{56.6,63},{56.6,65.2},{56.6,65.6},{56.6,66.6},{57,64.4},{57.4,59.8},{58,63},{58.2,64},{58.4,57.8},{58.4,61.6},{59,57.6},{59,59.6},{59,61.8},{59.6,61.8},{59.8,61.4},{60,58},{60,60.4},{60.4,59.4},{60.6,58.4},{61,61},{61.4,58.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
[30461] = {'Veranus',12600,12600,80,80,0,{[67] = {{38.8,65.4},{38.8,65.6}}},nil,67,nil,nil,16,nil,"",0},
|
||||
-- Quest 50094 Wild Basin: Sholazar Basin (zone 3711) beasts
|
||||
-- All hostile beasts scraped from Sholazar Basin filter page
|
||||
[32485] = {'King Krush',12600,12600,75,75,0,{[3711] = {{26.0,73.0},{28.0,45.0},{30.0,38.0},{32.0,36.0},{37.0,28.0},{47.0,42.0},{50.0,43.0},{51.0,82.0},{52.0,85.0},{55.0,83.0},{57.0,80.0},{59.0,83.0},{64.0,79.0},{65.0,82.0},{67.0,78.0}}},nil,3711,nil,nil,39,nil,"",0},
|
||||
[28009] = {'Shardhorn Rhino',12600,12600,75,76,0,{[3711] = {{22.0,51.0},{24.0,47.0},{26.0,46.0},{28.0,41.0},{30.0,39.0},{32.0,37.0},{35.0,43.0},{37.0,43.0},{40.0,43.0},{42.0,47.0},{44.0,50.0},{47.0,54.0},{49.0,59.0},{52.0,45.0}}},nil,3711,nil,nil,43,nil,"",0},
|
||||
[32481] = {'Aotona',12600,12600,75,75,0,{[3711] = {{40.0,59.0},{42.0,67.0},{43.0,52.0},{45.0,68.0},{47.0,55.0},{51.0,72.0},{54.0,51.0},{57.0,65.0}}},nil,3711,nil,nil,2,nil,"",0},
|
||||
[28097] = {'Pitch',12600,12600,76,76,0,{[3711] = {{50.0,76.0},{50.0,77.0},{51.0,76.0},{51.0,77.0}}},nil,3711,nil,nil,1,nil,"",0},
|
||||
[28083] = {'Serfex the Reaver',12600,12600,78,78,0,{[3711] = {{50.0,85.0},{51.0,86.0},{52.0,86.0},{58.0,83.0},{59.0,85.0}}},nil,3711,nil,nil,6,nil,"",0},
|
||||
[28001] = {'Dreadsaber',12600,12600,75,76,0,{[3711] = {{22.0,50.0},{24.0,47.0},{26.0,43.0},{28.0,41.0},{30.0,37.0},{32.0,37.0},{35.0,41.0},{37.0,41.0},{40.0,42.0},{42.0,50.0},{45.0,53.0},{47.0,48.0},{50.0,50.0}}},nil,3711,nil,nil,1,nil,"",0},
|
||||
[28213] = {'Hardknuckle Matriarch',12600,12600,77,77,0,{[3711] = {{65.0,75.0},{66.0,73.0},{66.0,74.0},{67.0,72.0},{67.0,73.0},{68.0,72.0}}},nil,3711,nil,nil,2,nil,"",0},
|
||||
[28297] = {'Shango',12600,12600,76,76,0,{[3711] = {{31.0,37.0},{32.0,35.0},{33.0,32.0},{34.0,31.0},{35.0,31.0}}},nil,3711,nil,nil,1,nil,"",0},
|
||||
[28358] = {'Venomtip',12600,12600,77,77,0,{[3711] = {{53.0,50.0},{56.0,50.0},{57.0,51.0},{58.0,52.0},{59.0,53.0},{60.0,55.0}}},nil,3711,nil,nil,20,nil,"",0},
|
||||
[28317] = {'Bushwhacker',12600,12600,76,76,0,{[3711] = {{46.0,63.0},{46.0,64.0},{47.0,63.0},{47.0,64.0}}},nil,3711,nil,nil,8,nil,"",0},
|
||||
[28096] = {'Hardknuckle Charger',12600,12600,76,77,0,{[3711] = {{55.0,69.0},{57.0,66.0},{58.0,64.0},{60.0,67.0},{62.0,67.0},{64.0,70.0},{66.0,70.0},{68.0,70.0},{70.0,69.0},{72.0,70.0},{74.0,69.0}}},nil,3711,nil,nil,2,nil,"",0},
|
||||
[28325] = {'Ravenous Mangal Crocolisk',12600,12600,76,80,0,{[3711] = {{54.0,64.0},{54.0,65.0},{55.0,63.0},{56.0,65.0},{57.0,62.0}}},nil,3711,nil,nil,6,nil,"",0},
|
||||
[28288] = {'Farunn',12600,12600,76,76,0,{[3711] = {{42.0,38.0},{46.0,41.0},{47.0,41.0},{48.0,43.0},{49.0,44.0}}},nil,3711,nil,nil,6,nil,"",0},
|
||||
[28399] = {'Zeptek the Destroyer',12600,12600,77,77,0,{[3711] = {{41.0,19.0},{41.0,20.0},{42.0,20.0}}},nil,3711,nil,nil,42,nil,"",0},
|
||||
[29044] = {'Goretalon Matriarch',12600,12600,78,78,0,{[3711] = {{57.0,23.0},{59.0,23.0},{60.0,22.0},{60.0,23.0}}},nil,3711,nil,nil,2,nil,"",0},
|
||||
[28086] = {'Sapphire Hive Wasp',12600,12600,76,77,0,{[3711] = {{43.0,78.0},{50.0,80.0},{51.0,83.0},{54.0,84.0},{56.0,80.0},{58.0,79.0},{60.0,75.0},{62.0,76.0}}},nil,3711,nil,nil,44,nil,"",0},
|
||||
[28011] = {'Emperor Cobra',12600,12600,75,76,0,{[3711] = {{36.0,58.0},{40.0,52.0},{42.0,51.0},{45.0,51.0},{47.0,58.0},{50.0,48.0},{52.0,48.0},{55.0,48.0},{57.0,52.0},{59.0,56.0}}},nil,3711,nil,nil,35,nil,"",0},
|
||||
[28085] = {'Sapphire Hive Drone',12600,12600,76,77,0,{[3711] = {{43.0,77.0},{48.0,79.0},{51.0,78.0},{54.0,75.0},{57.0,74.0},{60.0,70.0},{63.0,73.0},{65.0,76.0}}},nil,3711,nil,nil,44,nil,"",0},
|
||||
[28380] = {'Shattertusk Bull',12600,12600,76,77,0,{[3711] = {{35.0,31.0},{37.0,27.0},{40.0,29.0},{43.0,29.0},{49.0,43.0},{52.0,41.0},{54.0,30.0},{57.0,35.0},{60.0,33.0},{62.0,33.0}}},nil,3711,nil,nil,21,nil,"",0},
|
||||
[28847] = {'Siltslither Eel',12600,12600,1,77,0,{[3711] = {{47.0,62.0},{48.0,62.0},{48.0,64.0},{49.0,63.0}}},nil,3711,nil,nil,35,nil,"",0},
|
||||
[29033] = {'Spirit of Atha',12600,12600,79,80,0,{[3711] = {{35.0,41.0},{37.0,35.0},{38.0,36.0},{40.0,42.0},{42.0,39.0},{44.0,42.0}}},nil,3711,nil,nil,46,nil,"",0},
|
||||
[28010] = {'Stranded Thresher',12600,12600,75,76,0,{[3711] = {{46.0,62.0},{48.0,60.0},{50.0,62.0},{72.0,65.0},{73.0,64.0}}},nil,3711,nil,nil,35,nil,"",0},
|
||||
[28002] = {'Mangal Crocolisk',12600,12600,75,76,0,{[3711] = {{20.0,59.0},{22.0,58.0},{25.0,58.0},{30.0,59.0},{35.0,58.0},{40.0,53.0},{45.0,55.0},{50.0,50.0},{53.0,68.0}}},nil,3711,nil,nil,6,nil,"",0},
|
||||
[29034] = {'Spirit of Koosu',12600,12600,78,80,0,{[3711] = {{44.0,74.0},{48.0,68.0},{50.0,69.0},{56.0,85.0},{58.0,84.0},{60.0,85.0}}},nil,3711,nil,nil,46,nil,"",0},
|
||||
[28129] = {'Longneck Grazer',12600,12600,75,76,0,{[3711] = {{21.0,61.0},{24.0,62.0},{27.0,63.0},{30.0,64.0},{33.0,64.0},{36.0,80.0},{40.0,86.0},{44.0,86.0},{48.0,86.0}}},nil,3711,nil,nil,21,nil,"",0},
|
||||
[28004] = {'Goretalon Roc',12600,12600,75,76,0,{[3711] = {{54.0,23.0},{55.0,24.0},{56.0,23.0},{57.0,25.0},{58.0,26.0},{59.0,26.0},{60.0,27.0},{61.0,29.0}}},nil,3711,nil,nil,2,nil,"",0},
|
||||
[28087] = {'Sapphire Hive Queen',12600,12600,78,78,0,{[3711] = {{57.0,79.0},{57.0,80.0},{58.0,80.0}}},nil,3711,nil,nil,44,nil,"",0},
|
||||
[29018] = {'Spirit of Ha-Khalan',12600,12600,78,80,0,{[3711] = {{46.0,61.0},{48.0,60.0},{50.0,61.0},{51.0,63.0}}},nil,3711,nil,nil,46,nil,"",0},
|
||||
[28003] = {'Bittertide Hydra',12600,12600,75,76,0,{[3711] = {{32.0,38.0},{35.0,36.0},{38.0,37.0},{41.0,37.0},{43.0,40.0},{45.0,43.0},{48.0,43.0}}},nil,3711,nil,nil,38,nil,"",0},
|
||||
-- Requested WotLK Rare Spawns
|
||||
[32422] = {'Grocklar',12600,12600,73,74,4,{[394] = {{9.6,39.0},{10.4,39.8},{10.6,40.6},{11.2,42.2},{11.2,70.6},{11.4,42.6},{11.4,54.0},{11.6,42.8},{12.0,57.0},{12.0,70.8},{12.2,44.4},{12.2,54.8},{12.4,49.8},{12.4,53.0},{12.4,54.4},{12.6,53.6},{12.8,45.6},{12.8,50.0},{12.8,70.8},{13.0,54.6},{13.0,70.4},{13.2,48.4},{13.2,49.0},{13.2,51.4},{13.6,48.2},{14.0,52.4},{14.0,54.8},{14.2,53.0},{14.2,53.6},{14.2,69.4},{14.4,70.2},{14.6,50.0},{14.6,50.6},{14.6,51.6},{15.4,69.8},{15.8,69.8},{16.6,70.2},{17.4,70.6},{17.8,69.2},{18.4,72.2},{18.6,68.8},{18.6,72.4},{19.8,72.2},{20.2,56.0},{21.0,60.8},{21.2,71.8},{21.4,57.2},{21.4,71.4},{21.6,57.6},{21.6,67.8},{21.8,56.8},{21.8,71.2},{22.0,72.0},{22.8,72.4},{23.0,57.4},{23.2,58.2},{23.8,56.2},{24.2,57.2},{24.4,54.8},{24.8,58.6},{24.8,61.6},{25.0,55.0},{25.0,56.4},{25.0,59.6},{25.2,56.8},{25.8,55.2}}},nil,394,nil,nil,35,nil,"",0},
|
||||
[32429] = {'Seething Hate',12600,12600,73,73,4,{[394] = {{26.6,44.2},{28.0,45.4},{28.2,45.6},{28.8,46.4},{34.2,49.2},{34.2,49.6},{34.4,48.4},{34.6,48.8},{34.8,48.2},{38.4,49.0},{38.6,49.6},{38.8,49.2},{39.6,51.0},{40.2,49.2},{40.2,49.6}}},nil,394,nil,nil,35,nil,"",0},
|
||||
[32438] = {'Syreian the Bonecarver',12600,12600,73,73,4,{[394] = {{61.2,35.0},{61.2,35.8},{61.6,35.6},{63.0,36.8},{64.2,35.8},{64.8,29.6},{65.2,31.2},{65.4,35.8},{65.6,29.6},{65.6,33.2},{65.6,35.8},{65.6,37.8},{65.8,34.2},{66.0,29.2},{66.2,40.8},{66.4,40.0},{66.6,41.4},{66.6,42.6},{66.8,36.8},{66.8,38.4},{66.8,41.6},{67.0,28.2},{67.6,27.0},{68.6,31.6},{68.8,30.4},{68.8,31.4},{69.0,32.8},{69.2,27.2},{69.4,28.8},{70.4,33.4},{70.4,33.8},{70.6,33.6},{71.4,35.0},{71.6,34.8},{72.4,36.6},{73.0,36.0},{73.4,37.6},{74.2,43.0},{74.4,35.8},{74.4,38.2},{74.6,39.0},{75.0,38.0},{75.0,41.6},{75.6,38.2},{75.8,41.0}}},nil,394,nil,nil,35,nil,"",0},
|
||||
[38453] = {'Arcturis',12600,12600,74,74,4,{[394] = {{30.4,55.0},{31.0,55.4},{31.0,55.8},{32.8,55.2}}},nil,394,nil,nil,35,nil,"",0},
|
||||
-- Quest 50203 Zul'Drak Trophy: Rare NPCs in Zul'Drak (zone 66)
|
||||
[33776] = {'Gondria',12600,12600,77,77,4,{[66] = {{61.4,61.4},{61.4,62.4},{61.4,63},{62,63.2},{63,43.2},{63,43.6},{63.2,42.4},{63.6,42.8},{63.6,43.6},{66.8,77.8},{67.2,77.2},{67.6,79.2},{67.8,78.2},{68,77.4},{69.2,48},{69.6,48},{69.8,48.8},{77,70.4},{77.2,70.6},{77.6,70},{78.2,71.2}}},nil,66,nil,nil,35,nil,"",0},
|
||||
[32471] = {'Griegen',12600,12600,75,75,4,{[66] = {{13.2,56.2},{13.4,54.8},{14.4,56},{14.4,56.8},{14.6,55.4},{14.6,56.2},{17.2,71},{17.2,71.8},{18,70.8},{20.6,71.2},{21,78.8},{21.2,79.6},{21.6,70.2},{22.4,60.8},{22.8,61.2},{22.8,62},{24.4,62},{25,75.4},{25.2,77.2},{26.2,71},{26.4,53.8},{26.4,55.2},{26.4,70.2},{26.6,55.6},{26.6,56.6},{26.6,70.2},{26.6,71.2},{26.8,54.4},{27,54.8}}},nil,66,nil,nil,16,nil,"",0},
|
||||
[32475] = {'Terror Spinner',12600,12600,76,76,4,{[66] = {{52.4,31.6},{52.6,32.6},{53,32},{53.4,31.2},{60.6,37},{61.4,35.4},{61.4,36},{61.6,33.8},{61.6,35.8},{62.2,33.2},{70.8,28.8},{71.2,23},{71.2,24.2},{71.4,27.4},{71.6,23},{71.8,24},{71.8,25},{71.8,29.8},{72.4,27.6},{73.4,68.4},{73.6,66},{74.4,67.4},{74.8,66.4},{75.2,67},{76.4,42.8},{76.4,43.8},{76.6,68.8},{77.2,42.6},{81.4,34.2},{81.4,35},{81.6,34.6}}, [67] = {{72,75}}},nil,66,nil,nil,16,nil,"",0},
|
||||
[32447] = {'Zul\'drak Sentinel',12600,12600,76,76,4,{[66]={{21.2,87.2},{22.2,82.4},{22.2,83},{22.4,83.6},{22.8,83},{23,82.2},{23.6,82.4},{24.2,87},{24.4,83},{25.2,82.8},{25.6,83.4},{26.4,82.2},{27,82.6},{28,82.6},{28.4,82.2},{28.6,73.8},{28.8,72.4},{28.8,82.8},{29,75},{29,77.6},{29,81.2},{29,81.8},{29.2,75.8},{29.4,79.2},{29.4,79.8},{29.6,82.4},{39.6,67.4},{40,51.8},{40,59.8},{40.4,53},{40.4,54.4},{40.4,55},{40.4,56.2},{40.4,56.6},{40.4,58},{40.4,59.4},{40.4,61},{40.4,61.6},{40.4,62.6},{40.8,52.6},{41.4,55.4},{41.4,69.8},{41.8,56},{42.2,70},{42.8,71},{43.2,54.6},{43.2,71.8},{43.6,72.6},{44.2,54.4},{44.2,55.2},{44.4,73.8},{44.6,67.6},{45,67},{45,74.4},{45.2,59.4},{45.2,74.8},{45.6,59.2},{45.6,59.6},{45.8,75.8},{46,60.6},{46,61.6},{46,64.4},{46,66},{46,66.6},{46.4,65.2},{46.4,77.2},{46.6,77.2},{46.8,61},{46.8,64.4},{46.8,65.8},{46.8,78},{47.2,79},{47.4,63.2},{48,79.6},{48.4,79.4},{49,81.2},{50.6,83},{50.8,84}}},nil,66,nil,nil,16,nil,"",0},
|
||||
-- Quest 50153 Morogh Trophy: Rare NPCs in Dun Morogh (zone 1)
|
||||
[1132] = {'Timber',12600,12600,10,10,4,{[1] = {{30.6,44.2},{31.8,38.0},{34.6,41.2},{37.2,40.2}}},nil,1,nil,nil,1,nil,"",0},
|
||||
[1130] = {'Bjarn',12600,12600,12,12,4,{[1] = {{50.8,59.4},{55.4,55.4},{59.6,60.6},{65.0,59.6}}},nil,1,nil,nil,1,nil,"",0},
|
||||
[8503] = {'Gibblewilt',12600,12600,10,10,4,{[1] = {{24.0,43.4},{25.0,44.6},{26.4,36.6},{28.6,35.6}}},nil,1,nil,nil,1,nil,"",0},
|
||||
[1260] = {'Great Father Arctikus',12600,12600,10,10,4,{[1] = {{21.0,51.0},{23.0,52.4},{25.4,49.4},{29.6,48.4}}},nil,1,nil,nil,1,nil,"",0},
|
||||
[1137] = {'Edan the Howler',12600,12600,10,10,4,{[1] = {{38.4,48.2},{40.8,45.4},{42.2,49.4},{43.6,49.6}}},nil,1,nil,nil,1,nil,"",0},
|
||||
[1119] = {'Hammerspine',12600,12600,12,12,4,{[1] = {{71.4,51.4},{71.6,50.2},{72.2,53.6},{73.0,51.8}}},nil,1,nil,nil,1,nil,"",0},
|
||||
-- Quest 50164 Tirisfal Trophy: Rare NPCs in Tirisfal Glades (zone 85)
|
||||
[10357] = {'Ressan the Needler',12600,12600,11,11,4,{[85] = {{42,68.2},{42.2,69},{42.4,67.2},{42.6,68.8},{43,66.4},{43,67.8},{43.2,64.4},{43.4,67},{43.6,66.2},{43.6,67},{44,65},{44.2,68.2},{45,66.8},{45.4,64.4},{45.4,65.6},{45.8,62.6},{45.8,65.4},{45.8,66.8},{46.2,64.4},{46.4,65.8},{46.6,65.4},{46.6,66},{46.8,64.2},{48.4,65.6},{49.2,63.2},{49.2,65.2},{49.4,62.2},{49.4,64.4},{49.4,65.8},{49.4,66.6},{49.6,63.4},{49.6,64.6},{49.8,65.6},{49.8,66.6},{50.2,64.4},{51,66.2},{51.2,63.8},{51.4,62.2},{51.4,63.4},{51.4,65.2},{51.8,62.2},{51.8,66.2},{52.2,60},{52.2,63},{52.2,65},{52.4,61.2},{52.4,63.8},{52.6,62.2},{52.6,63.2},{52.6,63.8},{52.8,64.6},{53.4,67},{54.4,75.2},{54.8,67.4},{55.2,59.4},{55.2,59.8},{55.4,61},{55.4,61.8},{55.4,62.6},{55.6,59.4},{55.6,60},{55.6,61.8},{55.8,62.6},{56,61},{56.2,63.6},{56.6,60.2},{56.6,61.6},{56.8,61},{57,56.4},{57,59},{57.4,63},{58.2,62}}},nil,85,nil,nil,16,nil,"",0},
|
||||
[10359] = {'Sr\'iskulk',12600,12600,10,10,4,{[85] = {{79.6,47},{81.8,51.6},{82.2,54.2},{83,54.4},{83,55.8},{83.4,53.2},{83.4,54.8},{83.6,54.6},{83.8,53},{83.8,54.4},{83.8,56},{84,48.2},{84.2,50},{84.4,49.2},{84.4,50.6},{84.4,52.2},{84.6,50.2},{85,55.4},{85.2,48.2},{85.2,49.4},{85.2,50.8},{85.6,50.4},{88,50},{88.2,50.6},{88.4,51.8},{88.4,52.6},{88.4,53.8},{88.6,50.4},{88.8,48.6},{88.8,51},{88.8,53.6},{89,45.4},{89,52.6},{89.2,47.6},{89.2,51.6},{89.4,40.2},{89.4,41.4},{89.4,42},{89.4,46},{89.4,47.4},{89.6,41.2},{89.6,41.6},{89.6,43.4},{89.6,46},{89.6,47},{89.8,49.6},{90,53.6},{90.2,47.6},{90.6,44}}},nil,85,nil,nil,16,nil,"",0},
|
||||
[10356] = {'Bayne',12600,12600,10,10,4,{[85] = {{38,44.6},{39.2,41.2},{39.4,42},{39.4,42.6},{39.4,44},{40,40.4},{40,41.4},{40.2,43},{40.2,49.4},{40.2,53.4},{40.2,54.8},{40.4,42.4},{40.4,43.6},{40.6,42},{40.6,43},{40.8,41.4},{41,51},{41,54.6},{41.4,43.8},{41.4,52},{41.4,52.8},{41.4,53.8},{41.6,41.2},{41.6,53.6},{41.6,55},{41.8,42.4},{42,51.4},{42,52.6},{42.2,52.4},{42.6,53.8},{42.8,51.6},{42.8,55},{43,51.4},{43,52.6},{43.8,54.6},{44.2,52.8},{44.2,54},{44.8,50},{45,54},{45.2,51},{45.4,52},{45.4,52.8},{45.8,52.8},{46,51.4},{46.2,50},{46.2,51.6},{46.6,51.4},{46.6,52.4},{46.6,55},{46.6,56.2},{46.8,53.2},{46.8,54.4},{47,50.2},{47.6,51.8},{47.6,53.2},{48.4,49.2},{48.4,51.4},{49,50.8},{49,52.4},{49.4,50.2},{49.6,47.2},{49.8,49},{50,50.2},{50,50.8},{50.2,52.8},{50.4,52.4},{50.6,51},{51.2,50.4},{51.4,48.2},{51.4,48.8},{51.4,52.2},{52.6,53.4},{55.4,40.8},{55.6,39.4},{56.2,41.6},{56.4,40.4},{56.4,40.8},{56.6,41.6},{57,38.4},{57,39.8},{57.2,39.4},{57.2,41.2},{57.2,42.8},{57.6,41.2},{57.6,42},{58,39},{58.2,39.6},{58.6,39.8},{59,38.8},{59.2,47}}},nil,85,nil,nil,16,nil,"",0},
|
||||
[1936] = {'Farmer Solliden',12600,12600,10,10,4,{[85] = {{34.2,50.2},{34.4,51.4},{34.4,52.2},{34.6,51.4},{34.6,52.2},{34.8,52.6},{35,50.4},{35.6,52},{36.4,49.4},{36.4,50},{36.8,49.6},{36.8,50.8},{37,53},{37.2,48.4},{37.2,52},{37.4,49},{37.6,49},{37.8,52.8},{38,51.4},{38,51.8},{38,53.6},{38.2,50},{38.6,50.8},{38.6,52},{38.8,49.4},{39,52.6},{39.8,54.4},{40,51.6}}},nil,85,nil,nil,16,nil,"",0},
|
||||
[1531] = {'Lost Soul',12600,12600,10,10,4,{[85] = {{44.4,37.4},{44.4,37.6},{44.6,37.6},{44.8,37.2},{45,40.4},{45.8,43},{46,36.8},{46.4,40.4},{47,39.4},{47,40},{47.2,40.6},{47.4,35.4},{48,35},{48.4,36},{48.6,35.4},{48.6,36.2},{49,37.6},{49.4,37.4},{52.4,49},{53,45.2},{53.2,46.2},{53.2,46.6},{53.2,48.4},{53.2,48.6},{53.2,49.6},{53.6,45.4},{53.6,46.4},{53.6,46.6},{53.6,48.2},{53.6,49.2}}},nil,85,nil,nil,16,nil,"",0},
|
||||
[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},
|
||||
-- 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},
|
||||
|
||||
-- Quest 50196 Netherstorm Trophy: Rare NPCs in Netherstorm (zone 3523)
|
||||
[20932] = {'Nuramoc',13972,13972,70,70,4,{[3523] = {{22.6,80},{22.8,78.8},{24,79.2},{24,81.8},{24.6,79.6},{25.8,81.2},{26.6,82.4},{26.6,83.6},{28.6,80.4},{29.4,82.6},{29.8,82.4},{30,80.8},{30.4,79.6},{31.2,78.4},{31.8,79.2},{32,81.8},{32.8,28.8},{33.4,28.2},{33.4,31.4},{33.4,32.4},{33.6,25.4},{33.6,25.6},{34,27.6},{34.2,20.8},{34.4,22.2},{34.4,27.2},{34.4,29},{34.4,78},{34.6,27.8},{34.6,28.8},{34.6,33.4},{34.6,78.6},{34.8,30.8},{34.8,78.4},{35,26.2},{35,29.6},{35.2,34.2},{35.4,23.4},{35.4,23.8},{35.4,25.2},{35.4,31.8},{35.6,32.2},{35.8,20.4},{35.8,24.6},{36,21.2},{36,21.6},{36,23.8},{36.2,34.8},{36.4,22.8},{36.6,78.6},{37.8,78.6},{40.2,76.4},{42.2,76},{42.6,75.6},{43.8,69.4},{43.8,69.6},{43.8,71.8},{43.8,74.4},{43.8,78},{44,70.6},{44.8,72.6},{45.4,70.8},{45.4,72.2},{45.8,73.2},{46,71.2},{52.6,59.6},{53,59},{53.2,55.6},{54.2,57.6},{54.6,60},{55,61.2},{55.6,61},{56,58.6},{56,59.8},{56.6,59.2},{57.4,57.4},{58.4,60},{58.4,60.6},{58.6,59.6},{59.8,58.2},{60,60.6},{61,58.6},{61.4,60},{61.6,58.6},{61.6,59.6},{62.2,61},{62.6,58.4},{63.2,60.6},{63.4,59.6},{63.6,59.6},{64,61.6},{64.2,58.8},{64.8,59},{65.2,58.2},{65.4,62.4},{65.6,58.2},{66,62.2},{66.4,58.6},{66.6,62.4},{66.8,59.2},{67,60},{67.6,60.8},{67.6,61.6}}},nil,3523,nil,nil,16,nil,"",0},
|
||||
[18698] = {'Ever-Core the Punisher',12600,12600,68,69,4,{[3523] = {{19.8,69.4},{19.8,70},{20,67.4},{20.4,68},{20.4,73.4},{20.6,70},{21,75.2},{21.2,66},{21.2,76},{21.6,65.4},{21.6,77},{23.2,64.8},{23.2,75},{23.2,76.2},{23.4,39.2},{23.6,38.4},{24,37.2},{24,40.2},{24,41.4},{24.4,41.6},{24.4,64.6},{24.4,75.8},{24.8,65.4},{25.2,42.2},{25.2,42.6},{25.8,42.2},{26,65.4},{26.2,72.4},{26.2,73.2},{26.4,42.8},{26.6,72.8},{27,42.6},{27,69.4},{27.2,42},{27.2,70},{27.4,66.8},{27.6,67.4},{27.8,41.8},{28,72.4},{28.2,65.2},{28.4,41},{28.4,71.2},{28.8,44.2},{28.8,44.8},{29.2,43},{29.4,40.2},{29.4,40.8},{29.6,39.4},{29.6,39.8},{29.6,40.8},{29.6,43.8},{30,42.8},{30.4,42},{30.6,42},{30.8,42.6},{31,41},{57.4,41.6},{57.6,38.8},{57.6,43.2},{57.6,44},{58,38.4},{58.8,45.2},{59.4,34},{59.6,34.4},{59.6,45.6},{59.8,34.8},{60,33},{60.6,32.6},{61.4,46.8},{61.6,32.2},{61.8,47.6},{62,47},{63.4,32},{64.2,32},{64.2,48.2},{64.6,32},{65,33},{65.6,33.8},{65.8,46.6},{66,46.2},{66.4,45.2},{66.6,33.8},{66.8,34.8},{66.8,35.8},{67,38},{67.4,38.6},{67.8,44.8},{68,40.4},{68,40.6},{68,41.6},{68.2,43.8},{68.4,43}}},nil,3523,nil,nil,16,nil,"",0},
|
||||
[18697] = {'Chief Engineer Lorthander',12600,12600,68,69,4,{[3523] = {{26,40.8},{26.4,40},{26.4,42.4},{26.4,42.6},{26.6,40.8},{26.8,36.2},{26.8,38.8},{26.8,41.8},{27,37},{27.4,38.4},{27.8,39.4},{46.2,80.6},{46.4,79.8},{46.4,82},{46.4,83.2},{46.6,82.2},{46.6,83.2},{46.8,80.2},{47.4,81},{47.4,84.6},{47.6,84.4},{48.2,81.6},{48.4,81.4},{48.4,82.6},{48.8,81.2},{49.2,82},{58.2,63},{58.2,64.6},{58.4,63.6},{58.6,63.8},{59,62.6},{59.2,62.4},{59.2,67},{59.6,67.4},{59.8,65.8},{60.4,63.2},{60.6,65.8},{61.2,63.4},{61.2,63.6},{61.4,65.2},{61.6,64.6}}},nil,3523,nil,nil,16,nil,"",0},
|
||||
[32398] = { "King Ping", nil, nil, 71, 71, 2, { [495] = { { 25.6, 69.2 }, { 26.0, 63.8 }, { 26.6, 63.2 }, { 30.4, 71.4 }, { 30.8, 56.4 }, { 30.8, 70.8 }, { 31.0, 71.6 }, { 31.2, 56.6 }, { 31.2, 57.6 }, { 31.6, 77.4 }, { 31.8, 75.4 }, { 32.2, 75.8 }, { 32.6, 78.8 }, { 33.0, 80.2 }, { 33.4, 80.6 }, { 33.6, 80.2 }, { 33.6, 81.0 } } }, nil, 495, nil, nil, 12 },
|
||||
[32377] = { "Perobas the Bloodthirster", nil, nil, 71, 71, 2, { [495] = { { 47.8, 5.8 }, { 50.0, 4.6 }, { 50.4, 4.4 }, { 50.6, 4.2 }, { 52.4, 10.8 }, { 53.0, 11.8 }, { 53.2, 12.6 }, { 53.8, 11.8 }, { 60.0, 19.8 }, { 60.6, 21.0 }, { 60.8, 22.0 }, { 61.0, 19.8 }, { 68.2, 17.8 }, { 68.4, 17.2 }, { 68.6, 16.8 }, { 69.4, 14.2 }, { 71.2, 13.2 }, { 71.2, 14.6 }, { 71.4, 14.0 }, { 71.6, 14.4 }, { 72.2, 13.4 } } }, nil, 495, nil, nil, 12 },
|
||||
[32386] = { "Vigdis the War Maiden", nil, nil, 71, 71, 2, { [495] = { { 68.4, 46.0 }, { 68.4, 58.4 }, { 68.6, 48.6 }, { 68.8, 47.8 }, { 68.8, 59.0 }, { 70.0, 50.4 }, { 70.0, 56.8 }, { 70.0, 57.6 }, { 70.4, 49.2 }, { 70.6, 50.2 }, { 71.0, 52.2 }, { 71.0, 56.8 }, { 71.2, 55.4 }, { 71.2, 55.6 }, { 71.6, 44.4 }, { 71.6, 45.6 }, { 71.8, 47.0 }, { 72.2, 42.8 }, { 72.2, 48.6 }, { 72.2, 52.6 }, { 72.4, 44.8 }, { 72.4, 50.6 }, { 72.6, 46.0 }, { 72.6, 52.4 }, { 72.6, 61.2 }, { 72.8, 39.2 }, { 72.8, 41.0 }, { 72.8, 44.4 }, { 72.8, 49.0 }, { 72.8, 51.4 }, { 72.8, 61.8 }, { 73.0, 40.2 }, { 73.0, 48.0 }, { 73.2, 44.6 }, { 73.2, 53.2 }, { 73.6, 45.4 }, { 73.8, 49.6 }, { 73.8, 61.4 }, { 74.0, 52.6 }, { 74.2, 45.8 }, { 74.2, 47.8 }, { 74.2, 59.2 }, { 74.4, 54.6 }, { 74.4, 60.2 }, { 74.6, 50.0 }, { 74.6, 51.4 }, { 74.6, 54.8 }, { 74.8, 45.2 }, { 74.8, 56.6 }, { 74.8, 58.4 }, { 75.0, 48.2 }, { 75.0, 52.6 }, { 75.6, 45.2 }, { 76.2, 42.8 } } }, nil, 495, nil, nil, 12 },
|
||||
}
|
||||
|
||||
-- Backward compatibility
|
||||
|
||||
@@ -302,7 +302,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Quest 50031: Stormbound
|
||||
-- Kill 30 Elementals in Storm Peaks
|
||||
[50031] = {
|
||||
[1] = "Stormbound", -- Quest name
|
||||
[1] = "Stormbound", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Required level (Min level)
|
||||
[5] = 73, -- Quest level
|
||||
@@ -392,7 +392,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Quest 50095: Peak Predators
|
||||
-- Kill 75 beasts in The Storm Peaks
|
||||
[50095] = {
|
||||
[1] = "Peak Predators", -- Quest name
|
||||
[1] = "Peak Predators", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Required level (Min level)
|
||||
[5] = 73, -- Quest level
|
||||
@@ -422,7 +422,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Quest 50096: Peak Predators
|
||||
-- Kill 75 beasts in Icecrown
|
||||
[50096] = {
|
||||
[1] = "Peak Predators", -- Quest name
|
||||
[1] = "Peak Predators", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 73, -- Required level (Min level)
|
||||
[5] = 77, -- Quest level
|
||||
@@ -469,10 +469,10 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Kill 1 rare in The Storm Peaks
|
||||
[50205] = {
|
||||
[1] = "Storm Peaks Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Min level
|
||||
[5] = 80, -- Quest level
|
||||
[17] = 67, -- Zone (The Storm Peaks)
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Min level
|
||||
[5] = 80, -- Quest level
|
||||
[17] = 67, -- Zone (The Storm Peaks)
|
||||
[8] = {
|
||||
"Kill a rare NPC in The Storm Peaks to complete this quest.",
|
||||
"Kill a rare in The Storm Peaks"
|
||||
@@ -499,10 +499,10 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Kill 30 dragonkin in The Storm Peaks
|
||||
[50066] = {
|
||||
[1] = "Stormforged Scales", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Min level
|
||||
[5] = 80, -- Quest level
|
||||
[17] = 67, -- Zone (The Storm Peaks)
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Min level
|
||||
[5] = 80, -- Quest level
|
||||
[17] = 67, -- Zone (The Storm Peaks)
|
||||
[8] = {
|
||||
"The dragons of the Storm Peaks must be dealt with before we can proceed with our plans. Destroy 30 dragonkin in the Storm Peaks to show the Storm Peaks dragons that they are not welcome here.",
|
||||
"Slain: 0/30"
|
||||
@@ -545,7 +545,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Requires completing any 6 quests in Dun Morogh
|
||||
-- Auto-complete, no turn-in location
|
||||
[50098] = {
|
||||
[1] = "Morogh Missions", -- Quest name
|
||||
[1] = "Morogh Missions", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 1, -- Min level
|
||||
[5] = 60, -- Quest level
|
||||
@@ -561,7 +561,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Requires completing any 6 quests in Azuremyst Isle
|
||||
-- Auto-complete, no turn-in location
|
||||
[50100] = {
|
||||
[1] = "Azuremyst Aid", -- Quest name
|
||||
[1] = "Azuremyst Aid", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 1, -- Min level
|
||||
[5] = 60, -- Quest level
|
||||
@@ -576,7 +576,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Quest 50094: Wild Basin
|
||||
-- Kill 75 beasts in Sholazar Basin
|
||||
[50094] = {
|
||||
[1] = "Wild Basin", -- Quest name
|
||||
[1] = "Wild Basin", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Required level (Min level)
|
||||
[5] = 73, -- Quest level
|
||||
@@ -606,7 +606,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Quest 50202: Grizzly Trophy
|
||||
-- Kill 1 rare in Grizzly Hills
|
||||
[50202] = {
|
||||
[1] = "Grizzly Trophy", -- Quest name
|
||||
[1] = "Grizzly Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 74, -- Quest level
|
||||
[5] = 71, -- Min level
|
||||
@@ -624,7 +624,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
{
|
||||
-- 4 rare NPCs in Grizzly Hills
|
||||
{ 38453, 32429, 32422, 32438 }, -- Arcturis, Seething Hate, Grocklar, Syreian the Bonecarver
|
||||
38453, -- RootId: Arcturis (representative rare)
|
||||
38453, -- RootId: Arcturis (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
@@ -636,7 +636,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Quest 50203: Zul'Drak Trophy
|
||||
-- Kill 1 rare in Zul'Drak
|
||||
[50203] = {
|
||||
[1] = "Zul'Drak Trophy", -- Quest name
|
||||
[1] = "Zul'Drak Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 77, -- Quest level
|
||||
[5] = 74, -- Min level
|
||||
@@ -654,7 +654,7 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
{
|
||||
-- 4 rare NPCs in Zul'Drak
|
||||
{ 33776, 32471, 32475, 32447 }, -- Gondria, Griegen, Terror Spinner, Zul'drak Sentinel
|
||||
33776, -- RootId: Gondria (representative rare)
|
||||
33776, -- RootId: Gondria (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
@@ -711,10 +711,10 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Complete 6 quests in Teldrassil (Any Quest)
|
||||
[50099] = {
|
||||
[1] = "Shadow of Teldrassil", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 1, -- Min level
|
||||
[5] = 60, -- Quest level
|
||||
[17] = 141, -- Zone (Teldrassil)
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 1, -- Min level
|
||||
[5] = 60, -- Quest level
|
||||
[17] = 141, -- Zone (Teldrassil)
|
||||
[8] = {
|
||||
"This quest requires completing any 6 quests in Teldrassil. The quest will automatically complete once the objective is met.",
|
||||
"Complete 6 quests in Teldrassil"
|
||||
@@ -741,10 +741,10 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Complete 6 quests in Bloodmyst Isle (Any Quest)
|
||||
[50104] = {
|
||||
[1] = "Bloodmyst Recovery", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 10, -- Min level
|
||||
[5] = 1, -- Quest level
|
||||
[17] = 3525, -- Zone (Bloodmyst Isle)
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 10, -- Min level
|
||||
[5] = 1, -- Quest level
|
||||
[17] = 3525, -- Zone (Bloodmyst Isle)
|
||||
[8] = {
|
||||
"This quest requires completing any 6 quests in Bloodmyst Isle. The quest will automatically complete once the objective is met.",
|
||||
"Complete 6 quests in Bloodmyst Isle"
|
||||
@@ -981,8 +981,8 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
{ -- [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)
|
||||
{ 2598, 2603, 2600, 2604, 2606, 2779, 2605, 2609, 2602, 2601 },
|
||||
2606, -- RootId: Nimar the Slayer (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
@@ -1023,8 +1023,8 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 3 rare NPCs in Blade's Edge Mountains
|
||||
{ 18690, 18692, 18693 },
|
||||
18692, -- RootId: Hemathion (representative rare)
|
||||
{ 18690, 18692, 18693 },
|
||||
18692, -- RootId: Hemathion (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
@@ -1037,10 +1037,10 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Kill 40 demons in Nagrand
|
||||
[50044] = {
|
||||
[1] = "Fel Scars of Nagrand", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 64, -- Min level
|
||||
[5] = 67, -- Quest level
|
||||
[17] = 3518, -- Zone (Nagrand)
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 64, -- Min level
|
||||
[5] = 67, -- Quest level
|
||||
[17] = 3518, -- Zone (Nagrand)
|
||||
[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 40 Demons in Nagrand"
|
||||
@@ -1053,8 +1053,8 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 14 demon NPCs in Nagrand
|
||||
{ 18683, 17151, 17981, 22357, 18567, 17152, 18535, 18661, 22362, 22394, 18536, 18401, 18660, 16945 },
|
||||
18683, -- RootId: Voidwalker Minion (representative demon)
|
||||
{ 18683, 17151, 17981, 22357, 18567, 17152, 18535, 18661, 22362, 22394, 18536, 18401, 18660, 16945 },
|
||||
18683, -- RootId: Voidwalker Minion (representative demon)
|
||||
"Demon slain"
|
||||
}
|
||||
}
|
||||
@@ -1067,10 +1067,10 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Kill 1 rare in Netherstorm
|
||||
[50196] = {
|
||||
[1] = "Netherstorm Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 67, -- Min level
|
||||
[5] = 70, -- Quest level
|
||||
[17] = 3523, -- Zone (Netherstorm)
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 67, -- Min level
|
||||
[5] = 70, -- Quest level
|
||||
[17] = 3523, -- Zone (Netherstorm)
|
||||
[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 Netherstorm"
|
||||
@@ -1096,11 +1096,11 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
-- Quest 50199: Borean Trophy
|
||||
-- Kill 1 rare in Borean Tundra
|
||||
[50199] = {
|
||||
[1] = "Borean Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Min level
|
||||
[5] = 71, -- Quest level
|
||||
[17] = 3537, -- Zone (Borean Tundra)
|
||||
[1] = "Borean Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Min level
|
||||
[5] = 71, -- Quest level
|
||||
[17] = 3537, -- Zone (Borean Tundra)
|
||||
[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 Borean Tundra"
|
||||
@@ -1123,6 +1123,336 @@ EbonholdDB.questData = EbonholdDB.questData or {
|
||||
[30] = 1, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50034: Ashen Corruption
|
||||
-- Kill 40 demons in Ashenvale
|
||||
[50034] = {
|
||||
[1] = "Ashen Corruption", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 20, -- Min level
|
||||
[5] = 25, -- Quest level
|
||||
[17] = 331, -- Zone (Ashenvale)
|
||||
[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 40 Demons in Ashenvale"
|
||||
},
|
||||
[10] = {
|
||||
nil, -- [1] creatureObjective (not used)
|
||||
nil, -- [2] objectObjective (not used)
|
||||
nil, -- [3] itemObjective (not used)
|
||||
nil, -- [4] reputationObjective (not used)
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 23 demon NPCs in Ashenvale
|
||||
{ 6072, 3772, 3758, 17300, 6073, 3762, 3774, 11697, 3765, 3771, 3767, 3763, 4619, 6071, 3757, 3770, 3755, 3752, 6115, 3759, 10928, 3754, 10647 },
|
||||
6072, -- RootId: Diathorus the Seeker (representative demon)
|
||||
"Demon slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 40, -- Kill count
|
||||
},
|
||||
-- Quest 50197: Shadowmoon Trophy
|
||||
-- Kill 1 rare in Shadowmoon Valley
|
||||
[50197] = {
|
||||
[1] = "Shadowmoon Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 67, -- Min level
|
||||
[5] = 70, -- Quest level
|
||||
[17] = 3520, -- Zone (Shadowmoon Valley)
|
||||
[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 Shadowmoon Valley"
|
||||
},
|
||||
[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 Shadowmoon Valley
|
||||
{ 18694, 18695, 18696 }, -- Collidus the Warp-Watcher, Ambassador Jerrikar, Kraator
|
||||
18694, -- RootId: Collidus the Warp-Watcher (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 1, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50020: Spires of Chaos
|
||||
-- Kill 30 elementals in Thousand Needles
|
||||
[50020] = {
|
||||
[1] = "Spires of Chaos", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 25, -- Min level
|
||||
[5] = 30, -- Quest level
|
||||
[17] = 400, -- Zone (Thousand Needles)
|
||||
[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 30 Elementals in Thousand Needles"
|
||||
},
|
||||
[10] = {
|
||||
nil, -- [1] creatureObjective (not used)
|
||||
nil, -- [2] objectObjective (not used)
|
||||
nil, -- [3] itemObjective (not used)
|
||||
nil, -- [4] reputationObjective (not used)
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 5 elemental NPCs in Thousand Needles
|
||||
{ 4499, 4120, 10756, 9377, 10757 },
|
||||
4120, -- RootId: Thundering Boulderkin (representative elemental)
|
||||
"Elemental slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 30, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50173: Northern Jungle Trophy
|
||||
-- Kill 1 rare in Stranglethorn Vale (Northern)
|
||||
[50173] = {
|
||||
[1] = "Northern Jungle Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 25, -- Min level
|
||||
[5] = 45, -- Quest level
|
||||
[17] = 33, -- Zone (Stranglethorn Vale)
|
||||
[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 Stranglethorn Vale"
|
||||
},
|
||||
[10] = {
|
||||
nil, -- [1] creatureObjective (not used)
|
||||
nil, -- [2] objectObjective (not used)
|
||||
nil, -- [3] itemObjective (not used)
|
||||
nil, -- [4] reputationObjective (not used)
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 9 rare NPCs in Stranglethorn Vale
|
||||
{ 1552, 14488, 9046, 14492, 14487, 14491, 14490, 11383, 2541 },
|
||||
1552, -- RootId: Scale Belly (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 1, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50175: Alterac Trophy
|
||||
-- Kill 1 rare in Alterac Mountains
|
||||
[50175] = {
|
||||
[1] = "Alterac Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 25, -- Min level
|
||||
[5] = 40, -- Quest level
|
||||
[17] = 36, -- Zone (Alterac 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 Alterac Mountains"
|
||||
},
|
||||
[10] = {
|
||||
nil, -- [1] creatureObjective (not used)
|
||||
nil, -- [2] objectObjective (not used)
|
||||
nil, -- [3] itemObjective (not used)
|
||||
nil, -- [4] reputationObjective (not used)
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 8 rare NPCs in Alterac Mountains
|
||||
{ 2447, 14223, 14221, 14222, 2453, 2258, 14281, 2452 },
|
||||
2447, -- RootId: Narillasanz (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 1, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50089: Tundra Hunters
|
||||
-- Kill 75 beasts in Borean Tundra
|
||||
[50089] = {
|
||||
[1] = "Tundra Hunters", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Min level
|
||||
[5] = 73, -- Quest level
|
||||
[17] = 68, -- Zone (Borean Tundra)
|
||||
[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 75 Beasts in Borean Tundra"
|
||||
},
|
||||
[10] = {
|
||||
nil, -- [1] creatureObjective (not used)
|
||||
nil, -- [2] objectObjective (not used)
|
||||
nil, -- [3] itemObjective (not used)
|
||||
nil, -- [4] reputationObjective (not used)
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 43 Beasts in Borean Tundra
|
||||
{ 25454, 32361, 25488, 25968, 25675, 25487, 25203, 25829, 25680, 25489, 25481, 25791, 25482, 24614, 25295, 25774, 25743, 18375, 26174, 25498, 26160, 24637, 24613, 18379, 25862, 25850, 25204, 25596, 25750, 18378, 25464, 27074, 25881, 25817, 24765, 27365, 26047, 25606, 25988, 18376, 18380, 25362, 25990 },
|
||||
25454, -- RootId: Tundra Crawler (representative)
|
||||
"Beast slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 75, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50183: Southern Jungle Trophy
|
||||
-- Kill 1 rare in Stranglethorn Vale (Southern)
|
||||
[50183] = {
|
||||
[1] = "Southern Jungle Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 25, -- Min level
|
||||
[5] = 45, -- Quest level
|
||||
[17] = 33, -- Zone (Stranglethorn Vale)
|
||||
[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 Stranglethorn Vale"
|
||||
},
|
||||
[10] = {
|
||||
nil, -- [1] creatureObjective (not used)
|
||||
nil, -- [2] objectObjective (not used)
|
||||
nil, -- [3] itemObjective (not used)
|
||||
nil, -- [4] reputationObjective (not used)
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 9 rare NPCs in Stranglethorn Vale
|
||||
{ 1552, 14488, 9046, 14487, 14492, 14490, 14491, 2541, 11383 },
|
||||
1552, -- RootId: Scale Belly (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 1, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50200: Fjord Trophy
|
||||
-- Kill 1 rare in Howling Fjord
|
||||
[50200] = {
|
||||
[1] = "Fjord Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 68, -- Min level
|
||||
[5] = 72, -- Quest level
|
||||
[17] = 495, -- Zone (Howling Fjord)
|
||||
[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 Howling Fjord"
|
||||
},
|
||||
[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 Howling Fjord
|
||||
{ 32398, 32377, 32386 },
|
||||
32398, -- RootId: King Ping (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 1, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50045: Demon's at the Edge
|
||||
-- Kill 40 demons in Blade's Edge Mountains
|
||||
[50045] = {
|
||||
[1] = "Demon's at the Edge",
|
||||
[2] = { nil, { 600600 } },
|
||||
[4] = 65, -- Min level
|
||||
[5] = 68, -- Quest 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 40 Demons 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
|
||||
{
|
||||
-- 37 Demons in Blade's Edge Mountains
|
||||
{ 20557, 22180, 19973, 22195, 23355, 19960, 19979, 19963, 22291, 22304, 16952, 23353, 23174, 23173, 21021, 19747, 19978, 23078, 23055, 23212, 21837, 22500, 19980, 23199, 12922, 21519, 19961, 22204, 22499, 23220, 23113, 21516, 22281, 23230, 23354, 22474, 23275 },
|
||||
20557, -- RootId: Wrath Hound (representative demon)
|
||||
"Demon slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 40, -- Kill count
|
||||
},
|
||||
|
||||
-- Quest 50063: Frostbound Brood
|
||||
-- Kill 30 dragonkin in Borean Tundra
|
||||
[50063] = {
|
||||
[1] = "Frostbound Brood",
|
||||
[2] = { nil, { 600600 } },
|
||||
[4] = 68,
|
||||
[5] = 71,
|
||||
[17] = 3537, -- Zone (Borean Tundra)
|
||||
[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 30 Dragonkin in Borean Tundra"
|
||||
},
|
||||
[10] = {
|
||||
nil, -- [1] creatureObjective (not used)
|
||||
nil, -- [2] objectObjective (not used)
|
||||
nil, -- [3] itemObjective (not used)
|
||||
nil, -- [4] reputationObjective (not used)
|
||||
{ -- [5] killCreditObjective
|
||||
{
|
||||
-- 16 Dragonkin in Borean Tundra
|
||||
{ 25728, 26127, 25711, 25721, 25448, 32534, 25585, 26232, 25712, 25717, 25722, 24770, 25716, 26231, 25713, 26310 },
|
||||
25728, -- RootId: Coldarra Wyrmkin (representative dragonkin)
|
||||
"Dragonkin slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 30, -- Kill count
|
||||
},
|
||||
|
||||
|
||||
-- Quest 50178: Badlands Trophy
|
||||
-- Kill 1 rare in Badlands
|
||||
[50178] = {
|
||||
[1] = "Badlands Trophy", -- Quest name
|
||||
[2] = { nil, { 600600 } }, -- startedBy: {{npcIds}, {objectIds}, {itemIds}}
|
||||
[4] = 35, -- Min level
|
||||
[5] = 40, -- Quest level
|
||||
[17] = 3, -- Zone (Badlands)
|
||||
[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 Badlands"
|
||||
},
|
||||
[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 the Badlands
|
||||
{ 2850, 2931, 14224, 2754, 2753, 2752, 2749, 7057, 2744, 2751 },
|
||||
2850, -- RootId: Broken Tooth (representative rare)
|
||||
"Rare slain"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
[30] = 1, -- Kill count
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
-- Backward compatibility
|
||||
|
||||
@@ -122,7 +122,10 @@ function ZoneDB:GetAreaIdByUiMapId(uiMapId)
|
||||
end
|
||||
end
|
||||
if Questie.db.profile.debugEnabled then
|
||||
Questie:Debug(Questie.DEBUG_CRITICAL,
|
||||
-- NOTE: On Ascension, hub cities (Stormwind, Shattrath, etc.) may return a
|
||||
-- continent-level UiMapId from GetBestMapForUnit. This is harmless — the nil
|
||||
-- return is handled gracefully by GetCurrentZoneId's callers.
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"No AreaId found for UiMapId: " ..
|
||||
uiMapId .. ":" .. (C_Map.GetMapInfo(uiMapId) and C_Map.GetMapInfo(uiMapId).name or "nil"))
|
||||
end
|
||||
@@ -373,7 +376,7 @@ function _ZoneDB:RunTests()
|
||||
local success, result = pcall(ZoneDB.GetAreaIdByUiMapId, ZoneDB, map.mapID)
|
||||
if not success and not buggedMaps[map.mapID] then
|
||||
Questie:Error("[ZoneDBTests] ZoneDB.GetAreaIdByUiMapId fails for " ..
|
||||
map.name .. " (" .. map.mapID .. "). Result: " .. result)
|
||||
map.name .. " (" .. map.mapID .. "). Result: " .. result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -89,13 +89,10 @@ function QuestEventHandler:RegisterEvents()
|
||||
end
|
||||
|
||||
for questLogIndex = 1, 75 do
|
||||
local title, _, _, isHeader, _, _, _, questId = GetQuestLogTitle(questLogIndex)
|
||||
local title, level, questTag, isHeader, isCollapsed, isComplete, isDaily, questId = GetQuestLogTitle(
|
||||
questLogIndex)
|
||||
|
||||
if (not title) then
|
||||
break
|
||||
end
|
||||
|
||||
if (not isHeader) then
|
||||
if title and questId and (not isHeader) then
|
||||
quest = QuestieDB.GetQuest(questId)
|
||||
|
||||
if quest then
|
||||
@@ -107,7 +104,8 @@ function QuestEventHandler:RegisterEvents()
|
||||
sourceItemId = quest.sourceItemId
|
||||
|
||||
if sourceItemId then
|
||||
soureItemName, _, _, _, _, sourceItemType, _, _, _, _, _, soureClassID = GetItemInfo(sourceItemId)
|
||||
soureItemName, _, _, _, _, sourceItemType, _, _, _, _, _, soureClassID = GetItemInfo(
|
||||
sourceItemId)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -115,7 +113,8 @@ function QuestEventHandler:RegisterEvents()
|
||||
reqSourceItemId = quest.requiredSourceItems[1]
|
||||
|
||||
if reqSourceItemId then
|
||||
reqSoureItemName, _, _, _, _, reqSourceItemType, _, _, _, _, _, reqSoureClassID = GetItemInfo(reqSourceItemId)
|
||||
reqSoureItemName, _, _, _, _, reqSourceItemType, _, _, _, _, _, reqSoureClassID =
|
||||
GetItemInfo(reqSourceItemId)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -154,14 +153,16 @@ function QuestEventHandler:RegisterEvents()
|
||||
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?")
|
||||
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.")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieQuest] StaticPopup_Show: Quest Item Detected. Updating Static Popup.")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -170,12 +171,13 @@ function QuestEventHandler:RegisterEvents()
|
||||
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.")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieQuest] DeleteCursorItem: Quest Item deleted. Update all quests.")
|
||||
|
||||
C_Timer.After(0.25, function()
|
||||
_QuestEventHandler:UpdateAllQuests()
|
||||
deletedQuestItem = false
|
||||
end)
|
||||
_QuestEventHandler:UpdateAllQuests()
|
||||
deletedQuestItem = false
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -187,9 +189,9 @@ 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.")
|
||||
-- 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
|
||||
@@ -231,7 +233,7 @@ function _QuestEventHandler:QuestAccepted(questLogIndex, questId)
|
||||
QuestieCombatQueue:Queue(function()
|
||||
QuestieLib:CacheItemNames(questId)
|
||||
_QuestEventHandler:HandleQuestAccepted(questId)
|
||||
QuestieTracker:Update()
|
||||
QuestieTracker:Update()
|
||||
end)
|
||||
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[Quest Event] QUEST_ACCEPTED - skipNextUQLCEvent - ", skipNextUQLCEvent)
|
||||
@@ -240,13 +242,13 @@ 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
|
||||
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
|
||||
@@ -272,9 +274,9 @@ function _QuestEventHandler:HandleQuestAccepted(questId)
|
||||
else
|
||||
QuestieQuest:AcceptQuest(questId)
|
||||
end
|
||||
QuestieCompat.C_Timer.After(0.2, function()
|
||||
QuestieTracker:Update()
|
||||
end)
|
||||
QuestieCompat.C_Timer.After(0.2, function()
|
||||
QuestieTracker:Update()
|
||||
end)
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -301,7 +303,7 @@ function _QuestEventHandler:QuestTurnedIn(questId, xpReward, moneyReward)
|
||||
-- is empty
|
||||
questLog[questId].state = QUEST_LOG_STATES.QUEST_TURNED_IN
|
||||
elseif QuestieCompat.Is335 then
|
||||
questLog[questId] = {state = QUEST_LOG_STATES.QUEST_TURNED_IN}
|
||||
questLog[questId] = { state = QUEST_LOG_STATES.QUEST_TURNED_IN }
|
||||
end
|
||||
|
||||
local parentQuest = QuestieDB.QueryQuestSingle(questId, "parentQuest")
|
||||
@@ -316,7 +318,8 @@ function _QuestEventHandler:QuestTurnedIn(questId, xpReward, moneyReward)
|
||||
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")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "Quest:", questId,
|
||||
"Recieved a possible Quest Item - do a full Quest Log check")
|
||||
doFullQuestLogScan = true
|
||||
skipNextUQLCEvent = false
|
||||
else
|
||||
@@ -331,11 +334,11 @@ function _QuestEventHandler:QuestTurnedIn(questId, xpReward, moneyReward)
|
||||
-- QuestieQuest:CompleteQuest(questId)
|
||||
-- QuestieJourney:CompleteQuest(questId)
|
||||
-- QuestieAnnounce:CompletedQuest(questId)
|
||||
-- questLog[questId] = nil
|
||||
-- questLog[questId] = nil
|
||||
|
||||
QuestieCombatQueue:Queue(function()
|
||||
QuestieTracker:Update()
|
||||
end)
|
||||
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.
|
||||
@@ -386,7 +389,8 @@ function _QuestEventHandler:MarkQuestAsAbandoned(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)
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "QuestEventHandler:MarkQuestAsAbandoned - questLog entry missing for",
|
||||
questId)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -406,8 +410,8 @@ function _QuestEventHandler:MarkQuestAsAbandoned(questId)
|
||||
|
||||
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
|
||||
Questie:Debug(Questie.DEBUG_INFO, "Quest:", questId, "detected as auto-complete by description")
|
||||
objectivesWereComplete = true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -415,7 +419,8 @@ function _QuestEventHandler:MarkQuestAsAbandoned(questId)
|
||||
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)")
|
||||
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)
|
||||
@@ -502,14 +507,13 @@ function _QuestEventHandler:UnitQuestLogChanged(unitTarget)
|
||||
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)
|
||||
local title, level, questTag, isHeader, isCollapsed, isComplete, isDaily, qid = GetQuestLogTitle(questLogIndex)
|
||||
if title and qid and qid > 0 and (not isHeader) then
|
||||
gameQuestIds[qid] = true
|
||||
end
|
||||
@@ -651,7 +655,7 @@ function _QuestEventHandler:ZoneChangedNewArea()
|
||||
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
|
||||
-- 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")
|
||||
|
||||
@@ -10,7 +10,7 @@ local Sounds = QuestieLoader:ImportModule("Sounds")
|
||||
|
||||
--- COMPATIBILITY ---
|
||||
local GetQuestLogTitle = QuestieCompat.GetQuestLogTitle
|
||||
local C_QuestLog_GetQuestObjectives = QuestieCompat.C_QuestLog.GetQuestObjectives
|
||||
local C_QuestLog_GetQuestObjectives = QuestieCompat.C_QuestLog.GetQuestObjectives
|
||||
local HaveQuestData = QuestieCompat.HaveQuestData
|
||||
|
||||
local stringByte = string.byte
|
||||
@@ -53,7 +53,7 @@ local cache = {
|
||||
},
|
||||
[questId2] = ....,
|
||||
}
|
||||
]]--
|
||||
]] --
|
||||
|
||||
|
||||
---@class QuestLogCacheObjectiveData
|
||||
@@ -85,10 +85,10 @@ QuestLogCache.questLog_DO_NOT_MODIFY = cache
|
||||
---@return table? newObjectives, ObjectiveIndex[] changedObjIds @nil == cache miss in both addon and game caches. table {} == no objectives.
|
||||
local function GetNewObjectives(questId, oldObjectives, questLogIndex)
|
||||
local newObjectives = {} -- creating a fresh one to be able revert to old easily in case of missing data
|
||||
local changedObjIds -- not assigning {} for easier nil when nothing changed
|
||||
local changedObjIds -- not assigning {} for easier nil when nothing changed
|
||||
local objectives = C_QuestLog_GetQuestObjectives(questId, questLogIndex)
|
||||
|
||||
for objIndex=1, #objectives do -- iterate manually to be sure getting those in order
|
||||
for objIndex = 1, #objectives do -- iterate manually to be sure getting those in order
|
||||
local oldObj = oldObjectives[objIndex]
|
||||
local newObj = objectives[objIndex]
|
||||
-- Check if objective.text is in game's cache
|
||||
@@ -102,7 +102,7 @@ local function GetNewObjectives(questId, oldObjectives, questLogIndex)
|
||||
if (not changedObjIds) then
|
||||
changedObjIds = { objIndex }
|
||||
else
|
||||
changedObjIds[#changedObjIds+1] = objIndex
|
||||
changedObjIds[#changedObjIds + 1] = objIndex
|
||||
end
|
||||
|
||||
if oldObj and newObj and oldObj.numRequired ~= oldObj.numFulfilled and newObj.numRequired == newObj.numFulfilled then
|
||||
@@ -120,18 +120,22 @@ local function GetNewObjectives(questId, oldObjectives, questLogIndex)
|
||||
type = newObj.type,
|
||||
numRequired = newObj.numRequired,
|
||||
text = QuestieLib.TrimObjectiveText(newObj.text, newObj.type),
|
||||
finished = newObj.finished, -- gets overwritten with correct value later if quest isComplete
|
||||
finished = newObj.finished, -- gets overwritten with correct value later if quest isComplete
|
||||
numFulfilled = newObj.numFulfilled, -- gets overwritten with correct value later if quest isComplete
|
||||
}
|
||||
end
|
||||
else -- objective text not in game's cache
|
||||
if oldObj then
|
||||
Questie:Debug(Questie.DEBUG_INFO, "[GetNewObjectives] objective not in game's cache. Using addon's cache. questID, objIndex:", questId, objIndex)
|
||||
Questie:Debug(Questie.DEBUG_INFO,
|
||||
"[GetNewObjectives] objective not in game's cache. Using addon's cache. questID, objIndex:", questId,
|
||||
objIndex)
|
||||
-- Extremely unlikely that the objective has changed from cached version as a change SHOULD trigger fetching data into game cache.
|
||||
-- Possible bug point if there comes desync issues.
|
||||
newObjectives[objIndex] = oldObj
|
||||
else
|
||||
Questie:Debug(Questie.DEBUG_INFO, "[GetNewObjectives] \"WARNING\" objective not in game's cache nor addon's cache. questID, objIndex:", questId, objIndex)
|
||||
Questie:Debug(Questie.DEBUG_INFO,
|
||||
"[GetNewObjectives] \"WARNING\" objective not in game's cache nor addon's cache. questID, objIndex:",
|
||||
questId, objIndex)
|
||||
-- Objective has been never cached
|
||||
-- Tell to function caller that we couldn't get all required data from game's cache
|
||||
-- Don't loop rest of objectives as we won't anyway save those into cache[] and C_QuestLog.GetQuestObjectives() call already triggered game to initiate caching those into game's cache.
|
||||
@@ -158,7 +162,8 @@ function QuestLogCache.CheckForChanges(questIdsToCheck)
|
||||
|
||||
local numEntries = select(1, GetNumQuestLogEntries()) or 0
|
||||
for questLogIndex = 1, numEntries do
|
||||
local title, _, questTag, isHeader, _, isComplete, _, questId = GetQuestLogTitle(questLogIndex)
|
||||
local title, level, questTag, isHeader, isCollapsed, isComplete, isDaily, questId = GetQuestLogTitle(
|
||||
questLogIndex)
|
||||
|
||||
-- Skip weird/header entries / questId=0 (these happen a lot on your server)
|
||||
if title and questId and questId > 0 and (not isHeader) then
|
||||
@@ -173,8 +178,7 @@ function QuestLogCache.CheckForChanges(questIdsToCheck)
|
||||
|
||||
if newObjectives then
|
||||
if (not cachedQuest) or (#cachedObjectives == #newObjectives and #cachedObjectives > 0 and
|
||||
(cachedQuest.title ~= title or cachedQuest.questTag ~= questTag or cachedQuest.isComplete ~= isComplete)) then
|
||||
|
||||
(cachedQuest.title ~= title or cachedQuest.questTag ~= questTag or cachedQuest.isComplete ~= isComplete)) then
|
||||
changedObjIds = {}
|
||||
for i = 1, #newObjectives do
|
||||
changedObjIds[i] = i
|
||||
@@ -206,7 +210,9 @@ function QuestLogCache.CheckForChanges(questIdsToCheck)
|
||||
cacheMiss = true
|
||||
end
|
||||
else
|
||||
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestLogCache.CheckForChanges] HaveQuestData() == false. questId, index:", questId, questLogIndex)
|
||||
Questie:Debug(Questie.DEBUG_CRITICAL,
|
||||
"[QuestLogCache.CheckForChanges] HaveQuestData() == false. questId, index:", questId,
|
||||
questLogIndex)
|
||||
C_QuestLog_GetQuestObjectives(questId, questLogIndex)
|
||||
cacheMiss = true
|
||||
end
|
||||
@@ -226,29 +232,24 @@ function QuestLogCache.CheckForChanges(questIdsToCheck)
|
||||
return cacheMiss, changes
|
||||
end
|
||||
|
||||
|
||||
|
||||
function QuestLogCache.RemoveQuest(questId)
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestLogCache.RemoveQuest] remove questId:", questId)
|
||||
cache[questId] = nil
|
||||
end
|
||||
|
||||
|
||||
--- Tests if game client's cache has all quest log quests and objectives cached.
|
||||
--- Avoid using this function if possible.
|
||||
---@return boolean gameCacheOK
|
||||
function QuestLogCache.TestGameCache()
|
||||
local gameCacheOK = true
|
||||
for questLogIndex = 1, MAX_QUEST_LOG_INDEX do
|
||||
local title, _, _, isHeader, _, _, _, questId = GetQuestLogTitle(questLogIndex)
|
||||
if (not title) then
|
||||
break -- We exceeded the valid quest log entries
|
||||
end
|
||||
if (not isHeader) then
|
||||
local title, level, questTag, isHeader, isCollapsed, isComplete, isDaily, questId = GetQuestLogTitle(
|
||||
questLogIndex)
|
||||
if title and questId and (not isHeader) then
|
||||
if HaveQuestData(questId) then
|
||||
local objectives = C_QuestLog_GetQuestObjectives(questId, questLogIndex)
|
||||
|
||||
for objIndex=1, #objectives do
|
||||
for objIndex = 1, #objectives do
|
||||
local text = objectives[objIndex].text
|
||||
-- Check if objective.text is not in game's cache
|
||||
if (not text) or (stringByte(text, 1) == 32) then
|
||||
@@ -261,11 +262,11 @@ function QuestLogCache.TestGameCache()
|
||||
end
|
||||
end
|
||||
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestLogCache.TestGameCache]", (gameCacheOK and "Cache ok." or "Cache missing data."))
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestLogCache.TestGameCache]",
|
||||
(gameCacheOK and "Cache ok." or "Cache missing data."))
|
||||
return gameCacheOK
|
||||
end
|
||||
|
||||
|
||||
--- A wrapper function to add error check instead using exposed table directly.
|
||||
---@param questId QuestId
|
||||
---@return QuestLogCacheData? @NEVER EVER MODIFY THE RETURNED TABLE
|
||||
@@ -292,23 +293,21 @@ function QuestLogCache.GetQuestObjectives(questId)
|
||||
return cache[questId].objectives
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param q table @quest
|
||||
---@param i number @index of the objective
|
||||
---@param o table @objective
|
||||
local function DebugPrintObjective(q, i, o)
|
||||
if (o.raw_numFulfilled == o.numFulfilled) and (o.raw_finished == o.finished) then
|
||||
print(" ", i.."/"..#q.objectives..":",
|
||||
o.numFulfilled.."/"..o.numRequired.."="..tostring(o.finished),
|
||||
print(" ", i .. "/" .. #q.objectives .. ":",
|
||||
o.numFulfilled .. "/" .. o.numRequired .. "=" .. tostring(o.finished),
|
||||
o.type,
|
||||
"\""..o.raw_text.."\" \""..o.text.."\"")
|
||||
"\"" .. o.raw_text .. "\" \"" .. o.text .. "\"")
|
||||
else
|
||||
print(" ", i.."/"..#q.objectives..":",
|
||||
o.raw_numFulfilled.."/"..o.numRequired.."="..tostring(o.raw_finished),
|
||||
"FIX:", o.numFulfilled.."/"..o.numRequired.."="..tostring(o.finished),
|
||||
print(" ", i .. "/" .. #q.objectives .. ":",
|
||||
o.raw_numFulfilled .. "/" .. o.numRequired .. "=" .. tostring(o.raw_finished),
|
||||
"FIX:", o.numFulfilled .. "/" .. o.numRequired .. "=" .. tostring(o.finished),
|
||||
o.type,
|
||||
"\""..o.raw_text.."\" \""..o.text.."\"")
|
||||
"\"" .. o.raw_text .. "\" \"" .. o.text .. "\"")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -318,7 +317,8 @@ function QuestLogCache.DebugPrintCache()
|
||||
local count = 0
|
||||
for questId, q in pairs(cache) do
|
||||
count = count + 1
|
||||
print("Quest: ("..questId..") \""..q.title.."\" questTag="..tostring(q.questTag) ,"isComplete="..tostring(q.isComplete))
|
||||
print("Quest: (" .. questId .. ") \"" .. q.title .. "\" questTag=" .. tostring(q.questTag),
|
||||
"isComplete=" .. tostring(q.isComplete))
|
||||
if not next(q.objectives) then
|
||||
print(" no objectives")
|
||||
else
|
||||
@@ -332,12 +332,14 @@ end
|
||||
|
||||
--- Debug function, prints changes
|
||||
function QuestLogCache.DebugPrintCacheChanges(cacheMiss, changes)
|
||||
local highlight = ((not cacheMiss) and (not next(changes))) or (cacheMiss and next(changes)) -- highlight untypical cases. they are okey, but sometimes interesting.
|
||||
local highlight = ((not cacheMiss) and (not next(changes))) or
|
||||
(cacheMiss and next(changes)) -- highlight untypical cases. they are okey, but sometimes interesting.
|
||||
print("DebugPrintCacheChanges", GetTime(), (highlight and "\124cffFF4444CacheMiss:\124r" or "CacheMiss"), cacheMiss)
|
||||
|
||||
for questId, objIndexes in pairs(changes) do
|
||||
local q = cache[questId]
|
||||
print("Quest: ("..questId..") \""..q.title.."\" questTag="..tostring(q.questTag) ,"isComplete="..tostring(q.isComplete))
|
||||
print("Quest: (" .. questId .. ") \"" .. q.title .. "\" questTag=" .. tostring(q.questTag),
|
||||
"isComplete=" .. tostring(q.isComplete))
|
||||
if not next(objIndexes) then
|
||||
print(" no objectives changed (or quest doesn't have objectives)")
|
||||
else
|
||||
|
||||
+132
-73
@@ -17,7 +17,7 @@ local QuestieCorrections = QuestieLoader:ImportModule("QuestieCorrections")
|
||||
local l10n = QuestieLoader:ImportModule("l10n")
|
||||
|
||||
local DebugInformation = {} -- stores text of debug data dump per session
|
||||
local debugIndex = 0 -- current debug index, used so we can still retrieve info from previous offers
|
||||
local debugIndex = 0 -- current debug index, used so we can still retrieve info from previous offers
|
||||
local openDebugWindows = {} -- determines if existing debug window is already open, prevents duplicates
|
||||
|
||||
local GetBestMapForUnit = C_Map.GetBestMapForUnit
|
||||
@@ -249,15 +249,15 @@ local itemWhitelist = {
|
||||
}
|
||||
|
||||
local itemTripCodes = {
|
||||
['ItemWhitelisted'] = 0, -- itemID is whitelisted; we want all its data anyway
|
||||
['ItemMissingFromDB'] = 1, -- error when itemID is missing from DB entirely
|
||||
['StartQuestIDMismatch'] = 2, -- error when item quest start ID does not match Questie ItemDB
|
||||
['MissingDropFromNPC'] = 3, -- error when item dropped from npc (corpses) not matching ItemDB
|
||||
['MissingDropFromObject'] = 4, -- error when item dropped from object (chests in world) not matching ItemDB
|
||||
['MissingDropFromItem'] = 5, -- error when item dropped from item (lockboxes in inventory) not matching ItemDB
|
||||
['ContainerMissingFromNPCDB'] = 6, -- error when item's container is missing from NpcDB
|
||||
['ItemWhitelisted'] = 0, -- itemID is whitelisted; we want all its data anyway
|
||||
['ItemMissingFromDB'] = 1, -- error when itemID is missing from DB entirely
|
||||
['StartQuestIDMismatch'] = 2, -- error when item quest start ID does not match Questie ItemDB
|
||||
['MissingDropFromNPC'] = 3, -- error when item dropped from npc (corpses) not matching ItemDB
|
||||
['MissingDropFromObject'] = 4, -- error when item dropped from object (chests in world) not matching ItemDB
|
||||
['MissingDropFromItem'] = 5, -- error when item dropped from item (lockboxes in inventory) not matching ItemDB
|
||||
['ContainerMissingFromNPCDB'] = 6, -- error when item's container is missing from NpcDB
|
||||
['ContainerMissingFromObjectDB'] = 7, -- error when item's container is missing from ObjectDB
|
||||
['ContainerMissingFromItemDB'] = 8, -- error when item's container is missing from ItemDB
|
||||
['ContainerMissingFromItemDB'] = 8, -- error when item's container is missing from ItemDB
|
||||
}
|
||||
|
||||
-- determines whether to offer a debug offer for a looted item
|
||||
@@ -274,16 +274,20 @@ local function filterItem(itemID, itemInfo, containerGUID)
|
||||
-- OG chronoboon displacer was 184937 so safe to say any SoD items are higher than 190000
|
||||
return nil
|
||||
else
|
||||
if tContains(itemWhitelist, itemID) then -- if item is in our whitelist, we want it no matter what
|
||||
if tContains(itemWhitelist, itemID) then -- if item is in our whitelist, we want it no matter what
|
||||
return itemTripCodes.ItemWhitelisted
|
||||
elseif tContains(itemBlacklist, itemID) then -- if item is in our blacklist, ignore it
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - Item " .. itemID .. " is in debug offer item blacklist, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemFilter - Item " .. itemID .. " is in debug offer item blacklist, ignoring")
|
||||
return nil
|
||||
elseif UnitLevel(player) < minLevelForDebugOffers then -- if player level is below our threshold, ignore it
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - Player does not meet level threshold for debug offers, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemFilter - Player does not meet level threshold for debug offers, ignoring")
|
||||
return nil
|
||||
elseif QuestieCorrections.questItemBlacklist[itemID] then
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - Item " .. itemID .. " is in QuestieCorrections item blacklist, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemFilter - Item " ..
|
||||
itemID .. " is in QuestieCorrections item blacklist, ignoring")
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -312,7 +316,8 @@ local function filterItem(itemID, itemInfo, containerGUID)
|
||||
if questID ~= QuestieDB.QueryItemSingle(itemID, "startQuest") then
|
||||
return itemTripCodes.StartQuestIDMismatch
|
||||
else
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - QuestID for " .. itemID .. " present but matches DB, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemFilter - QuestID for " .. itemID .. " present but matches DB, ignoring")
|
||||
end
|
||||
else
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - QuestID value not present, ignoring")
|
||||
@@ -330,7 +335,8 @@ local function filterItem(itemID, itemInfo, containerGUID)
|
||||
if not lootTable or tContains(lootTable, containerID) == false then
|
||||
return itemTripCodes.MissingDropFromNPC
|
||||
else
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - NPC drop data for item " .. itemID .. " OK, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemFilter - NPC drop data for item " .. itemID .. " OK, ignoring")
|
||||
end
|
||||
elseif containerType == "GameObject" then -- if container is an object
|
||||
-- first check if object is even in our DB
|
||||
@@ -344,7 +350,8 @@ local function filterItem(itemID, itemInfo, containerGUID)
|
||||
if tContains(lootTable, containerID) == false then
|
||||
return itemTripCodes.MissingDropFromObject
|
||||
else
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - Object drop data for item " .. itemID .. " OK, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemFilter - Object drop data for item " .. itemID .. " OK, ignoring")
|
||||
end
|
||||
end
|
||||
elseif containerType == "Item" and containerID > 0 then -- if container is an item and there is an containerID for it
|
||||
@@ -360,12 +367,14 @@ local function filterItem(itemID, itemInfo, containerGUID)
|
||||
if tContains(lootTable, containerID) == false then
|
||||
return itemTripCodes.MissingDropFromItem
|
||||
else
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - ItemSource drop data for item " .. itemID .. " OK, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemFilter - ItemSource drop data for item " .. itemID .. " OK, ignoring")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemFilter - No data mismatches found for " .. itemID .. ", ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemFilter - No data mismatches found for " .. itemID .. ", ignoring")
|
||||
return nil -- if no exceptions raised, we don't need to create a debug offer
|
||||
end
|
||||
|
||||
@@ -378,13 +387,14 @@ local npcBlacklist = {
|
||||
local function _AppendUniversalText(input)
|
||||
local text = tostring(input)
|
||||
|
||||
text = text .. "\n|cFFAAAAAACharacter:|r Lvl " .. UnitLevel(player) .. " " .. string.upper(playerRace) .. " " .. playerClass
|
||||
text = text ..
|
||||
"\n|cFFAAAAAACharacter:|r Lvl " .. UnitLevel(player) .. " " .. string.upper(playerRace) .. " " .. playerClass
|
||||
|
||||
local mapID = GetBestMapForUnit(player)
|
||||
local pos = GetPlayerMapPosition(mapID, player);
|
||||
PosX = pos.x * 100
|
||||
PosY = pos.y * 100
|
||||
text = text .. "\n|cFFAAAAAAPlayer Coords:|r [" .. mapID .. "] " .. format("(%.3f, %.3f)", PosX, PosY)
|
||||
PosX = pos and (pos.x * 100) or 0
|
||||
PosY = pos and (pos.y * 100) or 0
|
||||
text = text .. "\n|cFFAAAAAAPlayer Coords:|r [" .. tostring(mapID) .. "] " .. format("(%.3f, %.3f)", PosX, PosY)
|
||||
|
||||
local questLog = ""
|
||||
for k in pairs(QuestLogCache.questLog_DO_NOT_MODIFY) do questLog = k .. ", " .. questLog end
|
||||
@@ -403,11 +413,12 @@ function QuestieDebugOffer.LootWindow()
|
||||
local debugContainer, _ = GetLootSourceInfo(1) -- happens early in case the rest of the code is so slow that the container closes before we're ready
|
||||
local inInstance, _ = IsInInstance()
|
||||
if inInstance == true then
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemLoot - Player looting item is in instance, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemLoot - Player looting item is in instance, ignoring")
|
||||
return -- temporary for SoD to reduce new raid loot triggering debug spam
|
||||
end
|
||||
|
||||
for i=1, #lootInfo do
|
||||
for i = 1, #lootInfo do
|
||||
local itemInfo = lootInfo[i]
|
||||
local itemLink = GetLootSlotLink(i)
|
||||
local itemID = 0
|
||||
@@ -420,7 +431,8 @@ function QuestieDebugOffer.LootWindow()
|
||||
|
||||
local tripCode = filterItem(itemID, itemInfo, debugContainer)
|
||||
if tripCode then
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - ItemLoot - Creating debug offer for item " .. itemID .. " reason " .. tripCode)
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - ItemLoot - Creating debug offer for item " .. itemID .. " reason " .. tripCode)
|
||||
debugIndex = debugIndex + 1
|
||||
if tripCode == itemTripCodes.ItemWhitelisted then
|
||||
DebugInformation[debugIndex] = "ItemDB is missing some data about this item!"
|
||||
@@ -443,13 +455,20 @@ function QuestieDebugOffer.LootWindow()
|
||||
else
|
||||
DebugInformation[debugIndex] = "General data mismatch for item!"
|
||||
end
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n\n|cFFAAAAAAItem ID:|r " .. tostring(itemID)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n\n|cFFAAAAAAItem ID:|r " .. tostring(itemID)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAItem Name:|r " .. itemLink
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAQuest Item:|r " .. tostring(itemInfo.isQuestItem)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAQuest ID:|r " .. tostring(itemInfo.questId)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAContainer:|r " .. tostring(debugContainer)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAQuest Item:|r " .. tostring(itemInfo.isQuestItem)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAQuest ID:|r " .. tostring(itemInfo.questId)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAContainer:|r " .. tostring(debugContainer)
|
||||
DebugInformation[debugIndex] = _AppendUniversalText(DebugInformation[debugIndex])
|
||||
Questie:Print(l10n("An item you just encountered has data missing from the Questie database.") .. " " .. l10n("Would you like to help us fix it?") .. " |cff71d5ff|Haddon:questie:offer:" .. debugIndex .. "|h[" .. l10n("More Info") .. "]|h|r")
|
||||
Questie:Print(l10n("An item you just encountered has data missing from the Questie database.") ..
|
||||
" " ..
|
||||
l10n("Would you like to help us fix it?") ..
|
||||
" |cff71d5ff|Haddon:questie:offer:" .. debugIndex .. "|h[" .. l10n("More Info") .. "]|h|r")
|
||||
return -- we only want to show one debug offer per interaction, so break on the first one
|
||||
end
|
||||
end
|
||||
@@ -460,10 +479,11 @@ function QuestieDebugOffer.QuestDialog()
|
||||
local questID = GetQuestID() -- obtain quest ID from dialog
|
||||
if questID <= 0 or questID == nil then
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - QuestDialog - Invalid quest ID from API, ignoring")
|
||||
return -- invalid data from API, abandon offer attempt
|
||||
return -- invalid data from API, abandon offer attempt
|
||||
end
|
||||
if UnitLevel(player) < minLevelForDebugOffers then -- if player level is below our threshold, ignore it
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - QuestDialog - Player does not meet level threshold for debug offers, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - QuestDialog - Player does not meet level threshold for debug offers, ignoring")
|
||||
return
|
||||
end
|
||||
if QuestieDB.QueryQuestSingle(questID, "name") == nil then -- if ID not in our DB
|
||||
@@ -474,77 +494,100 @@ function QuestieDebugOffer.QuestDialog()
|
||||
local rewardText = GetRewardText()
|
||||
local rewardXP = GetRewardXP()
|
||||
|
||||
if questText then questText = questText:gsub(GetUnitName(player), "<playername>") end -- strip out player name from quest text
|
||||
if questText then questText = questText:gsub(GetUnitName(player), "<playername>") end -- strip out player name from quest text
|
||||
if objectiveText then objectiveText = objectiveText:gsub(GetUnitName(player), "<playername>") end -- strip out player name from objective text
|
||||
if rewardText then rewardText = rewardText:gsub(GetUnitName(player), "<playername>") end -- strip out player name from reward text
|
||||
if rewardText then rewardText = rewardText:gsub(GetUnitName(player), "<playername>") end -- strip out player name from reward text
|
||||
|
||||
DebugInformation[debugIndex] = "Quest in dialog not present in QuestDB!"
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n\n|cFFAAAAAAQuest ID:|r " .. tostring(questID)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAQuest Name:|r " .. tostring(questTitle)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAQuest Text:|r " .. tostring(questText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAObjective Text:|r " .. tostring(objectiveText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAReward Text:|r " .. tostring(rewardText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAQuest Name:|r " .. tostring(questTitle)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAQuest Text:|r " .. tostring(questText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAObjective Text:|r " .. tostring(objectiveText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAReward Text:|r " .. tostring(rewardText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAReward XP:|r " .. tostring(rewardXP)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAQuestgiver:|r " .. tostring(UnitGUID(questnpc))
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAQuestgiver:|r " .. tostring(UnitGUID(questnpc))
|
||||
DebugInformation[debugIndex] = _AppendUniversalText(DebugInformation[debugIndex])
|
||||
Questie:Print(l10n("A quest you just encountered is missing from the Questie database.") .. " " .. l10n("Would you like to help us fix it?") .. " |cff71d5ff|Haddon:questie:offer:" .. debugIndex .. "|h[" .. l10n("More Info") .. "]|h|r")
|
||||
Questie:Print(l10n("A quest you just encountered is missing from the Questie database.") ..
|
||||
" " ..
|
||||
l10n("Would you like to help us fix it?") ..
|
||||
" |cff71d5ff|Haddon:questie:offer:" .. debugIndex .. "|h[" .. l10n("More Info") .. "]|h|r")
|
||||
end
|
||||
end
|
||||
|
||||
-- Missing questID when tracking
|
||||
---@param questID number
|
||||
function QuestieDebugOffer.QuestTracking(questID) -- ID supplied by tracker during update
|
||||
function QuestieDebugOffer.QuestTracking(questID) -- ID supplied by tracker during update
|
||||
if UnitLevel(player) < minLevelForDebugOffers then -- if player level is below our threshold, ignore it
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - QuestTracking - Player does not meet level threshold for debug offers, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - QuestTracking - Player does not meet level threshold for debug offers, ignoring")
|
||||
return
|
||||
end
|
||||
if QuestieDB.QueryQuestSingle(questID, "name") == nil then -- if ID not in our DB
|
||||
for i=1, GetNumQuestLogEntries() do
|
||||
local questTitle, questLevel, suggestedGroup, _, _, _, frequency, questLogId = GetQuestLogTitle(i)
|
||||
for i = 1, GetNumQuestLogEntries() do
|
||||
local questTitle, questLevel, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questLogId =
|
||||
GetQuestLogTitle(i)
|
||||
local questText, objectiveText = GetQuestLogQuestText(i)
|
||||
|
||||
if questText then questText = questText:gsub(GetUnitName(player), "<playername>") end -- strip out player name from quest text
|
||||
if questText then questText = questText:gsub(GetUnitName(player), "<playername>") end -- strip out player name from quest text
|
||||
if objectiveText then objectiveText = objectiveText:gsub(GetUnitName(player), "<playername>") end -- strip out player name from objective text
|
||||
|
||||
if questID == questLogId then
|
||||
debugIndex = debugIndex + 1
|
||||
DebugInformation[debugIndex] = "Quest in tracker not present in QuestDB!"
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n\n|cFFAAAAAAQuest ID:|r " .. tostring(questLogId)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAQuest Name:|r " .. tostring(questTitle)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAQuest Text:|r " .. tostring(questText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAAObjective Text:|r " .. tostring(objectiveText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n\n|cFFAAAAAAQuest ID:|r " .. tostring(questLogId)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAQuest Name:|r " .. tostring(questTitle)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAQuest Text:|r " .. tostring(questText)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAAObjective Text:|r " .. tostring(objectiveText)
|
||||
DebugInformation[debugIndex] = _AppendUniversalText(DebugInformation[debugIndex])
|
||||
Questie:Print(l10n("A quest in your quest log is missing from the Questie database and can't be tracked.") .. " " .. l10n("Would you like to help us fix it?") .. " |cff71d5ff|Haddon:questie:offer:" .. debugIndex .. "|h[" .. l10n("More Info") .. "]|h|r")
|
||||
Questie:Print(l10n(
|
||||
"A quest in your quest log is missing from the Questie database and can't be tracked.") ..
|
||||
" " ..
|
||||
l10n("Would you like to help us fix it?") ..
|
||||
" |cff71d5ff|Haddon:questie:offer:" .. debugIndex .. "|h[" .. l10n("More Info") .. "]|h|r")
|
||||
--print(tostring(QuestieDB.IsSoDRuneQuest(questlogid)))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local targetTimeout = {} -- store timeouts per-ID so we don't cause lag or spam chat if a player clicks on an unknown NPC often
|
||||
local targetTimeout = {} -- store timeouts per-ID so we don't cause lag or spam chat if a player clicks on an unknown NPC often
|
||||
local timeoutDurationOverworld = 120 -- how many seconds to ignore re-passes outside of instances
|
||||
local timeoutDurationInstance = 600 -- how many seconds to ignore re-passes outside of instances
|
||||
local timeoutDurationInstance = 600 -- how many seconds to ignore re-passes outside of instances
|
||||
-- Missing NPC ID when targeting
|
||||
function QuestieDebugOffer.NPCTarget()
|
||||
if UnitLevel(player) < minLevelForDebugOffers then -- if player level is below our threshold, ignore it
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - NPCTarget - Player does not meet level threshold for debug offers, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - NPCTarget - Player does not meet level threshold for debug offers, ignoring")
|
||||
return
|
||||
end
|
||||
local inInstance, _ = IsInInstance()
|
||||
if inInstance == true then -- temporary override for SoD launch to not prompt NPC debug offers inside instances at all, to prevent BFD spam
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - NPCTarget - Player targeting NPC is in instance, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - NPCTarget - Player targeting NPC is in instance, ignoring")
|
||||
return
|
||||
end
|
||||
local targetGUID = UnitGUID(target)
|
||||
local unit_type = strsplit("-", tostring(targetGUID)) -- determine target type
|
||||
if unit_type == "Creature" then -- if target is an NPC
|
||||
local unit_type = strsplit("-", tostring(targetGUID)) -- determine target type
|
||||
if unit_type == "Creature" then -- if target is an NPC
|
||||
local npcID = tonumber(targetGUID:match("-(%d+)-%x+$"), 10) -- obtain NPC ID
|
||||
if targetTimeout[npcID] == true then -- if target was already targeted recently
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - NPCTarget - Targeted NPC was targeted recently, ignoring")
|
||||
if not npcID then return end
|
||||
if targetTimeout[npcID] == true then -- if target was already targeted recently
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - NPCTarget - Targeted NPC was targeted recently, ignoring")
|
||||
return
|
||||
else -- if target was NOT targeted recently
|
||||
else -- if target was NOT targeted recently
|
||||
if tContains(npcBlacklist, npcID) then -- if NPC is in our blacklist, ignore it
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - NPCTarget - Targeted NPC is in NPC blacklist, ignoring")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieDebugOffer] - NPCTarget - Targeted NPC is in NPC blacklist, ignoring")
|
||||
return
|
||||
end
|
||||
targetTimeout[npcID] = true
|
||||
@@ -565,18 +608,26 @@ function QuestieDebugOffer.NPCTarget()
|
||||
elseif npcFriendly == false then
|
||||
npcStatus = "Neutral"
|
||||
end
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n\n|cFFAAAAAANPC ID:|r " .. tostring(npcID)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAANPC Name:|r " .. tostring(npcName)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAANPC Level:|r " .. tostring(npcLevel)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAANPC Health, Max:|r " .. tostring(npcHealth) .. ", " .. tostring(npcHealthMax)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] .. "\n|cFFAAAAAANPC Allegiance:|r " .. tostring(npcStatus)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n\n|cFFAAAAAANPC ID:|r " .. tostring(npcID)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAANPC Name:|r " .. tostring(npcName)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAANPC Level:|r " .. tostring(npcLevel)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAANPC Health, Max:|r " .. tostring(npcHealth) .. ", " .. tostring(npcHealthMax)
|
||||
DebugInformation[debugIndex] = DebugInformation[debugIndex] ..
|
||||
"\n|cFFAAAAAANPC Allegiance:|r " .. tostring(npcStatus)
|
||||
DebugInformation[debugIndex] = _AppendUniversalText(DebugInformation[debugIndex])
|
||||
Questie:Print(l10n("The NPC you just targeted is missing from the Questie database.") .. " " .. l10n("Would you like to help us fix it?") .. " |cff71d5ff|Haddon:questie:offer:" .. debugIndex .. "|h[" .. l10n("More Info") .. "]|h|r")
|
||||
Questie:Print(l10n("The NPC you just targeted is missing from the Questie database.") ..
|
||||
" " ..
|
||||
l10n("Would you like to help us fix it?") ..
|
||||
" |cff71d5ff|Haddon:questie:offer:" .. debugIndex .. "|h[" .. l10n("More Info") .. "]|h|r")
|
||||
end
|
||||
if inInstance == false then
|
||||
C_Timer.NewTimer (timeoutDurationOverworld, function() targetTimeout[npcID] = false end)
|
||||
C_Timer.NewTimer(timeoutDurationOverworld, function() targetTimeout[npcID] = false end)
|
||||
else
|
||||
C_Timer.NewTimer (timeoutDurationInstance, function() targetTimeout[npcID] = false end)
|
||||
C_Timer.NewTimer(timeoutDurationInstance, function() targetTimeout[npcID] = false end)
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -606,7 +657,8 @@ local function _CreateOfferFrame(popupText, discordURL, index)
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieDebugOffer] - An offer is already open, not creating new frame")
|
||||
return
|
||||
end
|
||||
local debugFrame = CreateFrame("Frame", "QuestieDebugOfferFrame", UIParent, BackdropTemplateMixin and "BackdropTemplate")
|
||||
local debugFrame = CreateFrame("Frame", "QuestieDebugOfferFrame", UIParent,
|
||||
BackdropTemplateMixin and "BackdropTemplate")
|
||||
debugFrame:SetPoint("CENTER")
|
||||
debugFrame:SetMovable(true)
|
||||
debugFrame:EnableMouse(true)
|
||||
@@ -623,7 +675,8 @@ local function _CreateOfferFrame(popupText, discordURL, index)
|
||||
|
||||
debugFrame.title = debugFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
|
||||
debugFrame.title:SetPoint("TOP", 0, -15)
|
||||
debugFrame.title:SetText("|TInterface\\Addons\\Questie\\Icons\\startendstart.tga:16|t |cFFFED218" .. l10n("Questie Debug Info") .. "|r |TInterface\\Addons\\Questie\\Icons\\startendstart.tga:16|t")
|
||||
debugFrame.title:SetText("|TInterface\\Addons\\Questie\\Icons\\startendstart.tga:16|t |cFFFED218" ..
|
||||
l10n("Questie Debug Info") .. "|r |TInterface\\Addons\\Questie\\Icons\\startendstart.tga:16|t")
|
||||
|
||||
-- Create a single large edit box with no background
|
||||
debugFrame.dataEditBox = CreateFrame("EditBox", nil, debugFrame)
|
||||
@@ -646,7 +699,10 @@ local function _CreateOfferFrame(popupText, discordURL, index)
|
||||
|
||||
debugFrame.discordText = debugFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
|
||||
debugFrame.discordText:SetPoint("TOP", debugFrame.dataEditBox, "BOTTOM", 0, -15)
|
||||
debugFrame.discordText:SetText("|cFFAAAAAA" .. l10n("Please share this info with us on") .. " |TInterface\\Addons\\Questie\\Icons\\discord.blp:16|t |cFF5765ECDiscord|r\n" .. "(" .. l10n("You can copy the data above") .. ")")
|
||||
debugFrame.discordText:SetText("|cFFAAAAAA" ..
|
||||
l10n("Please share this info with us on") ..
|
||||
" |TInterface\\Addons\\Questie\\Icons\\discord.blp:16|t |cFF5765ECDiscord|r\n" ..
|
||||
"(" .. l10n("You can copy the data above") .. ")")
|
||||
|
||||
debugFrame.discordLinkEditBox = CreateFrame("EditBox", nil, debugFrame, "InputBoxTemplate")
|
||||
debugFrame.discordLinkEditBox:SetSize(200, 20)
|
||||
@@ -666,7 +722,9 @@ local function _CreateOfferFrame(popupText, discordURL, index)
|
||||
debugFrame:SetBackdrop({
|
||||
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
|
||||
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
|
||||
tile = true, tileSize = 32, edgeSize = 32,
|
||||
tile = true,
|
||||
tileSize = 32,
|
||||
edgeSize = 32,
|
||||
insets = { left = 8, right = 8, top = 8, bottom = 8 }
|
||||
})
|
||||
|
||||
@@ -680,7 +738,8 @@ end
|
||||
function QuestieDebugOffer.ShowOffer(link)
|
||||
-- We also have access to the questie.dev domain (purchased by Logon)
|
||||
local discordURL = "https://discord.gg/Q6j4qByndw" -- redirect to #bug-redirect
|
||||
local i = tonumber(string.sub(link,21))
|
||||
local i = tonumber(string.sub(link, 21))
|
||||
if not i then return end
|
||||
local popupText = DebugInformation[i]
|
||||
|
||||
_CreateOfferFrame(popupText, discordURL, i)
|
||||
|
||||
@@ -91,7 +91,7 @@ function QuestieLearner:LearnNPC(npcId, name, level, subName, npcFlags, factionS
|
||||
end
|
||||
end
|
||||
if not found then
|
||||
table.insert(existing[7][zoneId], {x, y})
|
||||
table.insert(existing[7][zoneId], { x, y })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -117,7 +117,7 @@ function QuestieLearner:LearnQuest(questId, name, questLevel, requiredLevel, zon
|
||||
if type(objectives) == "table" then
|
||||
existing[8] = objectives
|
||||
elseif type(objectives) == "string" then
|
||||
existing[8] = {objectives}
|
||||
existing[8] = { objectives }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -140,7 +140,9 @@ function QuestieLearner:LearnQuestGiver(questId, npcId, isStart)
|
||||
existing[2][1] = existing[2][1] or {}
|
||||
local found = false
|
||||
for _, id in ipairs(existing[2][1]) do
|
||||
if id == npcId then found = true; break end
|
||||
if id == npcId then
|
||||
found = true; break
|
||||
end
|
||||
end
|
||||
if not found then table.insert(existing[2][1], npcId) end
|
||||
else
|
||||
@@ -148,7 +150,9 @@ function QuestieLearner:LearnQuestGiver(questId, npcId, isStart)
|
||||
existing[3][1] = existing[3][1] or {}
|
||||
local found = false
|
||||
for _, id in ipairs(existing[3][1]) do
|
||||
if id == npcId then found = true; break end
|
||||
if id == npcId then
|
||||
found = true; break
|
||||
end
|
||||
end
|
||||
if not found then table.insert(existing[3][1], npcId) end
|
||||
end
|
||||
@@ -188,7 +192,9 @@ function QuestieLearner:LearnItemDrop(itemId, npcId)
|
||||
existing[2] = existing[2] or {}
|
||||
local found = false
|
||||
for _, id in ipairs(existing[2]) do
|
||||
if id == npcId then found = true; break end
|
||||
if id == npcId then
|
||||
found = true; break
|
||||
end
|
||||
end
|
||||
if not found then table.insert(existing[2], npcId) end
|
||||
end
|
||||
@@ -221,7 +227,7 @@ function QuestieLearner:LearnObject(objectId, name)
|
||||
end
|
||||
end
|
||||
if not found then
|
||||
table.insert(existing[4][zoneId], {x, y})
|
||||
table.insert(existing[4][zoneId], { x, y })
|
||||
end
|
||||
end
|
||||
|
||||
@@ -513,13 +519,15 @@ function QuestieLearner:OnLootOpened()
|
||||
|
||||
local numItems = GetNumLootItems()
|
||||
for i = 1, numItems do
|
||||
local lootIcon, lootName, lootQuantity, currencyID, lootQuality, locked, isQuestItem, questId, isActive = GetLootSlotInfo(i)
|
||||
local lootIcon, lootName, lootQuantity, currencyID, lootQuality, locked, isQuestItem, questId, isActive =
|
||||
GetLootSlotInfo(i)
|
||||
if lootName then
|
||||
local link = GetLootSlotLink(i)
|
||||
if link then
|
||||
local itemId = tonumber(string.match(link, "item:(%d+)"))
|
||||
if itemId then
|
||||
local _, _, _, itemLevel, requiredLevel, itemType, itemSubType, _, _, _, _, itemClassId, itemSubClassId = GetItemInfo(link)
|
||||
local _, _, _, itemLevel, requiredLevel, itemType, itemSubType, _, _, _, _, itemClassId, itemSubClassId =
|
||||
GetItemInfo(link)
|
||||
self:LearnItem(itemId, lootName, itemLevel, requiredLevel, itemClassId, itemSubClassId)
|
||||
|
||||
if npcId then
|
||||
|
||||
@@ -6,7 +6,7 @@ Flow:
|
||||
----> Game cache should have all quests in it, data of each quest may be invalid.
|
||||
If data is invalid, Wait for next QUEST_LOG_UPDATE and check again.
|
||||
-----> Game Cache ok. Call possible callback functions.
|
||||
]]--
|
||||
]] --
|
||||
|
||||
---@class QuestieValidateGameCache
|
||||
local QuestieValidateGameCache = QuestieLoader:CreateModule("QuestieValidateGameCache")
|
||||
@@ -22,7 +22,7 @@ local GetQuestObjectives = QuestieCompat.C_QuestLog.GetQuestObjectives
|
||||
local HaveQuestData = QuestieCompat.HaveQuestData
|
||||
|
||||
local stringByte, tremove = string.byte, table.remove
|
||||
local tpack = QuestieLib.tpack
|
||||
local tpack = QuestieLib.tpack
|
||||
local tunpack = QuestieLib.tunpack
|
||||
|
||||
-- 3 * (Max possible number of quests in game quest log)
|
||||
@@ -50,11 +50,10 @@ function QuestieValidateGameCache.AddCallback(func, ...)
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieValidateGameCache] Calling a callback function imediately.")
|
||||
func(...)
|
||||
else
|
||||
callbacks[#callbacks+1] = {func, tpack(...)}
|
||||
callbacks[#callbacks + 1] = { func, tpack(...) }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function DestroyEventFrame()
|
||||
if eventFrame then
|
||||
eventFrame:UnregisterAllEvents()
|
||||
@@ -72,7 +71,9 @@ local function OnQuestLogUpdate()
|
||||
-- This is to wait until cache has atleast some refreshed data from a game server.
|
||||
if numberOfQuestLogUpdatesToSkip > 0 then
|
||||
numberOfQuestLogUpdatesToSkip = numberOfQuestLogUpdatesToSkip - 1
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieValidateGameCache] Skipping a QUEST_LOG_UPDATE event. Quest log has entries, quests:", numEntries, numQuests)
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieValidateGameCache] Skipping a QUEST_LOG_UPDATE event. Quest log has entries, quests:", numEntries,
|
||||
numQuests)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -80,11 +81,8 @@ local function OnQuestLogUpdate()
|
||||
local goodQuestsCount = 0 -- for debug stats
|
||||
|
||||
for i = 1, MAX_QUEST_LOG_INDEX do
|
||||
local title, _, _, isHeader, _, _, _, questId = GetQuestLogTitle(i)
|
||||
if (not title) then
|
||||
break -- We exceeded the data in the quest log
|
||||
end
|
||||
if (not isHeader) then
|
||||
local title, level, questTag, isHeader, isCollapsed, isComplete, isDaily, questId = GetQuestLogTitle(i)
|
||||
if title and questId and (not isHeader) then
|
||||
if (not HaveQuestData(questId)) then
|
||||
isQuestLogGood = false
|
||||
else
|
||||
@@ -95,11 +93,13 @@ local function OnQuestLogUpdate()
|
||||
-- On WotLK private servers, GetQuestObjectives can return nil for quests with
|
||||
-- no trackable objectives. This is not a broken cache state; treat it as an
|
||||
-- empty (valid) objective list so goodQuestsCount increments correctly.
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieValidateGameCache] GetQuestObjectives returned non-table for questId:", questId, "- treating as empty objectives")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[QuestieValidateGameCache] GetQuestObjectives returned non-table for questId:", questId,
|
||||
"- treating as empty objectives")
|
||||
objectiveList = {}
|
||||
end
|
||||
|
||||
for _, objective in pairs(objectiveList) do -- objectiveList may be {}, which is also a valid cached quest in quest log
|
||||
for _, objective in pairs(objectiveList) do -- objectiveList may be {}, which is also a valid cached quest in quest log
|
||||
if (not objective.text) or (stringByte(objective.text, 1) == 32) then -- if (text starts with a space " ") then
|
||||
-- Game hasn't cached the quest fully yet
|
||||
isQuestLogGood = false
|
||||
@@ -117,7 +117,8 @@ local function OnQuestLogUpdate()
|
||||
end
|
||||
|
||||
if not isQuestLogGood then
|
||||
Questie:Debug(Questie.DEBUG_INFO, "[QuestieValidateGameCache] Quest log is NOT yet okey. Good quest:", goodQuestsCount.."/"..numQuests )
|
||||
Questie:Debug(Questie.DEBUG_INFO, "[QuestieValidateGameCache] Quest log is NOT yet okey. Good quest:",
|
||||
goodQuestsCount .. "/" .. numQuests)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -125,12 +126,15 @@ local function OnQuestLogUpdate()
|
||||
-- This count mismatch can occur on WotLK private servers where GetNumQuestLogEntries
|
||||
-- returns a different value than objectives-loop counted. The cache is valid because
|
||||
-- isQuestLogGood already passed above. Log at debug level only.
|
||||
Questie:Debug(Questie.DEBUG_INFO, "[QuestieValidateGameCache] Quest count mismatch (expected "..tostring(numQuests)..", validated "..tostring(goodQuestsCount).."). Cache is still valid.")
|
||||
Questie:Debug(Questie.DEBUG_INFO,
|
||||
"[QuestieValidateGameCache] Quest count mismatch (expected " ..
|
||||
tostring(numQuests) .. ", validated " .. tostring(goodQuestsCount) .. "). Cache is still valid.")
|
||||
end
|
||||
|
||||
DestroyEventFrame()
|
||||
|
||||
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieValidateGameCache] Quest log is ok. Good quest:", goodQuestsCount.."/"..numQuests )
|
||||
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieValidateGameCache] Quest log is ok. Good quest:",
|
||||
goodQuestsCount .. "/" .. numQuests)
|
||||
|
||||
isCacheGood = true
|
||||
|
||||
@@ -148,7 +152,7 @@ local function OnPlayerEnteringWorld(_, _, isInitialLogin, isReloadingUi)
|
||||
if QuestieCompat.Is335 then
|
||||
isInitialLogin, isReloadingUi = false, true -- 335 Not skipping for now
|
||||
end
|
||||
assert(isInitialLogin or isReloadingUi) -- We should get to here only at login or at /reload.
|
||||
assert(isInitialLogin or isReloadingUi) -- We should get to here only at login or at /reload.
|
||||
|
||||
-- Game's quest log has still old cached data on the first QUEST_LOG_UPDATE after PLAYER_ENTERING_WORLD during login.
|
||||
-- So we need to skip that event.
|
||||
@@ -167,4 +171,4 @@ function QuestieValidateGameCache.StartCheck()
|
||||
eventFrame = CreateFrame("Frame")
|
||||
eventFrame:SetScript("OnEvent", OnPlayerEnteringWorld)
|
||||
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ local function _Questie_SilentGetQuestLogIndexByID(questId)
|
||||
local n = (GetNumQuestLogEntries and select(1, GetNumQuestLogEntries())) or 0
|
||||
if n > 0 and GetQuestLogTitle then
|
||||
for i = 1, n do
|
||||
local _, _, _, _, isHeader, _, _, _, qid = GetQuestLogTitle(i)
|
||||
local _, _, _, isHeader, _, _, _, qid = GetQuestLogTitle(i)
|
||||
qid = tonumber(qid)
|
||||
if (not isHeader) and qid and qid == questId then
|
||||
return i
|
||||
@@ -133,7 +133,8 @@ function MapIconTooltip:Show()
|
||||
local iconData = icon.data
|
||||
|
||||
if not iconData then
|
||||
Questie:Error("[MapIconTooltip:Show] handleMapIcon - iconData is nil! self.data.Id =", self.data.Id, "- Aborting!")
|
||||
Questie:Error("[MapIconTooltip:Show] handleMapIcon - iconData is nil! self.data.Id =", self.data.Id,
|
||||
"- Aborting!")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -166,14 +167,14 @@ function MapIconTooltip:Show()
|
||||
end
|
||||
|
||||
local orderedTooltips = {}
|
||||
local _qid = tonumber(iconData.Id)
|
||||
if _qid and _Questie_SilentGetQuestLogIndexByID(_qid) <= 0 then
|
||||
return
|
||||
end
|
||||
local _ok = pcall(iconData.ObjectiveData.Update, iconData.ObjectiveData)
|
||||
if not _ok then
|
||||
return
|
||||
end
|
||||
local _qid = tonumber(iconData.Id)
|
||||
if _qid and _Questie_SilentGetQuestLogIndexByID(_qid) <= 0 then
|
||||
return
|
||||
end
|
||||
local _ok = pcall(iconData.ObjectiveData.Update, iconData.ObjectiveData)
|
||||
if not _ok then
|
||||
return
|
||||
end
|
||||
if iconData.Type == "event" then
|
||||
local tip = _MapIconTooltip:GetEventObjectiveTooltip(icon.data)
|
||||
|
||||
@@ -257,26 +258,33 @@ end
|
||||
local quest = QuestieDB.GetQuest(questData.questId)
|
||||
local rewardString = ""
|
||||
if (quest and shift) then
|
||||
local xpReward = QuestXP:GetQuestLogRewardXP(questData.questId, Questie.db.profile.showQuestXpAtMaxLevel)
|
||||
local xpReward = QuestXP:GetQuestLogRewardXP(questData.questId,
|
||||
Questie.db.profile.showQuestXpAtMaxLevel)
|
||||
if xpReward > 0 then
|
||||
rewardString = QuestieLib:PrintDifficultyColor(quest.level, "(" .. FormatLargeNumber(xpReward) .. xpString .. ") ", QuestieDB.IsRepeatable(questData.questId), QuestieDB.IsActiveEventQuest(questData.questId), QuestieDB.IsPvPQuest(questData.questId))
|
||||
rewardString = QuestieLib:PrintDifficultyColor(quest.level,
|
||||
"(" .. FormatLargeNumber(xpReward) .. xpString .. ") ",
|
||||
QuestieDB.IsRepeatable(questData.questId),
|
||||
QuestieDB.IsActiveEventQuest(questData.questId), QuestieDB.IsPvPQuest(questData.questId))
|
||||
end
|
||||
|
||||
local moneyReward = QuestXP.GetQuestRewardMoney(questData.questId)
|
||||
if moneyReward > 0 then
|
||||
rewardString = rewardString .. Questie:Colorize("(" .. GetCoinTextureString(moneyReward) .. ") ", "white")
|
||||
rewardString = rewardString ..
|
||||
Questie:Colorize("(" .. GetCoinTextureString(moneyReward) .. ") ", "white")
|
||||
end
|
||||
end
|
||||
rewardString = rewardString .. questData.type
|
||||
|
||||
if (not shift) and reputationReward and next(reputationReward) then
|
||||
self:AddDoubleLine(REPUTATION_ICON_TEXTURE .. " " .. questData.title, rewardString, 1, 1, 1, 1, 1, 0);
|
||||
self:AddDoubleLine(REPUTATION_ICON_TEXTURE .. " " .. questData.title, rewardString, 1, 1, 1, 1, 1,
|
||||
0);
|
||||
else
|
||||
if shift then
|
||||
self:AddDoubleLine(questData.title, rewardString, 1, 1, 1, 1, 1, 0);
|
||||
else
|
||||
-- We use a transparent icon because this eases setting the correct margin
|
||||
self:AddDoubleLine(TRANSPARENT_ICON_TEXTURE .. " " .. questData.title, rewardString, 1, 1, 1, 1, 1, 0);
|
||||
self:AddDoubleLine(TRANSPARENT_ICON_TEXTURE .. " " .. questData.title, rewardString, 1, 1, 1,
|
||||
1, 1, 0);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -284,13 +292,15 @@ end
|
||||
local dataType = type(questData.subData)
|
||||
if dataType == "table" then
|
||||
for _, rawLine in pairs(questData.subData) do
|
||||
local lines = QuestieLib:TextWrap(rawLine, " ", false, math.max(375, Tooltip:GetWidth()), questData.questId) --275 is the default questlog width
|
||||
local lines = QuestieLib:TextWrap(rawLine, " ", false, math.max(375, Tooltip:GetWidth()),
|
||||
questData.questId) --275 is the default questlog width
|
||||
for _, line in pairs(lines) do
|
||||
self:AddLine(line, 0.86, 0.86, 0.86);
|
||||
end
|
||||
end
|
||||
elseif dataType == "string" then
|
||||
local lines = QuestieLib:TextWrap(questData.subData, " ", false, math.max(375, Tooltip:GetWidth())) --275 is the default questlog width
|
||||
local lines = QuestieLib:TextWrap(questData.subData, " ", false,
|
||||
math.max(375, Tooltip:GetWidth())) --275 is the default questlog width
|
||||
for _, line in pairs(lines) do
|
||||
self:AddLine(line, 0.86, 0.86, 0.86);
|
||||
end
|
||||
@@ -303,19 +313,21 @@ end
|
||||
local nextQuest = QuestieDB.GetQuest(nextQuestInChain)
|
||||
local firstInChain = true;
|
||||
while nextQuest ~= nil do
|
||||
|
||||
local nextQuestTitleString;
|
||||
local nextQuestXpRewardString = "";
|
||||
local nextQuestMoneyRewardString = "";
|
||||
local nextQuestIdString = "";
|
||||
local nextQuestTagString = "";
|
||||
if firstInChain then
|
||||
self:AddLine(" |T" .. QuestieLib.AddonPath .. "Icons\\nextquest.blp:16|t " .. l10n("Next in chain:"), 0.86, 0.86, 0.86)
|
||||
self:AddLine(
|
||||
" |T" .. QuestieLib.AddonPath .. "Icons\\nextquest.blp:16|t " .. l10n("Next in chain:"),
|
||||
0.86, 0.86, 0.86)
|
||||
firstInChain = false;
|
||||
end
|
||||
|
||||
if Questie.db.profile.enableTooltipsQuestLevel then
|
||||
nextQuestTitleString = string.format("%s", QuestieLib:GetLevelString(nextQuest.Id, "", nextQuest.level, true) .. nextQuest.name)
|
||||
nextQuestTitleString = string.format("%s",
|
||||
QuestieLib:GetLevelString(nextQuest.Id, "", nextQuest.level, true) .. nextQuest.name)
|
||||
else
|
||||
nextQuestTitleString = string.format("%s", nextQuest.name)
|
||||
end
|
||||
@@ -324,14 +336,17 @@ end
|
||||
nextQuestIdString = string.format(" (%d)", nextQuest.Id)
|
||||
end
|
||||
|
||||
local nextQuestXpReward = QuestXP:GetQuestLogRewardXP(nextQuest.Id, Questie.db.profile.showQuestXpAtMaxLevel);
|
||||
local nextQuestXpReward = QuestXP:GetQuestLogRewardXP(nextQuest.Id,
|
||||
Questie.db.profile.showQuestXpAtMaxLevel);
|
||||
if nextQuestXpReward > 0 then
|
||||
nextQuestXpRewardString = string.format(" (%s%s)", FormatLargeNumber(nextQuestXpReward), xpString);
|
||||
nextQuestXpRewardString = string.format(" (%s%s)", FormatLargeNumber(nextQuestXpReward),
|
||||
xpString);
|
||||
end
|
||||
|
||||
local nextQuestMoneyReward = QuestXP:GetQuestRewardMoney(nextQuest.Id);
|
||||
if nextQuestMoneyReward > 0 then
|
||||
nextQuestMoneyRewardString = Questie:Colorize(string.format(" (%s)", GetCoinTextureString(nextQuestMoneyReward)), "white");
|
||||
nextQuestMoneyRewardString = Questie:Colorize(
|
||||
string.format(" (%s)", GetCoinTextureString(nextQuestMoneyReward)), "white");
|
||||
end
|
||||
|
||||
if (QuestieDB.IsGroupQuest(nextQuest.Id) or QuestieDB.IsDungeonQuest(nextQuest.Id) or QuestieDB.IsRaidQuest(nextQuest.Id)) then
|
||||
@@ -339,8 +354,12 @@ end
|
||||
nextQuestTagString = Questie:Colorize(string.format(" (%s)", nextQuestTag), "yellow")
|
||||
end
|
||||
|
||||
local nextQuestString = string.format(" %s%s%s%s%s", nextQuestTitleString, nextQuestIdString, nextQuestXpRewardString, nextQuestMoneyRewardString, nextQuestTagString); -- we need an offset to align with description
|
||||
self:AddLine(QuestieLib:PrintDifficultyColor(nextQuest.level, nextQuestString, QuestieDB.IsRepeatable(nextQuest.Id), QuestieDB.IsActiveEventQuest(nextQuest.Id), QuestieDB.IsPvPQuest(nextQuest.Id)), 1, 1, 1);
|
||||
local nextQuestString = string.format(" %s%s%s%s%s", nextQuestTitleString, nextQuestIdString,
|
||||
nextQuestXpRewardString, nextQuestMoneyRewardString, nextQuestTagString); -- we need an offset to align with description
|
||||
self:AddLine(
|
||||
QuestieLib:PrintDifficultyColor(nextQuest.level, nextQuestString,
|
||||
QuestieDB.IsRepeatable(nextQuest.Id), QuestieDB.IsActiveEventQuest(nextQuest.Id),
|
||||
QuestieDB.IsPvPQuest(nextQuest.Id)), 1, 1, 1);
|
||||
nextQuest = QuestieDB.GetQuest(nextQuest.nextQuestInChain)
|
||||
end
|
||||
end
|
||||
@@ -374,7 +393,8 @@ end
|
||||
aldorPenalty = 0 - math.floor(rewardValue * 1.1)
|
||||
end
|
||||
|
||||
rewardTable[#rewardTable + 1] = (rewardValue > 0 and "+" or "") .. rewardValue .. " " .. factionName
|
||||
rewardTable[#rewardTable + 1] = (rewardValue > 0 and "+" or "") ..
|
||||
rewardValue .. " " .. factionName
|
||||
end
|
||||
end
|
||||
|
||||
@@ -386,7 +406,9 @@ end
|
||||
rewardTable[#rewardTable + 1] = scryersPenalty .. " " .. factionName
|
||||
end
|
||||
|
||||
self:AddLine(REPUTATION_ICON_TEXTURE .. " " .. Questie:Colorize(table.concat(rewardTable, " / "), "reputationBlue"), 1, 1, 1, 1, 1, 0)
|
||||
self:AddLine(
|
||||
REPUTATION_ICON_TEXTURE ..
|
||||
" " .. Questie:Colorize(table.concat(rewardTable, " / "), "reputationBlue"), 1, 1, 1, 1, 1, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -396,13 +418,16 @@ end
|
||||
for questId, textList in pairs(self.questOrder) do -- this logic really needs to be improved
|
||||
---@type Quest
|
||||
local quest = QuestieDB.GetQuest(questId);
|
||||
local questTitle = QuestieLib:GetColoredQuestName(questId, Questie.db.profile.enableTooltipsQuestLevel, true, true);
|
||||
local questTitle = QuestieLib:GetColoredQuestName(questId, Questie.db.profile.enableTooltipsQuestLevel, true,
|
||||
true);
|
||||
local xpReward = QuestXP:GetQuestLogRewardXP(questId, Questie.db.profile.showQuestXpAtMaxLevel);
|
||||
r, g, b = QuestieLib:GetDifficultyColorPercent(quest.level);
|
||||
if haveGiver then
|
||||
if shift and xpReward then
|
||||
self:AddLine(" ");
|
||||
self:AddDoubleLine(questTitle, "(" .. FormatLargeNumber(xpReward) .. xpString .. ") (" .. l10n("Active") .. ")", 0.2, 1, 0.2, 1, 1, 0);
|
||||
self:AddDoubleLine(questTitle,
|
||||
"(" .. FormatLargeNumber(xpReward) .. xpString .. ") (" .. l10n("Active") .. ")", 0.2, 1, 0.2, 1,
|
||||
1, 0);
|
||||
haveGiver = false -- looks better when only the first one shows (active)
|
||||
else
|
||||
self:AddLine(" ");
|
||||
@@ -411,7 +436,8 @@ end
|
||||
end
|
||||
else
|
||||
if (quest and shift and xpReward > 0) then
|
||||
self:AddDoubleLine(questTitle, "(" .. FormatLargeNumber(xpReward) .. xpString .. ")", 0.2, 1, 0.2, r, g, b);
|
||||
self:AddDoubleLine(questTitle, "(" .. FormatLargeNumber(xpReward) .. xpString .. ")", 0.2, 1, 0.2, r,
|
||||
g, b);
|
||||
firstLine = false;
|
||||
elseif (firstLine and not shift) then
|
||||
self:AddDoubleLine(questTitle, "(" .. l10n('Hold Shift') .. ")", 0.2, 1, 0.2, 0.43, 0.43, 0.43); --"(Shift+click)"
|
||||
@@ -592,9 +618,12 @@ function _MapIconTooltip:GetObjectiveTooltip(icon)
|
||||
local color = QuestieLib:GetRGBForObjective(iconData.ObjectiveData)
|
||||
if iconData.ObjectiveData.Needed then
|
||||
if iconData.ObjectiveData.Type == "spell" and iconData.ObjectiveData.spawnList[iconData.ObjectiveTargetId].ItemId then
|
||||
text = color .. tostring(QuestieDB.QueryItemSingle(iconData.ObjectiveData.spawnList[iconData.ObjectiveTargetId].ItemId, "name"))
|
||||
text = color ..
|
||||
tostring(QuestieDB.QueryItemSingle(iconData.ObjectiveData.spawnList[iconData.ObjectiveTargetId].ItemId,
|
||||
"name"))
|
||||
else
|
||||
text = color .. tostring(iconData.ObjectiveData.Collected) .. "/" .. tostring(iconData.ObjectiveData.Needed) .. " " .. text
|
||||
text = color ..
|
||||
tostring(iconData.ObjectiveData.Collected) .. "/" .. tostring(iconData.ObjectiveData.Needed) .. " " .. text
|
||||
end
|
||||
end
|
||||
if QuestieComms then
|
||||
@@ -617,17 +646,20 @@ function _MapIconTooltip:GetObjectiveTooltip(icon)
|
||||
if playerColor then
|
||||
local objectiveEntry = objectiveData[iconData.ObjectiveIndex]
|
||||
if not objectiveEntry then
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[_MapIconTooltip:GetObjectiveTooltip] No objective data for quest", quest.Id)
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[_MapIconTooltip:GetObjectiveTooltip] No objective data for quest", quest.Id)
|
||||
objectiveEntry = {} -- This will make "GetRGBForObjective" return default color
|
||||
end
|
||||
local remoteColor = QuestieLib:GetRGBForObjective(objectiveEntry)
|
||||
local colorizedPlayerName = " (" .. playerColor .. playerName .. "|r" .. remoteColor .. ")|r" .. playerType
|
||||
local colorizedPlayerName = " (" ..
|
||||
playerColor .. playerName .. "|r" .. remoteColor .. ")|r" .. playerType
|
||||
local remoteText = iconData.ObjectiveData.Description
|
||||
|
||||
if objectiveEntry and objectiveEntry.fulfilled and objectiveEntry.required then
|
||||
local fulfilled = objectiveEntry.fulfilled;
|
||||
local required = objectiveEntry.required;
|
||||
remoteText = remoteColor .. tostring(fulfilled) .. "/" .. tostring(required) .. " " .. remoteText .. colorizedPlayerName;
|
||||
remoteText = remoteColor ..
|
||||
tostring(fulfilled) .. "/" .. tostring(required) .. " " .. remoteText .. colorizedPlayerName;
|
||||
else
|
||||
remoteText = remoteColor .. remoteText .. colorizedPlayerName;
|
||||
end
|
||||
|
||||
@@ -259,12 +259,12 @@ function _QuestieTooltips:AddUnitDataToTooltip()
|
||||
local type, _, _, _, _, npcId, _ = strsplit("-", guid or "");
|
||||
|
||||
if name and (type == "Creature" or type == "Vehicle") and (
|
||||
name ~= QuestieTooltips.lastGametooltipUnit or
|
||||
(not QuestieTooltips.lastGametooltipCount) or
|
||||
_QuestieTooltips:CountTooltip() < QuestieTooltips.lastGametooltipCount or
|
||||
QuestieTooltips.lastGametooltipType ~= "monster" or
|
||||
lastGuid ~= guid
|
||||
) then
|
||||
name ~= QuestieTooltips.lastGametooltipUnit or
|
||||
(not QuestieTooltips.lastGametooltipCount) or
|
||||
_QuestieTooltips:CountTooltip() < QuestieTooltips.lastGametooltipCount or
|
||||
QuestieTooltips.lastGametooltipType ~= "monster" or
|
||||
lastGuid ~= guid
|
||||
) then
|
||||
QuestieTooltips.lastGametooltipUnit = name
|
||||
|
||||
local tooltipData = QuestieTooltips:GetTooltip("m_" .. npcId);
|
||||
@@ -273,7 +273,7 @@ function _QuestieTooltips:AddUnitDataToTooltip()
|
||||
if Questie.db.profile.enableTooltipsNPCID == true then
|
||||
GameTooltip:AddDoubleLine("NPC ID", "|cFFFFFFFF" .. npcId .. "|r")
|
||||
end
|
||||
for _, v in pairs (tooltipData) do
|
||||
for _, v in pairs(tooltipData) do
|
||||
GameTooltip:AddLine(v)
|
||||
end
|
||||
else
|
||||
@@ -307,23 +307,25 @@ function _QuestieTooltips:AddItemDataToTooltip()
|
||||
local name, link = self:GetItem()
|
||||
local itemId
|
||||
if link then
|
||||
itemId = select(3, string.match(link, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*):?(%d*):?(%-?%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?"))
|
||||
itemId = select(3,
|
||||
string.match(link,
|
||||
"|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*):?(%d*):?(%-?%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?"))
|
||||
end
|
||||
if name and itemId and (
|
||||
name ~= QuestieTooltips.lastGametooltipItem or
|
||||
(not QuestieTooltips.lastGametooltipCount) or
|
||||
_QuestieTooltips:CountTooltip() < QuestieTooltips.lastGametooltipCount or
|
||||
QuestieTooltips.lastGametooltipType ~= "item" or
|
||||
lastItemId ~= itemId or
|
||||
QuestieTooltips.lastFrameName ~= self:GetName()
|
||||
) then
|
||||
name ~= QuestieTooltips.lastGametooltipItem or
|
||||
(not QuestieTooltips.lastGametooltipCount) or
|
||||
_QuestieTooltips:CountTooltip() < QuestieTooltips.lastGametooltipCount or
|
||||
QuestieTooltips.lastGametooltipType ~= "item" or
|
||||
lastItemId ~= itemId or
|
||||
QuestieTooltips.lastFrameName ~= self:GetName()
|
||||
) then
|
||||
QuestieTooltips.lastGametooltipItem = name
|
||||
local tooltipData = QuestieTooltips:GetTooltip("i_" .. (itemId or 0));
|
||||
if tooltipData then
|
||||
if Questie.db.profile.enableTooltipsItemID == true then
|
||||
GameTooltip:AddDoubleLine("Item ID", "|cFFFFFFFF" .. itemId .. "|r")
|
||||
end
|
||||
for _, v in pairs (tooltipData) do
|
||||
for _, v in pairs(tooltipData) do
|
||||
self:AddLine(v)
|
||||
end
|
||||
end
|
||||
@@ -363,7 +365,7 @@ function _QuestieTooltips:AddObjectDataToTooltip(name)
|
||||
|
||||
if tooltipData[2] then
|
||||
-- Quest has objectives
|
||||
for index, line in pairs (tooltipData) do
|
||||
for index, line in pairs(tooltipData) do
|
||||
if index > 1 and (not alreadyAddedObjectiveLines[line]) then -- skip the first entry, it's the title
|
||||
local _, _, acquired, needed = string.find(line, "(%d+)/(%d+)")
|
||||
-- We need "tonumber", because acquired can contain parts of the color string
|
||||
@@ -386,7 +388,7 @@ end
|
||||
function _QuestieTooltips:CountTooltip()
|
||||
local tooltipCount = 0
|
||||
for i = 1, GameTooltip:NumLines() do
|
||||
local frame = _G["GameTooltipTextLeft"..i]
|
||||
local frame = _G["GameTooltipTextLeft" .. i]
|
||||
if frame and frame:GetText() then
|
||||
tooltipCount = tooltipCount + 1
|
||||
else
|
||||
|
||||
@@ -2278,7 +2278,6 @@ function QuestieTracker.RemoveQuestWatch(index, isQuestie)
|
||||
QuestieTracker:UntrackQuestId(questId)
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveQuestWatch] - by Blizzard", questId)
|
||||
end
|
||||
|
||||
end
|
||||
else
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTracker.RemoveQuestWatch] - by Questie")
|
||||
|
||||
@@ -70,7 +70,8 @@ local bindTruthTable = {
|
||||
['disabled'] = function() return false end,
|
||||
}
|
||||
|
||||
local _QuestLogScrollBar = QuestLogScrollFrameScrollBar or QuestLogListScrollFrame.ScrollBar or QuestLogListScrollFrameScrollBar
|
||||
local _QuestLogScrollBar = QuestLogScrollFrameScrollBar or QuestLogListScrollFrame.ScrollBar or
|
||||
QuestLogListScrollFrameScrollBar
|
||||
|
||||
---@param quest table The table provided by QuestieDB.GetQuest(questId)
|
||||
function TrackerUtils:ShowQuestLog(quest)
|
||||
@@ -107,7 +108,6 @@ function TrackerUtils:ShowQuestLog(quest)
|
||||
QuestLog_Update()
|
||||
end
|
||||
|
||||
|
||||
---@param title string The name of the WayPoint
|
||||
---@param zone number The zone ID number
|
||||
---@param x number X coordinate
|
||||
@@ -670,7 +670,8 @@ local function _GetZoneName(zoneOrSort, questId)
|
||||
else
|
||||
-- The quest has no explicit zone or category. Fallback to "Unknown Zone"
|
||||
zoneName = "Unknown Zone"
|
||||
Questie:Debug(Questie.DEBUG_CRITICAL, "[TrackerUtils:_GetZoneName] zoneOrSort", zoneOrSort, "of quest", questId, "is not in the Database!")
|
||||
Questie:Debug(Questie.DEBUG_CRITICAL, "[TrackerUtils:_GetZoneName] zoneOrSort", zoneOrSort, "of quest",
|
||||
questId, "is not in the Database!")
|
||||
end
|
||||
else
|
||||
-- Let's create custom Zones based on Sorting type.
|
||||
@@ -890,15 +891,18 @@ function TrackerUtils:GetSortedQuestIds()
|
||||
local playerPosition
|
||||
questZoneProximityTimer = C_Timer.NewTicker(5.0, function()
|
||||
if IsInInstance() and questZoneProximityTimer then
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP, "[TrackerUtils:GetSortedQuestIds] - Zone Proximity Timer Stoped!")
|
||||
Questie:Debug(Questie.DEBUG_DEVELOP,
|
||||
"[TrackerUtils:GetSortedQuestIds] - Zone Proximity Timer Stoped!")
|
||||
questZoneProximityTimer:Cancel()
|
||||
questZoneProximityTimer = nil
|
||||
else
|
||||
local position = _GetWorldPlayerPosition()
|
||||
if position then
|
||||
local distance = playerPosition and _GetDistance(position.x, position.y, playerPosition.x, playerPosition.y)
|
||||
local distance = playerPosition and
|
||||
_GetDistance(position.x, position.y, playerPosition.x, playerPosition.y)
|
||||
if not distance or distance > 0.01 then -- Position has changed
|
||||
Questie:Debug(Questie.DEBUG_SPAM, "[TrackerUtils:GetSortedQuestIds] - Zone Proximity Timer Updated!")
|
||||
Questie:Debug(Questie.DEBUG_SPAM,
|
||||
"[TrackerUtils:GetSortedQuestIds] - Zone Proximity Timer Updated!")
|
||||
playerPosition = position
|
||||
local orderCopy = {}
|
||||
|
||||
@@ -1006,9 +1010,11 @@ function TrackerUtils:GetSortedQuestIds()
|
||||
else
|
||||
local position = _GetWorldPlayerPosition()
|
||||
if position then
|
||||
local distance = playerPosition and _GetDistance(position.x, position.y, playerPosition.x, playerPosition.y)
|
||||
local distance = playerPosition and
|
||||
_GetDistance(position.x, position.y, playerPosition.x, playerPosition.y)
|
||||
if not distance or distance > 0.01 then -- Position has changed
|
||||
Questie:Debug(Questie.DEBUG_SPAM, "[TrackerUtils:GetSortedQuestIds] - Proximity Timer Updated!")
|
||||
Questie:Debug(Questie.DEBUG_SPAM,
|
||||
"[TrackerUtils:GetSortedQuestIds] - Proximity Timer Updated!")
|
||||
playerPosition = position
|
||||
local orderCopy = {}
|
||||
|
||||
@@ -1119,16 +1125,13 @@ function TrackerUtils:UpdateVoiceOverPlayButtons()
|
||||
end
|
||||
|
||||
for i = 1, 75 do
|
||||
local title, _, _, isHeader, _, _, _, questId = GetQuestLogTitle(i)
|
||||
local title, level, questTag, isHeader, isCollapsed, isComplete, isDaily, questId = GetQuestLogTitle(i)
|
||||
|
||||
if not (title and questId) then
|
||||
break
|
||||
end
|
||||
|
||||
if not isHeader then
|
||||
if title and questId and (not isHeader) then
|
||||
if not VoiceOver.QuestOverlayUI.questPlayButtons[questId] then
|
||||
VoiceOver.QuestOverlayUI:CreatePlayButton(questId)
|
||||
table.insert(VoiceOver.QuestOverlayUI.displayedButtons, VoiceOver.QuestOverlayUI.questPlayButtons[questId])
|
||||
table.insert(VoiceOver.QuestOverlayUI.displayedButtons,
|
||||
VoiceOver.QuestOverlayUI.questPlayButtons[questId])
|
||||
end
|
||||
end
|
||||
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.6
|
||||
## Version: 9.8.9
|
||||
## RequiredDeps:
|
||||
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
|
||||
## SavedVariables: QuestieConfig
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
## New Ebonhold Quests
|
||||
- **Outland**: Blade's Edge Trophy, Fel Scars of Nagrand, Netherstorm Trophy
|
||||
- **Northrend**: Borean Trophy
|
||||
- **Kalimdor**: Teldrassil Trophy, Darkshore Defense, Bloodmyst Recovery
|
||||
- **Azeroth**: Arathi Trophy, Elwynn Errands, Modan Trophy, Redridge Resolve, Westfall Trophy, Wetlands Trophy
|
||||
|
||||
Includes precise spawn tracking data overrides for numerous rare NPCs across these zones.
|
||||
+193
-134
@@ -11,22 +11,26 @@ This workflow aggregates vital information from the [Questie Wiki](https://githu
|
||||
**Wiki Page:** [Contributing](https://github.com/Questie/Questie/wiki/Contributing)
|
||||
|
||||
### Setup
|
||||
* **Fork & Clone:** Fork the repo and clone it *outside* your WoW directory.
|
||||
* **Symlink:** Create a symlink from your Clone to `Interface/AddOns/Questie`.
|
||||
* **Windows:** `mklink /J "C:\Path\To\WoW\_classic_\Interface\AddOns\Questie" "C:\Dev\Questie"`
|
||||
* **MacOS:** `ln -s ~/Dev/Questie /Applications/World\ of\ Warcraft/_classic_/Interface/AddOns/Questie`
|
||||
* **IDE:** Recommended: IntelliJ + EmmyLua or VSCode + Lua Extension (sumneko).
|
||||
|
||||
* **Fork & Clone:** Fork the repo and clone it *outside* your WoW directory.
|
||||
* **Symlink:** Create a symlink from your Clone to `Interface/AddOns/Questie`.
|
||||
* **Windows:** `mklink /J "C:\Path\To\WoW\_classic_\Interface\AddOns\Questie" "C:\Dev\Questie"`
|
||||
* **MacOS:** `ln -s ~/Dev/Questie /Applications/World\ of\ Warcraft/_classic_/Interface/AddOns/Questie`
|
||||
* **IDE:** Recommended: IntelliJ + EmmyLua or VSCode + Lua Extension (sumneko).
|
||||
|
||||
### Commit Messages (Changelog)
|
||||
|
||||
Prefix commits to auto-generate changelog entries:
|
||||
* `[quest]` e.g., `[quest] Fix pre quest for "Warm Welcome"`
|
||||
* `[db]` e.g., `[db] Fix location of "Lar'korwi"`
|
||||
* `[fix]` e.g., `[fix] Fix DMF dates for Era`
|
||||
* `[feature]` e.g., `[feature] Add gold reward`
|
||||
* `[locale]` e.g., `[locale] Add translation for "Next in chain"`
|
||||
|
||||
* `[quest]` e.g., `[quest] Fix pre quest for "Warm Welcome"`
|
||||
* `[db]` e.g., `[db] Fix location of "Lar'korwi"`
|
||||
* `[fix]` e.g., `[fix] Fix DMF dates for Era`
|
||||
* `[feature]` e.g., `[feature] Add gold reward`
|
||||
* `[locale]` e.g., `[locale] Add translation for "Next in chain"`
|
||||
|
||||
### Research & Documentation
|
||||
* **Export Path:** Always copy research files (task.md, walkthrough.md, implementation_plan.md, and transcript) to `C:\Users\kance\Documents\Research\Questie\[Task-Name]`.
|
||||
|
||||
* **Export Path:** Always copy research files (task.md, walkthrough.md, implementation_plan.md, and transcript) to `C:\Users\kance\Documents\Research\Questie\[Task-Name]`.
|
||||
|
||||
---
|
||||
|
||||
@@ -37,18 +41,21 @@ Prefix commits to auto-generate changelog entries:
|
||||
Questie employs a modular architecture where specialized systems handle different aspects of the addon.
|
||||
|
||||
### Core Modules
|
||||
* **Initialization:** `Modules/QuestieInit.lua` - Manages the staged loading process.
|
||||
* **Database:** `Database/QuestieDB.lua` - Central hub for quest, NPC, item, and object data.
|
||||
* **Map Integration:** `Modules/Map/QuestieMap.lua` - Handles icon placement and world map/minimap logic.
|
||||
* **Tracking:** `Modules/Tracker/QuestieTracker.lua` - Manages the on-screen quest objective tracker.
|
||||
* **Journey:** `Modules/Journey/QuestieJourney.lua` - Handles the quest history and search UI.
|
||||
* **Corrections:** `Database/Corrections/QuestieCorrections.lua` - Applies patches to the base game data.
|
||||
* **Communication:** `Modules/Network/QuestieComms.lua` - Manages data sharing between party members.
|
||||
|
||||
* **Initialization:** `Modules/QuestieInit.lua` - Manages the staged loading process.
|
||||
* **Database:** `Database/QuestieDB.lua` - Central hub for quest, NPC, item, and object data.
|
||||
* **Map Integration:** `Modules/Map/QuestieMap.lua` - Handles icon placement and world map/minimap logic.
|
||||
* **Tracking:** `Modules/Tracker/QuestieTracker.lua` - Manages the on-screen quest objective tracker.
|
||||
* **Journey:** `Modules/Journey/QuestieJourney.lua` - Handles the quest history and search UI.
|
||||
* **Corrections:** `Database/Corrections/QuestieCorrections.lua` - Applies patches to the base game data.
|
||||
* **Communication:** `Modules/Network/QuestieComms.lua` - Manages data sharing between party members.
|
||||
|
||||
### Addon Initialization Flow
|
||||
|
||||
Questie uses a coroutine-based staged initialization to minimize performance impact:
|
||||
1. **Stage 1: Data & Validation** - Loads database, applies corrections, and runs validators.
|
||||
2. **Stage 3 (Stage 2 is internal wait): UI & Hooks** - Initializes trackers, maps, event handlers, and UI elements.
|
||||
|
||||
1. **Stage 1: Data & Validation** - Loads database, applies corrections, and runs validators.
|
||||
2. **Stage 3 (Stage 2 is internal wait): UI & Hooks** - Initializes trackers, maps, event handlers, and UI elements.
|
||||
|
||||
**CRITICAL NOTE ON GLOBAL NAMESPACES:** Modules are injected into the global namespace via `QuestieCompat.PopulateGlobals()` during `ADDON_LOADED` or `PLAYER_LOGIN`. Event handlers (like `CHAT_MSG_SYSTEM` for auto-turn-in quests) can fire *before* global variables are injected depending on client load orders. **Always use localized module imports** (e.g., `local QuestiePlayer = QuestieLoader:ImportModule("QuestiePlayer")`) at the top of files to prevent `attempt to index global '<Module>' (a nil value)` exceptions.
|
||||
|
||||
@@ -61,50 +68,56 @@ Questie uses a coroutine-based staged initialization to minimize performance imp
|
||||
The database system is a central component that stores and manages all quest-related information.
|
||||
|
||||
### Database Categories
|
||||
|
||||
The database consists of four primary data types:
|
||||
* **Quest Data:** Information about quest requirements, objectives, rewards, etc.
|
||||
* **NPC Data:** Information about non-player characters, including spawn locations.
|
||||
* **Item Data:** Information about items, including where they drop.
|
||||
* **Object Data:** Information about world objects like chests, mining nodes, etc.
|
||||
|
||||
* **Quest Data:** Information about quest requirements, objectives, rewards, etc.
|
||||
* **NPC Data:** Information about non-player characters, including spawn locations.
|
||||
* **Item Data:** Information about items, including where they drop.
|
||||
* **Object Data:** Information about world objects like chests, mining nodes, etc.
|
||||
|
||||
### Database Structure
|
||||
* **Base Data:** Located in `Database/<Expansion>/` (e.g., `classicQuestDB.lua`). **DO NOT EDIT DIRECTLY.**
|
||||
* **Corrections:** Located in `Database/Corrections/`. THIS is where you make changes.
|
||||
* **Expansion NPC Database Fields (e.g., `wotlkNpcDB.lua`):**
|
||||
* Index 1: `name`
|
||||
* Index 7: `spawns` - Format: `{[zoneID] = { {x,y}, ... }}`
|
||||
* Index 9: `zoneID` (Primary zone)
|
||||
* Index 12: `factionID`
|
||||
|
||||
* **Base Data:** Located in `Database/<Expansion>/` (e.g., `classicQuestDB.lua`). **DO NOT EDIT DIRECTLY.**
|
||||
* **Corrections:** Located in `Database/Corrections/`. THIS is where you make changes.
|
||||
* **Expansion NPC Database Fields (e.g., `wotlkNpcDB.lua`):**
|
||||
* Index 1: `name`
|
||||
* Index 7: `spawns` - Format: `{[zoneID] = { {x,y}, ... }}`
|
||||
* Index 9: `zoneID` (Primary zone)
|
||||
* Index 12: `factionID`
|
||||
|
||||
### Zone & Area Management
|
||||
|
||||
`Database/Zones/zoneDB.lua` manages geographic data:
|
||||
* **UI Map Mapping:** Maps internal Area IDs to UI Map IDs.
|
||||
* **Dungeon Locations:** Tracks entrance coordinates for instances.
|
||||
* **Subzone Mapping:** Relates subzones to their parent zones for proper icon inheritance.
|
||||
|
||||
* **UI Map Mapping:** Maps internal Area IDs to UI Map IDs.
|
||||
* **Dungeon Locations:** Tracks entrance coordinates for instances.
|
||||
* **Subzone Mapping:** Relates subzones to their parent zones for proper icon inheritance.
|
||||
|
||||
### NPC Data Verification Best Practices
|
||||
|
||||
When implementing custom quests that require NPC spawn data:
|
||||
|
||||
1. **Verify NPC vs Object Classification**
|
||||
- Always check both `wotlkNpcDB.lua` AND `wotlkObjectDB.lua`
|
||||
- Wowhead may list objects in NPC search results (e.g., "Dragonblight Mage Hunter" ID 32572)
|
||||
- Use grep search: `grep -r "^\[NPC_ID\]" Database/Wotlk/` to confirm classification
|
||||
* Always check both `wotlkNpcDB.lua` AND `wotlkObjectDB.lua`
|
||||
* Wowhead may list objects in NPC search results (e.g., "Dragonblight Mage Hunter" ID 32572)
|
||||
* Use grep search: `grep -r "^\[NPC_ID\]" Database/Wotlk/` to confirm classification
|
||||
|
||||
2. **Spawn Data Completeness Verification**
|
||||
- NPCs in database may have nil spawns or incomplete spawn coordinates
|
||||
- Always compare scraped spawn counts with existing database entries
|
||||
- Common issues:
|
||||
- NPCs with `nil` spawn data (no coordinates at all)
|
||||
- NPCs with sparse spawn data (DB has 5 spawns, Wowhead shows 19)
|
||||
- NPCs with single spawn when multiple exist
|
||||
* NPCs in database may have nil spawns or incomplete spawn coordinates
|
||||
* Always compare scraped spawn counts with existing database entries
|
||||
* Common issues:
|
||||
* NPCs with `nil` spawn data (no coordinates at all)
|
||||
* NPCs with sparse spawn data (DB has 5 spawns, Wowhead shows 19)
|
||||
* NPCs with single spawn when multiple exist
|
||||
|
||||
3. **Individual NPC Page Scraping**
|
||||
- Scrape each NPC's individual Wowhead page for spawn coordinates
|
||||
- Use JavaScript to extract from `g_mapperData[zoneId][0].coords`
|
||||
- Don't rely on aggregate list views - they may not show all spawns
|
||||
* Scrape each NPC's individual Wowhead page for spawn coordinates
|
||||
* Use JavaScript to extract from `g_mapperData[zoneId][0].coords`
|
||||
* Don't rely on aggregate list views - they may not show all spawns
|
||||
|
||||
4. **Database Comparison Process**
|
||||
|
||||
```bash
|
||||
# Search for NPC in database
|
||||
grep "^\[NPC_ID\]" Database/Wotlk/wotlkNpcDB.lua
|
||||
@@ -114,17 +127,17 @@ When implementing custom quests that require NPC spawn data:
|
||||
```
|
||||
|
||||
5. **Common Spawn Data Issues Found**
|
||||
- **Infinite Dragonflight NPCs**: Often have nil spawns (dungeon/instance spawns not in overworld)
|
||||
- **Quest Givers/Vendors**: Usually have 1 spawn (correct)
|
||||
- **Patrol NPCs**: May have waypoint data instead of static spawns
|
||||
- **Rare Spawns**: May have fewer coordinates than common NPCs
|
||||
* **Infinite Dragonflight NPCs**: Often have nil spawns (dungeon/instance spawns not in overworld)
|
||||
* **Quest Givers/Vendors**: Usually have 1 spawn (correct)
|
||||
* **Patrol NPCs**: May have waypoint data instead of static spawns
|
||||
* **Rare Spawns**: May have fewer coordinates than common NPCs
|
||||
|
||||
6. **Example: Quest 50064 Findings**
|
||||
- 50 NPCs extracted from Wowhead
|
||||
- 1 was an object (excluded)
|
||||
- 6 NPCs had nil spawns in database
|
||||
- 3 NPCs had incomplete spawn data (11 in DB vs 42 scraped)
|
||||
- Result: 49 valid NPCs, spawn data inconsistencies documented
|
||||
* 50 NPCs extracted from Wowhead
|
||||
* 1 was an object (excluded)
|
||||
* 6 NPCs had nil spawns in database
|
||||
* 3 NPCs had incomplete spawn data (11 in DB vs 42 scraped)
|
||||
* Result: 49 valid NPCs, spawn data inconsistencies documented
|
||||
|
||||
---
|
||||
|
||||
@@ -135,26 +148,29 @@ When implementing custom quests that require NPC spawn data:
|
||||
Corrections patch the runtime database to fix incomplete or incorrect game data.
|
||||
|
||||
### Loading Order
|
||||
1. **Base Data** for the running expansion is loaded (e.g., TBC).
|
||||
2. **Corrections** are applied in order: Classic -> TBC -> WotLK.
|
||||
* TBC corrections apply to WotLK.
|
||||
* Classic corrections apply to TBC and WotLK.
|
||||
* *Note:* Corrections in later files can overwrite earlier ones.
|
||||
|
||||
1. **Base Data** for the running expansion is loaded (e.g., TBC).
|
||||
2. **Corrections** are applied in order: Classic -> TBC -> WotLK.
|
||||
* TBC corrections apply to WotLK.
|
||||
* Classic corrections apply to TBC and WotLK.
|
||||
* *Note:* Corrections in later files can overwrite earlier ones.
|
||||
|
||||
### NPC Correction File Structure
|
||||
|
||||
**CRITICAL**: NPC correction files (e.g., `tbcNPCFixes.lua`) have TWO sections:
|
||||
|
||||
1. **Main `Load()` Function** (lines 9-1064): Returns a table of corrections that apply to **ALL players** (both factions)
|
||||
- **Use this for**: General NPC spawn data, quest fixes, waypoints that apply to everyone
|
||||
- **Example**: Adding missing spawn coordinates for dragonkin NPCs
|
||||
* **Use this for**: General NPC spawn data, quest fixes, waypoints that apply to everyone
|
||||
* **Example**: Adding missing spawn coordinates for dragonkin NPCs
|
||||
|
||||
2. **Faction-Specific `LoadFactionFixes()` Function** (lines 1068+): Returns faction-specific corrections
|
||||
- **Use this for**: NPCs that only appear for Horde or Alliance (e.g., starting zone NPCs)
|
||||
- **Structure**: Returns `npcFixesHorde` or `npcFixesAlliance` based on player faction
|
||||
* **Use this for**: NPCs that only appear for Horde or Alliance (e.g., starting zone NPCs)
|
||||
* **Structure**: Returns `npcFixesHorde` or `npcFixesAlliance` based on player faction
|
||||
|
||||
**When adding NPC spawn data**: Add it to the **main `Load()` function** unless the NPC is faction-specific.
|
||||
|
||||
### Syntax
|
||||
|
||||
```lua
|
||||
-- Database/Corrections/tbcQuestFixes.lua
|
||||
[8300] = {
|
||||
@@ -164,71 +180,82 @@ Corrections patch the runtime database to fix incomplete or incorrect game data.
|
||||
```
|
||||
|
||||
### Critical Keys (QuestieDB.questKeys)
|
||||
* `startedBy` / `finishedBy`: `{ {Creature_IDs}, {Object_IDs}, {Item_IDs} }`.
|
||||
* Use `nil` for empty slots. Example: `{{123}, nil, nil}`.
|
||||
* `preQuestSingle`: List of required pre-quests.
|
||||
* `exclusiveTo`: List of quests that hide this one.
|
||||
* `nextQuestInChain`: ID of the next quest.
|
||||
* `requiredLevel` (Index [4]): Minimum level required to accept the quest.
|
||||
* `questLevel` (Index [5]): The actual level of the quest (determines XP/Colors).
|
||||
* `requiredRaces` (Index [6]): Bitmask (use `QuestieDB.raceKeys`).
|
||||
* **`zoneOrSort` (Index [17])**: **Zone ID** (positive for Area Table ID) or Quest Sort ID (negative). **This is the zone field for custom quests.**
|
||||
* **WARNING:** Do NOT use Index [6] (`requiredRaces`) for Zone ID. This is a common mistake that causes "Unknown Zone" errors.
|
||||
|
||||
* `startedBy` / `finishedBy`: `{ {Creature_IDs}, {Object_IDs}, {Item_IDs} }`.
|
||||
* Use `nil` for empty slots. Example: `{{123}, nil, nil}`.
|
||||
* `preQuestSingle`: List of required pre-quests.
|
||||
* `exclusiveTo`: List of quests that hide this one.
|
||||
* `nextQuestInChain`: ID of the next quest.
|
||||
* `requiredLevel` (Index [4]): Minimum level required to accept the quest.
|
||||
* `questLevel` (Index [5]): The actual level of the quest (determines XP/Colors).
|
||||
* `requiredRaces` (Index [6]): Bitmask (use `QuestieDB.raceKeys`).
|
||||
* **`zoneOrSort` (Index [17])**: **Zone ID** (positive for Area Table ID) or Quest Sort ID (negative). **This is the zone field for custom quests.**
|
||||
* **WARNING:** Do NOT use Index [6] (`requiredRaces`) for Zone ID. This is a common mistake that causes "Unknown Zone" errors.
|
||||
|
||||
---
|
||||
|
||||
## 5. Quest Tracking & Map Systems
|
||||
|
||||
### Quest Tracker Components
|
||||
|
||||
The tracker UI consists of several key components:
|
||||
* **TrackerBaseFrame:** The main frame that contains the entire tracker.
|
||||
* **TrackerHeaderFrame:** Contains the tracker's header with title and buttons.
|
||||
* **TrackerQuestFrame:** Manages the display of individual quests.
|
||||
* **TrackerLinePool:** A pool of line elements for quest objectives and text.
|
||||
|
||||
* **TrackerBaseFrame:** The main frame that contains the entire tracker.
|
||||
* **TrackerHeaderFrame:** Contains the tracker's header with title and buttons.
|
||||
* **TrackerQuestFrame:** Manages the display of individual quests.
|
||||
* **TrackerLinePool:** A pool of line elements for quest objectives and text.
|
||||
|
||||
### Combat Queue System (`QuestieCombatQueue.lua`)
|
||||
|
||||
**CRITICAL:** Avoids UI "taint" and errors by queuing operations during combat:
|
||||
* Queues operations requested during combat.
|
||||
* Executes queued operations immediately upon leaving combat (`PLAYER_REGEN_ENABLED`).
|
||||
* Essential for preventing interference with Blizzard's protected combat frames.
|
||||
|
||||
* Queues operations requested during combat.
|
||||
* Executes queued operations immediately upon leaving combat (`PLAYER_REGEN_ENABLED`).
|
||||
* Essential for preventing interference with Blizzard's protected combat frames.
|
||||
|
||||
### Map Icon & Tooltip System
|
||||
* **Frame Pooling:** Icons are managed via `QuestieFramePool` to reuse frames and reduce memory overhead.
|
||||
* **Icon Frames:** `QuestieFrame` displays the actual markers.
|
||||
* **HBD Integration:** Uses `HereBeDragons` (via `HBDHooks.lua`) for coordinate conversions.
|
||||
* **Tooltip System:** `MapIconTooltip` and `TooltipHandler` provide hover info, including party member progress.
|
||||
|
||||
* **Frame Pooling:** Icons are managed via `QuestieFramePool` to reuse frames and reduce memory overhead.
|
||||
* **Icon Frames:** `QuestieFrame` displays the actual markers.
|
||||
* **HBD Integration:** Uses `HereBeDragons` (via `HBDHooks.lua`) for coordinate conversions.
|
||||
* **Tooltip System:** `MapIconTooltip` and `TooltipHandler` provide hover info, including party member progress.
|
||||
|
||||
### QuestieArrow & Finisher Tracking (`QuestieArrow.lua`)
|
||||
* **Finisher Waypoints:** The Questie Arrow (`QuestieArrow:UpdateNearestTargets`) relies on `quest.isComplete` and `QuestieDB.IsComplete` to switch from targeting objectives to targeting the quest turn-in (Finisher) NPC or Object.
|
||||
* **Object Properties Limit:** When evaluating the exact finisher location, Questie quest objects contain limited attributes for the Finisher: only `.Id` and `.Type` (`"monster"` or `"object"`). Any attempt to index `quest.Finisher.Name` will fail and cause finisher logic to be skipped entirely.
|
||||
* **Distance Checks:** `_CollectFinisherSpawns` evaluates `HBD:GetWorldDistance`. If the finisher is in another zone and the player has auto-tracking enabled (`usingAutoLogic and zone ~= playerZoneId`), QuestieArrow will intentionally hide distant finisher marks.
|
||||
|
||||
* **Finisher Waypoints:** The Questie Arrow (`QuestieArrow:UpdateNearestTargets`) relies on `quest.isComplete` and `QuestieDB.IsComplete` to switch from targeting objectives to targeting the quest turn-in (Finisher) NPC or Object.
|
||||
* **Object Properties Limit:** When evaluating the exact finisher location, Questie quest objects contain limited attributes for the Finisher: only `.Id` and `.Type` (`"monster"` or `"object"`). Any attempt to index `quest.Finisher.Name` will fail and cause finisher logic to be skipped entirely.
|
||||
* **Distance Checks:** `_CollectFinisherSpawns` evaluates `HBD:GetWorldDistance`. If the finisher is in another zone and the player has auto-tracking enabled (`usingAutoLogic and zone ~= playerZoneId`), QuestieArrow will intentionally hide distant finisher marks.
|
||||
|
||||
### 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.
|
||||
|
||||
* **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.
|
||||
|
||||
### Objective Priority & Hide Conditions
|
||||
* **HideCondition Mechanism**: Allows hiding specific objectives (regular or extra) based on the player's quest log status.
|
||||
* `hideIfQuestActive`: Hides the objective if the specified Quest ID is in the player's log OR already completed.
|
||||
* `hideIfQuestComplete`: Hides the objective only if the specified Quest ID is already completed.
|
||||
* **Implementation**:
|
||||
* **Regular Objectives** (Monsters, Objects, Items): The `HideCondition` is stored as the **3rd field** in the objective sub-table (e.g., `{{NPC_ID, nil, {["hideIfQuestActive"] = 12966}}}`).
|
||||
* **Extra Objectives** (Index 27): The `HideCondition` is stored as the **6th field** in the extra objective sub-table.
|
||||
* **Immediate UI Feedback**: When a quest acceptance should immediately hide another objective or pivot the arrow, call `QuestieArrow:Refresh()` within the `AcceptQuest` TaskQueue in `QuestieQuest.lua`.
|
||||
|
||||
* **HideCondition Mechanism**: Allows hiding specific objectives (regular or extra) based on the player's quest log status.
|
||||
* `hideIfQuestActive`: Hides the objective if the specified Quest ID is in the player's log OR already completed.
|
||||
* `hideIfQuestComplete`: Hides the objective only if the specified Quest ID is already completed.
|
||||
* **Implementation**:
|
||||
* **Regular Objectives** (Monsters, Objects, Items): The `HideCondition` is stored as the **3rd field** in the objective sub-table (e.g., `{{NPC_ID, nil, {["hideIfQuestActive"] = 12966}}}`).
|
||||
* **Extra Objectives** (Index 27): The `HideCondition` is stored as the **6th field** in the extra objective sub-table.
|
||||
* **Immediate UI Feedback**: When a quest acceptance should immediately hide another objective or pivot the arrow, call `QuestieArrow:Refresh()` within the `AcceptQuest` TaskQueue in `QuestieQuest.lua`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Additional Systems
|
||||
|
||||
### Journey System
|
||||
* **My Journey:** A chronological record of the player's quest history.
|
||||
* **Quests By Zone:** Browse quests by zone, filtering by availability and completion status.
|
||||
* **Search:** Advanced search for quests, NPCs, items, and objects by name or ID.
|
||||
|
||||
* **My Journey:** A chronological record of the player's quest history.
|
||||
* **Quests By Zone:** Browse quests by zone, filtering by availability and completion status.
|
||||
* **Search:** Advanced search for quests, NPCs, items, and objects by name or ID.
|
||||
|
||||
### Network Communication
|
||||
* **QuestieComms:** Manages data sharing between party members.
|
||||
* **QuestieSerializer:** Converts complex tables to strings for transmission.
|
||||
* **QuestieAnnounce:** Provides options for announcing quest progress to chat.
|
||||
|
||||
* **QuestieComms:** Manages data sharing between party members.
|
||||
* **QuestieSerializer:** Converts complex tables to strings for transmission.
|
||||
* **QuestieAnnounce:** Provides options for announcing quest progress to chat.
|
||||
|
||||
---
|
||||
|
||||
@@ -237,6 +264,7 @@ The tracker UI consists of several key components:
|
||||
**Wiki Page:** [Localization](https://github.com/Questie/Questie/wiki/Localization-to-more-languages)
|
||||
|
||||
To test or add translations locally, use `QUESTIE_LOCALES_OVERRIDE` in a global scope (e.g. `Questie.lua` top):
|
||||
|
||||
```lua
|
||||
QUESTIE_LOCALES_OVERRIDE = {
|
||||
locale = 'deDE',
|
||||
@@ -257,16 +285,20 @@ QUESTIE_LOCALES_OVERRIDE = {
|
||||
|
||||
**Wiki Page:** [Debugging](https://github.com/Questie/Questie/wiki/Debugging)
|
||||
|
||||
* **Mocking Player State:** Add to top of `Questie.lua`:
|
||||
* **Mocking Player State:** Add to top of `Questie.lua`:
|
||||
|
||||
```lua
|
||||
UnitLevel = function() return 10; end
|
||||
UnitRace = function() return "nightelf", "nightelf"; end
|
||||
```
|
||||
* **Module Access:**
|
||||
|
||||
* **Module Access:**
|
||||
|
||||
```lua
|
||||
QuestieLoader:ImportModule("QuestieDB").GetQuest(123)
|
||||
```
|
||||
* **Verification:** Enable "Advanced Options" -> "Debug", open Journey, use Search tab to see the *final* data after corrections.
|
||||
|
||||
* **Verification:** Enable "Advanced Options" -> "Debug", open Journey, use Search tab to see the *final* data after corrections.
|
||||
|
||||
---
|
||||
|
||||
@@ -275,55 +307,75 @@ QUESTIE_LOCALES_OVERRIDE = {
|
||||
### Manual Spawn Extraction (Traditional Method)
|
||||
|
||||
**Page:** [Extracting Spawns](https://github.com/Questie/Questie/wiki/Extracting-spawn-locations-from-wowhead)
|
||||
* Use the Javascript snippet on Wowhead maps to generate Lua table output `{{x,y},...}}`.
|
||||
|
||||
* Use the Javascript snippet on Wowhead maps to generate Lua table output `{{x,y},...}}`.
|
||||
|
||||
### Automated NPC Extraction (Browser Automation)
|
||||
|
||||
For quests requiring all NPCs of a specific type in a zone (e.g., "kill all beasts"), use browser automation to extract NPC IDs from Wowhead's database.
|
||||
|
||||
**Wowhead Filter URL Format:**
|
||||
|
||||
```
|
||||
https://www.wowhead.com/wotlk/npcs/beasts?filter=6;ZONE_ID;0
|
||||
```
|
||||
|
||||
- Replace `beasts` with the creature type (beasts, humanoids, dragonkin, etc.)
|
||||
- Replace `ZONE_ID` with the zone ID (e.g., 3522 for Blade's Edge Mountains, 3523 for Netherstorm)
|
||||
* Replace `ZONE_ID` with the zone ID (e.g., 3522 for Blade's Edge Mountains, 3523 for Netherstorm)
|
||||
|
||||
**Extraction Method:**
|
||||
|
||||
1. Navigate to the filtered Wowhead URL
|
||||
2. Use JavaScript to access Wowhead's internal data:
|
||||
|
||||
```javascript
|
||||
const listview = Object.values(g_listviews).find(lv => lv.id === 'npcs');
|
||||
listview.data.map(npc => npc.id + ' - ' + npc.name).join('\n');
|
||||
```
|
||||
|
||||
3. This returns all NPC IDs and names matching the filter
|
||||
|
||||
**Example Use Cases:**
|
||||
- Quest 50085 (Savage Heights): Extracted 47 beast NPCs from Blade's Edge Mountains
|
||||
- Quest 50086 (Unstable Fauna): Extracted 18 beast NPCs from Netherstorm
|
||||
* Quest 50085 (Savage Heights): Extracted 47 beast NPCs from Blade's Edge Mountains
|
||||
* Quest 50086 (Unstable Fauna): Extracted 18 beast NPCs from Netherstorm
|
||||
|
||||
**Benefits:**
|
||||
- Faster than manual lookup
|
||||
- Ensures no NPCs are missed
|
||||
- Provides complete list for `killCreditObjective` implementation
|
||||
* Faster than manual lookup
|
||||
* Ensures no NPCs are missed
|
||||
* Provides complete list for `killCreditObjective` implementation
|
||||
|
||||
---
|
||||
|
||||
Custom server data should **NOT** use the Corrections system. Use separate database modules (e.g., `Database/Ebonhold/`).
|
||||
* **Quests:** Added to `EbonholdDB.questData` (or `EbonholdQuestDB.questData`).
|
||||
* **NPCs:** Added to `EbonholdDB.npcData`.
|
||||
|
||||
* **Quests:** Added to `EbonholdDB.questData` (or `EbonholdQuestDB.questData`).
|
||||
* **NPCs:** Added to `EbonholdDB.npcData`.
|
||||
|
||||
### Missing Base Data (Upstream Preservation)
|
||||
|
||||
If the original database files (standard Questie DB) are missing data (e.g. missing NPC spawns in TBC content), **DO NOT** add this data to the standard `Database/Corrections` folder.
|
||||
Instead, add the missing data to the **specific server's database folder** (e.g., `Database/Ebonhold/`).
|
||||
* **Reason:** Updating the main Questie database files (including standard corrections) will wipe local changes. Custom server database files are preserved during updates.
|
||||
|
||||
* **Reason:** Updating the main Questie database files (including standard corrections) will wipe local changes. Custom server database files are preserved during updates.
|
||||
|
||||
**CRITICAL OVERRIDE WARNING FOR CUSTOM DBs:**
|
||||
When adding missing coordinate data to pre-existing base NPCs via `EbonholdNpcDB.lua`, the custom database engine **does not perform a deep merge**. If you inject an entry that only defines the `[npcKeys.spawns]` array, it will obliterate the entire base NPC node (wiping its name, health, rank, and other metrics). This results in `attempt to index nil` errors rendering the Map Tooltips.
|
||||
|
||||
To safely override base coordinates, you must:
|
||||
|
||||
1. Copy the **entire** data array for the NPC from the `classicNpcDB.lua` or `wotlkNpcDB.lua` into your custom `EbonholdNpcDB.lua` and enrich it there.
|
||||
2. OR, if injecting massive coordinates is necessary without full transcribing, they can be injected into the base files (`Database/Corrections/wotlkNPCFixes.lua` deep-merges correctly), understanding that these edits are at risk of being wiped during a standard Questie version upgrade.
|
||||
|
||||
### Critical Rules for Custom Quests
|
||||
|
||||
#### 1. Never Duplicate Existing NPCs/Objects
|
||||
|
||||
NPCs/objects from base WotLK/TBC/Classic databases already exist with spawn data. Only add to custom DB if it's truly custom content.
|
||||
|
||||
#### 2. Object Data Structure - Use Indexed Fields
|
||||
|
||||
**✅ CORRECT:**
|
||||
|
||||
```lua
|
||||
[600600] = {
|
||||
[1] = "Elemental Shrine", -- Indexed fields
|
||||
@@ -341,6 +393,7 @@ NPCs/objects from base WotLK/TBC/Classic databases already exist with spawn data
|
||||
**Solution:** Use `killCreditObjective` (objectives[5]) to map multiple NPC IDs to a single counter while showing all NPC spawns on the map.
|
||||
|
||||
**Structure:**
|
||||
|
||||
```lua
|
||||
[10] = { -- objectives
|
||||
nil, -- [1] creatureObjective (not used)
|
||||
@@ -358,6 +411,7 @@ NPCs/objects from base WotLK/TBC/Classic databases already exist with spawn data
|
||||
```
|
||||
|
||||
**How It Works:**
|
||||
|
||||
1. **Database Processing** (`QuestieDB.lua:1276-1293`): Creates a `killcredit` objective with `IdList` and `RootId`
|
||||
2. **Spawn Handler** (`QuestieQuestPrivates.lua:65-73`): Iterates through `IdList` and creates map icons for each NPC
|
||||
3. **Tracker**: Shows single entry (e.g., "Shattered Rumbler slain: 0/30")
|
||||
@@ -365,10 +419,9 @@ NPCs/objects from base WotLK/TBC/Classic databases already exist with spawn data
|
||||
|
||||
**Example Use Case:**
|
||||
Quest 50026 requires killing 30 elementals. Six different elemental NPC types exist (17156, 17157, 22309, 22310, 22311, 22313). Using `killCreditObjective` ensures:
|
||||
- All six NPC types show on the map
|
||||
- Single tracker counter increments for any kill
|
||||
- No duplicate "0/30" entries in the tracker
|
||||
|
||||
* All six NPC types show on the map
|
||||
* Single tracker counter increments for any kill
|
||||
* No duplicate "0/30" entries in the tracker
|
||||
|
||||
#### 4. Server-Tracked Objectives ("Complete N Quests in Zone")
|
||||
|
||||
@@ -381,6 +434,7 @@ Missing objective data for quest <ID> Complete 6 quests in <Zone>
|
||||
**Root Cause:** `QuestieQuest:PopulateQuestLogInfo` (line 1578) requires a `quest.ObjectiveData[index]` entry for every objective the server reports. If the quest has no objectives defined (no `[10]` field) and no `triggerEnd` (`[9]`), `ObjectiveData` is empty and the error fires.
|
||||
|
||||
**Wrong Approach (do not do this):**
|
||||
|
||||
```lua
|
||||
-- Adding an all-nil [10] table does NOT create ObjectiveData entries
|
||||
[50111] = {
|
||||
@@ -407,6 +461,7 @@ Missing objective data for quest <ID> Complete 6 quests in <Zone>
|
||||
```
|
||||
|
||||
**How it works:**
|
||||
|
||||
1. `QuestieDB.GetQuest` reads `rawdata[9]` → sets `QO.triggerEnd`
|
||||
2. At line 1312-1320: `ObjectiveData[#ObjectiveData+1] = {Type="event", Text=..., Coordinates=nil}`
|
||||
3. `PopulateQuestLogInfo` finds `ObjectiveData[1]` → no error
|
||||
@@ -423,6 +478,7 @@ Missing objective data for quest <ID> Complete 6 quests in <Zone>
|
||||
**Solution:** Omit the `finishedBy` field (index 3) from the quest data. This prevents Questie from showing a turn-in icon or expecting a return trip.
|
||||
|
||||
**Structure:**
|
||||
|
||||
```lua
|
||||
[50026] = {
|
||||
[1] = "Quest Name",
|
||||
@@ -437,12 +493,12 @@ Missing objective data for quest <ID> Complete 6 quests in <Zone>
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
- Quest starter icon appears on the map
|
||||
- No turn-in icon appears after objectives are complete
|
||||
- Quest automatically completes on the server when objectives finish
|
||||
|
||||
* Quest starter icon appears on the map
|
||||
* No turn-in icon appears after objectives are complete
|
||||
* Quest automatically completes on the server when objectives finish
|
||||
|
||||
#### 5. Quest Data Structure
|
||||
|
||||
```lua
|
||||
[50026] = {
|
||||
[1] = "Quest Name",
|
||||
@@ -460,21 +516,24 @@ Missing objective data for quest <ID> Complete 6 quests in <Zone>
|
||||
## 11. Common Solutions
|
||||
|
||||
### No Objectives Shown
|
||||
* **Page:** [No Objectives](https://github.com/Questie/Questie/wiki/Example%3A-No-Objectives)
|
||||
* **Cause:** Quest references an item/object/NPC that has no spawn data.
|
||||
* **Fix:** Ensure the target NPC/Object exists and has `[4]` (spawns) filled. If it's an item, check `npcDrops`.
|
||||
|
||||
* **Page:** [No Objectives](https://github.com/Questie/Questie/wiki/Example%3A-No-Objectives)
|
||||
* **Cause:** Quest references an item/object/NPC that has no spawn data.
|
||||
* **Fix:** Ensure the target NPC/Object exists and has `[4]` (spawns) filled. If it's an item, check `npcDrops`.
|
||||
|
||||
### Breadcrumb Quests
|
||||
* **Page:** [Breadcrumb Quests](https://github.com/Questie/Questie/wiki/Example%3A-Breadcrumb-quests)
|
||||
* **Fix:** Use `nextQuestInChain` or `exclusiveTo` to hide the breadcrumb when the main quest is taken.
|
||||
|
||||
* **Page:** [Breadcrumb Quests](https://github.com/Questie/Questie/wiki/Example%3A-Breadcrumb-quests)
|
||||
* **Fix:** Use `nextQuestInChain` or `exclusiveTo` to hide the breadcrumb when the main quest is taken.
|
||||
|
||||
---
|
||||
|
||||
## 13. Debugging Stuck Arrows
|
||||
|
||||
### Scenario: Arrow persists on an NPC after picking up a follow-up quest
|
||||
1. **Check for Multiple Quests**: Verify if more than one active quest has an objective at that NPC. Use Journey search for the NPC ID.
|
||||
2. **Verify NPC Coordinate Overlap**: Compare NPC coordinates in `wotlkNpcDB.lua`. NPCs in the same hub (like Dun Niffelem) often share base coordinates. If Questie switches targets to a different NPC at the same location, the arrow will appear "stuck."
|
||||
- **Fix**: Override the quest finisher in `wotlkQuestFixes.lua` to point to a distinct NPC or Object (e.g., moving the arrow from the King to the Anvil).
|
||||
3. **Apply HideConditions**: If an objective is redundant once a breadcrumb quest is accepted, apply `hideIfQuestActive` to the correction data for that objective.
|
||||
4. **Confirm Database Loading**: Ensure `QuestieDB.GetQuest` is correctly parsing the `HideCondition` field for the objective type.
|
||||
|
||||
1. **Check for Multiple Quests**: Verify if more than one active quest has an objective at that NPC. Use Journey search for the NPC ID.
|
||||
2. **Verify NPC Coordinate Overlap**: Compare NPC coordinates in `wotlkNpcDB.lua`. NPCs in the same hub (like Dun Niffelem) often share base coordinates. If Questie switches targets to a different NPC at the same location, the arrow will appear "stuck."
|
||||
* **Fix**: Override the quest finisher in `wotlkQuestFixes.lua` to point to a distinct NPC or Object (e.g., moving the arrow from the King to the Anvil).
|
||||
3. **Apply HideConditions**: If an objective is redundant once a breadcrumb quest is accepted, apply `hideIfQuestActive` to the correction data for that objective.
|
||||
4. **Confirm Database Loading**: Ensure `QuestieDB.GetQuest` is correctly parsing the `HideCondition` field for the objective type.
|
||||
|
||||
Reference in New Issue
Block a user