1103 lines
41 KiB
Lua
1103 lines
41 KiB
Lua
--------------------------------------------------------------------------------
|
|
-- Nanami-UI: Tweaks -- Ported from ShaguTweaks
|
|
-- 1. Auto Stance - auto switch warrior/druid stance on spell cast
|
|
-- 2. SuperWoW - GUID-based cast/channel data for SuperWoW client
|
|
-- 3. Turtle Compat - hide TW's overlapping target HP text, etc.
|
|
-- 4. Cooldown Numbers - show remaining cooldown time as text overlay
|
|
-- 5. Dark UI - darken the entire interface
|
|
-- 6. WorldMap Window - turn fullscreen map into a movable/scalable window
|
|
-- 7. Auto Dismount - cancel shapeshift/mount when casting incompatible spells
|
|
--------------------------------------------------------------------------------
|
|
|
|
SFrames.Tweaks = SFrames.Tweaks or {}
|
|
local Tweaks = SFrames.Tweaks
|
|
|
|
SFrames.castdb = SFrames.castdb or {}
|
|
|
|
local function GetTweaksCfg()
|
|
if not SFramesDB or type(SFramesDB.Tweaks) ~= "table" then
|
|
return { autoStance = true, superWoW = true, turtleCompat = true,
|
|
cooldownNumbers = true, darkUI = false, worldMapWindow = false }
|
|
end
|
|
return SFramesDB.Tweaks
|
|
end
|
|
|
|
local function strsplit(delimiter, str)
|
|
local result = {}
|
|
local pattern = "([^" .. delimiter .. "]+)"
|
|
for match in string.gfind(str, pattern) do
|
|
table.insert(result, match)
|
|
end
|
|
return unpack(result)
|
|
end
|
|
|
|
-- hooksecurefunc polyfill for WoW 1.12 (vanilla)
|
|
local _hooks = {}
|
|
local _hooksecurefunc = hooksecurefunc
|
|
if not _hooksecurefunc then
|
|
_hooksecurefunc = function(tbl, name, func)
|
|
if type(tbl) == "string" then
|
|
func = name
|
|
name = tbl
|
|
tbl = getfenv(0)
|
|
end
|
|
if not tbl or not tbl[name] then return end
|
|
local key = tostring(func)
|
|
_hooks[key] = {}
|
|
_hooks[key].old = tbl[name]
|
|
_hooks[key].new = func
|
|
tbl[name] = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
|
local r1,r2,r3,r4,r5 = _hooks[key].old(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
|
pcall(_hooks[key].new, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
|
return r1,r2,r3,r4,r5
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Auto Stance
|
|
-- When a spell fails because you're in the wrong stance/form, automatically
|
|
-- switch to the required one. Works for warriors, druids, etc.
|
|
--------------------------------------------------------------------------------
|
|
local function InitAutoStance()
|
|
local frame = CreateFrame("Frame", "NanamiAutoStance")
|
|
local scanString = string.gsub(SPELL_FAILED_ONLY_SHAPESHIFT, "%%s", "(.+)")
|
|
|
|
frame:RegisterEvent("UI_ERROR_MESSAGE")
|
|
frame:SetScript("OnEvent", function()
|
|
for stances in string.gfind(arg1, scanString) do
|
|
for _, stance in pairs({ strsplit(",", stances) }) do
|
|
CastSpellByName(string.gsub(stance, "^%s*(.-)%s*$", "%1"))
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Auto Dismount / Cancel Shapeshift
|
|
-- When casting a spell that fails because you are mounted or shapeshifted,
|
|
-- automatically cancel the mount/shapeshift buff so the next cast succeeds.
|
|
--------------------------------------------------------------------------------
|
|
local function InitAutoDismount()
|
|
local dismount = CreateFrame("Frame", "NanamiAutoDismount")
|
|
|
|
local scanner = CreateFrame("GameTooltip", "NanamiDismountScan", nil, "GameTooltipTemplate")
|
|
scanner:SetOwner(WorldFrame, "ANCHOR_NONE")
|
|
|
|
local mountStrings = {
|
|
"^Increases speed by (.+)%%",
|
|
"^Erhöht Tempo um (.+)%%",
|
|
"^Aumenta la velocidad en un (.+)%%",
|
|
"^Augmente la vitesse de (.+)%%",
|
|
"^Скорость увеличена на (.+)%%",
|
|
"^이동 속도 (.+)%%만큼 증가",
|
|
"^速度提高(.+)%%",
|
|
"speed based on", "Slow and steady...", "Riding",
|
|
"Lento y constante...", "Aumenta la velocidad según tu habilidad de Montar.",
|
|
"根据您的骑行技能提高速度。", "根据骑术技能提高速度。", "又慢又稳......",
|
|
}
|
|
|
|
local shapeshiftIcons = {
|
|
"ability_racial_bearform", "ability_druid_catform",
|
|
"ability_druid_travelform", "spell_nature_forceofnature",
|
|
"ability_druid_aquaticform", "spell_nature_spiritwolf",
|
|
"ability_druid_treeoflife", "ability_druid_stagform",
|
|
}
|
|
|
|
local errorStrings = {}
|
|
local errorGlobals = {
|
|
"SPELL_FAILED_NOT_MOUNTED", "ERR_ATTACK_MOUNTED", "ERR_TAXIPLAYERALREADYMOUNTED",
|
|
"SPELL_FAILED_NOT_SHAPESHIFT", "SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED",
|
|
"SPELL_NOT_SHAPESHIFTED", "SPELL_NOT_SHAPESHIFTED_NOSPACE",
|
|
"ERR_CANT_INTERACT_SHAPESHIFTED", "ERR_NOT_WHILE_SHAPESHIFTED",
|
|
"ERR_NO_ITEMS_WHILE_SHAPESHIFTED", "ERR_TAXIPLAYERSHAPESHIFTED",
|
|
"ERR_MOUNT_SHAPESHIFTED",
|
|
}
|
|
for _, name in pairs(errorGlobals) do
|
|
local val = getfenv(0)[name]
|
|
if val then table.insert(errorStrings, val) end
|
|
end
|
|
|
|
dismount:RegisterEvent("UI_ERROR_MESSAGE")
|
|
dismount:SetScript("OnEvent", function()
|
|
if arg1 == SPELL_FAILED_NOT_STANDING then
|
|
SitOrStand()
|
|
return
|
|
end
|
|
|
|
local matched = false
|
|
for _, err in pairs(errorStrings) do
|
|
if arg1 == err then matched = true break end
|
|
end
|
|
if not matched then return end
|
|
|
|
for i = 0, 31 do
|
|
scanner:ClearLines()
|
|
scanner:SetPlayerBuff(i)
|
|
for line = 1, scanner:NumLines() do
|
|
local text = getfenv(0)["NanamiDismountScanTextLeft" .. line]
|
|
if text and text:GetText() then
|
|
for _, str in pairs(mountStrings) do
|
|
if string.find(text:GetText(), str) then
|
|
CancelPlayerBuff(i)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local buff = GetPlayerBuffTexture(i)
|
|
if buff then
|
|
for _, icon in pairs(shapeshiftIcons) do
|
|
if string.find(string.lower(buff), icon) then
|
|
CancelPlayerBuff(i)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- SuperWoW Compatibility
|
|
-- Provides GUID-based cast/channel data when SuperWoW client mod is active.
|
|
-- Data stored in SFrames.castdb[guid] for consumption by castbar features.
|
|
--------------------------------------------------------------------------------
|
|
local function InitSuperWoW()
|
|
if not GetPlayerBuffID or not CombatLogAdd or not SpellInfo then return end
|
|
|
|
local castdb = SFrames.castdb
|
|
|
|
local frame = CreateFrame("Frame", "NanamiSuperWoW")
|
|
frame:RegisterEvent("UNIT_CASTEVENT")
|
|
frame:SetScript("OnEvent", function()
|
|
if arg3 == "START" or arg3 == "CAST" or arg3 == "CHANNEL" then
|
|
local guid = arg1
|
|
local spell, icon, _
|
|
if SpellInfo and SpellInfo(arg4) then
|
|
spell, _, icon = SpellInfo(arg4)
|
|
end
|
|
spell = spell or UNKNOWN
|
|
icon = icon or "Interface\\Icons\\INV_Misc_QuestionMark"
|
|
|
|
if not castdb[guid] then castdb[guid] = {} end
|
|
castdb[guid].cast = spell
|
|
castdb[guid].rank = nil
|
|
castdb[guid].start = GetTime()
|
|
castdb[guid].casttime = arg5
|
|
castdb[guid].icon = icon
|
|
castdb[guid].channel = (arg3 == "CHANNEL") or false
|
|
|
|
SFrames.superwow_active = true
|
|
elseif arg3 == "FAIL" then
|
|
local guid = arg1
|
|
if castdb[guid] then
|
|
castdb[guid].cast = nil
|
|
castdb[guid].rank = nil
|
|
castdb[guid].start = nil
|
|
castdb[guid].casttime = nil
|
|
castdb[guid].icon = nil
|
|
castdb[guid].channel = nil
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Turtle WoW Compatibility
|
|
-- Hides TW's built-in target HP text that overlaps with Nanami-UI frames,
|
|
-- and applies other TW-specific fixes.
|
|
--------------------------------------------------------------------------------
|
|
local function ApplyWorldMapWindowLayout()
|
|
WorldMapFrame:SetMovable(true)
|
|
WorldMapFrame:EnableMouse(true)
|
|
WorldMapFrame:SetScale(.85)
|
|
WorldMapFrame:ClearAllPoints()
|
|
WorldMapFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 30)
|
|
WorldMapFrame:SetWidth(WorldMapButton:GetWidth() + 15)
|
|
WorldMapFrame:SetHeight(WorldMapButton:GetHeight() + 55)
|
|
if WorldMapFrameTitle then
|
|
WorldMapFrameTitle:SetPoint("TOP", WorldMapFrame, 0, 17)
|
|
end
|
|
BlackoutWorld:Hide()
|
|
end
|
|
|
|
local function InitTurtleCompat()
|
|
if not TargetHPText or not TargetHPPercText then return end
|
|
|
|
TargetHPText:Hide()
|
|
TargetHPText.Show = function() return end
|
|
|
|
TargetHPPercText:Hide()
|
|
TargetHPPercText.Show = function() return end
|
|
|
|
if WorldMapFrame_Maximize then
|
|
local origMaximize = WorldMapFrame_Maximize
|
|
WorldMapFrame_Maximize = function()
|
|
origMaximize()
|
|
local cfg = GetTweaksCfg()
|
|
if cfg.worldMapWindow ~= false then
|
|
ApplyWorldMapWindowLayout()
|
|
elseif WorldMapFrameTitle then
|
|
WorldMapFrameTitle:SetPoint("TOP", WorldMapFrame, 0, 17)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- WorldMap Window
|
|
-- Turn the fullscreen world map into a movable, scalable window.
|
|
-- Ctrl+Scroll to zoom, Shift+Scroll to change transparency, drag to move.
|
|
--------------------------------------------------------------------------------
|
|
local function HookScript(frame, script, func)
|
|
local prev = frame:GetScript(script)
|
|
frame:SetScript(script, function(a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
|
if prev then prev(a1,a2,a3,a4,a5,a6,a7,a8,a9) end
|
|
func(a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
|
end)
|
|
end
|
|
|
|
local function InitWorldMapWindow()
|
|
if Cartographer or METAMAP_TITLE then return end
|
|
|
|
table.insert(UISpecialFrames, "WorldMapFrame")
|
|
|
|
local _G = getfenv(0)
|
|
_G.ToggleWorldMap = function()
|
|
if WorldMapFrame:IsShown() then
|
|
WorldMapFrame:Hide()
|
|
else
|
|
WorldMapFrame:Show()
|
|
end
|
|
end
|
|
|
|
UIPanelWindows["WorldMapFrame"] = { area = "center" }
|
|
|
|
HookScript(WorldMapFrame, "OnShow", function()
|
|
this:EnableKeyboard(false)
|
|
this:EnableMouseWheel(1)
|
|
WorldMapFrame:SetScale(.85)
|
|
WorldMapFrame:SetAlpha(1)
|
|
WorldMapFrame:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
end)
|
|
|
|
HookScript(WorldMapFrame, "OnMouseWheel", function()
|
|
if IsShiftKeyDown() then
|
|
local newAlpha = WorldMapFrame:GetAlpha() + arg1 / 10
|
|
if newAlpha < 0.2 then newAlpha = 0.2 end
|
|
if newAlpha > 1 then newAlpha = 1 end
|
|
WorldMapFrame:SetAlpha(newAlpha)
|
|
elseif IsControlKeyDown() then
|
|
local newScale = WorldMapFrame:GetScale() + arg1 / 10
|
|
if newScale < 0.4 then newScale = 0.4 end
|
|
if newScale > 1.5 then newScale = 1.5 end
|
|
WorldMapFrame:SetScale(newScale)
|
|
end
|
|
end)
|
|
|
|
HookScript(WorldMapFrame, "OnMouseDown", function()
|
|
WorldMapFrame:StartMoving()
|
|
end)
|
|
|
|
HookScript(WorldMapFrame, "OnMouseUp", function()
|
|
WorldMapFrame:StopMovingOrSizing()
|
|
end)
|
|
|
|
ApplyWorldMapWindowLayout()
|
|
|
|
-- WorldMapTooltip: raw textures on a child frame (SetBackdrop is unreliable)
|
|
if WorldMapTooltip and not WorldMapTooltip._nanamiBG then
|
|
WorldMapTooltip._nanamiBG = true
|
|
|
|
local wmtBgFrame = CreateFrame("Frame", nil, WorldMapTooltip)
|
|
wmtBgFrame:SetAllPoints(WorldMapTooltip)
|
|
wmtBgFrame:SetFrameLevel(math.max(0, WorldMapTooltip:GetFrameLevel()))
|
|
|
|
local bg = wmtBgFrame:CreateTexture(nil, "BACKGROUND")
|
|
bg:SetTexture("Interface\\Buttons\\WHITE8X8")
|
|
bg:SetVertexColor(0.05, 0.05, 0.05, 1)
|
|
bg:SetAllPoints(wmtBgFrame)
|
|
|
|
local function MakeEdge(p1, r1, p2, r2, w, h)
|
|
local t = wmtBgFrame:CreateTexture(nil, "BORDER")
|
|
t:SetTexture("Interface\\Buttons\\WHITE8X8")
|
|
t:SetVertexColor(0.25, 0.25, 0.25, 1)
|
|
t:SetPoint(p1, WorldMapTooltip, r1)
|
|
t:SetPoint(p2, WorldMapTooltip, r2)
|
|
if w then t:SetWidth(w) end
|
|
if h then t:SetHeight(h) end
|
|
end
|
|
MakeEdge("TOPLEFT","TOPLEFT","TOPRIGHT","TOPRIGHT", nil, 1)
|
|
MakeEdge("BOTTOMLEFT","BOTTOMLEFT","BOTTOMRIGHT","BOTTOMRIGHT", nil, 1)
|
|
MakeEdge("TOPLEFT","TOPLEFT","BOTTOMLEFT","BOTTOMLEFT", 1, nil)
|
|
MakeEdge("TOPRIGHT","TOPRIGHT","BOTTOMRIGHT","BOTTOMRIGHT", 1, nil)
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Cooldown Numbers
|
|
-- Display remaining duration as text on every cooldown frame (>= 2 sec).
|
|
--------------------------------------------------------------------------------
|
|
local function TimeConvert(remaining)
|
|
local color = "|cffffffff"
|
|
if remaining < 5 then
|
|
color = "|cffff5555"
|
|
elseif remaining < 10 then
|
|
color = "|cffffff55"
|
|
end
|
|
|
|
if remaining < 60 then
|
|
return color .. math.ceil(remaining)
|
|
elseif remaining < 3600 then
|
|
return color .. math.ceil(remaining / 60) .. "m"
|
|
elseif remaining < 86400 then
|
|
return color .. math.ceil(remaining / 3600) .. "h"
|
|
else
|
|
return color .. math.ceil(remaining / 86400) .. "d"
|
|
end
|
|
end
|
|
|
|
local function CooldownOnUpdate()
|
|
local parent = this:GetParent()
|
|
if not parent then this:Hide() return end
|
|
|
|
if not this.tick then this.tick = GetTime() + 0.1 end
|
|
if this.tick > GetTime() then return end
|
|
this.tick = GetTime() + 0.1
|
|
|
|
this:SetAlpha(parent:GetAlpha())
|
|
|
|
if this.start < GetTime() then
|
|
local remaining = this.duration - (GetTime() - this.start)
|
|
if remaining > 0 then
|
|
this.text:SetText(TimeConvert(remaining))
|
|
else
|
|
this:Hide()
|
|
end
|
|
else
|
|
local time = time()
|
|
local startupTime = time - GetTime()
|
|
local cdTime = (2 ^ 32) / 1000 - this.start
|
|
local cdStartTime = startupTime - cdTime
|
|
local cdEndTime = cdStartTime + this.duration
|
|
local remaining = cdEndTime - time
|
|
if remaining >= 0 then
|
|
this.text:SetText(TimeConvert(remaining))
|
|
else
|
|
this:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
local function IsActionBarButtonName(name)
|
|
if not name then return false end
|
|
return string.find(name, "^ActionButton%d+$")
|
|
or string.find(name, "^BonusActionButton%d+$")
|
|
or string.find(name, "^MultiBarBottomLeftButton%d+$")
|
|
or string.find(name, "^MultiBarBottomRightButton%d+$")
|
|
or string.find(name, "^MultiBarLeftButton%d+$")
|
|
or string.find(name, "^MultiBarRightButton%d+$")
|
|
or string.find(name, "^PetActionButton%d+$")
|
|
or string.find(name, "^ShapeshiftButton%d+$")
|
|
end
|
|
|
|
local function UpdateActionBarCooldownMask(cooldown)
|
|
if not cooldown then return end
|
|
if cooldown.cooldownmask then
|
|
cooldown.cooldownmask:SetAllPoints(cooldown)
|
|
cooldown.cooldownmask:SetFrameStrata(cooldown:GetFrameStrata())
|
|
cooldown.cooldownmask:SetFrameLevel(cooldown:GetFrameLevel() + 1)
|
|
end
|
|
if cooldown.cooldowntext then
|
|
cooldown.cooldowntext:SetAllPoints(cooldown)
|
|
cooldown.cooldowntext:SetFrameStrata(cooldown:GetFrameStrata())
|
|
cooldown.cooldowntext:SetFrameLevel(cooldown:GetFrameLevel() + 2)
|
|
end
|
|
end
|
|
|
|
local function CreateCoolDown(cooldown, start, duration)
|
|
if not cooldown then return end
|
|
local parent = cooldown:GetParent()
|
|
if not parent then return end
|
|
if cooldown.readable then return end
|
|
|
|
local parentname = parent and parent.GetName and parent:GetName()
|
|
parentname = parentname or "UnknownCooldownFrame"
|
|
|
|
cooldown.cooldowntext = CreateFrame("Frame", parentname .. "NanamiCDText", cooldown)
|
|
cooldown.cooldowntext:SetAllPoints(cooldown)
|
|
cooldown.cooldowntext:SetFrameStrata(cooldown:GetFrameStrata())
|
|
cooldown.cooldowntext:SetFrameLevel(cooldown:GetFrameLevel() + 2)
|
|
cooldown.cooldowntext.text = cooldown.cooldowntext:CreateFontString(
|
|
parentname .. "NanamiCDFont", "OVERLAY")
|
|
|
|
local isActionBar = IsActionBarButtonName(parentname)
|
|
local size = parent:GetHeight() or 0
|
|
size = size > 0 and size * 0.64 or 12
|
|
size = size > 14 and 14 or size
|
|
|
|
if isActionBar then
|
|
local bigSize = size * 1.22
|
|
if bigSize < 13 then bigSize = 13 end
|
|
if bigSize > 18 then bigSize = 18 end
|
|
cooldown.cooldowntext.text:SetFont(STANDARD_TEXT_FONT, bigSize, "THICKOUTLINE")
|
|
else
|
|
cooldown.cooldowntext.text:SetFont(STANDARD_TEXT_FONT, size, "OUTLINE")
|
|
end
|
|
cooldown.cooldowntext.text:SetDrawLayer("OVERLAY", 7)
|
|
|
|
if isActionBar then
|
|
cooldown.cooldownmask = CreateFrame("Frame", parentname .. "NanamiCDMask", cooldown)
|
|
cooldown.cooldownmask:SetAllPoints(cooldown)
|
|
cooldown.cooldownmask:SetFrameStrata(cooldown:GetFrameStrata())
|
|
cooldown.cooldownmask:SetFrameLevel(cooldown:GetFrameLevel() + 1)
|
|
local mask = cooldown.cooldownmask:CreateTexture(nil, "BACKGROUND")
|
|
mask:SetTexture("Interface\\Buttons\\WHITE8X8")
|
|
mask:SetAllPoints(cooldown.cooldownmask)
|
|
mask:SetDrawLayer("BACKGROUND", 0)
|
|
mask:SetVertexColor(0, 0, 0, 0.45)
|
|
cooldown.cooldownmask.mask = mask
|
|
cooldown.cooldowntext.text:SetPoint("CENTER", cooldown.cooldowntext, "CENTER", 0, 0)
|
|
else
|
|
cooldown.cooldowntext.text:SetPoint("CENTER", cooldown.cooldowntext, "CENTER", 0, 0)
|
|
end
|
|
|
|
cooldown.cooldowntext:SetScript("OnUpdate", CooldownOnUpdate)
|
|
end
|
|
|
|
local function SetCooldown(frame, start, duration, enable)
|
|
if not frame then return end
|
|
if frame.noCooldownCount then return end
|
|
|
|
if not duration or duration < 2 then
|
|
if frame.cooldowntext then
|
|
frame.cooldowntext:Hide()
|
|
end
|
|
if frame.cooldownmask then
|
|
frame.cooldownmask:Hide()
|
|
end
|
|
return
|
|
end
|
|
|
|
if not frame.cooldowntext then
|
|
CreateCoolDown(frame, start, duration)
|
|
end
|
|
|
|
if frame.cooldowntext then
|
|
UpdateActionBarCooldownMask(frame)
|
|
if start > 0 and duration > 0 and (not enable or enable > 0) then
|
|
if frame.cooldownmask then frame.cooldownmask:Show() end
|
|
frame.cooldowntext:Show()
|
|
else
|
|
if frame.cooldownmask then frame.cooldownmask:Hide() end
|
|
frame.cooldowntext:Hide()
|
|
end
|
|
frame.cooldowntext.start = start
|
|
frame.cooldowntext.duration = duration
|
|
end
|
|
end
|
|
|
|
local function InitCooldownNumbers()
|
|
_hooksecurefunc("CooldownFrame_SetTimer", SetCooldown)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Quest Watch Timed Quest Countdown
|
|
-- Append remaining time for timed quests in the watched quest list (outside
|
|
-- quest detail UI), so players can see countdown directly on the main HUD.
|
|
--------------------------------------------------------------------------------
|
|
local function FormatQuestCountdown(seconds)
|
|
local s = tonumber(seconds) or 0
|
|
if s <= 0 then return "0s" end
|
|
|
|
local h = math.floor(s / 3600)
|
|
local m = math.floor(math.mod(s, 3600) / 60)
|
|
local sec = math.floor(math.mod(s, 60))
|
|
|
|
if h > 0 then
|
|
return string.format("%dh %02dm %02ds", h, m, sec)
|
|
elseif m > 0 then
|
|
return string.format("%dm %02ds", m, sec)
|
|
end
|
|
return string.format("%ds", sec)
|
|
end
|
|
|
|
local function InitQuestWatchCountdown()
|
|
if not QuestWatch_Update or not GetNumQuestWatches or not GetQuestLogTitle
|
|
or not GetQuestIndexForWatch or not GetQuestLogTimeLeft then
|
|
return
|
|
end
|
|
|
|
local function StripNanamiCountdown(text)
|
|
if not text then return text end
|
|
return string.gsub(text, " |cffffcc00%[剩余: [^%]]+%]|r$", "")
|
|
end
|
|
|
|
local applying = false
|
|
local function ApplyQuestWatchCountdown()
|
|
if applying then return end
|
|
applying = true
|
|
|
|
local timedByTitle = {}
|
|
local watchCount = tonumber(GetNumQuestWatches()) or 0
|
|
for i = 1, watchCount do
|
|
local questIndex = GetQuestIndexForWatch(i)
|
|
if questIndex and questIndex > 0 then
|
|
local title, level, tag, isHeader = GetQuestLogTitle(questIndex)
|
|
if title and not isHeader then
|
|
local timeLeft = GetQuestLogTimeLeft(questIndex)
|
|
if timeLeft and timeLeft > 0 then
|
|
timedByTitle[title] = FormatQuestCountdown(timeLeft)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local lineCount = tonumber(QUESTWATCHLINES) or 0
|
|
for i = 1, lineCount do
|
|
local fs = _G["QuestWatchLine" .. i]
|
|
if fs and fs.GetText and fs.SetText then
|
|
local text = fs:GetText()
|
|
if text and text ~= "" then
|
|
local clean = StripNanamiCountdown(text)
|
|
local timerText = timedByTitle[clean]
|
|
if timerText then
|
|
fs:SetText(clean .. " |cffffcc00[剩余: " .. timerText .. "]|r")
|
|
elseif clean ~= text then
|
|
fs:SetText(clean)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
applying = false
|
|
end
|
|
|
|
_hooksecurefunc("QuestWatch_Update", ApplyQuestWatchCountdown)
|
|
|
|
local ticker = CreateFrame("Frame", "NanamiQuestWatchCountdownTicker")
|
|
ticker._e = 0
|
|
ticker:SetScript("OnUpdate", function()
|
|
this._e = (this._e or 0) + (arg1 or 0)
|
|
if this._e < 1.0 then return end
|
|
this._e = 0
|
|
if (tonumber(GetNumQuestWatches()) or 0) > 0 then
|
|
pcall(ApplyQuestWatchCountdown)
|
|
end
|
|
end)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Dark UI
|
|
-- Turns the entire interface into darker colors by applying vertex color
|
|
-- tinting to all UI textures recursively.
|
|
--------------------------------------------------------------------------------
|
|
local function HookAddonOrVariable(addon, func)
|
|
local lurker = CreateFrame("Frame", nil)
|
|
lurker.func = func
|
|
lurker:RegisterEvent("ADDON_LOADED")
|
|
lurker:RegisterEvent("VARIABLES_LOADED")
|
|
lurker:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
lurker:SetScript("OnEvent", function()
|
|
if IsAddOnLoaded(addon) or getfenv(0)[addon] then
|
|
this:func()
|
|
this:UnregisterAllEvents()
|
|
end
|
|
end)
|
|
end
|
|
|
|
local borderBackdrop = {
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 8, edgeSize = 16,
|
|
insets = { left = 0, right = 0, top = 0, bottom = 0 }
|
|
}
|
|
|
|
local function AddBorder(frame, inset, color)
|
|
if not frame then return end
|
|
if frame.NanamiBorder then return frame.NanamiBorder end
|
|
|
|
local top, right, bottom, left
|
|
if type(inset) == "table" then
|
|
top, right, bottom, left = unpack(inset)
|
|
left, bottom = -left, -bottom
|
|
end
|
|
|
|
frame.NanamiBorder = CreateFrame("Frame", nil, frame)
|
|
frame.NanamiBorder:SetPoint("TOPLEFT", frame, "TOPLEFT",
|
|
(left or -inset), (top or inset))
|
|
frame.NanamiBorder:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT",
|
|
(right or inset), (bottom or -inset))
|
|
frame.NanamiBorder:SetBackdrop(borderBackdrop)
|
|
if color then
|
|
frame.NanamiBorder:SetBackdropBorderColor(color.r, color.g, color.b, 1)
|
|
end
|
|
return frame.NanamiBorder
|
|
end
|
|
|
|
local darkColor = { r = .3, g = .3, b = .3, a = .9 }
|
|
|
|
local darkBlacklist = {
|
|
["Solid Texture"] = true, ["WHITE8X8"] = true, ["StatusBar"] = true,
|
|
["BarFill"] = true, ["Portrait"] = true, ["Button"] = true,
|
|
["Icon"] = true, ["AddOns"] = true, ["StationeryTest"] = true,
|
|
["TargetDead"] = true, ["^KeyRing"] = true, ["GossipIcon"] = true,
|
|
["WorldMap\\(.+)\\"] = true, ["PetHappiness"] = true,
|
|
["Elite"] = true, ["Rare"] = true, ["ColorPickerWheel"] = true,
|
|
["ComboPoint"] = true, ["Skull"] = true,
|
|
["battlenetworking0"] = true, ["damage"] = true,
|
|
["tank"] = true, ["healer"] = true,
|
|
}
|
|
|
|
local darkRegionSkips = {
|
|
["ColorPickerFrame"] = { [15] = true }
|
|
}
|
|
|
|
local darkBackgrounds = {
|
|
["^SpellBookFrame$"] = { 325, 355, 17, -74 },
|
|
["^ItemTextFrame$"] = { 300, 355, 24, -74 },
|
|
}
|
|
|
|
local darkBorders = {
|
|
["ShapeshiftButton"] = 3, ["BuffButton"] = 3,
|
|
["TargetFrameBuff"] = 3, ["TempEnchant"] = 3,
|
|
["SpellButton"] = 3, ["SpellBookSkillLineTab"] = 3,
|
|
["ActionButton%d+$"] = 3, ["MultiBar(.+)Button%d+$"] = 3,
|
|
["KeyRingButton"] = 2,
|
|
["ActionBarUpButton"] = -3, ["ActionBarDownButton"] = -3,
|
|
["Character(.+)Slot$"] = 3, ["Inspect(.+)Slot$"] = 3,
|
|
["ContainerFrame(.+)Item"] = 3, ["MainMenuBarBackpackButton$"] = 3,
|
|
["CharacterBag(.+)Slot$"] = 3, ["ChatFrame(.+)Button"] = -2,
|
|
["PetFrameHappiness"] = 2, ["MicroButton"] = { -21, 0, 0, 0 },
|
|
}
|
|
|
|
local darkAddonFrames = {
|
|
["Blizzard_TalentUI"] = { "TalentFrame" },
|
|
["Blizzard_AuctionUI"] = { "AuctionFrame", "AuctionDressUpFrame" },
|
|
["Blizzard_CraftUI"] = { "CraftFrame" },
|
|
["Blizzard_InspectUI"] = { "InspectPaperDollFrame", "InspectHonorFrame", "InspectFrameTab1", "InspectFrameTab2" },
|
|
["Blizzard_MacroUI"] = { "MacroFrame", "MacroPopupFrame" },
|
|
["Blizzard_RaidUI"] = { "ReadyCheckFrame" },
|
|
["Blizzard_TradeSkillUI"] = { "TradeSkillFrame" },
|
|
-- ClassTrainerFrame replaced by TrainerUI.lua
|
|
}
|
|
|
|
local function IsDarkBlacklisted(texture)
|
|
local name = texture:GetName()
|
|
local tex = texture:GetTexture()
|
|
if not tex then return true end
|
|
|
|
if name then
|
|
for entry in pairs(darkBlacklist) do
|
|
if string.find(name, entry, 1) then return true end
|
|
end
|
|
end
|
|
|
|
for entry in pairs(darkBlacklist) do
|
|
if string.find(tex, entry, 1) then return true end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function AddSpecialBackground(frame, w, h, x, y)
|
|
frame.NanamiMaterial = frame.NanamiMaterial or frame:CreateTexture(nil, "OVERLAY")
|
|
frame.NanamiMaterial:SetTexture("Interface\\Stationery\\StationeryTest1")
|
|
frame.NanamiMaterial:SetWidth(w)
|
|
frame.NanamiMaterial:SetHeight(h)
|
|
frame.NanamiMaterial:SetPoint("TOPLEFT", frame, x, y)
|
|
frame.NanamiMaterial:SetVertexColor(.8, .8, .8)
|
|
end
|
|
|
|
local darkFrameSkips = {
|
|
["^SFramesChat"] = true,
|
|
["^SFramesPlayer"] = true,
|
|
["^SFramesTarget"] = true,
|
|
["^SFramesParty"] = true,
|
|
["^SFramesRaid"] = true,
|
|
["^SFramesMBuff"] = true,
|
|
["^SFramesMDebuff"] = true,
|
|
["^GameTooltip"] = true,
|
|
}
|
|
|
|
local function DarkenFrame(frame, r, g, b, a)
|
|
if not r and not g and not b then
|
|
r, g, b, a = darkColor.r, darkColor.g, darkColor.b, darkColor.a
|
|
end
|
|
|
|
local fname = frame and frame.GetName and frame:GetName()
|
|
if fname then
|
|
for pattern in pairs(darkFrameSkips) do
|
|
if string.find(fname, pattern) then return end
|
|
end
|
|
end
|
|
|
|
if frame and frame.GetChildren then
|
|
for _, child in pairs({ frame:GetChildren() }) do
|
|
DarkenFrame(child, r, g, b, a)
|
|
end
|
|
end
|
|
|
|
if frame and frame.GetRegions then
|
|
local name = frame.GetName and frame:GetName()
|
|
|
|
if frame.SetBackdropBorderColor then
|
|
frame:SetBackdropBorderColor(darkColor.r, darkColor.g, darkColor.b, darkColor.a)
|
|
end
|
|
|
|
for pattern, inset in pairs(darkBackgrounds) do
|
|
if name and string.find(name, pattern) then
|
|
AddSpecialBackground(frame, inset[1], inset[2], inset[3], inset[4])
|
|
end
|
|
end
|
|
|
|
for pattern, inset in pairs(darkBorders) do
|
|
if name and string.find(name, pattern) then
|
|
AddBorder(frame, inset, darkColor)
|
|
end
|
|
end
|
|
|
|
for id, region in pairs({ frame:GetRegions() }) do
|
|
if region.SetVertexColor and region:GetObjectType() == "Texture" then
|
|
if name and id and darkRegionSkips[name] and darkRegionSkips[name][id] then
|
|
-- skip
|
|
elseif region.GetBlendMode and region:GetBlendMode() == "ADD" then
|
|
-- skip blend textures
|
|
elseif IsDarkBlacklisted(region) then
|
|
-- skip blacklisted
|
|
else
|
|
region:SetVertexColor(r, g, b, a)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- StaticPopup Theme Skin
|
|
--------------------------------------------------------------------------------
|
|
local function InitPopupSkin()
|
|
local popupSkinned = {}
|
|
local font = (SFrames and SFrames.GetFont and SFrames:GetFont()) or "Fonts\\ARKai_T.ttf"
|
|
|
|
local _A = SFrames.ActiveTheme
|
|
local P = {
|
|
bg = _A.panelBg or { 0.12, 0.06, 0.10, 0.95 },
|
|
border = _A.panelBorder or { 0.55, 0.30, 0.42, 0.9 },
|
|
btnBg = _A.btnBg or { 0.18, 0.10, 0.15, 0.94 },
|
|
btnBd = _A.btnBorder or { 0.50, 0.30, 0.40, 0.80 },
|
|
text = _A.nameText or { 0.90, 0.88, 0.94 },
|
|
}
|
|
|
|
local function HidePopupTex(tex)
|
|
if not tex then return end
|
|
if tex.SetTexture then tex:SetTexture(nil) end
|
|
if tex.SetAlpha then tex:SetAlpha(0) end
|
|
if tex.Hide then tex:Hide() end
|
|
end
|
|
|
|
local function SkinButton(btn)
|
|
if not btn then return end
|
|
local regions = { btn:GetRegions() }
|
|
for _, r in ipairs(regions) do
|
|
if r and r.SetTexture and r:GetObjectType() == "Texture" then
|
|
local tex = r:GetTexture()
|
|
if tex and type(tex) == "string" and (string.find(tex, "UI%-Panel") or string.find(tex, "UI%-DialogBox")) then
|
|
r:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
HidePopupTex(btn.GetNormalTexture and btn:GetNormalTexture())
|
|
HidePopupTex(btn.GetPushedTexture and btn:GetPushedTexture())
|
|
HidePopupTex(btn.GetHighlightTexture and btn:GetHighlightTexture())
|
|
HidePopupTex(btn.GetDisabledTexture and btn:GetDisabledTexture())
|
|
|
|
local btnName = btn:GetName() or ""
|
|
for _, sfx in ipairs({"Left", "Right", "Middle"}) do
|
|
local t = _G[btnName .. sfx]
|
|
if t then t:SetAlpha(0); t:Hide() end
|
|
end
|
|
|
|
btn:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
|
edgeFile = "Interface\\Buttons\\WHITE8X8",
|
|
tile = false, tileSize = 0, edgeSize = 1,
|
|
insets = { left = 1, right = 1, top = 1, bottom = 1 },
|
|
})
|
|
btn:SetBackdropColor(P.btnBg[1], P.btnBg[2], P.btnBg[3], P.btnBg[4])
|
|
btn:SetBackdropBorderColor(P.btnBd[1], P.btnBd[2], P.btnBd[3], P.btnBd[4])
|
|
|
|
local fs = btn:GetFontString()
|
|
if fs then
|
|
fs:SetFont(font, 12, "OUTLINE")
|
|
fs:SetTextColor(P.text[1], P.text[2], P.text[3])
|
|
end
|
|
|
|
if not btn.nanamiPopupStyled then
|
|
btn.nanamiPopupStyled = true
|
|
local origEnter = btn:GetScript("OnEnter")
|
|
local origLeave = btn:GetScript("OnLeave")
|
|
|
|
btn:SetScript("OnEnter", function()
|
|
if origEnter then origEnter() end
|
|
this:SetBackdropColor(_A.btnHoverBg[1], _A.btnHoverBg[2], _A.btnHoverBg[3], _A.btnHoverBg[4])
|
|
if _A.btnHoverBorder then
|
|
this:SetBackdropBorderColor(_A.btnHoverBorder[1], _A.btnHoverBorder[2], _A.btnHoverBorder[3], _A.btnHoverBorder[4])
|
|
elseif _A.btnHoverBd then
|
|
this:SetBackdropBorderColor(_A.btnHoverBd[1], _A.btnHoverBd[2], _A.btnHoverBd[3], _A.btnHoverBd[4])
|
|
end
|
|
local t = this:GetFontString()
|
|
if t and _A.btnActiveText then t:SetTextColor(_A.btnActiveText[1], _A.btnActiveText[2], _A.btnActiveText[3]) end
|
|
end)
|
|
btn:SetScript("OnLeave", function()
|
|
if origLeave then origLeave() end
|
|
this:SetBackdropColor(P.btnBg[1], P.btnBg[2], P.btnBg[3], P.btnBg[4])
|
|
this:SetBackdropBorderColor(P.btnBd[1], P.btnBd[2], P.btnBd[3], P.btnBd[4])
|
|
local t = this:GetFontString()
|
|
if t then t:SetTextColor(P.text[1], P.text[2], P.text[3]) end
|
|
end)
|
|
btn:SetScript("OnMouseDown", function()
|
|
if _A.btnDownBg then
|
|
this:SetBackdropColor(_A.btnDownBg[1], _A.btnDownBg[2], _A.btnDownBg[3], _A.btnDownBg[4])
|
|
end
|
|
end)
|
|
btn:SetScript("OnMouseUp", function()
|
|
this:SetBackdropColor(_A.btnHoverBg[1], _A.btnHoverBg[2], _A.btnHoverBg[3], _A.btnHoverBg[4])
|
|
end)
|
|
end
|
|
end
|
|
|
|
local function SkinPopupFrame(frame)
|
|
if not frame then return end
|
|
local frameName = frame:GetName()
|
|
if not frameName then return end
|
|
|
|
if not popupSkinned[frameName] then
|
|
popupSkinned[frameName] = true
|
|
|
|
local regions = { frame:GetRegions() }
|
|
for _, r in ipairs(regions) do
|
|
if r and r:GetObjectType() == "Texture" then
|
|
local dl = r:GetDrawLayer()
|
|
if dl == "BACKGROUND" or dl == "BORDER" or dl == "ARTWORK" then
|
|
local tex = r:GetTexture() or ""
|
|
if type(tex) == "string" and (string.find(tex, "UI%-DialogBox") or string.find(tex, "UI%-Panel")) then
|
|
r:Hide()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
frame:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
tile = true, tileSize = 16, edgeSize = 14,
|
|
insets = { left = 3, right = 3, top = 3, bottom = 3 },
|
|
})
|
|
frame:SetBackdropColor(P.bg[1], P.bg[2], P.bg[3], P.bg[4])
|
|
frame:SetBackdropBorderColor(P.border[1], P.border[2], P.border[3], P.border[4])
|
|
|
|
local textFS = _G[frameName .. "Text"]
|
|
if textFS and textFS.SetFont then
|
|
textFS:SetFont(font, 13, "OUTLINE")
|
|
textFS:SetTextColor(P.text[1], P.text[2], P.text[3])
|
|
end
|
|
|
|
local editBox = _G[frameName .. "EditBox"]
|
|
if editBox then
|
|
editBox:SetBackdrop({
|
|
bgFile = "Interface\\Buttons\\WHITE8X8",
|
|
edgeFile = "Interface\\Buttons\\WHITE8X8",
|
|
tile = false, edgeSize = 1,
|
|
insets = { left = 1, right = 1, top = 1, bottom = 1 },
|
|
})
|
|
editBox:SetBackdropColor(0.05, 0.03, 0.05, 0.9)
|
|
editBox:SetBackdropBorderColor(P.btnBd[1], P.btnBd[2], P.btnBd[3], P.btnBd[4])
|
|
editBox:SetFont(font, 12, "OUTLINE")
|
|
editBox:SetTextColor(P.text[1], P.text[2], P.text[3])
|
|
end
|
|
|
|
local moneyFrame = _G[frameName .. "MoneyFrame"]
|
|
if moneyFrame then
|
|
local mRegions = { moneyFrame:GetRegions() }
|
|
for _, r in ipairs(mRegions) do
|
|
if r and r.SetFont then r:SetFont(font, 12, "OUTLINE") end
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, suffix in ipairs({"Button1", "Button2", "Button3"}) do
|
|
local btn = _G[frameName .. suffix]
|
|
if btn then SkinButton(btn) end
|
|
end
|
|
end
|
|
|
|
for i = 1, 4 do
|
|
local f = _G["StaticPopup" .. i]
|
|
if f then pcall(SkinPopupFrame, f) end
|
|
end
|
|
|
|
if StaticPopup_Show then
|
|
local origShow = StaticPopup_Show
|
|
StaticPopup_Show = function(a1, a2, a3, a4)
|
|
local dialog = origShow(a1, a2, a3, a4)
|
|
if dialog then
|
|
pcall(SkinPopupFrame, dialog)
|
|
end
|
|
return dialog
|
|
end
|
|
end
|
|
end
|
|
|
|
local function InitDarkUI()
|
|
local hookBuffButton_Update = BuffButton_Update
|
|
BuffButton_Update = function(buttonName, index, filter)
|
|
hookBuffButton_Update(buttonName, index, filter)
|
|
local name = buttonName and index and buttonName .. index or this:GetName()
|
|
local original = getfenv(0)[name .. "Border"]
|
|
if original and this.NanamiBorder then
|
|
local r, g, b = original:GetVertexColor()
|
|
this.NanamiBorder:SetBackdropBorderColor(r, g, b, 1)
|
|
original:SetAlpha(0)
|
|
end
|
|
end
|
|
|
|
TOOLTIP_DEFAULT_COLOR.r = darkColor.r
|
|
TOOLTIP_DEFAULT_COLOR.g = darkColor.g
|
|
TOOLTIP_DEFAULT_COLOR.b = darkColor.b
|
|
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.r = darkColor.r
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.g = darkColor.g
|
|
TOOLTIP_DEFAULT_BACKGROUND_COLOR.b = darkColor.b
|
|
|
|
DarkenFrame(UIParent)
|
|
DarkenFrame(WorldMapFrame)
|
|
DarkenFrame(DropDownList1)
|
|
DarkenFrame(DropDownList2)
|
|
DarkenFrame(DropDownList3)
|
|
|
|
local bars = { "Action", "BonusAction", "MultiBarBottomLeft",
|
|
"MultiBarBottomRight", "MultiBarLeft", "MultiBarRight", "Shapeshift" }
|
|
for _, prefix in pairs(bars) do
|
|
for i = 1, NUM_ACTIONBAR_BUTTONS do
|
|
local button = getfenv(0)[prefix .. "Button" .. i]
|
|
local texture = getfenv(0)[prefix .. "Button" .. i .. "NormalTexture"]
|
|
if button and texture then
|
|
texture:SetWidth(60)
|
|
texture:SetHeight(60)
|
|
texture:SetPoint("CENTER", 0, 0)
|
|
AddBorder(button, 3)
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, button in pairs({ MinimapZoomOut, MinimapZoomIn }) do
|
|
for _, func in pairs({ "GetNormalTexture", "GetDisabledTexture", "GetPushedTexture" }) do
|
|
if button[func] then
|
|
local tex = button[func](button)
|
|
if tex then
|
|
tex:SetVertexColor(darkColor.r + .2, darkColor.g + .2, darkColor.b + .2, 1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for addon, data in pairs(darkAddonFrames) do
|
|
local skip = false
|
|
if SFramesDB and SFramesDB.enableTradeSkill ~= false then
|
|
if addon == "Blizzard_TradeSkillUI" or addon == "Blizzard_CraftUI" then
|
|
skip = true
|
|
end
|
|
end
|
|
if not skip then
|
|
for _, frameName in pairs(data) do
|
|
local fn = frameName
|
|
HookAddonOrVariable(fn, function()
|
|
DarkenFrame(getfenv(0)[fn])
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
|
|
HookAddonOrVariable("Blizzard_TimeManager", function()
|
|
DarkenFrame(TimeManagerClockButton)
|
|
end)
|
|
|
|
HookAddonOrVariable("GameTooltipStatusBarBackdrop", function()
|
|
DarkenFrame(getfenv(0)["GameTooltipStatusBarBackdrop"])
|
|
end)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Module API
|
|
--------------------------------------------------------------------------------
|
|
function Tweaks:Initialize()
|
|
local cfg = GetTweaksCfg()
|
|
|
|
if cfg.autoStance ~= false then
|
|
local ok, err = pcall(InitAutoStance)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: AutoStance init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
|
|
if cfg.autoDismount ~= false then
|
|
local ok, err = pcall(InitAutoDismount)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: AutoDismount init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
|
|
if cfg.superWoW ~= false then
|
|
local ok, err = pcall(InitSuperWoW)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: SuperWoW init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
|
|
if cfg.turtleCompat ~= false then
|
|
local ok, err = pcall(InitTurtleCompat)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: TurtleCompat init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
|
|
if SFrames.WorldMap and SFrames.WorldMap.initialized then
|
|
-- New WorldMap module has taken over; skip legacy code
|
|
elseif cfg.worldMapWindow ~= false then
|
|
local ok, err = pcall(InitWorldMapWindow)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: WorldMapWindow init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
|
|
if cfg.cooldownNumbers ~= false then
|
|
local ok, err = pcall(InitCooldownNumbers)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: CooldownNumbers init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
|
|
do
|
|
local ok, err = pcall(InitQuestWatchCountdown)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: QuestWatchCountdown init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
|
|
if cfg.darkUI then
|
|
local ok, err = pcall(InitDarkUI)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: DarkUI init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
|
|
do
|
|
local ok, err = pcall(InitPopupSkin)
|
|
if not ok then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI: PopupSkin init failed: " .. tostring(err) .. "|r")
|
|
end
|
|
end
|
|
end
|