更新配置相关显示等
This commit is contained in:
@@ -220,9 +220,9 @@ end
|
||||
|
||||
function AFK:BuildModel(parent)
|
||||
local model = CreateFrame("PlayerModel", NextName("Model"), parent)
|
||||
model:SetWidth(420)
|
||||
model:SetHeight(520)
|
||||
model:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", 30, 70)
|
||||
model:SetWidth(520)
|
||||
model:SetHeight(640)
|
||||
model:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", 10, 65)
|
||||
model:SetFrameLevel(parent:GetFrameLevel() + 1)
|
||||
|
||||
-- Soft darkening on the right side so the info panel is readable
|
||||
@@ -868,10 +868,12 @@ function AFK:RefreshSkills()
|
||||
currentHeader = name or ""
|
||||
elseif name then
|
||||
local isWeapon = (currentHeader == "Weapon Skills" or currentHeader == "武器技能"
|
||||
or currentHeader == "Weapons" or currentHeader == "Combat")
|
||||
or currentHeader == "Weapons" or currentHeader == "Combat"
|
||||
or currentHeader == "武器")
|
||||
local isTrade = (currentHeader == "Trade Skills" or currentHeader == "专业技能"
|
||||
or currentHeader == "Professions")
|
||||
local isSecondary = (currentHeader == "Secondary Skills" or currentHeader == "辅助技能")
|
||||
or currentHeader == "Professions" or currentHeader == "专业")
|
||||
local isSecondary = (currentHeader == "Secondary Skills" or currentHeader == "辅助技能"
|
||||
or currentHeader == "Secondary")
|
||||
|
||||
if isWeapon and skillMax and skillMax > 0 then
|
||||
table.insert(weapons, { name = name, rank = skillRank or 0, max = skillMax })
|
||||
|
||||
@@ -1526,6 +1526,9 @@ local function ShortKeyText(key)
|
||||
key = string.gsub(key, "ALT%-", "A-")
|
||||
key = string.gsub(key, "MOUSEWHEELUP", "WhlUp")
|
||||
key = string.gsub(key, "MOUSEWHEELDOWN", "WhlDn")
|
||||
key = string.gsub(key, "BUTTON3", "M3")
|
||||
key = string.gsub(key, "BUTTON4", "M4")
|
||||
key = string.gsub(key, "BUTTON5", "M5")
|
||||
return key
|
||||
end
|
||||
|
||||
@@ -1547,21 +1550,29 @@ local function UpdateOverlayText(button)
|
||||
ov.label:SetText(t)
|
||||
end
|
||||
|
||||
local CLICK_TO_KEY = {
|
||||
MiddleButton = "BUTTON3",
|
||||
Button4 = "BUTTON4",
|
||||
Button5 = "BUTTON5",
|
||||
}
|
||||
|
||||
local function CreateBindOverlay(button)
|
||||
if keyBindOverlays[button] then return keyBindOverlays[button] end
|
||||
|
||||
local ov = CreateFrame("Button", nil, button)
|
||||
ov:SetAllPoints(button)
|
||||
ov:SetFrameLevel(button:GetFrameLevel() + 10)
|
||||
ov:RegisterForClicks("RightButtonUp")
|
||||
ov:RegisterForClicks("RightButtonUp", "MiddleButtonUp", "Button4Up", "Button5Up")
|
||||
|
||||
local bg = ov:CreateTexture(nil, "BACKGROUND")
|
||||
bg:SetAllPoints()
|
||||
bg:SetTexture(0, 0, 0, 0.55)
|
||||
|
||||
local label = ov:CreateFontString(nil, "OVERLAY")
|
||||
label:SetFont(SFrames:GetFont(), 9, "OUTLINE")
|
||||
label:SetFont(SFrames:GetFont(), 7, "OUTLINE")
|
||||
label:SetPoint("CENTER", ov, "CENTER", 0, 0)
|
||||
label:SetWidth(button:GetWidth() - 2)
|
||||
label:SetJustifyH("CENTER")
|
||||
label:SetTextColor(1, 0.82, 0)
|
||||
ov.label = label
|
||||
|
||||
@@ -1576,11 +1587,11 @@ local function CreateBindOverlay(button)
|
||||
if cmd then
|
||||
GameTooltip:AddLine(cmd, 1, 0.82, 0)
|
||||
local k1, k2 = GetBindingKey(cmd)
|
||||
if k1 then GameTooltip:AddLine("Key 1: " .. k1, 1, 1, 1) end
|
||||
if k2 then GameTooltip:AddLine("Key 2: " .. k2, 0.7, 0.7, 0.7) end
|
||||
if k1 then GameTooltip:AddLine("按键 1: " .. k1, 1, 1, 1) end
|
||||
if k2 then GameTooltip:AddLine("按键 2: " .. k2, 0.7, 0.7, 0.7) end
|
||||
end
|
||||
GameTooltip:AddLine("Press key to bind / Wheel to bind", 0.5, 0.8, 0.5)
|
||||
GameTooltip:AddLine("Right-click to clear", 0.8, 0.5, 0.5)
|
||||
GameTooltip:AddLine("按下按键/鼠标键/滚轮绑定", 0.5, 0.8, 0.5)
|
||||
GameTooltip:AddLine("右键点击清除绑定", 0.8, 0.5, 0.5)
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
ov:SetScript("OnLeave", function()
|
||||
@@ -1597,7 +1608,22 @@ local function CreateBindOverlay(button)
|
||||
SaveBindings(2)
|
||||
UpdateOverlayText(button)
|
||||
RefreshButtonHotkey(button)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff88ccff[Nanami-UI]|r Cleared bindings for " .. cmd)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff88ccff[Nanami-UI]|r 已清除 " .. cmd .. " 的绑定")
|
||||
end
|
||||
else
|
||||
local mouseKey = CLICK_TO_KEY[arg1]
|
||||
if mouseKey then
|
||||
local cmd = GetButtonBindingCmd(button)
|
||||
if not cmd then return end
|
||||
local keyStr = BuildKeyString(mouseKey)
|
||||
if not keyStr then return end
|
||||
local old = GetBindingAction(keyStr)
|
||||
if old and old ~= "" and old ~= cmd then SetBinding(keyStr, nil) end
|
||||
SetBinding(keyStr, cmd)
|
||||
SaveBindings(2)
|
||||
UpdateOverlayText(button)
|
||||
RefreshButtonHotkey(button)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff88ccff[Nanami-UI]|r " .. keyStr .. " -> " .. cmd)
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -1702,7 +1728,7 @@ function AB:EnterKeyBindMode()
|
||||
desc:SetPoint("TOP", title, "BOTTOM", 0, -6)
|
||||
desc:SetWidth(300)
|
||||
desc:SetJustifyH("CENTER")
|
||||
desc:SetText("悬停按钮 + 按键绑定 | 右键清除 | 滚轮绑定")
|
||||
desc:SetText("悬停按钮 + 按键/鼠标键/滚轮绑定 | 右键清除")
|
||||
desc:SetTextColor(0.82, 0.82, 0.82)
|
||||
|
||||
local saveBtn = CreateFrame("Button", "SFramesKeyBindSave", statusFrame, "UIPanelButtonTemplate")
|
||||
@@ -1713,12 +1739,57 @@ function AB:EnterKeyBindMode()
|
||||
saveBtn:SetScript("OnClick", function()
|
||||
AB:ExitKeyBindMode()
|
||||
end)
|
||||
|
||||
local _T = SFrames.ActiveTheme
|
||||
local function HideBindBtnTex(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
|
||||
HideBindBtnTex(saveBtn:GetNormalTexture())
|
||||
HideBindBtnTex(saveBtn:GetPushedTexture())
|
||||
HideBindBtnTex(saveBtn:GetHighlightTexture())
|
||||
HideBindBtnTex(saveBtn:GetDisabledTexture())
|
||||
for _, sfx in ipairs({"Left","Right","Middle"}) do
|
||||
local t = _G["SFramesKeyBindSave"..sfx]
|
||||
if t then t:SetAlpha(0); t:Hide() end
|
||||
end
|
||||
saveBtn: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 },
|
||||
})
|
||||
saveBtn:SetBackdropColor(_T.btnBg[1], _T.btnBg[2], _T.btnBg[3], _T.btnBg[4])
|
||||
saveBtn:SetBackdropBorderColor(_T.btnBorder[1], _T.btnBorder[2], _T.btnBorder[3], _T.btnBorder[4])
|
||||
local fs = saveBtn:GetFontString()
|
||||
if fs then fs:SetFont(SFrames:GetFont(), 11) end
|
||||
if fs then
|
||||
fs:SetFont(SFrames:GetFont(), 11, "OUTLINE")
|
||||
fs:SetTextColor(_T.btnText[1], _T.btnText[2], _T.btnText[3])
|
||||
end
|
||||
saveBtn:SetScript("OnEnter", function()
|
||||
this:SetBackdropColor(_T.btnHoverBg[1], _T.btnHoverBg[2], _T.btnHoverBg[3], _T.btnHoverBg[4])
|
||||
this:SetBackdropBorderColor(_T.btnHoverBorder[1], _T.btnHoverBorder[2], _T.btnHoverBorder[3], _T.btnHoverBorder[4])
|
||||
local t = this:GetFontString()
|
||||
if t then t:SetTextColor(_T.btnActiveText[1], _T.btnActiveText[2], _T.btnActiveText[3]) end
|
||||
end)
|
||||
saveBtn:SetScript("OnLeave", function()
|
||||
this:SetBackdropColor(_T.btnBg[1], _T.btnBg[2], _T.btnBg[3], _T.btnBg[4])
|
||||
this:SetBackdropBorderColor(_T.btnBorder[1], _T.btnBorder[2], _T.btnBorder[3], _T.btnBorder[4])
|
||||
local t = this:GetFontString()
|
||||
if t then t:SetTextColor(_T.btnText[1], _T.btnText[2], _T.btnText[3]) end
|
||||
end)
|
||||
saveBtn:SetScript("OnMouseDown", function()
|
||||
this:SetBackdropColor(_T.btnDownBg[1], _T.btnDownBg[2], _T.btnDownBg[3], _T.btnDownBg[4])
|
||||
end)
|
||||
saveBtn:SetScript("OnMouseUp", function()
|
||||
this:SetBackdropColor(_T.btnHoverBg[1], _T.btnHoverBg[2], _T.btnHoverBg[3], _T.btnHoverBg[4])
|
||||
end)
|
||||
end
|
||||
statusFrame:Show()
|
||||
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff88ccff[Nanami-UI]|r 按键绑定模式已开启。悬停按钮后按键绑定,右键清除,点击保存退出。")
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff88ccff[Nanami-UI]|r 按键绑定模式已开启。悬停按钮后按键/鼠标键/滚轮绑定,右键清除,ESC或点击保存退出。")
|
||||
end
|
||||
|
||||
function AB:ExitKeyBindMode()
|
||||
|
||||
29
BookUI.lua
29
BookUI.lua
@@ -74,6 +74,33 @@ local function TextHeight(fs, fallback)
|
||||
return fallback or 14
|
||||
end
|
||||
|
||||
local function StripItemTextHTML(text)
|
||||
if not text or text == "" then return text end
|
||||
if not string.find(text, "<") then return text end
|
||||
|
||||
text = string.gsub(text, "</?HTML>", "")
|
||||
text = string.gsub(text, "</?html>", "")
|
||||
text = string.gsub(text, "</?BODY>", "")
|
||||
text = string.gsub(text, "</?body>", "")
|
||||
text = string.gsub(text, "<H1[^>]*>", "")
|
||||
text = string.gsub(text, "<h1[^>]*>", "")
|
||||
text = string.gsub(text, "</H1>", "\n")
|
||||
text = string.gsub(text, "</h1>", "\n")
|
||||
text = string.gsub(text, "<P[^>]*>", "")
|
||||
text = string.gsub(text, "<p[^>]*>", "")
|
||||
text = string.gsub(text, "</P>", "\n")
|
||||
text = string.gsub(text, "</p>", "\n")
|
||||
text = string.gsub(text, "<BR/>", "\n")
|
||||
text = string.gsub(text, "<br/>", "\n")
|
||||
text = string.gsub(text, "<br>", "\n")
|
||||
text = string.gsub(text, "<[^>]+>", "")
|
||||
|
||||
text = string.gsub(text, "^[\n%s]+", "")
|
||||
text = string.gsub(text, "[\n%s]+$", "")
|
||||
text = string.gsub(text, "\n\n\n+", "\n\n")
|
||||
return text
|
||||
end
|
||||
|
||||
local function IsTrue(v)
|
||||
return v == true or v == 1
|
||||
end
|
||||
@@ -178,7 +205,7 @@ local function UpdateBookContent()
|
||||
text = ItemTextPageText:GetText() or ""
|
||||
end
|
||||
if text and text ~= "" then
|
||||
-- Keep paragraph gap readable: collapse 3+ consecutive newlines.
|
||||
text = StripItemTextHTML(text)
|
||||
text = string.gsub(text, "\n%s*\n%s*\n+", "\n\n")
|
||||
end
|
||||
local pageNum = ItemTextGetPage and tonumber(ItemTextGetPage()) or 1
|
||||
|
||||
75
Chat.lua
75
Chat.lua
@@ -6016,6 +6016,68 @@ function SFrames.Chat:StyleEditBox()
|
||||
self.emoteButton = eb
|
||||
end
|
||||
|
||||
if not self.langButton then
|
||||
if RDbItems and RDbItems.TriStateToggle then
|
||||
local lb = CreateFrame("Button", "SFramesChatLangButton", buttonParent)
|
||||
lb:SetWidth(18)
|
||||
lb:SetHeight(18)
|
||||
lb:SetFrameStrata("DIALOG")
|
||||
lb:SetFrameLevel(btnLevel)
|
||||
|
||||
local fs = lb:CreateFontString(nil, "ARTWORK")
|
||||
fs:SetFont(cfg.fontPath or "Fonts\\ARIALN.TTF", 11, "OUTLINE")
|
||||
fs:SetAllPoints(lb)
|
||||
fs:SetJustifyH("CENTER")
|
||||
fs:SetJustifyV("MIDDLE")
|
||||
lb.fontString = fs
|
||||
|
||||
local function UpdateLangButtonText()
|
||||
local mode = RDbItemsCfg and RDbItemsCfg.mode
|
||||
if mode == "en" then
|
||||
fs:SetText("E")
|
||||
fs:SetTextColor(0.4, 0.8, 1.0)
|
||||
elseif mode == "cn" then
|
||||
fs:SetText("中")
|
||||
fs:SetTextColor(1.0, 0.82, 0.4)
|
||||
else
|
||||
fs:SetText("--")
|
||||
fs:SetTextColor(0.6, 0.6, 0.6)
|
||||
end
|
||||
end
|
||||
|
||||
lb:SetScript("OnClick", function()
|
||||
RDbItems.TriStateToggle(this)
|
||||
UpdateLangButtonText()
|
||||
end)
|
||||
lb:SetScript("OnEnter", function()
|
||||
GameTooltip:SetOwner(this, "ANCHOR_TOP")
|
||||
local mode = RDbItemsCfg and RDbItemsCfg.mode
|
||||
if mode == "en" then
|
||||
GameTooltip:SetText("物品链接语言: 英文")
|
||||
elseif mode == "cn" then
|
||||
GameTooltip:SetText("物品链接语言: 中文")
|
||||
else
|
||||
GameTooltip:SetText("物品链接语言: 自动")
|
||||
end
|
||||
GameTooltip:AddLine("点击切换 Shift+点击物品时的链接语言", 0.7, 0.7, 0.7)
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
lb:SetScript("OnLeave", function() GameTooltip:Hide() end)
|
||||
|
||||
lb:EnableMouse(true)
|
||||
local hl = lb:CreateTexture(nil, "HIGHLIGHT")
|
||||
hl:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||||
hl:SetAllPoints(lb)
|
||||
hl:SetAlpha(0.15)
|
||||
|
||||
UpdateLangButtonText()
|
||||
lb._UpdateText = UpdateLangButtonText
|
||||
self.langButton = lb
|
||||
end
|
||||
elseif self.langButton and self.langButton._UpdateText then
|
||||
self.langButton._UpdateText()
|
||||
end
|
||||
|
||||
-- Re-parent in case buttons were created by an older version.
|
||||
self.rollButton:SetParent(self.editBackdrop)
|
||||
self.emoteButton:SetParent(self.editBackdrop)
|
||||
@@ -6025,12 +6087,22 @@ function SFrames.Chat:StyleEditBox()
|
||||
if self.emoteButton.SetFrameLevel then
|
||||
self.emoteButton:SetFrameLevel((editBox:GetFrameLevel() or 1) + 2)
|
||||
end
|
||||
if self.langButton then
|
||||
self.langButton:SetParent(self.editBackdrop)
|
||||
if self.langButton.SetFrameLevel then
|
||||
self.langButton:SetFrameLevel((editBox:GetFrameLevel() or 1) + 2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Re-anchor buttons every call so they track editBackdrop position
|
||||
self.rollButton:ClearAllPoints()
|
||||
self.rollButton:SetPoint("RIGHT", self.editBackdrop, "RIGHT", -4, 0)
|
||||
self.emoteButton:ClearAllPoints()
|
||||
self.emoteButton:SetPoint("RIGHT", self.rollButton, "LEFT", -2, 0)
|
||||
if self.langButton then
|
||||
self.langButton:ClearAllPoints()
|
||||
self.langButton:SetPoint("RIGHT", self.emoteButton, "LEFT", -2, 0)
|
||||
end
|
||||
|
||||
local function SaveFreeEditBoxPosition()
|
||||
if EnsureDB().editBoxPosition ~= "free" then return end
|
||||
@@ -6073,7 +6145,8 @@ function SFrames.Chat:StyleEditBox()
|
||||
editBox:SetParent(self.editBackdrop)
|
||||
editBox:ClearAllPoints()
|
||||
editBox:SetPoint("TOPLEFT", self.editBackdrop, "TOPLEFT", 4, -3)
|
||||
editBox:SetPoint("BOTTOMRIGHT", self.editBackdrop, "BOTTOMRIGHT", -45, 3)
|
||||
local rightPad = self.langButton and -65 or -45
|
||||
editBox:SetPoint("BOTTOMRIGHT", self.editBackdrop, "BOTTOMRIGHT", rightPad, 3)
|
||||
editBox:EnableMouse(true)
|
||||
self.editBackdrop:SetBackdropColor(CFG_THEME.panelBg[1], CFG_THEME.panelBg[2], CFG_THEME.panelBg[3], 0.96)
|
||||
local borderR, borderG, borderB = self:GetBorderColorRGB()
|
||||
|
||||
10
ConfigUI.lua
10
ConfigUI.lua
@@ -476,6 +476,7 @@ local function EnsureDB()
|
||||
if SFramesDB.smoothBars == nil then SFramesDB.smoothBars = true end
|
||||
if SFramesDB.mobRealHealth == nil then SFramesDB.mobRealHealth = true end
|
||||
if SFramesDB.showItemLevel == nil then SFramesDB.showItemLevel = true end
|
||||
if SFramesDB.showTooltipIDs == nil then SFramesDB.showTooltipIDs = true end
|
||||
if SFramesDB.itemCompare == nil then SFramesDB.itemCompare = true end
|
||||
if SFramesDB.gearScore == nil then SFramesDB.gearScore = true end
|
||||
|
||||
@@ -992,6 +993,13 @@ function SFrames.ConfigUI:BuildUIPage()
|
||||
))
|
||||
CreateDesc(enhSection, "Tooltip 显示当前职业各天赋EP评分及硬核评分,需要 ItemBonusLib", 36, -142, font, 480)
|
||||
|
||||
table.insert(controls, CreateCheckBox(enhSection,
|
||||
"显示物品/法术ID", 270, -126,
|
||||
function() return SFramesDB.showTooltipIDs ~= false end,
|
||||
function(checked) SFramesDB.showTooltipIDs = checked end
|
||||
))
|
||||
CreateDesc(enhSection, "在 Tooltip 中显示物品ID和法术ID", 292, -142, font, 218)
|
||||
|
||||
CreateLabel(enhSection, "提示:以上功能需要安装对应的 !Libs 库才能生效。", 14, -172, font, 10, 0.6, 0.6, 0.65)
|
||||
|
||||
-- ── ShaguTweaks 功能移植 ──────────────────────────────────────
|
||||
@@ -1911,7 +1919,7 @@ function SFrames.ConfigUI:BuildActionBarPage()
|
||||
end)
|
||||
|
||||
CreateDesc(abSection,
|
||||
"悬停动作条/姿态栏/宠物栏按钮,按下键盘键或滚轮绑定。右键清除。ESC 退出。也可用 /nui bind",
|
||||
"悬停动作条/姿态栏/宠物栏按钮,按下键盘键/鼠标键(3-5)/滚轮绑定。右键清除。ESC 退出。也可用 /nui bind",
|
||||
14, -100, font, 480)
|
||||
|
||||
table.insert(controls, CreateSlider(abSection, "按钮大小", 14, -130, 150, 24, 48, 1,
|
||||
|
||||
59
Core.lua
59
Core.lua
@@ -188,6 +188,28 @@ function SFrames:GetAuraTimeLeft(unit, index, isBuff)
|
||||
end
|
||||
end
|
||||
|
||||
-- Nanami-Plates SpellDB: combat log + spell DB tracking (most accurate for debuffs)
|
||||
if not isBuff and NanamiPlates_SpellDB and NanamiPlates_SpellDB.UnitDebuff then
|
||||
local effect, rank, tex, stacks, dtype, duration, timeleft, isOwn = NanamiPlates_SpellDB:UnitDebuff(unit, index)
|
||||
if timeleft and timeleft > 0 then
|
||||
return timeleft, effect
|
||||
end
|
||||
if effect and effect ~= "" and duration and duration > 0
|
||||
and NanamiPlates_Auras and NanamiPlates_Auras.timers then
|
||||
local unitKey = (UnitGUID and UnitGUID(unit)) or UnitName(unit) or ""
|
||||
local cached = NanamiPlates_Auras.timers[unitKey .. "_" .. effect]
|
||||
if not cached and UnitName(unit) then
|
||||
cached = NanamiPlates_Auras.timers[UnitName(unit) .. "_" .. effect]
|
||||
end
|
||||
if cached and cached.startTime and cached.duration then
|
||||
local remaining = cached.duration - (GetTime() - cached.startTime)
|
||||
if remaining > 0 then
|
||||
return remaining, effect
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback to ShaguTweaks libdebuff if available (Debuffs only usually)
|
||||
if ShaguTweaks and ShaguTweaks.libdebuff then
|
||||
if not isBuff then
|
||||
@@ -374,6 +396,43 @@ function SFrames:InitSlashCommands()
|
||||
else
|
||||
SFrames:Print("ActionBars module unavailable.")
|
||||
end
|
||||
elseif cmd == "debugbuffs" or cmd == "db" then
|
||||
local hex = SFrames.Theme and SFrames.Theme:GetAccentHex() or "ffffb3d9"
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|c" .. hex .. "[Nanami-UI]|r 当前所有 Buff:")
|
||||
for i = 0, 31 do
|
||||
local buffIndex = GetPlayerBuff(i, "HELPFUL")
|
||||
if buffIndex and buffIndex >= 0 then
|
||||
local name = SFrames:GetBuffName(buffIndex)
|
||||
local tex = GetPlayerBuffTexture(buffIndex) or "?"
|
||||
local tl = GetPlayerBuffTimeLeft(buffIndex)
|
||||
local timeStr = (tl and tl > 0 and tl < 99999) and string.format("%.1fs", tl) or "N/A"
|
||||
local hidden = SFrames:IsBuffHidden(buffIndex) and "|cffff4444[隐藏]|r" or ""
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format(" #%d: |cffffd100%s|r %s %s", i, name or "(nil)", timeStr, hidden))
|
||||
end
|
||||
end
|
||||
elseif cmd == "hidebuff" or cmd == "hb" then
|
||||
if args == "" then
|
||||
SFrames:Print("用法: /nui hidebuff <buff名称>")
|
||||
else
|
||||
if not SFramesDB.hiddenBuffs then SFramesDB.hiddenBuffs = {} end
|
||||
SFramesDB.hiddenBuffs[args] = true
|
||||
SFrames:Print("已隐藏 Buff: |cffffd100" .. args .. "|r")
|
||||
end
|
||||
elseif cmd == "unhidebuff" or cmd == "uhb" then
|
||||
if args == "" then
|
||||
SFrames:Print("用法: /nui unhidebuff <buff名称>")
|
||||
else
|
||||
if SFramesDB.hiddenBuffs then SFramesDB.hiddenBuffs[args] = nil end
|
||||
SFrames:Print("已取消隐藏 Buff: |cffffd100" .. args .. "|r")
|
||||
end
|
||||
elseif cmd == "listhidden" or cmd == "lh" then
|
||||
local hex = SFrames.Theme and SFrames.Theme:GetAccentHex() or "ffffb3d9"
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|c" .. hex .. "[Nanami-UI]|r 已隐藏的 Buff 列表:")
|
||||
if SFramesDB.hiddenBuffs then
|
||||
for name, _ in pairs(SFramesDB.hiddenBuffs) do
|
||||
DEFAULT_CHAT_FRAME:AddMessage(" |cffffd100" .. name .. "|r (用户自定义)")
|
||||
end
|
||||
end
|
||||
elseif cmd == "config" or cmd == "" then
|
||||
if SFrames.ConfigUI and SFrames.ConfigUI.Build then SFrames.ConfigUI:Build("ui") end
|
||||
else
|
||||
|
||||
@@ -8,6 +8,31 @@ local UPDATE_INTERVAL = 0.2
|
||||
local BASE_X = -209
|
||||
local BASE_Y = -26
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Buff Blacklist: Turtle WoW internal/proc buffs that should not appear
|
||||
--------------------------------------------------------------------------------
|
||||
local HIDDEN_BUFF_NAMES = {
|
||||
["防御状态"] = true,
|
||||
}
|
||||
|
||||
function SFrames:GetBuffName(buffIndex)
|
||||
if not SFrames.Tooltip then return nil end
|
||||
SFrames.Tooltip:ClearLines()
|
||||
SFrames.Tooltip:SetPlayerBuff(buffIndex)
|
||||
local nameObj = SFramesScanTooltipTextLeft1
|
||||
return nameObj and nameObj:GetText()
|
||||
end
|
||||
|
||||
function SFrames:IsBuffHidden(buffIndex)
|
||||
local name = self:GetBuffName(buffIndex)
|
||||
if not name or name == "" then return false end
|
||||
if HIDDEN_BUFF_NAMES[name] then return true end
|
||||
if SFramesDB and type(SFramesDB.hiddenBuffs) == "table" and SFramesDB.hiddenBuffs[name] then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local ROUND_BACKDROP = {
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
@@ -298,6 +323,7 @@ function MB:UpdateBuffs()
|
||||
for i = 0, 31 do
|
||||
local buffIndex, untilCancelled = GetPlayerBuff(i, "HELPFUL")
|
||||
if buffIndex and buffIndex >= 0 then
|
||||
if not SFrames:IsBuffHidden(buffIndex) then
|
||||
slotIdx = slotIdx + 1
|
||||
if slotIdx > MAX_BUFFS then break end
|
||||
|
||||
@@ -332,6 +358,7 @@ function MB:UpdateBuffs()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local hasMainHandEnchant, mainHandExpiration, mainHandCharges,
|
||||
hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Notes: 现代极简猫系单位框架插件 - 喵~ (Nanami-UI)
|
||||
## Author: AI Assistant
|
||||
## Version: 1.0.0
|
||||
## OptionalDeps: ShaguTweaks, Blizzard_CombatLog, HealComm-1.0, DruidManaLib-1.0, !Libs, pfQuest
|
||||
## OptionalDeps: ShaguTweaks, Blizzard_CombatLog, HealComm-1.0, DruidManaLib-1.0, !Libs, pfQuest, RDbItems
|
||||
## SavedVariablesPerCharacter: SFramesDB
|
||||
## SavedVariables: SFramesGlobalDB
|
||||
Bindings.xml
|
||||
|
||||
181
Tooltip.lua
181
Tooltip.lua
@@ -822,9 +822,18 @@ local function IC_AddSellPrice(tooltip, link, count)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
local function IC_AppendItemId(tooltip, link)
|
||||
if SFramesDB and SFramesDB.showTooltipIDs == false then return end
|
||||
local itemId = IC_GetItemIdFromLink(link)
|
||||
if itemId then
|
||||
tooltip:AddLine("物品ID: " .. itemId, 0.55, 0.55, 0.70)
|
||||
end
|
||||
end
|
||||
|
||||
local function IC_EnhanceTooltip(tooltip, link, count, skipSellPrice)
|
||||
if not link then return end
|
||||
IC_AppendItemLevel(tooltip, link)
|
||||
IC_AppendItemId(tooltip, link)
|
||||
if not SFramesDB or SFramesDB.itemCompare ~= false then
|
||||
local lib = IC_GetLib()
|
||||
if lib then
|
||||
@@ -1174,8 +1183,180 @@ function IC:HookTooltips()
|
||||
SetTooltipMoney(ItemRefTooltip, price)
|
||||
ItemRefTooltip:Show()
|
||||
end
|
||||
if itemId then
|
||||
ItemRefTooltip:AddLine("物品ID: " .. itemId, 0.55, 0.55, 0.70)
|
||||
ItemRefTooltip:Show()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Spell ID display
|
||||
---------------------------------------------------------------------------
|
||||
local spellIdCache = {}
|
||||
|
||||
local function TT_AddSpellIdLine(tooltip, sid)
|
||||
if not tooltip or not sid then return end
|
||||
if SFramesDB and SFramesDB.showTooltipIDs == false then return end
|
||||
tooltip:AddLine("法术ID: " .. sid, 0.55, 0.55, 0.70)
|
||||
tooltip:Show()
|
||||
end
|
||||
|
||||
local function TT_ExtractSpellId(link)
|
||||
if not link then return nil end
|
||||
local _, _, id = string.find(link, "spell:(%d+)")
|
||||
return id
|
||||
end
|
||||
|
||||
local function TT_CleanName(text)
|
||||
if not text then return nil end
|
||||
text = string.gsub(text, "|c%x%x%x%x%x%x%x%x", "")
|
||||
text = string.gsub(text, "|r", "")
|
||||
text = string.gsub(text, "|H.-|h", "")
|
||||
text = string.gsub(text, "|h", "")
|
||||
text = string.gsub(text, "^%s+", "")
|
||||
text = string.gsub(text, "%s+$", "")
|
||||
return text
|
||||
end
|
||||
|
||||
local function TT_BuildSpellCache()
|
||||
spellIdCache = {}
|
||||
local function ScanBook(bookType, count)
|
||||
if not GetSpellLink or count == 0 then return end
|
||||
for i = 1, count do
|
||||
local name, rank = GetSpellName(i, bookType)
|
||||
if name then
|
||||
local link = GetSpellLink(i, bookType)
|
||||
local sid = TT_ExtractSpellId(link)
|
||||
if sid then
|
||||
spellIdCache[name] = sid
|
||||
local clean = TT_CleanName(name)
|
||||
if clean and clean ~= name then
|
||||
spellIdCache[clean] = sid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local bookType = BOOKTYPE_SPELL or "spell"
|
||||
local numTabs = GetNumSpellTabs and GetNumSpellTabs() or 0
|
||||
local total = 0
|
||||
for t = 1, numTabs do
|
||||
local _, _, _, count = GetSpellTabInfo(t)
|
||||
total = total + (count or 0)
|
||||
end
|
||||
ScanBook(bookType, total)
|
||||
|
||||
if HasPetSpells then
|
||||
local numPet = HasPetSpells() or 0
|
||||
if numPet > 0 then
|
||||
ScanBook(BOOKTYPE_PET or "pet", numPet)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local spellCacheFrame = CreateFrame("Frame")
|
||||
spellCacheFrame:RegisterEvent("SPELLS_CHANGED")
|
||||
spellCacheFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
spellCacheFrame:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
||||
spellCacheFrame:RegisterEvent("PET_BAR_UPDATE")
|
||||
spellCacheFrame:SetScript("OnEvent", function()
|
||||
TT_BuildSpellCache()
|
||||
end)
|
||||
|
||||
local function TT_LookupSpellId(spellBookIdx, bookType)
|
||||
if GetSpellLink then
|
||||
local link = GetSpellLink(spellBookIdx, bookType)
|
||||
local sid = TT_ExtractSpellId(link)
|
||||
if sid then return sid end
|
||||
end
|
||||
local name = GetSpellName(spellBookIdx, bookType)
|
||||
if name then
|
||||
if spellIdCache[name] then return spellIdCache[name] end
|
||||
local clean = TT_CleanName(name)
|
||||
if clean and spellIdCache[clean] then return spellIdCache[clean] end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function TT_LookupByTooltipName(tooltip)
|
||||
local ttName = tooltip and tooltip:GetName()
|
||||
if not ttName then return nil end
|
||||
local left1 = _G[ttName .. "TextLeft1"]
|
||||
if not left1 then return nil end
|
||||
local raw = left1:GetText()
|
||||
if not raw or raw == "" then return nil end
|
||||
|
||||
if spellIdCache[raw] then return spellIdCache[raw] end
|
||||
|
||||
local clean = TT_CleanName(raw)
|
||||
if clean and spellIdCache[clean] then return spellIdCache[clean] end
|
||||
|
||||
local noRank = string.gsub(clean or raw, "%s*%(.-%)%s*$", "")
|
||||
if noRank ~= (clean or raw) and spellIdCache[noRank] then
|
||||
return spellIdCache[noRank]
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local orig_SetSpell = GameTooltip.SetSpell
|
||||
if orig_SetSpell then
|
||||
GameTooltip.SetSpell = function(self, id, bookType)
|
||||
orig_SetSpell(self, id, bookType)
|
||||
pcall(function()
|
||||
local sid = TT_LookupSpellId(id, bookType)
|
||||
if sid then
|
||||
TT_AddSpellIdLine(self, sid)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local orig_SetUnitBuff = GameTooltip.SetUnitBuff
|
||||
if orig_SetUnitBuff then
|
||||
GameTooltip.SetUnitBuff = function(self, unit, idx, filter)
|
||||
orig_SetUnitBuff(self, unit, idx, filter)
|
||||
pcall(function()
|
||||
local sid = TT_LookupByTooltipName(self)
|
||||
if sid then TT_AddSpellIdLine(self, sid) end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local orig_SetUnitDebuff = GameTooltip.SetUnitDebuff
|
||||
if orig_SetUnitDebuff then
|
||||
GameTooltip.SetUnitDebuff = function(self, unit, idx, filter)
|
||||
orig_SetUnitDebuff(self, unit, idx, filter)
|
||||
pcall(function()
|
||||
local sid = TT_LookupByTooltipName(self)
|
||||
if sid then TT_AddSpellIdLine(self, sid) end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local orig_SetCraftSpell = GameTooltip.SetCraftSpell
|
||||
if orig_SetCraftSpell then
|
||||
GameTooltip.SetCraftSpell = function(self, idx)
|
||||
orig_SetCraftSpell(self, idx)
|
||||
pcall(function()
|
||||
local sid = TT_LookupByTooltipName(self)
|
||||
if sid then TT_AddSpellIdLine(self, sid) end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local orig_SetTrackingSpell = GameTooltip.SetTrackingSpell
|
||||
if orig_SetTrackingSpell then
|
||||
GameTooltip.SetTrackingSpell = function(self)
|
||||
orig_SetTrackingSpell(self)
|
||||
pcall(function()
|
||||
local sid = TT_LookupByTooltipName(self)
|
||||
if sid then TT_AddSpellIdLine(self, sid) end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
51
Tweaks.lua
51
Tweaks.lua
@@ -789,6 +789,13 @@ local function InitPopupSkin()
|
||||
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() }
|
||||
@@ -801,6 +808,17 @@ local function InitPopupSkin()
|
||||
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",
|
||||
@@ -815,6 +833,39 @@ local function InitPopupSkin()
|
||||
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)
|
||||
|
||||
156
Units/Pet.lua
156
Units/Pet.lua
@@ -137,6 +137,8 @@ function SFrames.Pet:Initialize()
|
||||
self.frame.unit = "pet"
|
||||
f:Hide()
|
||||
|
||||
self:CreateCastbar()
|
||||
|
||||
SFrames:RegisterEvent("UNIT_PET", function() if arg1 == "player" then self:UpdateAll() end end)
|
||||
SFrames:RegisterEvent("PET_BAR_UPDATE", function() self:UpdateAll() end)
|
||||
SFrames:RegisterEvent("UNIT_HEALTH", function() if arg1 == "pet" then self:UpdateHealth() end end)
|
||||
@@ -785,3 +787,157 @@ function SFrames.Pet:UpdateFoodButton()
|
||||
if self.foodPanel then self.foodPanel:Hide() end
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Pet Castbar
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function SFrames.Pet:CreateCastbar()
|
||||
local f = self.frame
|
||||
local cbHeight = SFrames.Config.castbarHeight
|
||||
|
||||
local cb = SFrames:CreateStatusBar(f, "SFramesPetCastbar")
|
||||
cb:SetHeight(cbHeight)
|
||||
cb:SetPoint("BOTTOMLEFT", f, "TOPLEFT", 0, 4)
|
||||
cb:SetPoint("BOTTOMRIGHT", f, "TOPRIGHT", -(cbHeight + 6), 4)
|
||||
|
||||
local cbbg = CreateFrame("Frame", nil, f)
|
||||
cbbg:SetPoint("TOPLEFT", cb, "TOPLEFT", -1, 1)
|
||||
cbbg:SetPoint("BOTTOMRIGHT", cb, "BOTTOMRIGHT", 1, -1)
|
||||
cbbg:SetFrameLevel(cb:GetFrameLevel() - 1)
|
||||
SFrames:CreateUnitBackdrop(cbbg)
|
||||
|
||||
cb.bg = cb:CreateTexture(nil, "BACKGROUND")
|
||||
cb.bg:SetAllPoints()
|
||||
cb.bg:SetTexture(SFrames:GetTexture())
|
||||
cb.bg:SetVertexColor(_A.slotBg[1], _A.slotBg[2], _A.slotBg[3], _A.slotBg[4] or 1)
|
||||
cb:SetStatusBarColor(1, 0.7, 0)
|
||||
|
||||
cb.text = SFrames:CreateFontString(cb, 10, "LEFT")
|
||||
cb.text:SetPoint("LEFT", cb, "LEFT", 4, 0)
|
||||
|
||||
cb.time = SFrames:CreateFontString(cb, 10, "RIGHT")
|
||||
cb.time:SetPoint("RIGHT", cb, "RIGHT", -4, 0)
|
||||
|
||||
cb.icon = cb:CreateTexture(nil, "ARTWORK")
|
||||
cb.icon:SetWidth(cbHeight + 2)
|
||||
cb.icon:SetHeight(cbHeight + 2)
|
||||
cb.icon:SetPoint("LEFT", cb, "RIGHT", 4, 0)
|
||||
cb.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
|
||||
|
||||
local ibg = CreateFrame("Frame", nil, f)
|
||||
ibg:SetPoint("TOPLEFT", cb.icon, "TOPLEFT", -1, 1)
|
||||
ibg:SetPoint("BOTTOMRIGHT", cb.icon, "BOTTOMRIGHT", 1, -1)
|
||||
ibg:SetFrameLevel(cb:GetFrameLevel() - 1)
|
||||
SFrames:CreateUnitBackdrop(ibg)
|
||||
|
||||
cb:Hide()
|
||||
cbbg:Hide()
|
||||
cb.icon:Hide()
|
||||
ibg:Hide()
|
||||
|
||||
f.castbar = cb
|
||||
f.castbar.cbbg = cbbg
|
||||
f.castbar.ibg = ibg
|
||||
|
||||
f.castbarUpdater = CreateFrame("Frame", nil, f)
|
||||
f.castbarUpdater:SetScript("OnUpdate", function() SFrames.Pet:CastbarOnUpdate() end)
|
||||
end
|
||||
|
||||
function SFrames.Pet:CastbarOnUpdate()
|
||||
local cb = self.frame.castbar
|
||||
if not UnitExists("pet") then
|
||||
cb:Hide()
|
||||
cb.cbbg:Hide()
|
||||
cb.icon:Hide()
|
||||
cb.ibg:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
local cast, texture, startTime, endTime, channel
|
||||
|
||||
-- 1) Try native UnitCastingInfo / UnitChannelInfo (TurtleWoW extended API)
|
||||
local _UnitCastingInfo = UnitCastingInfo or (ShaguTweaks and ShaguTweaks.UnitCastingInfo)
|
||||
if _UnitCastingInfo then
|
||||
local c, _, _, tex, st, et = _UnitCastingInfo("pet")
|
||||
if c then
|
||||
cast, texture, startTime, endTime = c, tex, st, et
|
||||
end
|
||||
end
|
||||
|
||||
if not cast then
|
||||
local _UnitChannelInfo = UnitChannelInfo or (ShaguTweaks and ShaguTweaks.UnitChannelInfo)
|
||||
if _UnitChannelInfo then
|
||||
local c, _, _, tex, st, et = _UnitChannelInfo("pet")
|
||||
if c then
|
||||
cast, texture, startTime, endTime = c, tex, st, et
|
||||
channel = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 2) Fallback: SuperWoW castdb (GUID-based)
|
||||
if not cast and SFrames.castdb and UnitGUID then
|
||||
local guid = UnitGUID("pet")
|
||||
if guid then
|
||||
local entry = SFrames.castdb[guid]
|
||||
if entry and entry.cast and entry.start and entry.casttime then
|
||||
local elapsed = GetTime() - entry.start
|
||||
local duration = entry.casttime / 1000
|
||||
if elapsed < duration + 0.5 then
|
||||
cast = entry.cast
|
||||
texture = entry.icon
|
||||
startTime = entry.start * 1000
|
||||
endTime = (entry.start + duration) * 1000
|
||||
channel = entry.channel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if cast and startTime and endTime then
|
||||
local duration = (endTime - startTime) / 1000
|
||||
local cur = GetTime() - (startTime / 1000)
|
||||
|
||||
if channel then
|
||||
cur = duration + (startTime / 1000) - GetTime()
|
||||
end
|
||||
|
||||
if cur > duration then cur = duration end
|
||||
if cur < 0 then cur = 0 end
|
||||
|
||||
cb:SetMinMaxValues(0, duration)
|
||||
cb:SetValue(cur)
|
||||
cb.text:SetText(cast)
|
||||
cb.time:SetText(string.format("%.1f", channel and cur or math.max(duration - cur, 0)))
|
||||
|
||||
if texture then
|
||||
cb.icon:SetTexture(texture)
|
||||
end
|
||||
|
||||
cb:SetAlpha(1)
|
||||
cb.cbbg:SetAlpha(1)
|
||||
cb.icon:SetAlpha(1)
|
||||
cb.ibg:SetAlpha(1)
|
||||
|
||||
cb:Show()
|
||||
cb.cbbg:Show()
|
||||
cb.icon:Show()
|
||||
cb.ibg:Show()
|
||||
else
|
||||
if cb:IsShown() then
|
||||
local alpha = cb:GetAlpha() - 0.05
|
||||
if alpha > 0 then
|
||||
cb:SetAlpha(alpha)
|
||||
cb.cbbg:SetAlpha(alpha)
|
||||
cb.icon:SetAlpha(alpha)
|
||||
cb.ibg:SetAlpha(alpha)
|
||||
else
|
||||
cb:Hide()
|
||||
cb.cbbg:Hide()
|
||||
cb.icon:Hide()
|
||||
cb.ibg:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1418,11 +1418,14 @@ function SFrames.Player:CreateAuras()
|
||||
end
|
||||
|
||||
function SFrames.Player:UpdateAuras()
|
||||
local timeNow = GetTime()
|
||||
for i = 1, 16 do
|
||||
local b = self.frame.buffs[i]
|
||||
local buffIndex, untilCancelled = GetPlayerBuff(i - 1, "HELPFUL")
|
||||
if buffIndex >= 0 then
|
||||
local slotIdx = 0
|
||||
for i = 0, 31 do
|
||||
local buffIndex, untilCancelled = GetPlayerBuff(i, "HELPFUL")
|
||||
if buffIndex and buffIndex >= 0 then
|
||||
if not SFrames:IsBuffHidden(buffIndex) then
|
||||
slotIdx = slotIdx + 1
|
||||
if slotIdx > 16 then break end
|
||||
local b = self.frame.buffs[slotIdx]
|
||||
local texture = GetPlayerBuffTexture(buffIndex)
|
||||
if texture then
|
||||
b.icon:SetTexture(texture)
|
||||
@@ -1438,10 +1441,12 @@ function SFrames.Player:UpdateAuras()
|
||||
else
|
||||
b:Hide()
|
||||
end
|
||||
else
|
||||
b:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
for j = slotIdx + 1, 16 do
|
||||
self.frame.buffs[j]:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
-- Initialization Hook for Auras and Castbar
|
||||
@@ -1455,8 +1460,8 @@ function SFrames.Player:Initialize()
|
||||
self.auraUpdater.timer = 0
|
||||
self.auraUpdater:SetScript("OnUpdate", function()
|
||||
this.timer = this.timer + arg1
|
||||
SFrames.Player:UpdateFiveSecondRule()
|
||||
if this.timer >= 0.2 then
|
||||
SFrames.Player:UpdateFiveSecondRule()
|
||||
SFrames.Player:UpdateAuras()
|
||||
SFrames.Player:UpdatePower()
|
||||
SFrames.Player:UpdateHealPrediction()
|
||||
|
||||
@@ -935,36 +935,86 @@ function SFrames.TalentTree:ApplyVirtualPoints()
|
||||
return
|
||||
end
|
||||
|
||||
if not self.applyQueue then self.applyQueue = {} end
|
||||
self.applyQueue = {}
|
||||
|
||||
for tb = 1, GetNumTalentTabs() do
|
||||
local treeTalents = {}
|
||||
for idx = 1, GetNumTalents(tb) do
|
||||
local name, icon, tier, column, realRank = GetTalentInfo(tb, idx)
|
||||
local virtRank = self:GetVirtualRank(tb, idx)
|
||||
local diff = virtRank - realRank
|
||||
if diff > 0 then
|
||||
for i = 1, diff do
|
||||
table.insert(self.applyQueue, {tab = tb, index = idx})
|
||||
table.insert(treeTalents, {tab = tb, index = idx, tier = tier or 1})
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(treeTalents, function(a, b) return a.tier < b.tier end)
|
||||
for _, entry in ipairs(treeTalents) do
|
||||
table.insert(self.applyQueue, entry)
|
||||
end
|
||||
end
|
||||
|
||||
if table.getn(self.applyQueue) > 0 then
|
||||
self.frame:SetScript("OnUpdate", function()
|
||||
if table.getn(SFrames.TalentTree.applyQueue) > 0 then
|
||||
local t = table.remove(SFrames.TalentTree.applyQueue, 1)
|
||||
if table.getn(self.applyQueue) == 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|c" .. GetHex() .. "Nanami:|r 没有新的天赋点数需要应用。")
|
||||
return
|
||||
end
|
||||
|
||||
local total = table.getn(self.applyQueue)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|c" .. GetHex() .. "Nanami:|r 开始应用 " .. total .. " 个天赋点...")
|
||||
|
||||
if not self.applyEventFrame then
|
||||
self.applyEventFrame = CreateFrame("Frame", "NanamiTalentApplyFrame")
|
||||
end
|
||||
self.applyEventFrame:UnregisterAllEvents()
|
||||
|
||||
self.applyStallTimer = 0
|
||||
self.applyWaiting = false
|
||||
|
||||
local function FinishApply()
|
||||
self.applyEventFrame:UnregisterAllEvents()
|
||||
self.applyEventFrame:SetScript("OnUpdate", nil)
|
||||
self.applyQueue = {}
|
||||
self.applyWaiting = false
|
||||
self.simMode = false
|
||||
self:UpdateSimModeLabel()
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|c" .. GetHex() .. "Nanami:|r 天赋应用完成。")
|
||||
end
|
||||
|
||||
local function TryNextTalent()
|
||||
if table.getn(self.applyQueue) == 0 then
|
||||
FinishApply()
|
||||
return
|
||||
end
|
||||
local t = table.remove(self.applyQueue, 1)
|
||||
LearnTalent(t.tab, t.index)
|
||||
self.applyWaiting = true
|
||||
self.applyStallTimer = 0
|
||||
end
|
||||
|
||||
self.applyEventFrame:RegisterEvent("CHARACTER_POINTS_CHANGED")
|
||||
self.applyEventFrame:SetScript("OnEvent", function()
|
||||
if not SFrames.TalentTree.applyWaiting then return end
|
||||
SFrames.TalentTree.applyWaiting = false
|
||||
SFrames.TalentTree.applyStallTimer = 0
|
||||
TryNextTalent()
|
||||
end)
|
||||
|
||||
self.applyEventFrame:SetScript("OnUpdate", function()
|
||||
if not SFrames.TalentTree.applyWaiting then return end
|
||||
SFrames.TalentTree.applyStallTimer = (SFrames.TalentTree.applyStallTimer or 0) + (arg1 or 0)
|
||||
if SFrames.TalentTree.applyStallTimer >= 2.0 then
|
||||
SFrames.TalentTree.applyStallTimer = 0
|
||||
SFrames.TalentTree.applyWaiting = false
|
||||
if table.getn(SFrames.TalentTree.applyQueue) > 0 then
|
||||
TryNextTalent()
|
||||
else
|
||||
this:SetScript("OnUpdate", nil)
|
||||
SFrames.TalentTree.simMode = false
|
||||
SFrames.TalentTree:UpdateSimModeLabel()
|
||||
FinishApply()
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|c" .. GetHex() .. "Nanami:|r 没有新的天赋点数需要应用。")
|
||||
end
|
||||
|
||||
TryNextTalent()
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -821,25 +821,67 @@ function SFrames.Target:TickAuras()
|
||||
if not UnitExists("target") then return end
|
||||
|
||||
local timeNow = GetTime()
|
||||
local npFormat = NanamiPlates_Auras and NanamiPlates_Auras.FormatTime
|
||||
local hasNP = NanamiPlates_SpellDB and NanamiPlates_SpellDB.FindEffectData
|
||||
|
||||
local targetName, targetLevel, targetGUID
|
||||
if hasNP then
|
||||
targetName = UnitName("target")
|
||||
targetLevel = UnitLevel("target") or 0
|
||||
targetGUID = UnitGUID and UnitGUID("target")
|
||||
end
|
||||
|
||||
-- Buffs
|
||||
for i = 1, 16 do
|
||||
local b = self.frame.buffs[i]
|
||||
if b:IsShown() and b.expirationTime then
|
||||
local timeLeft = b.expirationTime - timeNow
|
||||
if timeLeft > 0 and timeLeft < 3600 then
|
||||
if npFormat then
|
||||
local text, r, g, bc, a = npFormat(timeLeft)
|
||||
b.cdText:SetText(text)
|
||||
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
|
||||
else
|
||||
b.cdText:SetText(SFrames:FormatTime(timeLeft))
|
||||
end
|
||||
else
|
||||
b.cdText:SetText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Debuffs: re-query SpellDB for live-accurate timers
|
||||
for i = 1, 16 do
|
||||
local b = self.frame.debuffs[i]
|
||||
if b:IsShown() and b.expirationTime then
|
||||
local timeLeft = b.expirationTime - timeNow
|
||||
if timeLeft > 0 and timeLeft < 3600 then
|
||||
if b:IsShown() then
|
||||
local timeLeft = nil
|
||||
|
||||
if hasNP and b.effectName then
|
||||
local data = targetGUID and NanamiPlates_SpellDB:FindEffectData(targetGUID, targetLevel, b.effectName)
|
||||
if not data and targetName then
|
||||
data = NanamiPlates_SpellDB:FindEffectData(targetName, targetLevel, b.effectName)
|
||||
end
|
||||
if data and data.start and data.duration then
|
||||
local remaining = data.duration + data.start - timeNow
|
||||
if remaining > 0 then
|
||||
timeLeft = remaining
|
||||
b.expirationTime = timeNow + remaining
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not timeLeft and b.expirationTime then
|
||||
timeLeft = b.expirationTime - timeNow
|
||||
end
|
||||
|
||||
if timeLeft and timeLeft > 0 and timeLeft < 3600 then
|
||||
if npFormat then
|
||||
local text, r, g, bc, a = npFormat(timeLeft)
|
||||
b.cdText:SetText(text)
|
||||
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
|
||||
else
|
||||
b.cdText:SetText(SFrames:FormatTime(timeLeft))
|
||||
end
|
||||
else
|
||||
b.cdText:SetText("")
|
||||
end
|
||||
@@ -895,29 +937,65 @@ function SFrames.Target:UpdateAuras()
|
||||
end
|
||||
|
||||
-- Debuffs
|
||||
local hasNP = NanamiPlates_SpellDB and NanamiPlates_SpellDB.UnitDebuff
|
||||
local npFormat = NanamiPlates_Auras and NanamiPlates_Auras.FormatTime
|
||||
|
||||
for i = 1, 16 do
|
||||
local texture = UnitDebuff("target", i)
|
||||
local b = self.frame.debuffs[i]
|
||||
b:SetID(i) -- Ensure ID is set for tooltips
|
||||
b:SetID(i)
|
||||
if texture then
|
||||
b.icon:SetTexture(texture)
|
||||
|
||||
-- Scrape tooltip for duration
|
||||
local timeLeft = 0
|
||||
local effectName = nil
|
||||
|
||||
if hasNP then
|
||||
local effect, rank, _, stacks, dtype, duration, npTimeLeft, isOwn = NanamiPlates_SpellDB:UnitDebuff("target", i)
|
||||
effectName = effect
|
||||
if npTimeLeft and npTimeLeft > 0 then
|
||||
timeLeft = npTimeLeft
|
||||
elseif effect and effect ~= "" and duration and duration > 0
|
||||
and NanamiPlates_Auras and NanamiPlates_Auras.timers then
|
||||
local unitKey = (UnitGUID and UnitGUID("target")) or UnitName("target") or ""
|
||||
local cached = NanamiPlates_Auras.timers[unitKey .. "_" .. effect]
|
||||
if not cached and UnitName("target") then
|
||||
cached = NanamiPlates_Auras.timers[UnitName("target") .. "_" .. effect]
|
||||
end
|
||||
if cached and cached.startTime and cached.duration then
|
||||
local remaining = cached.duration - (GetTime() - cached.startTime)
|
||||
if remaining > 0 then timeLeft = remaining end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if timeLeft <= 0 then
|
||||
SFrames.Tooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
SFrames.Tooltip:ClearLines()
|
||||
SFrames.Tooltip:SetUnitDebuff("target", i)
|
||||
local timeLeft = SFrames:GetAuraTimeLeft("target", i, false)
|
||||
timeLeft = SFrames:GetAuraTimeLeft("target", i, false)
|
||||
end
|
||||
|
||||
if timeLeft and timeLeft > 0 then
|
||||
b.expirationTime = GetTime() + timeLeft
|
||||
b.effectName = effectName
|
||||
if npFormat then
|
||||
local text, r, g, bc, a = npFormat(timeLeft)
|
||||
b.cdText:SetText(text)
|
||||
if r then b.cdText:SetTextColor(r, g, bc, a or 1) end
|
||||
else
|
||||
b.cdText:SetText(SFrames:FormatTime(timeLeft))
|
||||
end
|
||||
else
|
||||
b.expirationTime = nil
|
||||
b.effectName = nil
|
||||
b.cdText:SetText("")
|
||||
end
|
||||
|
||||
b:Show()
|
||||
else
|
||||
b.expirationTime = nil
|
||||
b.effectName = nil
|
||||
b.cdText:SetText("")
|
||||
b:Hide()
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user