完成焦点等开发
This commit is contained in:
@@ -70,7 +70,7 @@ local EQUIP_SLOTS_RIGHT = {
|
||||
}
|
||||
local EQUIP_SLOTS_BOTTOM = {
|
||||
{ id = 16, name = "MainHandSlot" }, { id = 17, name = "SecondaryHandSlot" },
|
||||
{ id = 18, name = "RangedSlot" }, { id = 0, name = "AmmoSlot" },
|
||||
{ id = 18, name = "RangedSlot" }, { name = "AmmoSlot" },
|
||||
}
|
||||
|
||||
local TAB_NAMES = { "装备", "声望", "技能", "荣誉" }
|
||||
@@ -438,11 +438,15 @@ local TALENT_DB = {
|
||||
meleeCrit = {
|
||||
{ names = {"Cruelty", "残忍"}, perRank = 1 },
|
||||
{ names = {"Malice", "恶意"}, perRank = 1 },
|
||||
{ names = {"Lethal Shots", "致命射击"}, perRank = 1 },
|
||||
{ names = {"Killer Instinct", "杀戮本能", "致命本能"}, perRank = 1 },
|
||||
{ names = {"Conviction", "信念", "坚定信念"}, perRank = 1 },
|
||||
{ names = {"Sharpened Claws", "利爪强化", "尖锐之爪"}, perRank = 2 },
|
||||
{ names = {"Thundering Strikes", "雷霆一击", "雷霆之击"}, perRank = 1 },
|
||||
},
|
||||
rangedCrit = {
|
||||
{ names = {"Lethal Shots", "夺命射击"}, perRank = 1 },
|
||||
{ names = {"Killer Instinct", "杀戮本能", "致命本能"}, perRank = 1 },
|
||||
},
|
||||
spellCrit = {
|
||||
{ names = {"Arcane Instability", "奥术不稳定"}, perRank = 1 },
|
||||
{ names = {"Critical Mass", "临界质量"}, perRank = 2 },
|
||||
@@ -458,7 +462,7 @@ local function ScanTalentBonuses()
|
||||
if _talentCache and _talentCacheTime and (now - _talentCacheTime) < 5 then
|
||||
return _talentCache
|
||||
end
|
||||
local r = { meleeHit = 0, spellHit = 0, meleeCrit = 0, spellCrit = 0,
|
||||
local r = { meleeHit = 0, spellHit = 0, meleeCrit = 0, rangedCrit = 0, spellCrit = 0,
|
||||
talentDetails = {} }
|
||||
if not GetNumTalentTabs then _talentCache = r; _talentCacheTime = now; return r end
|
||||
|
||||
@@ -532,7 +536,7 @@ local function FullRangedCrit()
|
||||
local _, agi = UnitStat("player", 2); agiCrit = (agi or 0) / ratio
|
||||
end
|
||||
local gearCrit = GetGearBonus("RANGEDCRIT") + GetGearBonus("CRIT")
|
||||
local talentCrit = GetTalentBonus("meleeCrit")
|
||||
local talentCrit = GetTalentBonus("rangedCrit")
|
||||
return baseCrit + agiCrit + gearCrit + talentCrit,
|
||||
baseCrit, agiCrit, gearCrit, talentCrit
|
||||
end
|
||||
@@ -1320,6 +1324,14 @@ function CP:BuildEquipmentPage()
|
||||
if page.built then return end
|
||||
page.built = true
|
||||
|
||||
-- Resolve AmmoSlot ID dynamically (may vary by client)
|
||||
for _, si in ipairs(EQUIP_SLOTS_BOTTOM) do
|
||||
if si.name == "AmmoSlot" and not si.id then
|
||||
local slotId = GetInventorySlotInfo("AmmoSlot")
|
||||
si.id = slotId or 0
|
||||
end
|
||||
end
|
||||
|
||||
local contentH = FRAME_H - (HEADER_H + TAB_BAR_H) - INNER_PAD - 4
|
||||
local scrollArea = CreateScrollFrame(page, CONTENT_W, contentH)
|
||||
scrollArea:SetPoint("TOPLEFT", page, "TOPLEFT", 0, 0)
|
||||
@@ -1547,6 +1559,72 @@ function CP:BuildEquipmentPage()
|
||||
end)
|
||||
page.rotRight = rotRight
|
||||
|
||||
-- Gear action toolbar: small icon buttons next to model toolbar
|
||||
local gearTbW = segW * 3 + 2
|
||||
local gearToolbar = CreateFrame("Frame", nil, page)
|
||||
gearToolbar:SetWidth(gearTbW)
|
||||
gearToolbar:SetHeight(tbH)
|
||||
gearToolbar:SetPoint("BOTTOM", modelBg, "BOTTOM", 0, 5 + tbH + 2)
|
||||
gearToolbar:SetFrameLevel(page:GetFrameLevel() + 6)
|
||||
SetPixelBackdrop(gearToolbar, { 0.04, 0.04, 0.06, 0.75 }, { 0.22, 0.22, 0.28, 0.5 })
|
||||
page.gearToolbar = gearToolbar
|
||||
|
||||
local function MakeGearToolBtn(parent, w, text, ox, tooltip, onClick)
|
||||
local btn = CreateFrame("Button", nil, parent)
|
||||
btn:SetWidth(w)
|
||||
btn:SetHeight(tbH - 2)
|
||||
btn:SetPoint("LEFT", parent, "LEFT", ox, 0)
|
||||
btn:SetFrameLevel(parent:GetFrameLevel() + 1)
|
||||
btn:SetBackdrop({
|
||||
bgFile = "Interface\\Buttons\\WHITE8X8",
|
||||
tile = false, tileSize = 0, edgeSize = 0,
|
||||
})
|
||||
btn:SetBackdropColor(0, 0, 0, 0)
|
||||
local fs = MakeFS(btn, 8, "CENTER", { 0.5, 0.5, 0.55 })
|
||||
fs:SetPoint("CENTER", btn, "CENTER", 0, 0)
|
||||
fs:SetText(text)
|
||||
btn.label = fs
|
||||
btn:SetScript("OnEnter", function()
|
||||
this:SetBackdropColor(T.slotBg[1], T.slotBg[2], T.slotBg[3], T.slotBg[4] or 0.5)
|
||||
this.label:SetTextColor(T.nameText[1], T.nameText[2], T.nameText[3])
|
||||
if tooltip then
|
||||
GameTooltip:SetOwner(this, "ANCHOR_BOTTOM")
|
||||
GameTooltip:AddLine(tooltip, 1, 1, 1)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end)
|
||||
btn:SetScript("OnLeave", function()
|
||||
this:SetBackdropColor(0, 0, 0, 0)
|
||||
this.label:SetTextColor(T.dimText[1], T.dimText[2], T.dimText[3])
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
btn:SetScript("OnClick", onClick)
|
||||
return btn
|
||||
end
|
||||
|
||||
local gStripBtn = MakeGearToolBtn(gearToolbar, segW, "脱", 1, "一键脱装", function() CP:StripAllGear() end)
|
||||
page.gStripBtn = gStripBtn
|
||||
|
||||
local gSep1 = gearToolbar:CreateTexture(nil, "OVERLAY")
|
||||
gSep1:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||||
gSep1:SetVertexColor(T.sepColor[1], T.sepColor[2], T.sepColor[3], T.sepColor[4] or 0.4)
|
||||
gSep1:SetWidth(1)
|
||||
gSep1:SetHeight(tbH - 4)
|
||||
gSep1:SetPoint("LEFT", gearToolbar, "LEFT", segW + 1, 0)
|
||||
|
||||
local gEquipBtn = MakeGearToolBtn(gearToolbar, segW, "穿", segW + 1, "一键穿装", function() CP:QuickEquipLastSet() end)
|
||||
page.gEquipBtn = gEquipBtn
|
||||
|
||||
local gSep2 = gearToolbar:CreateTexture(nil, "OVERLAY")
|
||||
gSep2:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||||
gSep2:SetVertexColor(T.sepColor[1], T.sepColor[2], T.sepColor[3], T.sepColor[4] or 0.4)
|
||||
gSep2:SetWidth(1)
|
||||
gSep2:SetHeight(tbH - 4)
|
||||
gSep2:SetPoint("LEFT", gearToolbar, "LEFT", segW * 2 + 1, 0)
|
||||
|
||||
local gSetsBtn = MakeGearToolBtn(gearToolbar, segW, "案", segW * 2 + 1, "装备方案管理", function() CP:ToggleGearSetPopup() end)
|
||||
page.gSetsBtn = gSetsBtn
|
||||
|
||||
-- Equipment slots
|
||||
local slotY = -6
|
||||
page.equipSlots = {}
|
||||
@@ -2064,7 +2142,7 @@ function CP:BuildEquipmentPage()
|
||||
if gearC > 0 then CS.TipKV(" 装备暴击:", string.format("+%d%%", gearC)) end
|
||||
if talC > 0 then
|
||||
CS.TipKV(" 天赋暴击:", string.format("+%d%%", talC))
|
||||
for _, d in ipairs(CS.GetTalentDetailsFor("meleeCrit")) do
|
||||
for _, d in ipairs(CS.GetTalentDetailsFor("rangedCrit")) do
|
||||
CS.TipLine(string.format(" %s (%d/%d) +%d%%",
|
||||
d.name, d.rank, d.maxRank, d.bonus), 0.55,0.55,0.6)
|
||||
end
|
||||
@@ -2765,6 +2843,13 @@ function CP:CreateEquipSlot(parent, slotID, slotName)
|
||||
ilvlText:SetText("")
|
||||
frame.ilvlText = ilvlText
|
||||
|
||||
local durText = frame:CreateFontString(nil, "OVERLAY")
|
||||
durText:SetFont(GetFont(), 7, "OUTLINE")
|
||||
durText:SetPoint("TOPLEFT", frame, "TOPLEFT", 2, -2)
|
||||
durText:SetTextColor(0.4, 1, 0.4)
|
||||
durText:SetText("")
|
||||
frame.durText = durText
|
||||
|
||||
local glow = frame:CreateTexture(nil, "OVERLAY")
|
||||
glow:SetTexture("Interface\\Buttons\\UI-ActionButton-Border")
|
||||
glow:SetBlendMode("ADD")
|
||||
@@ -2822,7 +2907,7 @@ function CP:CreateEquipSlot(parent, slotID, slotName)
|
||||
CP:ShowSwapPopup(this)
|
||||
else
|
||||
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
||||
if GetInventoryItemLink("player", this.slotID) then
|
||||
if GetInventoryItemLink("player", this.slotID) or GetInventoryItemTexture("player", this.slotID) then
|
||||
GameTooltip:SetInventoryItem("player", this.slotID)
|
||||
else
|
||||
local label = SLOT_LABEL[this.slotName] or this.slotName
|
||||
@@ -2926,6 +3011,34 @@ function CP:UpdateEquipment()
|
||||
if slot then
|
||||
local tex = GetInventoryItemTexture("player", si.id)
|
||||
local link = GetInventoryItemLink("player", si.id)
|
||||
-- Ammo slot special: try tooltip-based detection when texture/link fail
|
||||
if not tex and si.name == "AmmoSlot" then
|
||||
if not CP._ammoTip then
|
||||
CP._ammoTip = CreateFrame("GameTooltip", "SFramesCPAmmoTip", UIParent, "GameTooltipTemplate")
|
||||
CP._ammoTip:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", -300, -300)
|
||||
end
|
||||
local tip = CP._ammoTip
|
||||
tip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
tip:ClearLines()
|
||||
tip:SetInventoryItem("player", si.id)
|
||||
local nLines = tip:NumLines() or 0
|
||||
if nLines > 0 then
|
||||
local txtObj = getglobal("SFramesCPAmmoTipTextLeft1")
|
||||
if txtObj then
|
||||
local ammoName = txtObj:GetText()
|
||||
if ammoName and ammoName ~= "" then
|
||||
-- Ammo is equipped but API can't return texture; use a generic icon
|
||||
tex = "Interface\\Icons\\INV_Ammo_Arrow_02"
|
||||
-- Try to get the real icon via GetItemInfo if available
|
||||
if GetItemInfo then
|
||||
local _, _, _, _, _, _, _, _, _, itemTex = GetItemInfo(ammoName)
|
||||
if itemTex then tex = itemTex end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
tip:Hide()
|
||||
end
|
||||
if tex then
|
||||
slot.icon:SetTexture(tex)
|
||||
slot.icon:SetVertexColor(1, 1, 1)
|
||||
@@ -2939,6 +3052,54 @@ function CP:UpdateEquipment()
|
||||
slot.ilvlText:SetText("")
|
||||
end
|
||||
end
|
||||
-- Durability display (tooltip scan for 1.12 clients)
|
||||
if slot.durText then
|
||||
local dur, durMax
|
||||
-- Try direct API first (pcall for safety)
|
||||
if GetInventoryItemDurability then
|
||||
local ok, c, m = pcall(GetInventoryItemDurability, si.id)
|
||||
if ok then dur, durMax = c, m end
|
||||
end
|
||||
-- Fallback: scan tooltip
|
||||
if not dur and link then
|
||||
if not CP._durTip then
|
||||
CP._durTip = CreateFrame("GameTooltip", "SFramesCPDurTip", UIParent, "GameTooltipTemplate")
|
||||
CP._durTip:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", -300, -300)
|
||||
end
|
||||
local tip = CP._durTip
|
||||
tip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
tip:ClearLines()
|
||||
tip:SetInventoryItem("player", si.id)
|
||||
local nLines = tip:NumLines() or 0
|
||||
for li = 1, nLines do
|
||||
local txtObj = getglobal("SFramesCPDurTipTextLeft" .. li)
|
||||
if txtObj then
|
||||
local line = txtObj:GetText()
|
||||
if line then
|
||||
local _, _, c, m = string.find(line, "(%d+)%s*/%s*(%d+)")
|
||||
if c and m then
|
||||
dur, durMax = tonumber(c), tonumber(m)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
tip:Hide()
|
||||
end
|
||||
if dur and durMax and durMax > 0 then
|
||||
local pct = math.floor(dur / durMax * 100)
|
||||
slot.durText:SetText(pct .. "%")
|
||||
if pct <= 25 then
|
||||
slot.durText:SetTextColor(1, 0.2, 0.2)
|
||||
elseif pct <= 50 then
|
||||
slot.durText:SetTextColor(1, 0.8, 0.2)
|
||||
else
|
||||
slot.durText:SetTextColor(0.4, 1, 0.4)
|
||||
end
|
||||
else
|
||||
slot.durText:SetText("")
|
||||
end
|
||||
end
|
||||
local quality = GetItemQualityFromLink(link)
|
||||
if quality and quality >= 2 and QUALITY_COLORS[quality] then
|
||||
local qc = QUALITY_COLORS[quality]
|
||||
@@ -2960,6 +3121,7 @@ function CP:UpdateEquipment()
|
||||
slot.currentBorderColor = nil
|
||||
slot.qualGlow:Hide()
|
||||
if slot.ilvlText then slot.ilvlText:SetText("") end
|
||||
if slot.durText then slot.durText:SetText("") end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3848,6 +4010,430 @@ function CP:UpdatePet()
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Gear Set Management: Strip / Equip / Save / Load / Delete
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- All equippable slot IDs (excluding shirt=4, tabard=19, ammo=0)
|
||||
local GEAR_SLOT_IDS = { 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }
|
||||
|
||||
-- One-click strip: unequip all gear into bags
|
||||
function CP:StripAllGear()
|
||||
-- Save current gear as "_lastStripped" before stripping
|
||||
self:SaveGearSetInternal("_lastStripped")
|
||||
local count = 0
|
||||
for _, sid in ipairs(GEAR_SLOT_IDS) do
|
||||
if GetInventoryItemLink("player", sid) then
|
||||
PickupInventoryItem(sid)
|
||||
PutItemInBackpack()
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if count > 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ccff[Nanami-UI]|r 已脱下 " .. count .. " 件装备")
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ccff[Nanami-UI]|r 当前没有可脱下的装备")
|
||||
end
|
||||
CP:ScheduleEquipUpdate()
|
||||
end
|
||||
|
||||
-- Internal: save current gear to DB
|
||||
function CP:SaveGearSetInternal(name)
|
||||
if not SFramesDB then SFramesDB = {} end
|
||||
if not SFramesDB.gearSets then SFramesDB.gearSets = {} end
|
||||
local set = {}
|
||||
for _, sid in ipairs(GEAR_SLOT_IDS) do
|
||||
local link = GetInventoryItemLink("player", sid)
|
||||
if link then
|
||||
set[sid] = link
|
||||
end
|
||||
end
|
||||
SFramesDB.gearSets[name] = set
|
||||
end
|
||||
|
||||
-- Save gear set with user-provided name
|
||||
function CP:SaveGearSet(name)
|
||||
if not name or name == "" then return end
|
||||
self:SaveGearSetInternal(name)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ccff[Nanami-UI]|r 装备方案 |cffffd100" .. name .. "|r 已保存")
|
||||
end
|
||||
|
||||
-- Load gear set by name
|
||||
function CP:LoadGearSet(name)
|
||||
if not SFramesDB or not SFramesDB.gearSets or not SFramesDB.gearSets[name] then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ccff[Nanami-UI]|r 找不到装备方案: " .. (name or "nil"))
|
||||
return
|
||||
end
|
||||
local set = SFramesDB.gearSets[name]
|
||||
local equipped = 0
|
||||
|
||||
-- Find item in bags by link matching (item:ID portion)
|
||||
local function FindInBags(targetLink)
|
||||
if not targetLink then return nil, nil end
|
||||
local _, _, targetId = string.find(targetLink, "item:(%d+)")
|
||||
if not targetId then return nil, nil end
|
||||
for bag = 0, 4 do
|
||||
local slots = GetContainerNumSlots(bag)
|
||||
if slots and slots > 0 then
|
||||
for slot = 1, slots do
|
||||
local bagLink = GetContainerItemLink(bag, slot)
|
||||
if bagLink then
|
||||
local _, _, bagId = string.find(bagLink, "item:(%d+)")
|
||||
if bagId == targetId then
|
||||
return bag, slot
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
for _, sid in ipairs(GEAR_SLOT_IDS) do
|
||||
local targetLink = set[sid]
|
||||
if targetLink then
|
||||
-- Check if already wearing this item
|
||||
local currentLink = GetInventoryItemLink("player", sid)
|
||||
if currentLink then
|
||||
local _, _, curId = string.find(currentLink, "item:(%d+)")
|
||||
local _, _, tarId = string.find(targetLink, "item:(%d+)")
|
||||
if curId == tarId then
|
||||
-- Already wearing, skip
|
||||
else
|
||||
local bag, slot = FindInBags(targetLink)
|
||||
if bag and slot then
|
||||
PickupContainerItem(bag, slot)
|
||||
PickupInventoryItem(sid)
|
||||
equipped = equipped + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
local bag, slot = FindInBags(targetLink)
|
||||
if bag and slot then
|
||||
PickupContainerItem(bag, slot)
|
||||
PickupInventoryItem(sid)
|
||||
equipped = equipped + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if equipped > 0 then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ccff[Nanami-UI]|r 已装备 " .. equipped .. " 件 (方案: |cffffd100" .. name .. "|r)")
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ccff[Nanami-UI]|r 方案 |cffffd100" .. name .. "|r 中的装备已全部穿戴或不在背包中")
|
||||
end
|
||||
CP:ScheduleEquipUpdate()
|
||||
end
|
||||
|
||||
-- Delete gear set
|
||||
function CP:DeleteGearSet(name)
|
||||
if not SFramesDB or not SFramesDB.gearSets then return end
|
||||
SFramesDB.gearSets[name] = nil
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ccff[Nanami-UI]|r 装备方案 |cffffd100" .. name .. "|r 已删除")
|
||||
end
|
||||
|
||||
-- Quick equip: load the "_lastStripped" auto-saved set
|
||||
function CP:QuickEquipLastSet()
|
||||
if SFramesDB and SFramesDB.gearSets and SFramesDB.gearSets["_lastStripped"] then
|
||||
self:LoadGearSet("_lastStripped")
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ccff[Nanami-UI]|r 没有最近脱下的装备记录,请先使用一键脱装或保存方案")
|
||||
end
|
||||
end
|
||||
|
||||
-- Get sorted list of user-created gear set names
|
||||
function CP:GetGearSetNames()
|
||||
local names = {}
|
||||
if SFramesDB and SFramesDB.gearSets then
|
||||
for k, _ in pairs(SFramesDB.gearSets) do
|
||||
if string.sub(k, 1, 1) ~= "_" then
|
||||
table.insert(names, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(names)
|
||||
return names
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Gear Set Popup UI
|
||||
--------------------------------------------------------------------------------
|
||||
local gearSetPopup
|
||||
|
||||
function CP:ToggleGearSetPopup()
|
||||
if gearSetPopup and gearSetPopup:IsShown() then
|
||||
gearSetPopup:Hide()
|
||||
return
|
||||
end
|
||||
self:ShowGearSetPopup()
|
||||
end
|
||||
|
||||
function CP:ShowGearSetPopup()
|
||||
if not panel then return end
|
||||
|
||||
local POPUP_W = 200
|
||||
local ROW_H = 20
|
||||
local PAD = 6
|
||||
|
||||
if not gearSetPopup then
|
||||
gearSetPopup = CreateFrame("Frame", "SFramesCPGearSetPopup", panel)
|
||||
gearSetPopup:SetWidth(POPUP_W)
|
||||
gearSetPopup:SetFrameStrata("TOOLTIP")
|
||||
gearSetPopup:SetFrameLevel(200)
|
||||
SetRoundBackdrop(gearSetPopup, T.bg, T.border)
|
||||
gearSetPopup:Hide()
|
||||
gearSetPopup:EnableMouse(true)
|
||||
|
||||
-- Title
|
||||
local title = MakeFS(gearSetPopup, 10, "CENTER", T.gold)
|
||||
title:SetPoint("TOP", gearSetPopup, "TOP", 0, -PAD)
|
||||
title:SetText("装备方案管理")
|
||||
gearSetPopup.title = title
|
||||
|
||||
-- Save current button
|
||||
local saveBtn = CreateFrame("Button", NextName("GSave"), gearSetPopup)
|
||||
saveBtn:SetWidth(POPUP_W - PAD * 2)
|
||||
saveBtn:SetHeight(ROW_H)
|
||||
saveBtn:SetPoint("TOP", gearSetPopup, "TOP", 0, -(PAD + 16))
|
||||
SetPixelBackdrop(saveBtn, { 0.15, 0.35, 0.15, 0.8 }, T.tabBorder)
|
||||
local saveTxt = MakeFS(saveBtn, 9, "CENTER", { 0.6, 1, 0.6 })
|
||||
saveTxt:SetPoint("CENTER", saveBtn, "CENTER", 0, 0)
|
||||
saveTxt:SetText("+ 保存当前装备为新方案")
|
||||
saveBtn.label = saveTxt
|
||||
saveBtn:SetScript("OnEnter", function()
|
||||
this:SetBackdropColor(0.2, 0.45, 0.2, 0.9)
|
||||
this.label:SetTextColor(0.8, 1, 0.8)
|
||||
end)
|
||||
saveBtn:SetScript("OnLeave", function()
|
||||
this:SetBackdropColor(0.15, 0.35, 0.15, 0.8)
|
||||
this.label:SetTextColor(0.6, 1, 0.6)
|
||||
end)
|
||||
saveBtn:SetScript("OnClick", function()
|
||||
CP:ShowGearSetNameInput()
|
||||
end)
|
||||
gearSetPopup.saveBtn = saveBtn
|
||||
|
||||
gearSetPopup.rows = {}
|
||||
end
|
||||
|
||||
-- Rebuild set list
|
||||
local names = self:GetGearSetNames()
|
||||
local numSets = table.getn(names)
|
||||
|
||||
-- Hide old rows
|
||||
for _, row in ipairs(gearSetPopup.rows) do
|
||||
row:Hide()
|
||||
end
|
||||
|
||||
local contentTop = -(PAD + 16 + ROW_H + 4)
|
||||
|
||||
for i = 1, numSets do
|
||||
local row = gearSetPopup.rows[i]
|
||||
if not row then
|
||||
row = CreateFrame("Frame", nil, gearSetPopup)
|
||||
row:SetWidth(POPUP_W - PAD * 2)
|
||||
row:SetHeight(ROW_H)
|
||||
|
||||
local bg = row:CreateTexture(nil, "BACKGROUND")
|
||||
bg:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||||
bg:SetVertexColor(0.12, 0.12, 0.16, 0.6)
|
||||
bg:SetAllPoints(row)
|
||||
row.bg = bg
|
||||
|
||||
local nameText = MakeFS(row, 9, "LEFT", T.nameText)
|
||||
nameText:SetPoint("LEFT", row, "LEFT", 6, 0)
|
||||
nameText:SetWidth(POPUP_W - PAD * 2 - 60)
|
||||
row.nameText = nameText
|
||||
|
||||
-- Load button
|
||||
local loadBtn = CreateFrame("Button", nil, row)
|
||||
loadBtn:SetWidth(24)
|
||||
loadBtn:SetHeight(ROW_H - 4)
|
||||
loadBtn:SetPoint("RIGHT", row, "RIGHT", -28, 0)
|
||||
loadBtn:SetFrameLevel(row:GetFrameLevel() + 1)
|
||||
SetPixelBackdrop(loadBtn, T.tabBg, T.tabBorder)
|
||||
local loadTxt = MakeFS(loadBtn, 8, "CENTER", { 0.5, 0.8, 1 })
|
||||
loadTxt:SetPoint("CENTER", loadBtn, "CENTER", 0, 0)
|
||||
loadTxt:SetText("穿")
|
||||
loadBtn.label = loadTxt
|
||||
loadBtn:SetScript("OnEnter", function()
|
||||
this:SetBackdropColor(T.tabActiveBg[1], T.tabActiveBg[2], T.tabActiveBg[3], 0.7)
|
||||
this.label:SetTextColor(0.7, 0.95, 1)
|
||||
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
||||
GameTooltip:AddLine("加载此方案", 1, 1, 1)
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
loadBtn:SetScript("OnLeave", function()
|
||||
this:SetBackdropColor(T.tabBg[1], T.tabBg[2], T.tabBg[3], T.tabBg[4])
|
||||
this.label:SetTextColor(0.5, 0.8, 1)
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
row.loadBtn = loadBtn
|
||||
|
||||
-- Delete button
|
||||
local delBtn = CreateFrame("Button", nil, row)
|
||||
delBtn:SetWidth(24)
|
||||
delBtn:SetHeight(ROW_H - 4)
|
||||
delBtn:SetPoint("RIGHT", row, "RIGHT", -2, 0)
|
||||
delBtn:SetFrameLevel(row:GetFrameLevel() + 1)
|
||||
SetPixelBackdrop(delBtn, { 0.35, 0.12, 0.12, 0.8 }, T.tabBorder)
|
||||
local delTxt = MakeFS(delBtn, 8, "CENTER", { 1, 0.5, 0.5 })
|
||||
delTxt:SetPoint("CENTER", delBtn, "CENTER", 0, 0)
|
||||
delTxt:SetText("X")
|
||||
delBtn.label = delTxt
|
||||
delBtn:SetScript("OnEnter", function()
|
||||
this:SetBackdropColor(0.5, 0.15, 0.15, 0.9)
|
||||
this.label:SetTextColor(1, 0.7, 0.7)
|
||||
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
||||
GameTooltip:AddLine("删除此方案", 1, 0.3, 0.3)
|
||||
GameTooltip:Show()
|
||||
end)
|
||||
delBtn:SetScript("OnLeave", function()
|
||||
this:SetBackdropColor(0.35, 0.12, 0.12, 0.8)
|
||||
this.label:SetTextColor(1, 0.5, 0.5)
|
||||
GameTooltip:Hide()
|
||||
end)
|
||||
row.delBtn = delBtn
|
||||
|
||||
gearSetPopup.rows[i] = row
|
||||
end
|
||||
|
||||
row:SetPoint("TOPLEFT", gearSetPopup, "TOPLEFT", PAD, contentTop - (i - 1) * (ROW_H + 2))
|
||||
row.nameText:SetText(names[i])
|
||||
row.setName = names[i]
|
||||
|
||||
row.loadBtn:SetScript("OnClick", function()
|
||||
CP:LoadGearSet(this:GetParent().setName)
|
||||
gearSetPopup:Hide()
|
||||
end)
|
||||
row.delBtn:SetScript("OnClick", function()
|
||||
CP:DeleteGearSet(this:GetParent().setName)
|
||||
CP:ShowGearSetPopup()
|
||||
end)
|
||||
|
||||
row:Show()
|
||||
end
|
||||
|
||||
-- Hide extra rows
|
||||
for i = numSets + 1, table.getn(gearSetPopup.rows) do
|
||||
gearSetPopup.rows[i]:Hide()
|
||||
end
|
||||
|
||||
local totalH = PAD + 16 + ROW_H + 4 + numSets * (ROW_H + 2) + PAD
|
||||
if totalH < 70 then totalH = 70 end
|
||||
gearSetPopup:SetHeight(totalH)
|
||||
|
||||
-- Position popup to the right of the panel
|
||||
gearSetPopup:ClearAllPoints()
|
||||
gearSetPopup:SetPoint("TOPLEFT", panel, "TOPRIGHT", 4, 0)
|
||||
gearSetPopup:Show()
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Gear Set Name Input Dialog
|
||||
--------------------------------------------------------------------------------
|
||||
local gearSetNameInput
|
||||
|
||||
function CP:ShowGearSetNameInput()
|
||||
if not panel then return end
|
||||
|
||||
if not gearSetNameInput then
|
||||
local f = CreateFrame("Frame", "SFramesCPGearSetNameInput", UIParent)
|
||||
f:SetWidth(240)
|
||||
f:SetHeight(90)
|
||||
f:SetPoint("CENTER", UIParent, "CENTER", 0, 100)
|
||||
f:SetFrameStrata("DIALOG")
|
||||
f:SetFrameLevel(250)
|
||||
SetRoundBackdrop(f, T.bg, T.border)
|
||||
f:EnableMouse(true)
|
||||
f:SetMovable(true)
|
||||
f:RegisterForDrag("LeftButton")
|
||||
f:SetScript("OnDragStart", function() this:StartMoving() end)
|
||||
f:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
|
||||
f:Hide()
|
||||
|
||||
local title = MakeFS(f, 10, "CENTER", T.gold)
|
||||
title:SetPoint("TOP", f, "TOP", 0, -8)
|
||||
title:SetText("输入方案名称")
|
||||
|
||||
local editBox = CreateFrame("EditBox", "SFramesCPGearSetEditBox", f)
|
||||
editBox:SetWidth(200)
|
||||
editBox:SetHeight(22)
|
||||
editBox:SetPoint("TOP", f, "TOP", 0, -28)
|
||||
editBox:SetFontObject(ChatFontNormal)
|
||||
editBox:SetAutoFocus(true)
|
||||
editBox:SetMaxLetters(30)
|
||||
SetPixelBackdrop(editBox, { 0.08, 0.08, 0.1, 0.9 }, T.tabBorder)
|
||||
editBox:SetTextInsets(6, 6, 2, 2)
|
||||
f.editBox = editBox
|
||||
|
||||
local okBtn = CreateFrame("Button", nil, f)
|
||||
okBtn:SetWidth(80)
|
||||
okBtn:SetHeight(20)
|
||||
okBtn:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 20, 8)
|
||||
SetPixelBackdrop(okBtn, { 0.15, 0.35, 0.15, 0.8 }, T.tabBorder)
|
||||
local okTxt = MakeFS(okBtn, 9, "CENTER", { 0.6, 1, 0.6 })
|
||||
okTxt:SetPoint("CENTER", okBtn, "CENTER", 0, 0)
|
||||
okTxt:SetText("保存")
|
||||
okBtn:SetScript("OnEnter", function()
|
||||
this:SetBackdropColor(0.2, 0.45, 0.2, 0.9)
|
||||
end)
|
||||
okBtn:SetScript("OnLeave", function()
|
||||
this:SetBackdropColor(0.15, 0.35, 0.15, 0.8)
|
||||
end)
|
||||
okBtn:SetScript("OnClick", function()
|
||||
local name = f.editBox:GetText()
|
||||
if name and name ~= "" then
|
||||
CP:SaveGearSet(name)
|
||||
f:Hide()
|
||||
if gearSetPopup and gearSetPopup:IsShown() then
|
||||
CP:ShowGearSetPopup()
|
||||
end
|
||||
end
|
||||
end)
|
||||
f.okBtn = okBtn
|
||||
|
||||
local cancelBtn = CreateFrame("Button", nil, f)
|
||||
cancelBtn:SetWidth(80)
|
||||
cancelBtn:SetHeight(20)
|
||||
cancelBtn:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -20, 8)
|
||||
SetPixelBackdrop(cancelBtn, { 0.35, 0.12, 0.12, 0.8 }, T.tabBorder)
|
||||
local cancelTxt = MakeFS(cancelBtn, 9, "CENTER", { 1, 0.6, 0.6 })
|
||||
cancelTxt:SetPoint("CENTER", cancelBtn, "CENTER", 0, 0)
|
||||
cancelTxt:SetText("取消")
|
||||
cancelBtn:SetScript("OnEnter", function()
|
||||
this:SetBackdropColor(0.45, 0.15, 0.15, 0.9)
|
||||
end)
|
||||
cancelBtn:SetScript("OnLeave", function()
|
||||
this:SetBackdropColor(0.35, 0.12, 0.12, 0.8)
|
||||
end)
|
||||
cancelBtn:SetScript("OnClick", function()
|
||||
f:Hide()
|
||||
end)
|
||||
f.cancelBtn = cancelBtn
|
||||
|
||||
editBox:SetScript("OnEnterPressed", function()
|
||||
local name = this:GetText()
|
||||
if name and name ~= "" then
|
||||
CP:SaveGearSet(name)
|
||||
f:Hide()
|
||||
if gearSetPopup and gearSetPopup:IsShown() then
|
||||
CP:ShowGearSetPopup()
|
||||
end
|
||||
end
|
||||
end)
|
||||
editBox:SetScript("OnEscapePressed", function()
|
||||
f:Hide()
|
||||
end)
|
||||
|
||||
gearSetNameInput = f
|
||||
end
|
||||
|
||||
gearSetNameInput.editBox:SetText("")
|
||||
gearSetNameInput:Show()
|
||||
gearSetNameInput.editBox:SetFocus()
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Events
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user