From 862c7c17d6663f3876bb0abb5018aa1577e4769b Mon Sep 17 00:00:00 2001 From: jKalfis Date: Thu, 3 Sep 2026 18:24:28 +0100 Subject: [PATCH] Add files via upload --- modules/questgossip.lua | 688 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 688 insertions(+) create mode 100644 modules/questgossip.lua diff --git a/modules/questgossip.lua b/modules/questgossip.lua new file mode 100644 index 0000000..a1ec924 --- /dev/null +++ b/modules/questgossip.lua @@ -0,0 +1,688 @@ +------------------------------------------------------------ +-- pfUI-DQB +-- Quest & Gossip module +-- +-- Controls the visual appearance of Blizzard Quest/Gossip +-- frames without modifying pfUI itself. +------------------------------------------------------------ + +local DQB = pfUI and pfUI.dqb + +if not DQB then + return +end + + +------------------------------------------------------------ +-- Helpers +------------------------------------------------------------ + +local function GetConfig() + return pfUI_config + and pfUI_config.dqb + and pfUI_config.dqb.questgossip +end + + +local function IsModuleEnabled() + if not DQB:IsEnabled() then + return false + end + + local config = GetConfig() + + return config ~= nil +end + + +------------------------------------------------------------ +-- Color +------------------------------------------------------------ + +local function HexToRGB(hex) + if not hex then + return 1, 1, 1 + end + + hex = tostring(hex) + + hex = string.gsub(hex, "#", "") + + if string.len(hex) ~= 6 then + return 1, 1, 1 + end + + local r = tonumber(string.sub(hex, 1, 2), 16) + local g = tonumber(string.sub(hex, 3, 4), 16) + local b = tonumber(string.sub(hex, 5, 6), 16) + + if not r or not g or not b then + return 1, 1, 1 + end + + return r / 255, g / 255, b / 255 +end + + +local function GetBackgroundColor() + local config = GetConfig() + + if not config then + return 0, 0, 0, 0.85 + end + + local r, g, b = HexToRGB(config.background_color) + + local alpha = tonumber(config.background_alpha) + + if not alpha then + alpha = 0.85 + end + + if alpha < 0 then + alpha = 0 + elseif alpha > 1 then + alpha = 1 + end + + return r, g, b, alpha +end + + +local function GetTextColor() + local config = GetConfig() + + if not config then + return 1, 1, 1, 1 + end + + local r, g, b = HexToRGB(config.text_color) + + return r, g, b, 1 +end + + +------------------------------------------------------------ +-- Font +------------------------------------------------------------ + +local function GetTextFont() + local config = GetConfig() + + if not config then + return pfUI.font_default or STANDARD_TEXT_FONT + end + + local font = config.text_font + + if not font or font == "" then + return pfUI.font_default or STANDARD_TEXT_FONT + end + + -------------------------------------------------------- + -- "Arial" is kept as a friendly default value. + -- WoW does not normally expose an Arial path, so use + -- pfUI's configured default font in that case. + -------------------------------------------------------- + + if string.lower(font) == "arial" then + return pfUI.font_default or STANDARD_TEXT_FONT + end + + -------------------------------------------------------- + -- pfUI media path + -- + -- Example: + -- font:default + -------------------------------------------------------- + + if string.find(font, "font:") then + return pfUI.media[font] + end + + -------------------------------------------------------- + -- Direct font path + -------------------------------------------------------- + + if string.find(font, "\\") then + return font + end + + if string.find(font, "/") then + return font + end + + -------------------------------------------------------- + -- Unknown short name. + -- Fall back to pfUI default. + -------------------------------------------------------- + + return pfUI.font_default or STANDARD_TEXT_FONT +end + + +local function GetTextSize() + local config = GetConfig() + + if not config then + return 12 + end + + local size = tonumber(config.text_size) + + if not size then + size = 12 + end + + if size < 1 then + size = 1 + end + + return size +end + + +local function GetTextStyle() + local config = GetConfig() + + if not config then + return "" + end + + local style = config.text_style + + if not style then + return "" + end + + style = tostring(style) + + if style == "" then + return "" + end + + return style +end + + +------------------------------------------------------------ +-- Text styling +------------------------------------------------------------ + +local function ApplyText(text) + if not text then + return + end + + if not IsModuleEnabled() then + return + end + + local config = GetConfig() + + if not config or config.text_global ~= "1" then + return + end + + local r, g, b, a = GetTextColor() + local font = GetTextFont() + local size = GetTextSize() + local style = GetTextStyle() + + -------------------------------------------------------- + -- Text colour + -------------------------------------------------------- + + text:SetTextColor(r, g, b, a) + + -------------------------------------------------------- + -- Shadow + -------------------------------------------------------- + + text:SetShadowColor(0, 0, 0, 1) + text:SetShadowOffset(1, -1) + + -------------------------------------------------------- + -- Font + -------------------------------------------------------- + + if font then + text:SetFont(font, size, style) + end +end + + +------------------------------------------------------------ +-- Apply to all FontStrings belonging to a frame +------------------------------------------------------------ + +local function ApplyFrameText(frame) + if not frame then + return + end + + -------------------------------------------------------- + -- Regions + -------------------------------------------------------- + + local regions = { frame:GetRegions() } + + for _, region in pairs(regions) do + if region and region:GetObjectType() == "FontString" then + ApplyText(region) + end + end + + -------------------------------------------------------- + -- Children + -------------------------------------------------------- + + local children = { frame:GetChildren() } + + for _, child in pairs(children) do + ApplyFrameText(child) + end +end + + +------------------------------------------------------------ +-- Gossip / Quest option buttons +------------------------------------------------------------ + +local function ApplyOptionButtons() + if not IsModuleEnabled() then + return + end + + -------------------------------------------------------- + -- Gossip options + -------------------------------------------------------- + + for i = 1, 32 do + + local gossipButton = _G["GossipTitleButton" .. i] + + if gossipButton then + ApplyFrameText(gossipButton) + end + + ---------------------------------------------------- + -- Quest options in greeting + ---------------------------------------------------- + + local questButton = _G["QuestTitleButton" .. i] + + if questButton then + ApplyFrameText(questButton) + end + end +end + + +------------------------------------------------------------ +-- Main Quest/Gossip text +------------------------------------------------------------ + +local function ApplyQuestGossipText() + if not IsModuleEnabled() then + return + end + + local texts = { + + ---------------------------------------------------- + -- Quest + ---------------------------------------------------- + + QuestTitleText, + QuestDescriptionText, + + QuestProgressTitleText, + QuestProgressText, + QuestProgressRequiredItemsText, + QuestProgressRequiredMoneyText, + + QuestRewardTitleText, + QuestRewardText, + QuestRewardRewardTitleText, + QuestRewardItemChooseText, + QuestRewardItemReceiveText, + QuestRewardSpellLearnText, + + QuestDetailItemReceiveText, + QuestDetailSpellLearnText, + + ---------------------------------------------------- + -- Greeting / Gossip + ---------------------------------------------------- + + GreetingText, + GossipGreetingText, + CurrentQuestsText, + AvailableQuestsText, + + ---------------------------------------------------- + -- Objectives + ---------------------------------------------------- + + QuestObjectiveText, + QuestObjectivesText, + QuestObjectiveTitleText, + QuestObjectivesTitleText, + + ---------------------------------------------------- + -- NPC names + ---------------------------------------------------- + + QuestFrameNpcNameText, + GossipFrameNpcNameText, + } + + for _, text in pairs(texts) do + ApplyText(text) + end + + -------------------------------------------------------- + -- Apply recursively as a safety net. + -- + -- This catches text fields that Blizzard creates + -- dynamically or which are not present in the static + -- list above. + -------------------------------------------------------- + + if QuestFrame then + ApplyFrameText(QuestFrame) + end + + if GossipFrame then + ApplyFrameText(GossipFrame) + end + + ApplyOptionButtons() +end + + +------------------------------------------------------------ +-- Background +------------------------------------------------------------ + +local backgroundFrames = {} + + +local function CreateBackground(frame) + if not frame then + return nil + end + + if frame.dqbBackground then + return frame.dqbBackground + end + + local background = frame:CreateTexture(nil, "BACKGROUND") + + background:SetAllPoints() + + frame.dqbBackground = background + + table.insert(backgroundFrames, { + frame = frame, + background = background, + }) + + return background +end + + +local function ApplyBackground(frame) + if not frame then + return + end + + local config = GetConfig() + + if not config then + return + end + + local background = CreateBackground(frame) + + if not background then + return + end + + -------------------------------------------------------- + -- DQB background disabled + -------------------------------------------------------- + + if config.background_global ~= "1" then + background:Hide() + return + end + + -------------------------------------------------------- + -- DQB background enabled + -------------------------------------------------------- + + local r, g, b, a = GetBackgroundColor() + + background:SetTexture(1, 1, 1, 1) + background:SetVertexColor(r, g, b, a) + background:Show() +end + + +local function ApplyScrollBackground(scroll) + if not scroll then + return + end + + local config = GetConfig() + + if not config then + return + end + + local background = scroll.dqbBackground + + if not background then + background = scroll:CreateTexture(nil, "BACKGROUND") + background:SetAllPoints() + scroll.dqbBackground = background + end + + -------------------------------------------------------- + -- Disabled + -------------------------------------------------------- + + if config.background_global ~= "1" then + background:Hide() + return + end + + -------------------------------------------------------- + -- Enabled + -------------------------------------------------------- + + local r, g, b, a = GetBackgroundColor() + + background:SetTexture(1, 1, 1, 1) + background:SetVertexColor(r, g, b, a) + background:Show() +end + + +local function ApplyAllBackgrounds() + if not IsModuleEnabled() then + return + end + + -------------------------------------------------------- + -- Main frames + -------------------------------------------------------- + + ApplyBackground(QuestFrame) + ApplyBackground(GossipFrame) + + -------------------------------------------------------- + -- Quest panels + -------------------------------------------------------- + + ApplyScrollBackground(QuestGreetingScrollFrame) + ApplyScrollBackground(QuestDetailScrollFrame) + ApplyScrollBackground(QuestProgressScrollFrame) + ApplyScrollBackground(QuestRewardScrollFrame) + + -------------------------------------------------------- + -- Gossip + -------------------------------------------------------- + + ApplyScrollBackground(GossipGreetingScrollFrame) +end + + +------------------------------------------------------------ +-- Hooks +------------------------------------------------------------ + +local function HookFunction(name, func) + if _G[name] then + hooksecurefunc(name, func) + end +end + + +local function InstallHooks() + + -------------------------------------------------------- + -- Quest updates + -------------------------------------------------------- + + HookFunction("QuestFrameItems_Update", function() + ApplyQuestGossipText() + ApplyAllBackgrounds() + end) + + + HookFunction("QuestFrameProgressItems_Update", function() + ApplyQuestGossipText() + ApplyAllBackgrounds() + end) + + + HookFunction("QuestRewardItem_OnClick", function() + ApplyQuestGossipText() + end) + + + HookFunction("QuestFrame_SetTextColor", function(text) + ApplyText(text) + end) + + + HookFunction("QuestFrame_SetTitleTextColor", function(text) + ApplyText(text) + end) + + + HookFunction("QuestInfo_Display", function() + ApplyQuestGossipText() + ApplyAllBackgrounds() + end) + + + -------------------------------------------------------- + -- Gossip updates + -------------------------------------------------------- + + HookFunction("GossipFrameUpdate", function() + ApplyQuestGossipText() + ApplyAllBackgrounds() + end) + + + HookFunction("GossipFrameAvailableQuestsUpdate", function() + ApplyOptionButtons() + ApplyQuestGossipText() + end) + + + HookFunction("GossipFrameActiveQuestsUpdate", function() + ApplyOptionButtons() + ApplyQuestGossipText() + end) + + + HookFunction("GossipFrameOptionsUpdate", function() + ApplyOptionButtons() + ApplyQuestGossipText() + end) + + + -------------------------------------------------------- + -- Quest panels + -------------------------------------------------------- + + HookFunction("QuestFrameGreetingPanel_OnShow", function() + ApplyQuestGossipText() + ApplyAllBackgrounds() + end) + + + HookFunction("QuestFrameDetailPanel_OnShow", function() + ApplyQuestGossipText() + ApplyAllBackgrounds() + end) + + + HookFunction("QuestFrameProgressPanel_OnShow", function() + ApplyQuestGossipText() + ApplyAllBackgrounds() + end) + + + HookFunction("QuestFrameRewardPanel_OnShow", function() + ApplyQuestGossipText() + ApplyAllBackgrounds() + end) +end + + +------------------------------------------------------------ +-- Apply current configuration +------------------------------------------------------------ + +local function Apply() + if not IsModuleEnabled() then + return + end + + ApplyQuestGossipText() + ApplyAllBackgrounds() +end + + +------------------------------------------------------------ +-- Register module +------------------------------------------------------------ + +DQB:RegisterModule("questgossip", function() + + -------------------------------------------------------- + -- Install hooks only once + -------------------------------------------------------- + + if DQB.questGossipHooksInstalled then + Apply() + return + end + + DQB.questGossipHooksInstalled = true + + InstallHooks() + + -------------------------------------------------------- + -- Initial application + -------------------------------------------------------- + + Apply() +end) \ No newline at end of file