Files
pfUI-DQB/modules/questgossip.lua
T
2026-09-03 18:24:28 +01:00

688 lines
16 KiB
Lua

------------------------------------------------------------
-- 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)