chore: release v9.7.12
- Fixed missing Finisher frame pool reset - Fixed tracker force-complete race condition on custom quests
This commit is contained in:
@@ -0,0 +1,137 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## v9.7.12
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Quest]** Fixed an issue where tracking icons for dynamically updated custom quests like Peak Predators would prematurely disappear due to sync delays on WotLK servers.
|
||||||
|
- **[Map]** Resolved a frame pool leak that prevented the yellow Finisher icon from appearing immediately on the map after turning in or completing a quest.
|
||||||
|
|
||||||
|
|
||||||
|
## v9.7.11
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Quest]** Fixed an issue where quest objective icons and waypoints failed to clear from the map after a quest was completed or abandoned.
|
||||||
|
- **[Tracker]** Prevented quests from falsely flagging as complete and wiping tracking data when the World of Warcraft server drops its objective arrays. Fixes "Peak Predators" icons disappearing randomly.
|
||||||
|
- **[Database]** Corrected an error that improperly identified Item Finishers as GameObject Finishers on custom servers, causing map pinpointing errors (e.g. `[QuestieDB:GetObject] rawdata is nil for objectID:`).
|
||||||
|
- **[Database]** Appended correct fallback spawn data for the "Thorim" listen bunny (`NPC 30514`) so Sibling Rivalry's turn in/listen point functions correctly on WotLK clients.
|
||||||
|
|
||||||
|
## v9.7.10
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Arrow]** Refactored Arrow logic to drastically improve target distance calculations and prioritize targets correctly based on the player's current zone.
|
||||||
|
- **[Arrow]** Fixed a bug where the Arrow would mistakenly point to previously completed objective locations instead of the Quest Finisher's exact location.
|
||||||
|
- **[Tracker]** Fixed `QuestieDB.IsComplete` edge case returning incomplete incorrectly; now verifies `numFulfilled == numRequired` to immediately acknowledge completed quests while awaiting the server flag.
|
||||||
|
- **[Tracker]** Resolved false-positive "broken quest log" errors spamming chat on WotLK servers by correctly handling API responses for trackable objectives.
|
||||||
|
- **[Tracker]** Demoted harmless WotLK objective cache count mismatches from Error to Debug visibility level to eliminate chat spam on login.
|
||||||
|
- **[Quest]** Fixed quest arrow pointing to the key-drop NPC after using all consumable quest keys (e.g. Cold Iron Key for "They Took Our Men!" quest 12843). When a quest uses a key item that is consumed on interaction, it leaves the bag and `CheckQuestSourceItem` returns false, incorrectly triggering a quest reset that re-drew the key source NPC on the map. Now checks if all tracked objectives are already `Completed=true` before applying the reset, preventing the spurious icon.
|
||||||
|
|
||||||
|
## v9.7.9
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Quest]** Fixed tracker objective count staying stale (e.g. stuck at 14/16 when quest is complete) when an autoloot bot bypasses the standard loot frame. Registered `BAG_UPDATE_DELAYED` event to force a full quest log scan on bag changes, catching progress updates that `QUEST_WATCH_UPDATE` would normally fire for manual looting.
|
||||||
|
|
||||||
|
## v9.7.8
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Quest]** Fixed "There was an error populating objectives" error in chat for `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone"). `_RegisterObjectiveTooltips` now silently returns for `event`-type objectives with no `spawnList` — these have nothing to register a tooltip for.
|
||||||
|
|
||||||
|
## v9.7.7
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Quest]** Fixed "Missing event data for Objective" error appearing in chat for all `triggerEnd` quests with no map coordinates (e.g., "complete N quests in zone" types). Nil coordinates are valid for server-tracked objectives with no pin — the handler now returns silently instead of logging a visible error.
|
||||||
|
|
||||||
|
## v9.7.6
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Database]** Fixed "Missing objective data" error for all "complete N quests in zone" quest types (IDs 50151, 50145, 50098, 50100, 50149, 50099, 50108, 50111, 50150). Added `triggerEnd` (`[9]`) field so Questie correctly registers the server-tracked objective without drawing map pins.
|
||||||
|
|
||||||
|
## v9.7.5
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Quest]** Fixed objective pins/icons persisting on the map after a quest is completed or abandoned. Added `CleanupRemovedQuestsFallback` which diffs Questie's quest log against the game's actual quest log on every `QUEST_LOG_UPDATE` and correctly calls `CompleteQuest` or `AbandonedQuest` for any quest that silently disappeared, ensuring map icons are removed.
|
||||||
|
- **[Quest]** Fixed re-accepted repeatable custom quests (e.g., Stormforged Scales) not showing objective icons on the map after being accepted a second time.
|
||||||
|
|
||||||
|
### New Quests
|
||||||
|
- **[Database]** Added **Storm Peak Orders** (ID 50150) - *The Storm Peaks*
|
||||||
|
- Objective: Complete any 6 quests in The Storm Peaks.
|
||||||
|
- **[Database]** Added **Wild Basin** (ID 50094) - *Sholazar Basin*
|
||||||
|
- Objective: Kill 75 Beasts. Includes 29 Beast NPC types with full spawn coordinates.
|
||||||
|
- NPCs: King Krush, Shardhorn Rhino, Aotona, Pitch, Serfex the Reaver, Dreadsaber, Hardknuckle Matriarch, Shango, Venomtip, Bushwhacker, Hardknuckle Charger, Ravenous Mangal Crocolisk, Farunn, Zeptek the Destroyer, Goretalon Matriarch, Sapphire Hive Wasp, Emperor Cobra, Sapphire Hive Drone, Shattertusk Bull, Siltslither Eel, Spirit of Atha, Stranded Thresher, Mangal Crocolisk, Spirit of Koosu, Longneck Grazer, Goretalon Roc, Sapphire Hive Queen, Spirit of Ha-Khalan, Bittertide Hydra
|
||||||
|
|
||||||
|
## v9.7.4
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Tooltips]** Fixed "attempt to concatenate local 'name' (a nil value)" error when quest starters/finishers have missing names in the database.
|
||||||
|
- **[Database]** Added missing spawn coordinates for Quest 50031 "Stormbound" elementals in Storm Peaks (zone 67).
|
||||||
|
- **[Database]** Fixed "Unknown Zone" issue for custom quests by correcting Zone ID index usage (swapped `[6]` RequiredRaces for `[17]` ZoneID).
|
||||||
|
- **[Database]** Corrected Dragonblight Zone ID in custom quest definitions.
|
||||||
|
|
||||||
|
### New Quests
|
||||||
|
- **[Database]** Added **Morogh Missions** (ID 50098) - *Dun Morogh*
|
||||||
|
- Objective: Complete any 6 quests in Dun Morogh. Auto-completes upon reaching the objective.
|
||||||
|
- **[Database]** Added **Azuremyst Aid** (ID 50100) - *Azuremyst Isle*
|
||||||
|
- Objective: Complete any 6 quests in Azuremyst Isle. Auto-completes upon reaching the objective.
|
||||||
|
- **[Database]** Added **Stormforged Scales** (ID 50066) - *The Storm Peaks*
|
||||||
|
- Objective: Kill 30 Dragonkin. Includes 8 Dragonkin NPC types with full spawn coordinates.
|
||||||
|
- **[Database]** Added **Peak Predators** (ID 50095) - *The Storm Peaks*
|
||||||
|
- Objective: Kill 75 Beasts. Includes 24 Beast NPC types with full spawn coordinates.
|
||||||
|
- **[Database]** Added **Peak Predators** (ID 50096) - *Icecrown*
|
||||||
|
- Objective: Kill 75 Beasts. Includes 12 Beast NPC types with full spawn coordinates.
|
||||||
|
- **[Database]** Added **Icecrown Advance** (ID 50151) - *Icecrown*
|
||||||
|
- Objective: Complete any 6 quests in Icecrown. Auto-completes upon reaching the objective.
|
||||||
|
- **[Database]** Added **Storm Peaks Trophy** (ID 50205) - *The Storm Peaks*
|
||||||
|
- Objective: Kill 1 Rare in The Storm Peaks. Includes 4 Rare NPC types (Skoll, Time-Lost Proto-Drake, Vyragosa, Dirkee) with full spawn coordinates.
|
||||||
|
|
||||||
|
## v9.7.3
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
- **[Database]** Implemented **Ebonhold Database Module**.
|
||||||
|
- Created dedicated `Database/Ebonhold/` structure for custom server data.
|
||||||
|
- Added `EbonholdLoader` to inject custom Quests, NPCs, Objects, and Items as overrides.
|
||||||
|
- **Note:** This structure preserves custom data during upstream Questie updates.
|
||||||
|
- **[Objectives]** Implemented **Automated Text Retrieval**.
|
||||||
|
- Questie now attempts to fetch quest text from the server at runtime for custom quests that are missing from the database.
|
||||||
|
- Added "Objectives Board" (ID 600600) as a global quest starter.
|
||||||
|
|
||||||
|
### Quests (Custom Content)
|
||||||
|
- **[New]** Added **Heart of the Dragonflights** (ID 50064) - *Dragonblight*
|
||||||
|
- Objective: Kill 30 Dragonkin. Includes 49 Dragonkin NPC types.
|
||||||
|
- **[New]** Added **Skies of Blade's Edge** (ID 50060) - *Blade's Edge Mountains*
|
||||||
|
- Objective: Kill 75 Dragonkin. Includes 17 Dragonkin NPC types.
|
||||||
|
- **[New]** Added **Shadowed Beasts** (ID 50087) - *Shadowmoon Valley*
|
||||||
|
- Objective: Kill 75 Beasts. Includes 25 Beast NPC types.
|
||||||
|
- **[New]** Added **Forest Stalkers** (ID 50083) - *Terokkar Forest*
|
||||||
|
- Objective: Kill 75 Beasts. Includes 53 Beast NPC types.
|
||||||
|
- **[New]** Added **Savage Heights** (ID 50085) - *Blade's Edge Mountains*
|
||||||
|
- Objective: Kill 75 Beasts. Includes 47 Beast NPC types.
|
||||||
|
- **[New]** Added **Unstable Fauna** (ID 50086) - *Netherstorm*
|
||||||
|
- Objective: Kill 75 Beasts. Includes 18 Beast NPC types.
|
||||||
|
- **[New]** Added **Elemental Balance** (ID 50026) - *Nagrand*
|
||||||
|
- Objective: Kill 30 Elementals. Includes 12 Elemental NPC types.
|
||||||
|
- **[New]** Added **Redridge Trophy** (ID 50160) and **Zangarmarsh Trophy** (ID 50192).
|
||||||
|
|
||||||
|
### New Ascension Quests
|
||||||
|
- **Westfall**: Agria's Medicine, Seven Years of Bad Luck, Worm-Eaten Apple, Goldshire's Generosity, Bookworm, Knowledge Corrupts, The Ruins of Northshire, Accursed Sisterhood, Words That Shepherd Madness, Oracular Idol, A Betrayal Within, The Maid I Left Behind, The Saddest Among Us, The Threat Swept Downstream, Stay a While, Defias Disruption.
|
||||||
|
- **Dun Morogh**: A Small Mistake, We Found Her!, The Scout's Favor, Old Mirsinth, Smoke on the Wind, A Promising Path, A Fitting Disguise, His Radiant Majesty, Deciphering Radiation, Soaking the Masses, Sever the Right Hand, A Growing Business, Thunderbrew's Hop, Stay a While, Live-Fire Demo, Bots on Strike, A Brother's Betrayal, The True Story, Timber for the Coldhewn, Icehide the Unbroken.
|
||||||
|
- **Teldrassil**: The Carrion Road, The Sister Who Never Returned, Finding the Good Meat, Transsubstantiating the Flesh, Communion Banquet, A Trail of Petals, Restless entrails, A Dark Warning, The Aid of Theren-Dion, No Place for Scavengers, Termites in Teldrassil, Stay a While, Elydna's Heirloom.
|
||||||
|
- **Durotar**: To Find a Cure, A Dangerous Sample, Knowledge of the Centaurs, Those Who Fell, The Way is Shut, The Sinister Triad, So That He May Hear Again, A Sinister Ritual, Innocents for Sinners, Unease Makes Tongues Wag, A Door Left Ajar, Esgramor's Master, Shinies!, Echoes of Hirsutta, Auction the Past, Stay a While, Durotar's Dire Drought, The Queen's Decree, Avianna's Rose, The Last Piece, Reversion.
|
||||||
|
- **Tirisfal Glades**: Rude Awakening, Marla's Last Wish, Monsters With Noble Intentions, Restless Family Members, An Unspeakable Secret, A Noble Heritage, The True Heir of the Cains, The Friends We Make Along the Way, I'm Home, Apothecary Flemer, The Nature of Freedom, Spotless Standing, Stay a While, More Than the Sum of its Parts, Scarlet Correspondence, A Humble Duty, The Balnirs' Rest, Brewing Disarray, This Is Justice.
|
||||||
|
- **Mulgore**: Death and Tribute, Death and Exile, Death and Dishonor, Death and Justice, Death by Laughter, To Whom I Devote, Fighting Over Carrion, Smoke on the Horizon, Amphora of Sacred Water, Stay a While, Exile of Embers, The Smoke that Remembers, The Circle’s Rite.
|
||||||
|
|
||||||
|
### New Ebonhold Quests
|
||||||
|
- **Outland**: Elemental Balance, Savage Heights, Unstable Fauna, Forest Stalkers, Marsh Predators, Skies of Blade's Edge, Shadowed Beasts, Zangarmarsh Trophy.
|
||||||
|
- **Northrend**: Tundra Turbulence, Stormbound, Dragonblight Trophy, Heart of the Dragonflights, Peak Predators, Icecrown Advance, Storm Peaks Trophy, Stormforged Scales, Fjord Front, Wild Basin, Grizzly Trophy, Zul'Drak Trophy, Basin Expeditions.
|
||||||
|
- **Azeroth**: Redridge Trophy, Morogh Missions, Azuremyst Aid, Shadow of Teldrassil, Trials of Durotar, Song of the Woods, Morogh Trophy, Tirisfal Trophy.
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Tracker]** **Combat Update Fix**: Tracker now updates objectives immediately during combat without causing Lua errors or taint.
|
||||||
|
- **[Tracker]** **Bag Update Fix**: Quest progress now updates immediately when looting items (fixes delay with loot bots).
|
||||||
|
- **[Arrow]** **Refined Visibility Logic**:
|
||||||
|
- **Auto Nearby**: Arrow correctly defaults to showing the nearest quest when no quests are tracked.
|
||||||
|
- **Zone Filter**: In "Auto Mode", the arrow hides if the nearest quest is in a different zone.
|
||||||
|
- **Instance Filter**: Arrow explicitly hides if the target is in a different instance.
|
||||||
|
- **[Map]** Fixed an issue where completed quest icons would persist on the map (`RequestMapUpdate` logic).
|
||||||
|
- **[Database]** Updated `wotlkNpcDB.lua` with scraped spawn data for 12 key beast NPCs in Terokkar Forest to ensure accuracy.
|
||||||
|
- **[Arrow]** Fixed a nil function error for `_CollectObjective` when processing incomplete quests.
|
||||||
|
- **[Arrow]** Fixed syntax issues that prevented `QuestieArrow` module from initializing correctly.
|
||||||
|
- **[Database]** Fixed a runtime crash in `ZoneDB` when encountering maps with no AreaId mapping (e.g., Kalimdor).
|
||||||
@@ -0,0 +1,397 @@
|
|||||||
|
---@class QuestieFramePool
|
||||||
|
local QuestieFramePool = QuestieLoader:CreateModule("QuestieFramePool")
|
||||||
|
-------------------------
|
||||||
|
--Import modules.
|
||||||
|
-------------------------
|
||||||
|
---@type QuestieQuest
|
||||||
|
local QuestieQuest = QuestieLoader:ImportModule("QuestieQuest")
|
||||||
|
---@type QuestieMap
|
||||||
|
local QuestieMap = QuestieLoader:ImportModule("QuestieMap")
|
||||||
|
---@type MapIconTooltip
|
||||||
|
local MapIconTooltip = QuestieLoader:ImportModule("MapIconTooltip")
|
||||||
|
---@type QuestieLib
|
||||||
|
local QuestieLib = QuestieLoader:ImportModule("QuestieLib")
|
||||||
|
---@type l10n
|
||||||
|
local l10n = QuestieLoader:ImportModule("l10n")
|
||||||
|
|
||||||
|
--- COMPATIBILITY ---
|
||||||
|
local C_Timer = QuestieCompat.C_Timer
|
||||||
|
local WorldMapFrame = QuestieCompat.WorldMapFrame
|
||||||
|
|
||||||
|
local HBDPins = QuestieCompat.HBDPins or LibStub("HereBeDragonsQuestie-Pins-2.0")
|
||||||
|
|
||||||
|
-- set pins parent to QuestieFrameGroup for easier compatibility with other addons
|
||||||
|
-- cant use this because it fucks with everything, but we gotta stick with HereBeDragonsQuestie anyway
|
||||||
|
HBDPins.MinimapGroup = CreateFrame("Frame", "QuestieFrameGroup", Minimap)
|
||||||
|
local WAYPOINT_COLOR = { 1, 0.72, 0, 0.5}
|
||||||
|
|
||||||
|
local _QuestieFramePool = {}
|
||||||
|
local numberOfFrames = 0
|
||||||
|
|
||||||
|
local unusedFrames = {}
|
||||||
|
local usedFrames = {};
|
||||||
|
local allFrames = {}
|
||||||
|
|
||||||
|
StaticPopupDialogs["QUESTIE_CONFIRMHIDE"] = {
|
||||||
|
text = "", -- set before showing
|
||||||
|
questID = 0, -- set before showing
|
||||||
|
button1 = l10n("Yes"),
|
||||||
|
button2 = l10n("No"),
|
||||||
|
OnAccept = function()
|
||||||
|
QuestieQuest:HideQuest(StaticPopupDialogs["QUESTIE_CONFIRMHIDE"].questID)
|
||||||
|
end,
|
||||||
|
SetQuest = function(self, id)
|
||||||
|
self.questID = id
|
||||||
|
self.text = l10n("Are you sure you want to hide the quest '%s'?\nIf this quest isn't actually available, please report it to us!", QuestieLib:GetColoredQuestName(id, Questie.db.profile.enableTooltipsQuestLevel, false, true))
|
||||||
|
|
||||||
|
-- locale might not be loaded when this is first created (this does happen almost always)
|
||||||
|
self.button1 = l10n("Yes")
|
||||||
|
self.button2 = l10n("No")
|
||||||
|
end,
|
||||||
|
OnShow = function(self)
|
||||||
|
self:SetFrameStrata("TOOLTIP")
|
||||||
|
end,
|
||||||
|
timeout = 0,
|
||||||
|
whileDead = true,
|
||||||
|
hideOnEscape = true,
|
||||||
|
preferredIndex = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Global Functions --
|
||||||
|
---@return IconFrame
|
||||||
|
function QuestieFramePool:GetFrame()
|
||||||
|
--Questie:Debug(Questie.DEBUG_SPAM, "[QuestieFramePool:GetFrame]")
|
||||||
|
|
||||||
|
---@type IconFrame
|
||||||
|
local returnFrame = next(unusedFrames)
|
||||||
|
returnFrame = returnFrame and unusedFrames[returnFrame]
|
||||||
|
|
||||||
|
if returnFrame and returnFrame.frameId and usedFrames[returnFrame.frameId] then
|
||||||
|
-- something went horribly wrong (desync bug?) don't use this frame since its already in use
|
||||||
|
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieFramePool:GetFrame] Tried to reuse frame, but that frame is already in use. frameId:", returnFrame.frameId)
|
||||||
|
returnFrame = nil
|
||||||
|
end
|
||||||
|
if not returnFrame then
|
||||||
|
returnFrame = _QuestieFramePool:QuestieCreateFrame()
|
||||||
|
else
|
||||||
|
--Questie:Debug(Questie.DEBUG_SPAM, "[QuestieFramePool:GetFrame] Reusing frame")
|
||||||
|
unusedFrames[returnFrame.frameId] = nil
|
||||||
|
end
|
||||||
|
if returnFrame ~= nil and returnFrame.hidden and returnFrame._show ~= nil and returnFrame._hide ~= nil then -- restore state to normal (toggle questie)
|
||||||
|
returnFrame.hidden = false
|
||||||
|
returnFrame.Show = returnFrame._show;
|
||||||
|
returnFrame.Hide = returnFrame._hide;
|
||||||
|
returnFrame._show = nil
|
||||||
|
returnFrame._hide = nil
|
||||||
|
end
|
||||||
|
returnFrame.FadeLogic = nil
|
||||||
|
returnFrame.faded = nil
|
||||||
|
returnFrame.miniMapIcon = nil
|
||||||
|
|
||||||
|
returnFrame.data = nil
|
||||||
|
returnFrame.x = nil;
|
||||||
|
returnFrame.y = nil;
|
||||||
|
returnFrame.AreaID = nil;
|
||||||
|
returnFrame.UiMapID = nil
|
||||||
|
|
||||||
|
if returnFrame.texture then
|
||||||
|
returnFrame.texture:SetVertexColor(1, 1, 1, 1)
|
||||||
|
end
|
||||||
|
returnFrame.loaded = true
|
||||||
|
returnFrame.shouldBeShowing = nil
|
||||||
|
returnFrame.hidden = nil
|
||||||
|
|
||||||
|
if returnFrame.BaseOnShow then
|
||||||
|
returnFrame:SetScript("OnShow", returnFrame.BaseOnShow)
|
||||||
|
end
|
||||||
|
|
||||||
|
if returnFrame.BaseOnUpdate then
|
||||||
|
returnFrame.glowLogicTimer = C_Timer.NewTicker(1, returnFrame.BaseOnUpdate);
|
||||||
|
else
|
||||||
|
returnFrame:SetScript("OnUpdate", nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
if returnFrame.BaseOnHide then
|
||||||
|
returnFrame:SetScript("OnHide", returnFrame.BaseOnHide)
|
||||||
|
end
|
||||||
|
|
||||||
|
usedFrames[returnFrame.frameId] = returnFrame
|
||||||
|
return returnFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
function QuestieFramePool:UpdateGlowConfig(mini, mode)
|
||||||
|
if mode then
|
||||||
|
for _, icon in pairs(usedFrames) do
|
||||||
|
if (((mini and icon.miniMapIcon) or not mini) and icon.glow) and icon.IsShown and icon:IsShown() then
|
||||||
|
icon:GetScript("OnShow")(icon) -- forces a glow update
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _, icon in pairs(usedFrames) do
|
||||||
|
if ((mini and icon.miniMapIcon) or (not mini and not icon.miniMapIcon)) and icon.glow then
|
||||||
|
icon.glow:Hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function QuestieFramePool:UpdateColorConfig(mini, enable)
|
||||||
|
if enable then
|
||||||
|
for _, icon in pairs(usedFrames) do
|
||||||
|
if (mini and icon.miniMapIcon) or (not mini and not icon.miniMapIcon) then
|
||||||
|
local colors = {1, 1, 1}
|
||||||
|
if icon.data.IconColor ~= nil then
|
||||||
|
colors = icon.data.IconColor
|
||||||
|
end
|
||||||
|
icon.texture:SetVertexColor(colors[1], colors[2], colors[3], 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _, icon in pairs(usedFrames) do
|
||||||
|
if (mini and icon.miniMapIcon) or (not mini and not icon.miniMapIcon) then
|
||||||
|
icon.texture:SetVertexColor(1, 1, 1, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function QuestieFramePool:RecycleFrame(frame)
|
||||||
|
--Questie:Debug(Questie.DEBUG_SPAM, "[QuestieFramePool:RecycleFrame]")
|
||||||
|
usedFrames[frame.frameId] = nil
|
||||||
|
unusedFrames[frame.frameId] = frame
|
||||||
|
end
|
||||||
|
|
||||||
|
function _QuestieFramePool:QuestieCreateFrame()
|
||||||
|
--Questie:Debug(Questie.DEBUG_SPAM, "[QuestieFramePool:QuestieCreateFrame]")
|
||||||
|
numberOfFrames = numberOfFrames + 1
|
||||||
|
local newFrame = QuestieFramePool.Qframe:New(numberOfFrames, MapIconTooltip.Show)
|
||||||
|
|
||||||
|
tinsert(allFrames, newFrame)
|
||||||
|
return newFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---@param iconFrame IconFrame @The parent frame for the current line.
|
||||||
|
---@param waypointTable table<number, Point> @A table containing waypoints {{X, Y}, ...}
|
||||||
|
---@param lineWidth number @Width of the line.
|
||||||
|
---@param color number[] @A table consisting of 4 variable {1, 1, 1, 1} RGB-Opacity
|
||||||
|
---@return LineFrame[]
|
||||||
|
function QuestieFramePool:CreateWaypoints(iconFrame, waypointTable, lineWidth, color, areaId)
|
||||||
|
local lineFrameList = {}
|
||||||
|
local lastPos
|
||||||
|
--Set defaults if needed.
|
||||||
|
local lWidth = lineWidth or 1.5;
|
||||||
|
local col = color or WAYPOINT_COLOR
|
||||||
|
|
||||||
|
for _, waypointSubTable in pairs(waypointTable) do
|
||||||
|
lastPos = nil
|
||||||
|
for _, waypoint in pairs(waypointSubTable) do
|
||||||
|
if lastPos then
|
||||||
|
local lineFrame = QuestieFramePool:CreateLine(iconFrame, lastPos[1], lastPos[2], waypoint[1], waypoint[2], lWidth, col, areaId)
|
||||||
|
tinsert(lineFrameList, lineFrame);
|
||||||
|
end
|
||||||
|
lastPos = waypoint
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return lineFrameList;
|
||||||
|
end
|
||||||
|
|
||||||
|
local lineFrameCount = 1
|
||||||
|
|
||||||
|
---@param iconFrame IconFrame @The parent frame for the current line.
|
||||||
|
---@param startX number @A value between 0-100
|
||||||
|
---@param startY number @A value between 0-100
|
||||||
|
---@param endX number @A value between 0-100
|
||||||
|
---@param endY number @A value between 0-100
|
||||||
|
---@param lineWidth number @Width of the line.
|
||||||
|
---@param color number[] @A table consisting of 4 variable {1, 1, 1, 1} RGB-Opacity
|
||||||
|
---@return LineFrame
|
||||||
|
---@class LineFrame @A frame that contains the line used in waypoints.
|
||||||
|
function QuestieFramePool:CreateLine(iconFrame, startX, startY, endX, endY, lineWidth, color, areaId)
|
||||||
|
|
||||||
|
--Create the framepool for lines if it does not already exist.
|
||||||
|
if not QuestieFramePool.Routes_Lines then
|
||||||
|
QuestieFramePool.Routes_Lines={}
|
||||||
|
end
|
||||||
|
--Names are not stricktly needed, but it is nice for debugging.
|
||||||
|
local frameName = "questieLineFrame".. lineFrameCount;
|
||||||
|
|
||||||
|
--tremove default always picks the last element, however counting arrays is kinda bugged? So just get index 1 instead.
|
||||||
|
local lineFrame = tremove(QuestieFramePool.Routes_Lines, 1) or CreateFrame("Button", frameName, iconFrame);
|
||||||
|
if not lineFrame.frameId then
|
||||||
|
lineFrame.frameId = lineFrameCount;
|
||||||
|
end
|
||||||
|
|
||||||
|
local canvas = WorldMapFrame:GetCanvas()
|
||||||
|
|
||||||
|
local width = canvas:GetWidth();
|
||||||
|
local height = canvas:GetHeight();
|
||||||
|
|
||||||
|
--Setting the parent is required to get the correct frame levels.
|
||||||
|
|
||||||
|
lineFrame:SetParent(canvas) --This fixes the pan and zoom for lines
|
||||||
|
if QuestieCompat.Is335 then
|
||||||
|
lineFrame.CreateLine = QuestieCompat.CreateLine
|
||||||
|
else
|
||||||
|
lineFrame:SetFrameLevel(2015) -- This needs to be high, because of the regular WorldMapFrame.ScrollContainer
|
||||||
|
lineFrame:SetFrameStrata("FULLSCREEN")
|
||||||
|
end
|
||||||
|
|
||||||
|
--How to identify what the frame actually contains, this is not used atm could easily be changed.
|
||||||
|
lineFrame.type = "line"
|
||||||
|
|
||||||
|
--Include the line in the iconFrame.
|
||||||
|
if not iconFrame.data.lineFrames then
|
||||||
|
iconFrame.data.lineFrames = {};
|
||||||
|
end
|
||||||
|
tinsert(iconFrame.data.lineFrames, lineFrame);
|
||||||
|
lineFrame.iconFrame = iconFrame;
|
||||||
|
lineFrame.data = iconFrame.data
|
||||||
|
lineFrame.x = (startX + endX) / 2
|
||||||
|
lineFrame.y = (startY + endY) / 2
|
||||||
|
lineFrame.AreaID = areaId or iconFrame.AreaID
|
||||||
|
lineFrame.texture = iconFrame.texture
|
||||||
|
|
||||||
|
function lineFrame:Unload()
|
||||||
|
if not self.iconFrame then
|
||||||
|
return -- already unloaded
|
||||||
|
end
|
||||||
|
self:Hide();
|
||||||
|
self.iconFrame = nil;
|
||||||
|
self.x = nil
|
||||||
|
self.y = nil
|
||||||
|
self.data = nil
|
||||||
|
self.texture = nil
|
||||||
|
self.AreaID = nil
|
||||||
|
HBDPins:RemoveWorldMapIcon(Questie, self)
|
||||||
|
tinsert(QuestieFramePool.Routes_Lines, self);
|
||||||
|
end
|
||||||
|
local line = lineFrame.line or lineFrame:CreateLine();
|
||||||
|
lineFrame.line = line;
|
||||||
|
|
||||||
|
line.dR = color[1];
|
||||||
|
line.dG = color[2];
|
||||||
|
line.dB = color[3];
|
||||||
|
line.dA = color[4];
|
||||||
|
line:SetColorTexture(color[1],color[2],color[3],color[4]);
|
||||||
|
|
||||||
|
local lineBorder = lineFrame.lineBorder or lineFrame:CreateLine();
|
||||||
|
lineFrame.lineBorder = lineBorder;
|
||||||
|
|
||||||
|
lineBorder.dR = color[1];
|
||||||
|
lineBorder.dG = color[2];
|
||||||
|
lineBorder.dB = color[3];
|
||||||
|
lineBorder.dA = color[4];
|
||||||
|
lineBorder:SetColorTexture(0,0,0,color[4]/2);
|
||||||
|
|
||||||
|
-- Set texture coordinates and anchors
|
||||||
|
--line:ClearAllPoints();
|
||||||
|
|
||||||
|
startX = startX * width / 100
|
||||||
|
startY = startY * height / -100 -- We do by / -100 due to using the top left point
|
||||||
|
endX = endX * width / 100
|
||||||
|
endY = endY * height / -100
|
||||||
|
|
||||||
|
width = abs(startX - endX) + lineWidth * 4
|
||||||
|
height = abs(startY - endY) + lineWidth * 4
|
||||||
|
|
||||||
|
local framePosX = max(startX, endX) - lineWidth * 2 - width / 2
|
||||||
|
local framePosY = min(startY, endY) + lineWidth * 2 + height / 2
|
||||||
|
|
||||||
|
lineFrame:SetHeight(height);
|
||||||
|
lineFrame:SetWidth(width);
|
||||||
|
lineFrame:SetPoint("TOPLEFT", canvas, "TOPLEFT", framePosX, framePosY)
|
||||||
|
|
||||||
|
line:SetDrawLayer("OVERLAY", -5)
|
||||||
|
line:SetStartPoint("TOPLEFT", startX - framePosX, startY - framePosY)
|
||||||
|
line:SetEndPoint("TOPLEFT", endX - framePosX, endY - framePosY)
|
||||||
|
line:SetThickness(lineWidth);
|
||||||
|
|
||||||
|
lineBorder:SetDrawLayer("OVERLAY", -6)
|
||||||
|
lineBorder:SetStartPoint("TOPLEFT", startX - framePosX, startY - framePosY)
|
||||||
|
lineBorder:SetEndPoint("TOPLEFT", endX - framePosX, endY - framePosY)
|
||||||
|
lineBorder:SetThickness(lineWidth+2);
|
||||||
|
|
||||||
|
lineFrame:EnableMouse(true)
|
||||||
|
|
||||||
|
--- This is needed because HBD will show the icons again after switching zones and stuff like that
|
||||||
|
function lineFrame:FakeHide()
|
||||||
|
if not self.hidden then
|
||||||
|
self.shouldBeShowing = self:IsShown();
|
||||||
|
self._show = self.Show;
|
||||||
|
self.Show = function()
|
||||||
|
self.shouldBeShowing = true;
|
||||||
|
end
|
||||||
|
self:Hide();
|
||||||
|
self._hide = self.Hide;
|
||||||
|
self.Hide = function()
|
||||||
|
self.shouldBeShowing = false;
|
||||||
|
end
|
||||||
|
self.hidden = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- This is needed because HBD will show the icons again after switching zones and stuff like that
|
||||||
|
function lineFrame:FakeShow()
|
||||||
|
if self.hidden then
|
||||||
|
self.hidden = false
|
||||||
|
self.Show = self._show;
|
||||||
|
self.Hide = self._hide;
|
||||||
|
self._show = nil
|
||||||
|
self._hide = nil
|
||||||
|
if self.shouldBeShowing then
|
||||||
|
self:Show();
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--lineFrame:SetBackdrop({ -- mouseover debugging
|
||||||
|
-- bgFile = "Interface/Tooltips/UI-Tooltip-Background",
|
||||||
|
-- edgeFile = nil,
|
||||||
|
-- edgeSize = 0,
|
||||||
|
-- insets = { left = 0, right = 0, top = 0, bottom = 0 },
|
||||||
|
--})
|
||||||
|
|
||||||
|
--lineFrame:SetBackdropColor(1,0,1,1)
|
||||||
|
|
||||||
|
lineFrame:SetScript("OnEnter", function(self)
|
||||||
|
if self and self.iconFrame then
|
||||||
|
local script = self.iconFrame:GetScript("OnEnter")
|
||||||
|
if script then
|
||||||
|
script(self.iconFrame)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
lineFrame:SetScript("OnLeave", function(self)
|
||||||
|
if self and self.iconFrame then
|
||||||
|
local script = self.iconFrame:GetScript("OnLeave")
|
||||||
|
if script then
|
||||||
|
script(self.iconFrame)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
lineFrame:RegisterForClicks("RightButtonUp", "LeftButtonUp")
|
||||||
|
lineFrame:SetScript("OnClick", function(self, button)
|
||||||
|
if self and self.iconFrame then
|
||||||
|
local script = self.iconFrame:GetScript("OnClick")
|
||||||
|
if script then
|
||||||
|
script(self.iconFrame, button)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
lineFrame:Hide();
|
||||||
|
|
||||||
|
|
||||||
|
--Should we keep these frames in the questIdFrames? Currently it is also a child of the icon.
|
||||||
|
--Maybe the unload of the parent should just unload the children.
|
||||||
|
--For safety we check this here too.
|
||||||
|
--if (QuestieMap.questIdFrames[lineFrame.iconFrame.data.Id] == nil) then
|
||||||
|
-- QuestieMap.questIdFrames[lineFrame.iconFrame.data.Id] = {}
|
||||||
|
--end
|
||||||
|
--tinsert(QuestieMap.questIdFrames[lineFrame.iconFrame.data.Id], lineFrame:GetName());
|
||||||
|
|
||||||
|
--Keep a total lineFrame count for names.
|
||||||
|
lineFrameCount = lineFrameCount + 1;
|
||||||
|
return lineFrame
|
||||||
|
end
|
||||||
@@ -0,0 +1,398 @@
|
|||||||
|
---@class QuestieFramePool
|
||||||
|
local QuestieFramePool = QuestieLoader:CreateModule("QuestieFramePool")
|
||||||
|
-------------------------
|
||||||
|
--Import modules.
|
||||||
|
-------------------------
|
||||||
|
---@type QuestieQuest
|
||||||
|
local QuestieQuest = QuestieLoader:ImportModule("QuestieQuest")
|
||||||
|
---@type QuestieMap
|
||||||
|
local QuestieMap = QuestieLoader:ImportModule("QuestieMap")
|
||||||
|
---@type MapIconTooltip
|
||||||
|
local MapIconTooltip = QuestieLoader:ImportModule("MapIconTooltip")
|
||||||
|
---@type QuestieLib
|
||||||
|
local QuestieLib = QuestieLoader:ImportModule("QuestieLib")
|
||||||
|
---@type l10n
|
||||||
|
local l10n = QuestieLoader:ImportModule("l10n")
|
||||||
|
|
||||||
|
--- COMPATIBILITY ---
|
||||||
|
local C_Timer = QuestieCompat.C_Timer
|
||||||
|
local WorldMapFrame = QuestieCompat.WorldMapFrame
|
||||||
|
|
||||||
|
local HBDPins = QuestieCompat.HBDPins or LibStub("HereBeDragonsQuestie-Pins-2.0")
|
||||||
|
|
||||||
|
-- set pins parent to QuestieFrameGroup for easier compatibility with other addons
|
||||||
|
-- cant use this because it fucks with everything, but we gotta stick with HereBeDragonsQuestie anyway
|
||||||
|
HBDPins.MinimapGroup = CreateFrame("Frame", "QuestieFrameGroup", Minimap)
|
||||||
|
local WAYPOINT_COLOR = { 1, 0.72, 0, 0.5}
|
||||||
|
|
||||||
|
local _QuestieFramePool = {}
|
||||||
|
local numberOfFrames = 0
|
||||||
|
|
||||||
|
local unusedFrames = {}
|
||||||
|
local usedFrames = {};
|
||||||
|
local allFrames = {}
|
||||||
|
|
||||||
|
StaticPopupDialogs["QUESTIE_CONFIRMHIDE"] = {
|
||||||
|
text = "", -- set before showing
|
||||||
|
questID = 0, -- set before showing
|
||||||
|
button1 = l10n("Yes"),
|
||||||
|
button2 = l10n("No"),
|
||||||
|
OnAccept = function()
|
||||||
|
QuestieQuest:HideQuest(StaticPopupDialogs["QUESTIE_CONFIRMHIDE"].questID)
|
||||||
|
end,
|
||||||
|
SetQuest = function(self, id)
|
||||||
|
self.questID = id
|
||||||
|
self.text = l10n("Are you sure you want to hide the quest '%s'?\nIf this quest isn't actually available, please report it to us!", QuestieLib:GetColoredQuestName(id, Questie.db.profile.enableTooltipsQuestLevel, false, true))
|
||||||
|
|
||||||
|
-- locale might not be loaded when this is first created (this does happen almost always)
|
||||||
|
self.button1 = l10n("Yes")
|
||||||
|
self.button2 = l10n("No")
|
||||||
|
end,
|
||||||
|
OnShow = function(self)
|
||||||
|
self:SetFrameStrata("TOOLTIP")
|
||||||
|
end,
|
||||||
|
timeout = 0,
|
||||||
|
whileDead = true,
|
||||||
|
hideOnEscape = true,
|
||||||
|
preferredIndex = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Global Functions --
|
||||||
|
---@return IconFrame
|
||||||
|
function QuestieFramePool:GetFrame()
|
||||||
|
--Questie:Debug(Questie.DEBUG_SPAM, "[QuestieFramePool:GetFrame]")
|
||||||
|
|
||||||
|
---@type IconFrame
|
||||||
|
local returnFrame = next(unusedFrames)
|
||||||
|
returnFrame = returnFrame and unusedFrames[returnFrame]
|
||||||
|
|
||||||
|
if returnFrame and returnFrame.frameId and usedFrames[returnFrame.frameId] then
|
||||||
|
-- something went horribly wrong (desync bug?) don't use this frame since its already in use
|
||||||
|
Questie:Debug(Questie.DEBUG_CRITICAL, "[QuestieFramePool:GetFrame] Tried to reuse frame, but that frame is already in use. frameId:", returnFrame.frameId)
|
||||||
|
returnFrame = nil
|
||||||
|
end
|
||||||
|
if not returnFrame then
|
||||||
|
returnFrame = _QuestieFramePool:QuestieCreateFrame()
|
||||||
|
else
|
||||||
|
--Questie:Debug(Questie.DEBUG_SPAM, "[QuestieFramePool:GetFrame] Reusing frame")
|
||||||
|
unusedFrames[returnFrame.frameId] = nil
|
||||||
|
end
|
||||||
|
if returnFrame ~= nil and returnFrame.hidden and returnFrame._show ~= nil and returnFrame._hide ~= nil then -- restore state to normal (toggle questie)
|
||||||
|
returnFrame.hidden = false
|
||||||
|
returnFrame.Show = returnFrame._show;
|
||||||
|
returnFrame.Hide = returnFrame._hide;
|
||||||
|
returnFrame._show = nil
|
||||||
|
returnFrame._hide = nil
|
||||||
|
end
|
||||||
|
returnFrame.FadeLogic = nil
|
||||||
|
returnFrame.faded = nil
|
||||||
|
returnFrame.miniMapIcon = nil
|
||||||
|
|
||||||
|
returnFrame.data = nil
|
||||||
|
returnFrame.x = nil;
|
||||||
|
returnFrame.y = nil;
|
||||||
|
returnFrame.AreaID = nil;
|
||||||
|
returnFrame.UiMapID = nil
|
||||||
|
|
||||||
|
if returnFrame.texture then
|
||||||
|
returnFrame.texture:SetVertexColor(1, 1, 1, 1)
|
||||||
|
end
|
||||||
|
returnFrame.loaded = true
|
||||||
|
returnFrame.shouldBeShowing = nil
|
||||||
|
returnFrame.hidden = nil
|
||||||
|
returnFrame._needsUnload = nil
|
||||||
|
|
||||||
|
if returnFrame.BaseOnShow then
|
||||||
|
returnFrame:SetScript("OnShow", returnFrame.BaseOnShow)
|
||||||
|
end
|
||||||
|
|
||||||
|
if returnFrame.BaseOnUpdate then
|
||||||
|
returnFrame.glowLogicTimer = C_Timer.NewTicker(1, returnFrame.BaseOnUpdate);
|
||||||
|
else
|
||||||
|
returnFrame:SetScript("OnUpdate", nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
if returnFrame.BaseOnHide then
|
||||||
|
returnFrame:SetScript("OnHide", returnFrame.BaseOnHide)
|
||||||
|
end
|
||||||
|
|
||||||
|
usedFrames[returnFrame.frameId] = returnFrame
|
||||||
|
return returnFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
function QuestieFramePool:UpdateGlowConfig(mini, mode)
|
||||||
|
if mode then
|
||||||
|
for _, icon in pairs(usedFrames) do
|
||||||
|
if (((mini and icon.miniMapIcon) or not mini) and icon.glow) and icon.IsShown and icon:IsShown() then
|
||||||
|
icon:GetScript("OnShow")(icon) -- forces a glow update
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _, icon in pairs(usedFrames) do
|
||||||
|
if ((mini and icon.miniMapIcon) or (not mini and not icon.miniMapIcon)) and icon.glow then
|
||||||
|
icon.glow:Hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function QuestieFramePool:UpdateColorConfig(mini, enable)
|
||||||
|
if enable then
|
||||||
|
for _, icon in pairs(usedFrames) do
|
||||||
|
if (mini and icon.miniMapIcon) or (not mini and not icon.miniMapIcon) then
|
||||||
|
local colors = {1, 1, 1}
|
||||||
|
if icon.data.IconColor ~= nil then
|
||||||
|
colors = icon.data.IconColor
|
||||||
|
end
|
||||||
|
icon.texture:SetVertexColor(colors[1], colors[2], colors[3], 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _, icon in pairs(usedFrames) do
|
||||||
|
if (mini and icon.miniMapIcon) or (not mini and not icon.miniMapIcon) then
|
||||||
|
icon.texture:SetVertexColor(1, 1, 1, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function QuestieFramePool:RecycleFrame(frame)
|
||||||
|
--Questie:Debug(Questie.DEBUG_SPAM, "[QuestieFramePool:RecycleFrame]")
|
||||||
|
usedFrames[frame.frameId] = nil
|
||||||
|
unusedFrames[frame.frameId] = frame
|
||||||
|
end
|
||||||
|
|
||||||
|
function _QuestieFramePool:QuestieCreateFrame()
|
||||||
|
--Questie:Debug(Questie.DEBUG_SPAM, "[QuestieFramePool:QuestieCreateFrame]")
|
||||||
|
numberOfFrames = numberOfFrames + 1
|
||||||
|
local newFrame = QuestieFramePool.Qframe:New(numberOfFrames, MapIconTooltip.Show)
|
||||||
|
|
||||||
|
tinsert(allFrames, newFrame)
|
||||||
|
return newFrame
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---@param iconFrame IconFrame @The parent frame for the current line.
|
||||||
|
---@param waypointTable table<number, Point> @A table containing waypoints {{X, Y}, ...}
|
||||||
|
---@param lineWidth number @Width of the line.
|
||||||
|
---@param color number[] @A table consisting of 4 variable {1, 1, 1, 1} RGB-Opacity
|
||||||
|
---@return LineFrame[]
|
||||||
|
function QuestieFramePool:CreateWaypoints(iconFrame, waypointTable, lineWidth, color, areaId)
|
||||||
|
local lineFrameList = {}
|
||||||
|
local lastPos
|
||||||
|
--Set defaults if needed.
|
||||||
|
local lWidth = lineWidth or 1.5;
|
||||||
|
local col = color or WAYPOINT_COLOR
|
||||||
|
|
||||||
|
for _, waypointSubTable in pairs(waypointTable) do
|
||||||
|
lastPos = nil
|
||||||
|
for _, waypoint in pairs(waypointSubTable) do
|
||||||
|
if lastPos then
|
||||||
|
local lineFrame = QuestieFramePool:CreateLine(iconFrame, lastPos[1], lastPos[2], waypoint[1], waypoint[2], lWidth, col, areaId)
|
||||||
|
tinsert(lineFrameList, lineFrame);
|
||||||
|
end
|
||||||
|
lastPos = waypoint
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return lineFrameList;
|
||||||
|
end
|
||||||
|
|
||||||
|
local lineFrameCount = 1
|
||||||
|
|
||||||
|
---@param iconFrame IconFrame @The parent frame for the current line.
|
||||||
|
---@param startX number @A value between 0-100
|
||||||
|
---@param startY number @A value between 0-100
|
||||||
|
---@param endX number @A value between 0-100
|
||||||
|
---@param endY number @A value between 0-100
|
||||||
|
---@param lineWidth number @Width of the line.
|
||||||
|
---@param color number[] @A table consisting of 4 variable {1, 1, 1, 1} RGB-Opacity
|
||||||
|
---@return LineFrame
|
||||||
|
---@class LineFrame @A frame that contains the line used in waypoints.
|
||||||
|
function QuestieFramePool:CreateLine(iconFrame, startX, startY, endX, endY, lineWidth, color, areaId)
|
||||||
|
|
||||||
|
--Create the framepool for lines if it does not already exist.
|
||||||
|
if not QuestieFramePool.Routes_Lines then
|
||||||
|
QuestieFramePool.Routes_Lines={}
|
||||||
|
end
|
||||||
|
--Names are not stricktly needed, but it is nice for debugging.
|
||||||
|
local frameName = "questieLineFrame".. lineFrameCount;
|
||||||
|
|
||||||
|
--tremove default always picks the last element, however counting arrays is kinda bugged? So just get index 1 instead.
|
||||||
|
local lineFrame = tremove(QuestieFramePool.Routes_Lines, 1) or CreateFrame("Button", frameName, iconFrame);
|
||||||
|
if not lineFrame.frameId then
|
||||||
|
lineFrame.frameId = lineFrameCount;
|
||||||
|
end
|
||||||
|
|
||||||
|
local canvas = WorldMapFrame:GetCanvas()
|
||||||
|
|
||||||
|
local width = canvas:GetWidth();
|
||||||
|
local height = canvas:GetHeight();
|
||||||
|
|
||||||
|
--Setting the parent is required to get the correct frame levels.
|
||||||
|
|
||||||
|
lineFrame:SetParent(canvas) --This fixes the pan and zoom for lines
|
||||||
|
if QuestieCompat.Is335 then
|
||||||
|
lineFrame.CreateLine = QuestieCompat.CreateLine
|
||||||
|
else
|
||||||
|
lineFrame:SetFrameLevel(2015) -- This needs to be high, because of the regular WorldMapFrame.ScrollContainer
|
||||||
|
lineFrame:SetFrameStrata("FULLSCREEN")
|
||||||
|
end
|
||||||
|
|
||||||
|
--How to identify what the frame actually contains, this is not used atm could easily be changed.
|
||||||
|
lineFrame.type = "line"
|
||||||
|
|
||||||
|
--Include the line in the iconFrame.
|
||||||
|
if not iconFrame.data.lineFrames then
|
||||||
|
iconFrame.data.lineFrames = {};
|
||||||
|
end
|
||||||
|
tinsert(iconFrame.data.lineFrames, lineFrame);
|
||||||
|
lineFrame.iconFrame = iconFrame;
|
||||||
|
lineFrame.data = iconFrame.data
|
||||||
|
lineFrame.x = (startX + endX) / 2
|
||||||
|
lineFrame.y = (startY + endY) / 2
|
||||||
|
lineFrame.AreaID = areaId or iconFrame.AreaID
|
||||||
|
lineFrame.texture = iconFrame.texture
|
||||||
|
|
||||||
|
function lineFrame:Unload()
|
||||||
|
if not self.iconFrame then
|
||||||
|
return -- already unloaded
|
||||||
|
end
|
||||||
|
self:Hide();
|
||||||
|
self.iconFrame = nil;
|
||||||
|
self.x = nil
|
||||||
|
self.y = nil
|
||||||
|
self.data = nil
|
||||||
|
self.texture = nil
|
||||||
|
self.AreaID = nil
|
||||||
|
HBDPins:RemoveWorldMapIcon(Questie, self)
|
||||||
|
tinsert(QuestieFramePool.Routes_Lines, self);
|
||||||
|
end
|
||||||
|
local line = lineFrame.line or lineFrame:CreateLine();
|
||||||
|
lineFrame.line = line;
|
||||||
|
|
||||||
|
line.dR = color[1];
|
||||||
|
line.dG = color[2];
|
||||||
|
line.dB = color[3];
|
||||||
|
line.dA = color[4];
|
||||||
|
line:SetColorTexture(color[1],color[2],color[3],color[4]);
|
||||||
|
|
||||||
|
local lineBorder = lineFrame.lineBorder or lineFrame:CreateLine();
|
||||||
|
lineFrame.lineBorder = lineBorder;
|
||||||
|
|
||||||
|
lineBorder.dR = color[1];
|
||||||
|
lineBorder.dG = color[2];
|
||||||
|
lineBorder.dB = color[3];
|
||||||
|
lineBorder.dA = color[4];
|
||||||
|
lineBorder:SetColorTexture(0,0,0,color[4]/2);
|
||||||
|
|
||||||
|
-- Set texture coordinates and anchors
|
||||||
|
--line:ClearAllPoints();
|
||||||
|
|
||||||
|
startX = startX * width / 100
|
||||||
|
startY = startY * height / -100 -- We do by / -100 due to using the top left point
|
||||||
|
endX = endX * width / 100
|
||||||
|
endY = endY * height / -100
|
||||||
|
|
||||||
|
width = abs(startX - endX) + lineWidth * 4
|
||||||
|
height = abs(startY - endY) + lineWidth * 4
|
||||||
|
|
||||||
|
local framePosX = max(startX, endX) - lineWidth * 2 - width / 2
|
||||||
|
local framePosY = min(startY, endY) + lineWidth * 2 + height / 2
|
||||||
|
|
||||||
|
lineFrame:SetHeight(height);
|
||||||
|
lineFrame:SetWidth(width);
|
||||||
|
lineFrame:SetPoint("TOPLEFT", canvas, "TOPLEFT", framePosX, framePosY)
|
||||||
|
|
||||||
|
line:SetDrawLayer("OVERLAY", -5)
|
||||||
|
line:SetStartPoint("TOPLEFT", startX - framePosX, startY - framePosY)
|
||||||
|
line:SetEndPoint("TOPLEFT", endX - framePosX, endY - framePosY)
|
||||||
|
line:SetThickness(lineWidth);
|
||||||
|
|
||||||
|
lineBorder:SetDrawLayer("OVERLAY", -6)
|
||||||
|
lineBorder:SetStartPoint("TOPLEFT", startX - framePosX, startY - framePosY)
|
||||||
|
lineBorder:SetEndPoint("TOPLEFT", endX - framePosX, endY - framePosY)
|
||||||
|
lineBorder:SetThickness(lineWidth+2);
|
||||||
|
|
||||||
|
lineFrame:EnableMouse(true)
|
||||||
|
|
||||||
|
--- This is needed because HBD will show the icons again after switching zones and stuff like that
|
||||||
|
function lineFrame:FakeHide()
|
||||||
|
if not self.hidden then
|
||||||
|
self.shouldBeShowing = self:IsShown();
|
||||||
|
self._show = self.Show;
|
||||||
|
self.Show = function()
|
||||||
|
self.shouldBeShowing = true;
|
||||||
|
end
|
||||||
|
self:Hide();
|
||||||
|
self._hide = self.Hide;
|
||||||
|
self.Hide = function()
|
||||||
|
self.shouldBeShowing = false;
|
||||||
|
end
|
||||||
|
self.hidden = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- This is needed because HBD will show the icons again after switching zones and stuff like that
|
||||||
|
function lineFrame:FakeShow()
|
||||||
|
if self.hidden then
|
||||||
|
self.hidden = false
|
||||||
|
self.Show = self._show;
|
||||||
|
self.Hide = self._hide;
|
||||||
|
self._show = nil
|
||||||
|
self._hide = nil
|
||||||
|
if self.shouldBeShowing then
|
||||||
|
self:Show();
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--lineFrame:SetBackdrop({ -- mouseover debugging
|
||||||
|
-- bgFile = "Interface/Tooltips/UI-Tooltip-Background",
|
||||||
|
-- edgeFile = nil,
|
||||||
|
-- edgeSize = 0,
|
||||||
|
-- insets = { left = 0, right = 0, top = 0, bottom = 0 },
|
||||||
|
--})
|
||||||
|
|
||||||
|
--lineFrame:SetBackdropColor(1,0,1,1)
|
||||||
|
|
||||||
|
lineFrame:SetScript("OnEnter", function(self)
|
||||||
|
if self and self.iconFrame then
|
||||||
|
local script = self.iconFrame:GetScript("OnEnter")
|
||||||
|
if script then
|
||||||
|
script(self.iconFrame)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
lineFrame:SetScript("OnLeave", function(self)
|
||||||
|
if self and self.iconFrame then
|
||||||
|
local script = self.iconFrame:GetScript("OnLeave")
|
||||||
|
if script then
|
||||||
|
script(self.iconFrame)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
lineFrame:RegisterForClicks("RightButtonUp", "LeftButtonUp")
|
||||||
|
lineFrame:SetScript("OnClick", function(self, button)
|
||||||
|
if self and self.iconFrame then
|
||||||
|
local script = self.iconFrame:GetScript("OnClick")
|
||||||
|
if script then
|
||||||
|
script(self.iconFrame, button)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
lineFrame:Hide();
|
||||||
|
|
||||||
|
|
||||||
|
--Should we keep these frames in the questIdFrames? Currently it is also a child of the icon.
|
||||||
|
--Maybe the unload of the parent should just unload the children.
|
||||||
|
--For safety we check this here too.
|
||||||
|
--if (QuestieMap.questIdFrames[lineFrame.iconFrame.data.Id] == nil) then
|
||||||
|
-- QuestieMap.questIdFrames[lineFrame.iconFrame.data.Id] = {}
|
||||||
|
--end
|
||||||
|
--tinsert(QuestieMap.questIdFrames[lineFrame.iconFrame.data.Id], lineFrame:GetName());
|
||||||
|
|
||||||
|
--Keep a total lineFrame count for names.
|
||||||
|
lineFrameCount = lineFrameCount + 1;
|
||||||
|
return lineFrame
|
||||||
|
end
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,250 @@
|
|||||||
|
## Interface: 30300
|
||||||
|
## Title: Questie - Ebonhold
|
||||||
|
## Author: Questie Team
|
||||||
|
## Notes: A standalone Classic QuestHelper
|
||||||
|
## Notes-esMX: Ayundante de misión
|
||||||
|
## Notes-esES: Ayundante de misión
|
||||||
|
## Notes-ptBR: Ajudante de missão
|
||||||
|
## Notes-frFR: Assistant de quête
|
||||||
|
## Version: 9.7.12
|
||||||
|
## RequiredDeps:
|
||||||
|
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
|
||||||
|
## SavedVariables: QuestieConfig
|
||||||
|
## SavedVariablesPerCharacter: QuestieConfigCharacter
|
||||||
|
## X-Curse-Project-ID: 334372
|
||||||
|
## X-Wago-ID: qv634BKb
|
||||||
|
## X-WOW_PROJECT_ID: 11
|
||||||
|
|
||||||
|
# Loader module
|
||||||
|
Modules\Libs\QuestieLoader.lua
|
||||||
|
|
||||||
|
# COMPATIBILITY
|
||||||
|
Modules\QuestieCompat.lua
|
||||||
|
Compat\embeds.xml
|
||||||
|
|
||||||
|
Modules\VersionCheck.lua
|
||||||
|
|
||||||
|
# Thread Manager
|
||||||
|
Modules\Libs\ThreadLib.lua
|
||||||
|
#Message Handler
|
||||||
|
Modules\Libs\MessageHandler.lua
|
||||||
|
|
||||||
|
#Quest XP
|
||||||
|
Database\QuestXP\QuestieXP.lua
|
||||||
|
Database\QuestXP\DB\xpDB-wotlk.lua
|
||||||
|
|
||||||
|
# stream module (used by DB)
|
||||||
|
Modules\QuestieStream.lua
|
||||||
|
|
||||||
|
# Zones
|
||||||
|
Database\Zones\zoneTables.lua
|
||||||
|
# Ascension Custom Zones
|
||||||
|
Database\Ascension\Zones\AscensionZoneTables.lua
|
||||||
|
Database\Ascension\Zones\AscensionUiMapData.lua
|
||||||
|
# Ebonhold Custom Zones
|
||||||
|
Database\Ebonhold\Zones\EbonholdZoneTables.lua
|
||||||
|
Database\Ebonhold\Zones\EbonholdUiMapData.lua
|
||||||
|
Database\Zones\zoneDB.lua
|
||||||
|
|
||||||
|
|
||||||
|
# Databases
|
||||||
|
Database\Wotlk\wotlkItemDB.lua
|
||||||
|
Database\Wotlk\wotlkNpcDB.lua
|
||||||
|
Database\Wotlk\wotlkObjectDB.lua
|
||||||
|
Database\Wotlk\wotlkQuestDB.lua
|
||||||
|
Database\QuestieDB.lua
|
||||||
|
Database\questDB.lua
|
||||||
|
Database\objectDB.lua
|
||||||
|
Database\npcDB.lua
|
||||||
|
Database\itemDB.lua
|
||||||
|
Database\Constants.lua
|
||||||
|
Database\MeetingStones.lua
|
||||||
|
|
||||||
|
# Ascension Custom Database
|
||||||
|
Database\Ascension\Bronzebeard\AscensionNpcDB.lua
|
||||||
|
Database\Ascension\Bronzebeard\AscensionObjectDB.lua
|
||||||
|
Database\Ascension\Bronzebeard\AscensionItemDB.lua
|
||||||
|
Database\Ascension\Bronzebeard\AscensionQuestDB.lua
|
||||||
|
Database\Ascension\AscensionLoader.lua
|
||||||
|
|
||||||
|
# Ebonhold Custom Database
|
||||||
|
Database\Ebonhold\Ebonhold\EbonholdNpcDB.lua
|
||||||
|
Database\Ebonhold\Ebonhold\EbonholdObjectDB.lua
|
||||||
|
Database\Ebonhold\Ebonhold\EbonholdItemDB.lua
|
||||||
|
Database\Ebonhold\Ebonhold\EbonholdQuestDB.lua
|
||||||
|
Database\Ebonhold\EbonholdLoader.lua
|
||||||
|
|
||||||
|
|
||||||
|
# Corrections
|
||||||
|
Database\Corrections\AutoTableUpdates.lua
|
||||||
|
Database\Corrections\QuestieCorrections.lua
|
||||||
|
Database\Corrections\QuestieItemBlacklist.lua
|
||||||
|
Database\Corrections\QuestieNPCBlacklist.lua
|
||||||
|
Database\Corrections\QuestieQuestBlacklist.lua
|
||||||
|
#Database\Corrections\SoMPhases.lua
|
||||||
|
Database\Corrections\QuestieEvent.lua
|
||||||
|
|
||||||
|
# Automatic General Corrections
|
||||||
|
Database\Corrections\Automatic\itemStartFixes.lua
|
||||||
|
Database\Corrections\Automatic\classicQuestReputationFixes.lua
|
||||||
|
|
||||||
|
# Classic Corrections
|
||||||
|
Database\Corrections\classicQuestFixes.lua
|
||||||
|
Database\Corrections\classicNPCFixes.lua
|
||||||
|
Database\Corrections\classicItemFixes.lua
|
||||||
|
Database\Corrections\classicObjectFixes.lua
|
||||||
|
|
||||||
|
# TBC Corrections
|
||||||
|
Database\Corrections\tbcQuestFixes.lua
|
||||||
|
Database\Corrections\tbcNPCFixes.lua
|
||||||
|
Database\Corrections\tbcItemFixes.lua
|
||||||
|
Database\Corrections\tbcObjectFixes.lua
|
||||||
|
|
||||||
|
# Wotlk Corrections
|
||||||
|
Database\Corrections\wotlkQuestFixes.lua
|
||||||
|
Database\Corrections\wotlkNPCFixes.lua
|
||||||
|
Database\Corrections\wotlkItemFixes.lua
|
||||||
|
Database\Corrections\wotlkObjectFixes.lua
|
||||||
|
|
||||||
|
# Compiler
|
||||||
|
Database\compiler.lua
|
||||||
|
|
||||||
|
# Localization
|
||||||
|
Localization\l10n.lua
|
||||||
|
Localization\Translations\Translations.xml
|
||||||
|
|
||||||
|
Localization\lookups\lookupQuestCategories.lua
|
||||||
|
Localization\lookups\lookupZones.lua
|
||||||
|
Localization\lookups\Wotlk\lookupItems\lookupItems.xml
|
||||||
|
Localization\lookups\Wotlk\lookupNpcs\lookupNpcs.xml
|
||||||
|
Localization\lookups\Wotlk\lookupObjects\lookupObjects.xml
|
||||||
|
Localization\lookups\Wotlk\lookupQuests\lookupQuests.xml
|
||||||
|
|
||||||
|
# Libs
|
||||||
|
Modules\Libs\QuestieLib.lua
|
||||||
|
Modules\Libs\QuestieSerializer.lua
|
||||||
|
Modules\Libs\QuestieCombatQueue.lua
|
||||||
|
Modules\Libs\RamerDouglasPeucker.lua
|
||||||
|
|
||||||
|
# Modules
|
||||||
|
Modules\QuestieValidateGameCache.lua
|
||||||
|
Modules\Arrow\QuestieArrow.lua
|
||||||
|
Modules\QuestieInit.lua
|
||||||
|
Modules\MinimapIcon.lua
|
||||||
|
Modules\QuestieProfessions.lua
|
||||||
|
Modules\QuestieReputation.lua
|
||||||
|
Modules\QuestieEventHandler.lua
|
||||||
|
Modules\QuestieLearner.lua
|
||||||
|
Modules\Migration.lua
|
||||||
|
Modules\QuestieMenu\Townsfolk.lua
|
||||||
|
Modules\QuestieMenu\ClassTrainers.lua
|
||||||
|
Modules\QuestieMenu\Mailboxes.lua
|
||||||
|
Modules\QuestieMenu\MeetingStones.lua
|
||||||
|
Modules\QuestieMenu\ProfessionTrainers.lua
|
||||||
|
Modules\QuestieMenu\QuestieMenu.lua
|
||||||
|
Modules\QuestieAnnounce.lua
|
||||||
|
Modules\QuestieShutUp.lua
|
||||||
|
Modules\Sounds.lua
|
||||||
|
Modules\TaskQueue.lua
|
||||||
|
Modules\QuestiePlayer.lua
|
||||||
|
#Modules\QuestieDebugOffer.lua
|
||||||
|
Modules\WorldMapButton\WorldMapButton.lua
|
||||||
|
#Modules\WorldMapButton\QuestieWorldMapButtonTemplate.xml
|
||||||
|
|
||||||
|
# QuestLinks
|
||||||
|
Modules\QuestLinks\ChatFilter.lua
|
||||||
|
Modules\QuestLinks\Hooks.lua
|
||||||
|
Modules\QuestLinks\Link.lua
|
||||||
|
|
||||||
|
# Tooltips
|
||||||
|
Modules\Tooltips\Tooltip.lua
|
||||||
|
Modules\Tooltips\MapIconTooltip.lua
|
||||||
|
Modules\Tooltips\TooltipHandler.lua
|
||||||
|
|
||||||
|
# Auto
|
||||||
|
Modules\Auto\QuestieAuto.lua
|
||||||
|
Modules\Auto\Privates.lua
|
||||||
|
Modules\Auto\DisallowedIDs.lua
|
||||||
|
|
||||||
|
# FramePool
|
||||||
|
Modules\FramePool\QuestieFramePool.lua
|
||||||
|
Modules\FramePool\QuestieFrame.lua
|
||||||
|
|
||||||
|
# Map
|
||||||
|
Modules\Map\QuestieMap.lua
|
||||||
|
Modules\Map\QuestieMapUtils.lua
|
||||||
|
#Modules\Map\HBDHooks.lua
|
||||||
|
Modules\Map\WeaponMasterSkills.lua
|
||||||
|
|
||||||
|
|
||||||
|
# Quest
|
||||||
|
Modules\Quest\AvailableQuests.lua
|
||||||
|
Modules\Quest\QuestLogCache.lua
|
||||||
|
Modules\Quest\DailyQuests.lua
|
||||||
|
Modules\Quest\IsleOfQuelDanas.lua
|
||||||
|
Modules\Quest\QuestEventHandler.lua
|
||||||
|
Modules\Quest\QuestgiverFrame.lua
|
||||||
|
Modules\Quest\QuestieQuest.lua
|
||||||
|
Modules\Quest\QuestieQuestPrivates.lua
|
||||||
|
|
||||||
|
Modules\QuestieNameplate.lua
|
||||||
|
Modules\QuestieCoordinates.lua
|
||||||
|
|
||||||
|
# Network
|
||||||
|
Modules\Network\QuestieComms.lua
|
||||||
|
Modules\Network\QuestieCommsData.lua
|
||||||
|
|
||||||
|
# Journey
|
||||||
|
Modules\Journey\QuestieJourney.lua
|
||||||
|
Modules\Journey\QuestieJourneyPrivates.lua
|
||||||
|
Modules\Journey\QuestieJourneyUtils.lua
|
||||||
|
Modules\Journey\History.lua
|
||||||
|
Modules\Journey\QuestDetailsFrame.lua
|
||||||
|
Modules\Journey\tabs\MyJourney\Note.lua
|
||||||
|
Modules\Journey\tabs\MyJourney\MyJourney.lua
|
||||||
|
Modules\Journey\tabs\MyJourney\MyJourneyTab.lua
|
||||||
|
Modules\Journey\tabs\QuestsByZone\QuestsByZone.lua
|
||||||
|
Modules\Journey\tabs\QuestsByZone\QuestsByZoneTab.lua
|
||||||
|
#Modules\Journey\tabs\Search\Search.lua
|
||||||
|
#Modules\Journey\tabs\Search\SearchTab.lua
|
||||||
|
Modules\Journey\QuestieSearch.lua
|
||||||
|
Modules\Journey\QuestieSearchResults.lua
|
||||||
|
|
||||||
|
# Tracker
|
||||||
|
Modules\Tracker\QuestieTracker.lua
|
||||||
|
Modules\Tracker\TrackerUtils.lua
|
||||||
|
Modules\Tracker\TrackerMenu.lua
|
||||||
|
Modules\Tracker\TrackerFadeTicker.lua
|
||||||
|
Modules\Tracker\TrackerBaseFrame.lua
|
||||||
|
Modules\Tracker\TrackerHeaderFrame.lua
|
||||||
|
Modules\Tracker\TrackerQuestFrame.lua
|
||||||
|
Modules\Tracker\TrackerQuestTimers.lua
|
||||||
|
Modules\Tracker\TrackerLinePool.lua
|
||||||
|
|
||||||
|
# Tutorial
|
||||||
|
Modules\Tutorial\ChooseObjectiveType.lua
|
||||||
|
Modules\Tutorial\Tutorial.lua
|
||||||
|
|
||||||
|
#Modules\QuestieDBMIntegration.lua
|
||||||
|
Modules\QuestieSlash.lua
|
||||||
|
|
||||||
|
# Options
|
||||||
|
Modules\Options\QuestieOptions.lua
|
||||||
|
Modules\Options\QuestieOptionsDefaults.lua
|
||||||
|
Modules\Options\QuestieOptionsUtils.lua
|
||||||
|
Modules\Options\AdvancedTab\QuestieOptionsAdvanced.lua
|
||||||
|
Modules\Options\AutoTab\QuestieOptionsAuto.lua
|
||||||
|
Modules\Options\DBMTab\QuestieOptionsDBM.lua
|
||||||
|
Modules\Options\GeneralTab\QuestieOptionsGeneral.lua
|
||||||
|
Modules\Options\IconsTab\QuestieOptionsIcons.lua
|
||||||
|
Modules\Options\NameplateTab\QuestieOptionsNameplate.lua
|
||||||
|
Modules\Options\TrackerTab\QuestieOptionsTracker.lua
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
Modules\QuestieCleanup.lua
|
||||||
|
|
||||||
|
# Profiler
|
||||||
|
Modules\QuestieProfiler.lua
|
||||||
|
|
||||||
|
# Main
|
||||||
|
Questie.lua
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
<div align="center">
|
||||||
|
|
||||||
|
# Questie (3.3.5a)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
[](https://xurkon.github.io/PE-Questie/)
|
||||||
|
[](https://www.patreon.com/Xurkon)
|
||||||
|
[](https://www.paypal.me/Xurkon)
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
<br/>
|
||||||
|
**A fork of the WoW Classic Questie addon aiming to provide compatibility with ANY private server.**
|
||||||
|
|
||||||
|
[⬇ **Download Latest**](https://github.com/Xurkon/PE-Questie/releases/latest) • [📂 **View Source**](https://github.com/Xurkon/PE-Questie) • [📖 **Read Documentation**](https://xurkon.github.io/PE-Questie/)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📥 Installation
|
||||||
|
|
||||||
|
1. [Download](https://github.com/Xurkon/PE-Questie/releases) the archive.
|
||||||
|
2. Extract it into the `Interface/AddOns/` directory. The folder name should be `Questie-335`.
|
||||||
|
3. **Custom Server Support**: If you are playing on a server emulating a previous expansion (Classic or TBC) using the 3.3.5 client, you can add `-Classic` or `-TBC` to the folder name to load specific datasets.
|
||||||
|
4. **Map Compatibility**: If your server lacks a world map patch, enable `Options → Advanced → Use WotLK map data`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Fixes & Compatibility
|
||||||
|
|
||||||
|
### 🛡️ Nameplates
|
||||||
|
- Explicitly skips **Ascension Nameplates** to avoid conflicts, while maintaining compatibility with generic nameplate addons.
|
||||||
|
|
||||||
|
### 📊 Quest Tracker
|
||||||
|
- **Ascension API**: Fully compatible with custom quest APIs; no crashes on auto-turn-in quests.
|
||||||
|
- **Header Persistence**: Resolved issues where quest headers would disappear from the tracker.
|
||||||
|
- **Dynamic Updates**: Instant refresh when accepting, completing, or abandoning quests.
|
||||||
|
- **Combat Safety**: Protected with `pcall` to prevent UI lockups during intense combat updates.
|
||||||
|
|
||||||
|
### 💬 Tooltips
|
||||||
|
- Fixed all legacy Lua errors.
|
||||||
|
- **New Feature**: Displays if an NPC drops an item that starts a quest directly in the tooltip.
|
||||||
|
|
||||||
|
### 🗺️ Maps (Minimap & World Map)
|
||||||
|
- **Minimap**: Fixed zoom-related Lua errors.
|
||||||
|
- **World Map**: Full support for Ascension's `WorldMapFrame` (minimized mode), **Mapster**, and **Magnify-WotLK**.
|
||||||
|
- **Icon Cleanup**: Resolved "ghost icon" bug where completed quests remained visible on the map.
|
||||||
|
|
||||||
|
### 📦 Custom IDs
|
||||||
|
- Native support for large integer IDs common on custom private servers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Features
|
||||||
|
|
||||||
|
### ⚔️ Ascension Scaling
|
||||||
|
- Quests automatically scale to character level, perfectly matching the Ascension Scaling system.
|
||||||
|
|
||||||
|
### 📍 Visual Map Objectives
|
||||||
|
Notes for quest starters, turn-ins, and complex objectives are drawn directly on your maps.
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="https://i.imgur.com/4abi5yu.png" height="200" alt="Quest Givers" />
|
||||||
|
<img src="https://i.imgur.com/DgvBHyh.png" height="200" alt="Quest Complete" />
|
||||||
|
<img src="https://i.imgur.com/uPykHKC.png" height="200" alt="Quest Tooltip" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### 📜 Advanced Quest Tracker
|
||||||
|
- **Smart Tracking**: Automatically tracks quests upon acceptance.
|
||||||
|
- **Expanded Capacity**: Displays up to 20 quests (original limit: 5).
|
||||||
|
- **Interactive**: Left-click to open the log; Right-click for focus modes or TomTom arrow integration.
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="https://user-images.githubusercontent.com/8838573/67285596-24dbab00-f4d8-11e9-9ae1-7dd6206b5e48.png" width="400" alt="Tracker" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### 🗺️ My Journey & Quests by Zone
|
||||||
|
- **Journey Log**: Record every major step of your adventure.
|
||||||
|
- **Completionist View**: Lists all available and completed quests per zone to ensure nothing is missed.
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="https://user-images.githubusercontent.com/8838573/67285651-3cb32f00-f4d8-11e9-95d8-e8ceb2a8d871.png" height="200" alt="Journey" />
|
||||||
|
<img src="https://user-images.githubusercontent.com/8838573/67285665-450b6a00-f4d8-11e9-9283-325d26c7c70d.png" height="200" alt="Zone Quests" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### 🔍 Database Search & Config
|
||||||
|
- **Global Search**: Find any NPC, Object, or Quest in the massive Questie database.
|
||||||
|
- **Deep Customization**: Adjust everything from icon scale to tracking logic.
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="https://user-images.githubusercontent.com/8838573/67285691-4f2d6880-f4d8-11e9-8656-b3e37dce2f05.png" height="200" alt="Search" />
|
||||||
|
<img src="https://user-images.githubusercontent.com/8838573/67285731-61a7a200-f4d8-11e9-9026-b1eeaad0d721.png" height="200" alt="Config" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 👥 Credits
|
||||||
|
- **Questie Team** - Original addon developers.
|
||||||
|
- **Xurkon** - Private Expansion fork and maintenance.
|
||||||
|
- **Project Ascension & Ebonhold Communities** - Testing and data feedback.
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
MIT License - See [LICENSE](LICENSE) for details.
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v9.7.12
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- **[Quest]** Fixed an issue where tracking icons for dynamically updated custom quests like Peak Predators would prematurely disappear due to sync delays on WotLK servers.
|
||||||
|
- **[Map]** Resolved a frame pool leak that prevented the yellow Finisher icon from appearing immediately on the map after turning in or completing a quest.
|
||||||
|
|
||||||
|
|
||||||
## v9.7.11
|
## v9.7.11
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ function QuestieFramePool:GetFrame()
|
|||||||
returnFrame.loaded = true
|
returnFrame.loaded = true
|
||||||
returnFrame.shouldBeShowing = nil
|
returnFrame.shouldBeShowing = nil
|
||||||
returnFrame.hidden = nil
|
returnFrame.hidden = nil
|
||||||
|
returnFrame._needsUnload = nil
|
||||||
|
|
||||||
if returnFrame.BaseOnShow then
|
if returnFrame.BaseOnShow then
|
||||||
returnFrame:SetScript("OnShow", returnFrame.BaseOnShow)
|
returnFrame:SetScript("OnShow", returnFrame.BaseOnShow)
|
||||||
|
|||||||
@@ -1660,10 +1660,11 @@ function QuestieQuest:PopulateQuestLogInfo(quest)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if #quest.Objectives == 0 and #quest.SpecialObjectives == 0 and ((quest.triggerEnd and #quest.triggerEnd > 0) or (quest.Finisher and quest.Finisher.Id ~= nil)) then
|
if #quest.Objectives == 0 and #quest.SpecialObjectives == 0 and (not quest.ObjectiveData or #quest.ObjectiveData == 0) and ((quest.triggerEnd and #quest.triggerEnd > 0) or (quest.Finisher and quest.Finisher.Id ~= nil)) then
|
||||||
-- Some quests when picked up will be flagged isComplete == 0 but the quest.Objective table or quest.SpecialObjectives table is nil. This
|
-- Some quests when picked up will be flagged isComplete == 0 but the quest.Objective table or quest.SpecialObjectives table is nil. This
|
||||||
-- check assumes the Quest should have been flagged questLogEngtry.isComplete == 1. We're specifically looking for a quest.triggerEnd or
|
-- check assumes the Quest should have been flagged questLogEngtry.isComplete == 1. We're specifically looking for a quest.triggerEnd or
|
||||||
-- a quest.Finisher.Id because this might throw an error if there is nothing to populate when we call QuestieQuest:AddFinisher().
|
-- a quest.Finisher.Id because this might throw an error if there is nothing to populate when we call QuestieQuest:AddFinisher().
|
||||||
|
-- We added a check for quest.ObjectiveData to ensure we don't prematurely complete quests that are just waiting for the server to sync their objectives.
|
||||||
QuestieMap:UnloadQuestFrames(quest.Id)
|
QuestieMap:UnloadQuestFrames(quest.Id)
|
||||||
QuestieQuest:AddFinisher(quest)
|
QuestieQuest:AddFinisher(quest)
|
||||||
quest.isComplete = true
|
quest.isComplete = true
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
## Notes-esES: Ayundante de misión
|
## Notes-esES: Ayundante de misión
|
||||||
## Notes-ptBR: Ajudante de missão
|
## Notes-ptBR: Ajudante de missão
|
||||||
## Notes-frFR: Assistant de quête
|
## Notes-frFR: Assistant de quête
|
||||||
## Version: 9.7.11
|
## Version: 9.7.12
|
||||||
## RequiredDeps:
|
## RequiredDeps:
|
||||||
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
|
## OptionalDeps: Ace3, CallbackHandler-1.0, HereBeDragons, LibDataBroker-1.1, LibDBIcon-1.0, LibSharedMedia-3.0, LibStub, LibUIDropDownMenu
|
||||||
## SavedVariables: QuestieConfig
|
## SavedVariables: QuestieConfig
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Questie (3.3.5a)
|
# Questie (3.3.5a)
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
[](https://xurkon.github.io/PE-Questie/)
|
[](https://xurkon.github.io/PE-Questie/)
|
||||||
[](https://www.patreon.com/Xurkon)
|
[](https://www.patreon.com/Xurkon)
|
||||||
|
|||||||
Reference in New Issue
Block a user