390 lines
16 KiB
Lua
390 lines
16 KiB
Lua
---@class QuestieLink
|
|
local QuestieLink = QuestieLoader:CreateModule("QuestieLink")
|
|
-------------------------
|
|
--Import modules
|
|
-------------------------
|
|
---@type QuestieDB
|
|
local QuestieDB = QuestieLoader:ImportModule("QuestieDB")
|
|
---@type QuestieLib
|
|
local QuestieLib = QuestieLoader:ImportModule("QuestieLib")
|
|
---@type QuestiePlayer
|
|
local QuestiePlayer = QuestieLoader:ImportModule("QuestiePlayer")
|
|
---@type TrackerUtils
|
|
local TrackerUtils = QuestieLoader:ImportModule("TrackerUtils")
|
|
---@type l10n
|
|
local l10n = QuestieLoader:ImportModule("l10n")
|
|
|
|
--- COMPATIBILITY ---
|
|
local GetQuestLink = QuestieCompat.GetQuestLink
|
|
local CALENDAR_WEEKDAY_NAMES = QuestieCompat.CALENDAR_WEEKDAY_NAMES
|
|
local CALENDAR_FULLDATE_MONTH_NAMES = QuestieCompat.CALENDAR_FULLDATE_MONTH_NAMES
|
|
|
|
QuestieLink.lastItemRefTooltip = ""
|
|
|
|
-- Forward declaration
|
|
local _AddQuestTitle, _AddQuestStatus, _AddQuestDescription, _AddQuestRequirements, _GetQuestStarter, _GetQuestFinisher, _AddPlayerQuestProgress
|
|
local _AddTooltipLine, _AddColoredTooltipLine
|
|
|
|
|
|
local oldItemSetHyperlink = ItemRefTooltip.SetHyperlink
|
|
--- Override of the default SetHyperlink function to filter Questie links
|
|
---@param link string
|
|
function ItemRefTooltip:SetHyperlink(link, ...)
|
|
local questiePrefix, questId = string.match(link, "(questie):(%d+):")
|
|
local isQuestieLink = questiePrefix == "questie"
|
|
|
|
if (not ItemRefTooltip:IsShown()) then
|
|
QuestieLink.lastItemRefTooltip = ""
|
|
else
|
|
QuestieLink.lastItemRefTooltip = QuestieLink.lastItemRefTooltip or link
|
|
end
|
|
|
|
if isQuestieLink and questId then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTooltips:ItemRefTooltip] SetHyperlink:", link)
|
|
ShowUIPanel(ItemRefTooltip)
|
|
ItemRefTooltip:SetOwner(UIParent, "ANCHOR_PRESERVE");
|
|
QuestieLink:CreateQuestTooltip(link)
|
|
ItemRefTooltip:Show()
|
|
|
|
local tooltipText = ItemRefTooltipTextLeft1:GetText()
|
|
if QuestieLink.lastItemRefTooltip == tooltipText then
|
|
ItemRefTooltip:Hide()
|
|
QuestieLink.lastItemRefTooltip = ""
|
|
return
|
|
end
|
|
|
|
QuestieLink.lastItemRefTooltip = tooltipText
|
|
return
|
|
else
|
|
-- Make sure to call the default function so everything that is not Questie can be handled (item links e.g.)
|
|
oldItemSetHyperlink(self, link, ...)
|
|
end
|
|
end
|
|
|
|
---@return string
|
|
function QuestieLink:GetQuestLinkStringById(questId)
|
|
local questName = QuestieDB.QueryQuestSingle(questId, "name");
|
|
local questLevel, _ = QuestieLib.GetTbcLevel(questId);
|
|
return QuestieLink:GetQuestLinkString(questLevel, questName, questId)
|
|
end
|
|
|
|
---@return string
|
|
function QuestieLink:GetQuestLinkString(questLevel, questName, questId)
|
|
local questLink = GetQuestLink and GetQuestLink(questId)
|
|
questName = questName or (questLink and string.match(questLink, "%[(.-)%]")) or "Quest"
|
|
local questString = "["..questName.." ("..tostring(questId)..")]"
|
|
|
|
if Questie.db.profile.trackerShowQuestLevel then
|
|
questString = questString:gsub("%[", "[["..tostring(questLevel).."] ")
|
|
end
|
|
|
|
return questLink and questLink:gsub("%[(.-)%]", questString) or questString
|
|
end
|
|
|
|
---@return string
|
|
function QuestieLink:GetQuestHyperLink(questId, senderGUID)
|
|
local coloredQuestName = QuestieLib:GetColoredQuestName(questId, Questie.db.profile.trackerShowQuestLevel, true, false)
|
|
|
|
if not coloredQuestName then
|
|
return nil
|
|
end
|
|
|
|
local questLevel, _ = QuestieLib.GetTbcLevel(questId)
|
|
local isRepeatable = QuestieDB.IsRepeatable(questId)
|
|
|
|
if (not senderGUID) then
|
|
senderGUID = UnitGUID("player")
|
|
end
|
|
|
|
return "|Hquestie:"..questId..":"..senderGUID.."|h"..QuestieLib:PrintDifficultyColor(questLevel, "[", isRepeatable, QuestieDB.IsActiveEventQuest(questId), QuestieDB.IsPvPQuest(questId))..coloredQuestName..QuestieLib:PrintDifficultyColor(questLevel, "]", isRepeatable, QuestieDB.IsActiveEventQuest(questId), QuestieDB.IsPvPQuest(questId)).."|h"
|
|
end
|
|
|
|
function QuestieLink:CreateQuestTooltip(link)
|
|
local isQuestieLink, _, _ = string.match(link, "questie:(%d+):.*")
|
|
if isQuestieLink then
|
|
---@type string
|
|
local questIdStr = select(2, strsplit(":", link))
|
|
local questId = tonumber(questIdStr)
|
|
local quest = QuestieDB.GetQuest(questId)
|
|
|
|
if quest then
|
|
_AddQuestTitle(quest)
|
|
_AddQuestStatus(quest)
|
|
|
|
_AddTooltipLine(" ")
|
|
|
|
_AddQuestDescription(quest)
|
|
_AddQuestRequirements(quest)
|
|
local starterName, starterZoneName = _GetQuestStarter(quest)
|
|
local finisherName, finisherZoneName = _GetQuestFinisher(quest)
|
|
_AddPlayerQuestProgress(quest, starterName, starterZoneName, finisherName, finisherZoneName)
|
|
end
|
|
end
|
|
end
|
|
|
|
---@param text string
|
|
---@param wrapText boolean?
|
|
_AddTooltipLine = function (text, wrapText)
|
|
ItemRefTooltip:AddLine(text, 1, 1, 1, wrapText)
|
|
end
|
|
|
|
---@param text string
|
|
---@param color string
|
|
---@param wrapText boolean?
|
|
_AddColoredTooltipLine = function (text, color, wrapText)
|
|
text = Questie:Colorize(text, color)
|
|
ItemRefTooltip:AddLine(text, 1, 1, 1, wrapText)
|
|
end
|
|
|
|
_AddQuestTitle = function(quest)
|
|
local questLevel = QuestieLib:GetLevelString(quest.Id, quest.name, quest.level, false)
|
|
|
|
local titleColor = "gold"
|
|
if quest.specialFlags == 1 then
|
|
titleColor = "blue"
|
|
end
|
|
|
|
if Questie.db.profile.trackerShowQuestLevel and Questie.db.profile.enableTooltipsQuestID then
|
|
_AddColoredTooltipLine(questLevel .. quest.name .. " (" .. quest.Id .. ")", titleColor)
|
|
elseif Questie.db.profile.trackerShowQuestLevel and (not Questie.db.profile.enableTooltipsQuestID) then
|
|
_AddColoredTooltipLine(questLevel .. quest.name, titleColor)
|
|
elseif Questie.db.profile.enableTooltipsQuestID and (not Questie.db.profile.trackerShowQuestLevel) then
|
|
_AddColoredTooltipLine(quest.name .. " (" .. quest.Id .. ")", titleColor)
|
|
else
|
|
_AddColoredTooltipLine(quest.name, titleColor)
|
|
end
|
|
end
|
|
|
|
_AddQuestStatus = function (quest)
|
|
if QuestiePlayer.currentQuestlog[quest.Id] then
|
|
local onQuestText = l10n("You are on this quest")
|
|
local stateText
|
|
local questIsComplete = QuestieDB.IsComplete(quest.Id)
|
|
if questIsComplete == 1 then
|
|
stateText = Questie:Colorize(l10n("Complete"), "green")
|
|
elseif questIsComplete == -1 then
|
|
stateText = Questie:Colorize(l10n("Failed"), "red")
|
|
end
|
|
|
|
if stateText then
|
|
_AddTooltipLine(onQuestText .. " (" .. stateText .. ")")
|
|
else
|
|
_AddColoredTooltipLine(onQuestText, "green")
|
|
end
|
|
elseif Questie.db.char.complete[quest.Id] then
|
|
_AddColoredTooltipLine(l10n("You have completed this quest"), "green")
|
|
elseif (UnitLevel("player") < quest.requiredLevel or (not QuestieDB.IsDoable(quest.Id))) and (not Questie.db.char.hidden[quest.Id]) then
|
|
_AddColoredTooltipLine(l10n("You are ineligible for this quest"), "red")
|
|
elseif quest.specialFlags == 1 then
|
|
_AddColoredTooltipLine(l10n("This quest is repeatable"), "yellow")
|
|
else
|
|
_AddColoredTooltipLine(l10n("You have not done this quest"), "yellow")
|
|
end
|
|
end
|
|
|
|
_AddQuestDescription = function (quest)
|
|
if quest and quest.Description and quest.Description[1] then
|
|
_AddColoredTooltipLine(quest.Description[1], "white", true)
|
|
if #quest.Description > 2 then
|
|
for i = 2, #quest.Description do
|
|
--_AddTooltipLine(" ") -- this is just adding extra lines between text definitions in DB files
|
|
_AddColoredTooltipLine(quest.Description[i], "white", true)
|
|
end
|
|
end
|
|
else
|
|
_AddColoredTooltipLine(l10n("This quest is an automatic completion quest and does not contain an objective."), "white", true)
|
|
end
|
|
end
|
|
|
|
_AddQuestRequirements = function (quest)
|
|
if #quest.ObjectiveData > 0 and not (QuestiePlayer.currentQuestlog[quest.Id] or Questie.db.char.complete[quest.Id]) then
|
|
for i = 1, #quest.ObjectiveData do
|
|
local currentObjective = quest.ObjectiveData[i]
|
|
if currentObjective then
|
|
if currentObjective.Text then
|
|
if currentObjective == quest.ObjectiveData[1] then
|
|
_AddTooltipLine(" ")
|
|
_AddColoredTooltipLine(l10n("Requirements"), "gold")
|
|
end
|
|
_AddColoredTooltipLine(currentObjective.Text, "white")
|
|
else
|
|
local objectiveName
|
|
if currentObjective.Type == "monster" then
|
|
objectiveName = QuestieDB.QueryNPCSingle(currentObjective.Id, "name")
|
|
else
|
|
objectiveName = QuestieDB.QueryItemSingle(currentObjective.Id, "name")
|
|
end
|
|
|
|
if objectiveName then
|
|
if currentObjective == quest.ObjectiveData[1] then
|
|
_AddTooltipLine(" ")
|
|
_AddColoredTooltipLine(l10n("Requirements"), "gold")
|
|
end
|
|
_AddColoredTooltipLine(objectiveName, "white")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
_GetQuestStarter = function (quest)
|
|
if quest.Starts then
|
|
local starterName, starterZoneName
|
|
if quest.Starts.NPC ~= nil then
|
|
local npc = QuestieDB:GetNPC(quest.Starts.NPC[1])
|
|
starterName = npc.name
|
|
|
|
if npc.zoneID ~= 0 then
|
|
starterZoneName = TrackerUtils:GetZoneNameByID(npc.zoneID)
|
|
else
|
|
starterZoneName = TrackerUtils:GetZoneNameByID(quest.zoneOrSort)
|
|
end
|
|
elseif quest.Starts.Item ~= nil then
|
|
local item = QuestieDB:GetItem(quest.Starts.Item[1])
|
|
starterName = item.name
|
|
|
|
if item.Sources and item.Sources[1] and item.Sources[1].Type then
|
|
local itemSource = item.Sources[1]
|
|
local dropStart
|
|
|
|
if itemSource.Type == "monster" then
|
|
dropStart = QuestieDB:GetNPC(itemSource.Id)
|
|
elseif itemSource.Type == "object" then
|
|
dropStart = QuestieDB:GetObject(itemSource.Id)
|
|
end
|
|
|
|
if item.zoneID ~= 0 then
|
|
starterZoneName = TrackerUtils:GetZoneNameByID(dropStart.zoneID)
|
|
else
|
|
starterZoneName = TrackerUtils:GetZoneNameByID(quest.zoneOrSort)
|
|
end
|
|
else
|
|
starterZoneName = TrackerUtils:GetZoneNameByID(quest.zoneOrSort)
|
|
end
|
|
elseif quest and quest.Starts and quest.Starts.GameObject and quest.Starts.GameObject[1] then
|
|
local object = QuestieDB:GetObject(quest.Starts.GameObject[1])
|
|
starterName = object.name
|
|
if object.zoneID ~= 0 then
|
|
starterZoneName = TrackerUtils:GetZoneNameByID(object.zoneID)
|
|
else
|
|
starterZoneName = TrackerUtils:GetZoneNameByID(quest.zoneOrSort)
|
|
end
|
|
end
|
|
|
|
return starterName, starterZoneName
|
|
end
|
|
|
|
return nil, nil
|
|
end
|
|
|
|
_GetQuestFinisher = function (quest)
|
|
if quest.Finisher and quest.Finisher.Id then
|
|
local finisherName, finisherZoneName
|
|
if quest.Finisher.Type == "monster" then
|
|
local npc = QuestieDB:GetNPC(quest.Finisher.Id)
|
|
finisherName = npc.name
|
|
|
|
if npc.zoneID ~= 0 then
|
|
finisherZoneName = TrackerUtils:GetZoneNameByID(npc.zoneID)
|
|
else
|
|
finisherZoneName = TrackerUtils:GetZoneNameByID(quest.zoneOrSort)
|
|
end
|
|
elseif quest.Finisher.Type == "object" then
|
|
local object = QuestieDB:GetObject(quest.Finisher.Id)
|
|
finisherName = object.name
|
|
|
|
if object.zoneID ~= 0 then
|
|
finisherZoneName = TrackerUtils:GetZoneNameByID(object.zoneID)
|
|
else
|
|
finisherZoneName = TrackerUtils:GetZoneNameByID(quest.zoneOrSort)
|
|
end
|
|
else
|
|
finisherZoneName = TrackerUtils:GetZoneNameByID(quest.zoneOrSort)
|
|
end
|
|
|
|
return finisherName, finisherZoneName
|
|
end
|
|
|
|
return nil, nil
|
|
end
|
|
|
|
_AddPlayerQuestProgress = function (quest, starterName, starterZoneName, finisherName, finisherZoneName)
|
|
if QuestiePlayer.currentQuestlog[quest.Id] then
|
|
-- On Quest: display quest progress
|
|
if (QuestieDB.IsComplete(quest.Id) == 0) then
|
|
_AddTooltipLine(" ")
|
|
_AddTooltipLine(l10n("Your progress")..":")
|
|
for _, objective in pairs(quest.Objectives) do
|
|
local objDesc = objective.Description:gsub("%.", "")
|
|
|
|
if objective.Needed > 0 then
|
|
local lineEnding = tostring(objective.Collected) .. "/" .. tostring(objective.Needed)
|
|
_AddTooltipLine(" - " .. QuestieLib:GetRGBForObjective(objective) .. objDesc .. ": " .. lineEnding.."|r")
|
|
end
|
|
end
|
|
-- Completed Quest (not turned in): display quest ended by npc and zone
|
|
else
|
|
if finisherName then
|
|
_AddTooltipLine(" ")
|
|
_AddTooltipLine((l10n("Ended by")..": " .. Questie:Colorize(finisherName, "gray")))
|
|
end
|
|
if finisherZoneName then
|
|
_AddTooltipLine(" ")
|
|
_AddTooltipLine((l10n("Found in")..": " .. Questie:Colorize(finisherZoneName, "gray")))
|
|
end
|
|
end
|
|
else
|
|
-- Completed Quest (turned in)
|
|
if Questie.db.char.complete[quest.Id] == true then
|
|
if Questie.db.char.journey then
|
|
local timestamp
|
|
for i = 1, #Questie.db.char.journey do
|
|
if Questie.db.char.journey[i].Quest ~= nil and Questie.db.char.journey[i].Quest == quest.Id then
|
|
local year = tonumber(date("%Y", Questie.db.char.journey[i].Timestamp))
|
|
local day = CALENDAR_WEEKDAY_NAMES[ tonumber(date("%w", Questie.db.char.journey[i].Timestamp)) + 1 ]
|
|
local month = CALENDAR_FULLDATE_MONTH_NAMES[ tonumber(date("%m", Questie.db.char.journey[i].Timestamp)) ]
|
|
timestamp = Questie:Colorize(date( "[ "..day ..", ".. month .." %d, "..year.." @ %H:%M ] " , Questie.db.char.journey[i].Timestamp), "blue")
|
|
end
|
|
end
|
|
if timestamp then
|
|
_AddTooltipLine(" ")
|
|
_AddTooltipLine(l10n("Completed on:"))
|
|
_AddTooltipLine(timestamp)
|
|
end
|
|
end
|
|
-- Not on Quest: display quest started by npc and zone
|
|
else
|
|
if starterName then
|
|
_AddTooltipLine(" ")
|
|
_AddTooltipLine((l10n("Started by")..": " .. Questie:Colorize(starterName, "gray")))
|
|
end
|
|
if starterZoneName then
|
|
_AddTooltipLine((l10n("Found in")..": " .. Questie:Colorize(starterZoneName, "gray")))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
hooksecurefunc("ChatFrame_OnHyperlinkShow", function(...)
|
|
-- FIX: Added InCombatLockdown guard to prevent tainting secure execution paths.
|
|
if InCombatLockdown() then return end
|
|
local _, link, _, button = ...
|
|
if (IsShiftKeyDown() and ChatEdit_GetActiveWindow() and button == "LeftButton") then
|
|
local linkType, questId, _ = string.split(":", link)
|
|
if linkType and linkType == "questie" and questId then
|
|
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTooltips:OnHyperlinkShow] Relinking Quest Link to chat:", link)
|
|
questId = tonumber(questId)
|
|
|
|
local success, quest = pcall(QuestieDB.GetQuest, QuestieDB, questId)
|
|
if success and quest then
|
|
local msg = ChatFrame1EditBox:GetText()
|
|
if msg then
|
|
ChatFrame1EditBox:SetText("")
|
|
ChatEdit_InsertLink(QuestieLink:GetQuestLinkString(quest.level, quest.name, questId))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|