v9.7.2: Ebonhold Database integration and core logic refinements

This commit is contained in:
Xurkon
2026-02-14 21:13:44 -06:00
parent 0a2cc15641
commit 6ef85d4e2d
573 changed files with 1751730 additions and 2 deletions
+406
View File
@@ -0,0 +1,406 @@
---@class QuestieTooltips
local QuestieTooltips = QuestieLoader:CreateModule("QuestieTooltips");
local _QuestieTooltips = QuestieTooltips.private
-------------------------
--Import modules.
-------------------------
---@type QuestieComms
local QuestieComms = QuestieLoader:ImportModule("QuestieComms");
---@type QuestieLib
local QuestieLib = QuestieLoader:ImportModule("QuestieLib");
---@type QuestiePlayer
local QuestiePlayer = QuestieLoader:ImportModule("QuestiePlayer");
---@type QuestieDB
local QuestieDB = QuestieLoader:ImportModule("QuestieDB");
---@type l10n
local l10n = QuestieLoader:ImportModule("l10n")
--- COMPATIBILITY ---
local UnitInParty = QuestieCompat.UnitInParty
local IsInGroup = QuestieCompat.IsInGroup
local GetClassColor = QuestieCompat.GetClassColor
local tinsert = table.insert
QuestieTooltips.lastGametooltip = ""
QuestieTooltips.lastGametooltipCount = -1;
QuestieTooltips.lastGametooltipType = "";
QuestieTooltips.lastFrameName = "";
QuestieTooltips.lookupByKey = {
--["u_Grell"] = {questid, {"Line 1", "Line 2"}}
}
QuestieTooltips.lookupKeysByQuestId = {
--["questId"] = {"u_Grell", ... }
}
local MAX_GROUP_MEMBER_COUNT = 6
local _InitObjectiveTexts
---@param questId number
---@param key string monster: m_, items: i_, objects: o_ + string name of the objective
---@param objective table
function QuestieTooltips:RegisterObjectiveTooltip(questId, key, objective)
if not QuestieTooltips.lookupByKey[key] then
QuestieTooltips.lookupByKey[key] = {};
end
if not QuestieTooltips.lookupKeysByQuestId[questId] then
QuestieTooltips.lookupKeysByQuestId[questId] = {}
end
local tooltip = {
questId = questId,
objective = objective,
};
QuestieTooltips.lookupByKey[key][tostring(questId) .. " " .. objective.Index] = tooltip
tinsert(QuestieTooltips.lookupKeysByQuestId[questId], key)
end
---@param questId number
---@param name string The name of the object or NPC the tooltip should show on
---@param starterId number The ID of the object or NPC the tooltip should show on
---@param key string @Either m_<npcId> or o_<objectId>
function QuestieTooltips:RegisterQuestStartTooltip(questId, name, starterId, key)
if not QuestieTooltips.lookupByKey[key] then
QuestieTooltips.lookupByKey[key] = {};
end
if not QuestieTooltips.lookupKeysByQuestId[questId] then
QuestieTooltips.lookupKeysByQuestId[questId] = {}
end
local tooltip = {
questId = questId,
name = name,
starterId = starterId,
};
QuestieTooltips.lookupByKey[key][tostring(questId) .. " " .. name .. " " .. starterId] = tooltip
tinsert(QuestieTooltips.lookupKeysByQuestId[questId], key)
end
---@param questId number
function QuestieTooltips:RemoveQuest(questId)
if (not QuestieTooltips.lookupKeysByQuestId[questId]) then
-- Tooltip has already been removed
return
end
-- Remove tooltip related keys from quest table so that
-- it can be readded/registered by other quest functions.
local quest = QuestieDB.GetQuest(questId)
if quest then
for _, objective in pairs(quest.Objectives) do
objective.AlreadySpawned = {}
objective.hasRegisteredTooltips = false
objective.registeredItemTooltips = false
end
for _, objective in pairs(quest.SpecialObjectives) do
objective.AlreadySpawned = {}
objective.hasRegisteredTooltips = false
objective.registeredItemTooltips = false
end
end
Questie:Debug(Questie.DEBUG_DEVELOP, "[QuestieTooltips:RemoveQuest]", questId)
for _, key in pairs(QuestieTooltips.lookupKeysByQuestId[questId] or {}) do
--Count to see if we should remove the main object
local totalCount = 0
local totalRemoved = 0
for _, tooltipData in pairs(QuestieTooltips.lookupByKey[key] or {}) do
--Remove specific quest
if (tooltipData.questId == questId and tooltipData.objective) then
QuestieTooltips.lookupByKey[key][tostring(tooltipData.questId) .. " " .. tooltipData.objective.Index] = nil
totalRemoved = totalRemoved + 1
elseif (tooltipData.questId == questId and tooltipData.name) then
QuestieTooltips.lookupByKey[key][tostring(tooltipData.questId) .. " " .. tooltipData.name .. " " .. tooltipData.starterId] = nil
totalRemoved = totalRemoved + 1
end
totalCount = totalCount + 1
end
if (totalCount == totalRemoved) then
QuestieTooltips.lookupByKey[key] = nil
end
end
QuestieTooltips.lookupKeysByQuestId[questId] = nil
end
-- This code is related to QuestieComms, here we fetch all the tooltip data that exist in QuestieCommsData
-- It uses a similar system like here with i_ID etc as keys.
local function _FetchTooltipsForGroupMembers(key, tooltipData)
local anotherPlayer = false;
if QuestieComms and QuestieComms.data:KeyExists(key) then
---@tooltipData @tooltipData[questId][playerName][objectiveIndex].text
local tooltipDataExternal = QuestieComms.data:GetTooltip(key);
for questId, playerList in pairs(tooltipDataExternal) do
if (not tooltipData[questId]) then
tooltipData[questId] = {
title = QuestieLib:GetColoredQuestName(questId, Questie.db.profile.enableTooltipsQuestLevel, true, true)
}
end
for playerName, _ in pairs(playerList) do
local playerInfo = QuestiePlayer:GetPartyMemberByName(playerName);
if playerInfo or QuestieComms.remotePlayerEnabled[playerName] then
anotherPlayer = true
break
end
end
if anotherPlayer then
break
end
end
end
if QuestieComms.data:KeyExists(key) and anotherPlayer then
---@tooltipData @tooltipData[questId][playerName][objectiveIndex].text
local tooltipDataExternal = QuestieComms.data:GetTooltip(key);
for questId, playerList in pairs(tooltipDataExternal) do
if (not tooltipData[questId]) then
tooltipData[questId] = {
title = QuestieLib:GetColoredQuestName(questId, Questie.db.profile.enableTooltipsQuestLevel, true, true)
}
end
for playerName, objectives in pairs(playerList) do
local playerInfo = QuestiePlayer:GetPartyMemberByName(playerName);
if playerInfo or QuestieComms.remotePlayerEnabled[playerName] then
anotherPlayer = true;
for objectiveIndex, objective in pairs(objectives) do
if (not objective) then
objective = {}
end
tooltipData[questId].objectivesText = _InitObjectiveTexts(tooltipData[questId].objectivesText, objectiveIndex, playerName)
local text;
local color = QuestieLib:GetRGBForObjective(objective)
if objective.required then
text = " " .. color .. tostring(objective.fulfilled) .. "/" .. tostring(objective.required) .. " " .. objective.text;
else
text = " " .. color .. objective.text;
end
tooltipData[questId].objectivesText[objectiveIndex][playerName] = { ["color"] = color, ["text"] = text };
end
end
end
end
end
return anotherPlayer
end
---@param key string
function QuestieTooltips:GetTooltip(key)
Questie:Debug(Questie.DEBUG_SPAM, "[QuestieTooltips:GetTooltip]", key)
if (not key) then
return nil
end
if QuestiePlayer.numberOfGroupMembers > MAX_GROUP_MEMBER_COUNT then
return nil -- temporary disable tooltips in raids, we should make a proper fix
end
--Do not remove! This is the datastrucutre for tooltipData!
--[[tooltipdata[questId] = {
title = coloredTitle,
objectivesText = {
[objectiveIndex] = {
[playerName] = {
[color] = color,
[text] = text
}
}
}
}]]
--
local tooltipData = {}
local tooltipLines = {}
if QuestieTooltips.lookupByKey[key] then
local playerName = UnitName("player")
for k, tooltip in pairs(QuestieTooltips.lookupByKey[key]) do
if tooltip.name then
if Questie.db.profile.showQuestsInNpcTooltip then
local questString = QuestieLib:GetColoredQuestName(tooltip.questId, Questie.db.profile.enableTooltipsQuestLevel, true, true)
tinsert(tooltipLines, questString)
end
else
local objective = tooltip.objective
if not (objective.IsSourceItem or objective.IsRequiredSourceItem) then
-- Tooltip was registered for a sourceItem or requiredSourceItem and not a real "objective"
objective:Update()
end
local questId = tooltip.questId
local objectiveIndex = objective.Index;
if (not tooltipData[questId]) then
tooltipData[questId] = {
title = QuestieLib:GetColoredQuestName(questId, Questie.db.profile.enableTooltipsQuestLevel, true, true)
}
end
if not QuestiePlayer.currentQuestlog[questId] then
-- TODO: Is this still required?
QuestieTooltips.lookupByKey[key][k] = nil
else
tooltipData[questId].objectivesText = _InitObjectiveTexts(tooltipData[questId].objectivesText, objectiveIndex, playerName)
local text;
local color = QuestieLib:GetRGBForObjective(objective)
if objective.Type == "spell" and objective.spawnList[tonumber(key:sub(3))].ItemId then
text = " " .. color .. tostring(QuestieDB.QueryItemSingle(objective.spawnList[tonumber(key:sub(3))].ItemId, "name"));
tooltipData[questId].objectivesText[objectiveIndex][playerName] = { ["color"] = color, ["text"] = text };
elseif objective.Needed then
text = " " .. color .. tostring(objective.Collected) .. "/" .. tostring(objective.Needed) .. " " .. tostring(objective.Description);
tooltipData[questId].objectivesText[objectiveIndex][playerName] = { ["color"] = color, ["text"] = text };
else
text = " " .. color .. tostring(objective.Description);
tooltipData[questId].objectivesText[objectiveIndex][playerName] = { ["color"] = color, ["text"] = text };
end
end
end
end
end
local anotherPlayer = false
if IsInGroup() then
anotherPlayer = _FetchTooltipsForGroupMembers(key, tooltipData)
end
local playerName = UnitName("player")
for questId, questData in pairs(tooltipData) do
local hasObjective = false
local tempObjectives = {}
for _, playerList in pairs(questData.objectivesText or {}) do
for objectivePlayerName, objectiveInfo in pairs(playerList) do
local playerInfo = QuestiePlayer:GetPartyMemberByName(objectivePlayerName)
local playerColor
local playerType = ""
if playerInfo then
playerColor = "|c" .. playerInfo.colorHex
elseif QuestieComms.remotePlayerEnabled[objectivePlayerName] and QuestieComms.remoteQuestLogs[questId] and QuestieComms.remoteQuestLogs[questId][objectivePlayerName] and (not Questie.db.profile.onlyPartyShared or UnitInParty(objectivePlayerName)) then
playerColor = QuestieComms.remotePlayerClasses[playerName]
if playerColor then
playerColor = Questie:GetClassColor(playerColor)
playerType = " (" .. l10n("Nearby") .. ")"
end
end
if objectivePlayerName == playerName and anotherPlayer then -- why did we have this case
local _, classFilename = UnitClass("player");
local _, _, _, argbHex = GetClassColor(classFilename)
objectiveInfo.text = objectiveInfo.text .. " (|c" .. argbHex .. objectivePlayerName .. "|r" .. objectiveInfo.color .. ")|r"
elseif playerColor and objectivePlayerName ~= playerName then
objectiveInfo.text = objectiveInfo.text .. " (" .. playerColor .. objectivePlayerName .. "|r" .. objectiveInfo.color .. ")|r" .. playerType
end
-- We want the player to be on top.
if objectivePlayerName == playerName then
tinsert(tempObjectives, 1, objectiveInfo.text);
hasObjective = true
elseif playerColor then
tinsert(tempObjectives, objectiveInfo.text);
hasObjective = true
end
end
end
if hasObjective then
tinsert(tooltipLines, questData.title);
for _, text in pairs(tempObjectives) do
tinsert(tooltipLines, text);
end
end
end
return tooltipLines
end
_InitObjectiveTexts = function(objectivesText, objectiveIndex, playerName)
if (not objectivesText) then
objectivesText = {}
end
if (not objectivesText[objectiveIndex]) then
objectivesText[objectiveIndex] = {}
end
if (not objectivesText[objectiveIndex][playerName]) then
objectivesText[objectiveIndex][playerName] = {}
end
return objectivesText
end
function QuestieTooltips:Initialize()
-- For the clicked item frame.
ItemRefTooltip:HookScript("OnTooltipSetItem", _QuestieTooltips.AddItemDataToTooltip)
ItemRefTooltip:HookScript("OnHide", function(self)
if (not self.IsForbidden) or (not self:IsForbidden()) then -- do we need this here also
QuestieTooltips.lastGametooltip = ""
QuestieTooltips.lastItemRefTooltip = ""
QuestieTooltips.lastGametooltipItem = nil
QuestieTooltips.lastGametooltipUnit = nil
QuestieTooltips.lastGametooltipCount = 0
QuestieTooltips.lastFrameName = "";
end
end)
-- For the hover frame.
GameTooltip:HookScript("OnTooltipSetUnit", function(self)
if QuestiePlayer.numberOfGroupMembers > MAX_GROUP_MEMBER_COUNT then
-- When in a raid, we want as little code running as possible
return
end
_QuestieTooltips.AddUnitDataToTooltip(self)
end)
GameTooltip:HookScript("OnTooltipSetItem", _QuestieTooltips.AddItemDataToTooltip)
GameTooltip:HookScript("OnShow", function(self)
if QuestiePlayer.numberOfGroupMembers > MAX_GROUP_MEMBER_COUNT then
-- When in a raid, we want as little code running as possible
return
end
if (not self.IsForbidden) or (not self:IsForbidden()) then -- do we need this here also
QuestieTooltips.lastGametooltipItem = nil
QuestieTooltips.lastGametooltipUnit = nil
QuestieTooltips.lastGametooltipCount = 0
QuestieTooltips.lastFrameName = "";
end
end)
GameTooltip:HookScript("OnHide", function(self)
if QuestiePlayer.numberOfGroupMembers > MAX_GROUP_MEMBER_COUNT then
-- When in a raid, we want as little code running as possible
return
end
if (not self.IsForbidden) or (not self:IsForbidden()) then -- do we need this here also
QuestieTooltips.lastGametooltip = ""
QuestieTooltips.lastItemRefTooltip = ""
QuestieTooltips.lastGametooltipItem = nil
QuestieTooltips.lastGametooltipUnit = nil
QuestieTooltips.lastGametooltipCount = 0
end
end)
-- Fired whenever the cursor hovers something with a tooltip. And then on every frame
GameTooltip:HookScript("OnUpdate", function(self)
if QuestiePlayer.numberOfGroupMembers > MAX_GROUP_MEMBER_COUNT then
-- When in a raid, we want as little code running as possible
return
end
if (not self.IsForbidden) or (not self:IsForbidden()) then
--Because this is an OnUpdate we need to check that it is actually not a Unit or Item to think its a
local uName, unit = self:GetUnit()
local iName, link = self:GetItem()
local sName, spell = self:GetSpell()
if (uName == nil and unit == nil and iName == nil and link == nil and sName == nil and spell == nil) and (
QuestieTooltips.lastGametooltip ~= GameTooltipTextLeft1:GetText() or
(not QuestieTooltips.lastGametooltipCount) or
_QuestieTooltips:CountTooltip() < QuestieTooltips.lastGametooltipCount
or QuestieTooltips.lastGametooltipType ~= "object"
) and (not self.ShownAsMapIcon) then -- We are hovering over a Questie map icon which adds it's own tooltip
_QuestieTooltips:AddObjectDataToTooltip(GameTooltipTextLeft1:GetText())
QuestieTooltips.lastGametooltipCount = _QuestieTooltips:CountTooltip()
end
QuestieTooltips.lastGametooltip = GameTooltipTextLeft1:GetText()
end
end)
end
return QuestieTooltips