mirror of
https://github.com/Lacustat/Freewood-OctoWoW-Loot.git
synced 2026-11-09 03:19:02 +00:00
Freewood-OctoWoW-Loot 0.1.136
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016onJCSHLwhs9udhC9ZLzk9
This commit is contained in:
+413
@@ -0,0 +1,413 @@
|
||||
-- Freewood-OctoWoW-Loot: Tab "Beute" und Einstellungsabschnitt
|
||||
-- Links die Blacklist, rechts Hinzufuegen, Zuletzt erhalten und das Protokoll der geloeschten Items.
|
||||
|
||||
local ADDON, NS = ...
|
||||
|
||||
local FW = _G.Freewood
|
||||
local Loot = NS.Loot
|
||||
if not FW or not Loot then
|
||||
return
|
||||
end
|
||||
|
||||
local UI = FW.UI
|
||||
|
||||
local LIST_W = 380
|
||||
local ROW_H, ROW_GAP = 38, 4
|
||||
local SMALL_H = 30
|
||||
|
||||
local function ColoredName(name, quality, id)
|
||||
local text = name or ("#" .. tostring(id))
|
||||
return "|cff" .. UI.RarityHex(quality) .. text .. "|r"
|
||||
end
|
||||
|
||||
local function ListRow(parent)
|
||||
local row = UI.CreatePanel(parent, "card", "bronze")
|
||||
row:SetHeight(ROW_H)
|
||||
row.icon = row:CreateTexture(nil, "ARTWORK")
|
||||
row.icon:SetSize(28, 28)
|
||||
row.icon:SetPoint("LEFT", row, "LEFT", 6, 0)
|
||||
row.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
||||
row.name = UI.CreateLabel(row, "", { size = 12 })
|
||||
row.name:SetPoint("LEFT", row.icon, "RIGHT", 10, 0)
|
||||
row.name:SetPoint("RIGHT", row, "RIGHT", -112, 0)
|
||||
row.name:SetWordWrap(false)
|
||||
row.idLabel = UI.CreateLabel(row, "", { size = 10, color = "textDim", justify = "RIGHT" })
|
||||
row.idLabel:SetPoint("RIGHT", row, "RIGHT", -40, 0)
|
||||
row.remove = UI.CreateButton(row, "X", 26, 24, nil, "danger")
|
||||
row.remove:SetPoint("RIGHT", row, "RIGHT", -6, 0)
|
||||
UI.AttachTooltip(row.remove, function() return FW.L.LOOT_REMOVE end, "")
|
||||
-- Tooltip des Items beim Darueberfahren
|
||||
row:EnableMouse(true)
|
||||
row:SetScript("OnEnter", function(self)
|
||||
if self.itemID and GameTooltip then
|
||||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||||
pcall(GameTooltip.SetItemByID, GameTooltip, self.itemID)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end)
|
||||
row:SetScript("OnLeave", function()
|
||||
if GameTooltip then GameTooltip:Hide() end
|
||||
end)
|
||||
return row
|
||||
end
|
||||
|
||||
-- Setzt Symbol und Name einer Zeile (die Item-Daten koennen verzoegert kommen)
|
||||
local function FillItem(row, id, fallbackName)
|
||||
row.itemID = id
|
||||
row.icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
|
||||
row.name:SetText(ColoredName(fallbackName, 1, id))
|
||||
FW.Util.RequestItem(id, function(info)
|
||||
if row.itemID ~= id or not info then
|
||||
return
|
||||
end
|
||||
row.icon:SetTexture(info.icon)
|
||||
row.name:SetText(ColoredName(info.name, info.quality, id))
|
||||
end)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Tab
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local function Build(content)
|
||||
local L = FW.L
|
||||
local f = CreateFrame("Frame", nil, content)
|
||||
|
||||
local listRows, recentRows, logRows = {}, {}, {}
|
||||
|
||||
---------------- links: Blacklist ----------------
|
||||
local listTitle = UI.CreateLabel(f, L.LOOT_LIST_HEADER, { font = "heading", size = 14, color = "goldLight" })
|
||||
listTitle:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
|
||||
local pendingLabel = UI.CreateLabel(f, "", { size = 11, color = "textDim", justify = "RIGHT" })
|
||||
pendingLabel:SetPoint("TOPRIGHT", f, "TOPLEFT", LIST_W, -4)
|
||||
local listDivider = UI.CreateDivider(f)
|
||||
listDivider:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -26)
|
||||
listDivider:SetWidth(LIST_W)
|
||||
|
||||
local listScroll = UI.CreateScrollFrame(f)
|
||||
listScroll:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -36)
|
||||
listScroll:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 0)
|
||||
listScroll:SetWidth(LIST_W)
|
||||
|
||||
local listEmpty = UI.CreateLabel(listScroll.child, L.LOOT_LIST_EMPTY, { size = 12, color = "textDim", justifyV = "TOP" })
|
||||
listEmpty:SetPoint("TOPLEFT", listScroll.child, "TOPLEFT", 4, -6)
|
||||
listEmpty:SetPoint("TOPRIGHT", listScroll.child, "TOPRIGHT", -4, -6)
|
||||
listEmpty:SetWordWrap(true)
|
||||
|
||||
local separator = f:CreateTexture(nil, "ARTWORK")
|
||||
separator:SetColorTexture(UI.Color("bronze", 0.5))
|
||||
separator:SetWidth(1)
|
||||
separator:SetPoint("TOPLEFT", f, "TOPLEFT", LIST_W + 10, 0)
|
||||
separator:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", LIST_W + 10, 0)
|
||||
|
||||
---------------- rechts ----------------
|
||||
local right = CreateFrame("Frame", nil, f)
|
||||
right:SetPoint("TOPLEFT", f, "TOPLEFT", LIST_W + 22, 0)
|
||||
right:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0)
|
||||
|
||||
local addTitle = UI.CreateLabel(right, L.LOOT_ADD_HEADER, { font = "heading", size = 14, color = "goldLight" })
|
||||
addTitle:SetPoint("TOPLEFT", right, "TOPLEFT", 0, 0)
|
||||
local addDivider = UI.CreateDivider(right)
|
||||
addDivider:SetPoint("TOPLEFT", right, "TOPLEFT", 0, -26)
|
||||
addDivider:SetPoint("TOPRIGHT", right, "TOPRIGHT", 0, -26)
|
||||
|
||||
local status = UI.CreateLabel(right, "", { size = 11, color = "textDim" })
|
||||
local function SetStatus(text, colorKey)
|
||||
status:SetText(text or "")
|
||||
status:SetTextColor(UI.Color(colorKey or "textDim"))
|
||||
end
|
||||
local function TryAdd(input)
|
||||
local ok, result = Loot:Add(input)
|
||||
if ok then
|
||||
local info = FW.Util.GetItem and FW.Util.GetItem(result)
|
||||
SetStatus(string.format(FW.L.LOOT_ADD_OK, (info and info.name) or ("#" .. result)), "success")
|
||||
return true
|
||||
end
|
||||
if result == "already" then
|
||||
SetStatus(FW.L.LOOT_ADD_ALREADY, "goldLight")
|
||||
elseif result == "full" then
|
||||
SetStatus(FW.L.LOOT_ADD_FULL, "danger")
|
||||
else
|
||||
SetStatus(FW.L.LOOT_ADD_INVALID, "danger")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Ablagefeld fuer Items aus der Tasche
|
||||
local drop = UI.CreateItemSlot(right, 44)
|
||||
drop:SetPoint("TOPLEFT", right, "TOPLEFT", 0, -38)
|
||||
drop:EnableMouse(true)
|
||||
local function OnDrop()
|
||||
local kind, id = GetCursorInfo()
|
||||
if kind == "item" then
|
||||
ClearCursor()
|
||||
TryAdd(id)
|
||||
end
|
||||
end
|
||||
drop:SetScript("OnReceiveDrag", OnDrop)
|
||||
drop:SetScript("OnMouseUp", OnDrop)
|
||||
local dropLabel = UI.CreateLabel(right, L.LOOT_ADD_DROP, { size = 12, color = "textDim" })
|
||||
dropLabel:SetPoint("LEFT", drop, "RIGHT", 12, 0)
|
||||
|
||||
-- Eingabefeld
|
||||
local box = UI.CreatePanel(right, "bgDeep", "bronze")
|
||||
box:SetHeight(26)
|
||||
box:SetPoint("TOPLEFT", right, "TOPLEFT", 0, -92)
|
||||
box:SetPoint("TOPRIGHT", right, "TOPRIGHT", -118, -92)
|
||||
local edit = CreateFrame("EditBox", nil, box)
|
||||
edit:SetAutoFocus(false)
|
||||
edit:SetPoint("TOPLEFT", box, "TOPLEFT", 8, -2)
|
||||
edit:SetPoint("BOTTOMRIGHT", box, "BOTTOMRIGHT", -8, 2)
|
||||
edit:SetMaxLetters(200)
|
||||
if not edit:SetFont(UI.GetFontPath("body"), 12, "") then
|
||||
edit:SetFont("Fonts\\FRIZQT__.TTF", 12, "")
|
||||
end
|
||||
edit:SetTextColor(UI.Color("text"))
|
||||
edit:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
|
||||
local function Submit()
|
||||
local text = edit:GetText()
|
||||
if text and text ~= "" and TryAdd(text) then
|
||||
edit:SetText("")
|
||||
edit:ClearFocus()
|
||||
end
|
||||
end
|
||||
edit:SetScript("OnEnterPressed", Submit)
|
||||
local boxHint = UI.CreateLabel(box, L.LOOT_ADD_BOX, { size = 12, color = "textDim" })
|
||||
boxHint:SetPoint("LEFT", box, "LEFT", 10, 0)
|
||||
edit:SetScript("OnTextChanged", function(self)
|
||||
if self:GetText() == "" then boxHint:Show() else boxHint:Hide() end
|
||||
end)
|
||||
local addButton = UI.CreateButton(right, L.LOOT_ADD_BUTTON, 110, 26, Submit, "primary")
|
||||
addButton:SetPoint("TOPRIGHT", right, "TOPRIGHT", 0, -92)
|
||||
|
||||
-- Shift-Klick auf Item-Links in unser Feld
|
||||
local function InsertLink(link)
|
||||
if type(link) == "string" and edit:HasFocus() then
|
||||
edit:Insert(link)
|
||||
end
|
||||
end
|
||||
if hooksecurefunc then
|
||||
if _G.ChatEdit_InsertLink then
|
||||
hooksecurefunc("ChatEdit_InsertLink", InsertLink)
|
||||
elseif _G.ChatFrameUtil and _G.ChatFrameUtil.InsertLink then
|
||||
hooksecurefunc(_G.ChatFrameUtil, "InsertLink", InsertLink)
|
||||
end
|
||||
end
|
||||
|
||||
local hint = UI.CreateLabel(right, L.LOOT_ADD_HINT, { size = 11, color = "textDim", justifyV = "TOP" })
|
||||
hint:SetPoint("TOPLEFT", right, "TOPLEFT", 0, -126)
|
||||
hint:SetPoint("TOPRIGHT", right, "TOPRIGHT", 0, -126)
|
||||
hint:SetHeight(28)
|
||||
hint:SetWordWrap(true)
|
||||
status:SetPoint("TOPLEFT", right, "TOPLEFT", 0, -156)
|
||||
status:SetPoint("TOPRIGHT", right, "TOPRIGHT", 0, -156)
|
||||
status:SetWordWrap(false)
|
||||
|
||||
-- Zuletzt erhalten
|
||||
local recentTitle = UI.CreateLabel(right, L.LOOT_RECENT_HEADER, { font = "heading", size = 14, color = "goldLight" })
|
||||
recentTitle:SetPoint("TOPLEFT", right, "TOPLEFT", 0, -182)
|
||||
local recentDivider = UI.CreateDivider(right)
|
||||
recentDivider:SetPoint("TOPLEFT", right, "TOPLEFT", 0, -206)
|
||||
recentDivider:SetPoint("TOPRIGHT", right, "TOPRIGHT", 0, -206)
|
||||
local recentScroll = UI.CreateScrollFrame(right)
|
||||
recentScroll:SetPoint("TOPLEFT", right, "TOPLEFT", 0, -214)
|
||||
recentScroll:SetPoint("BOTTOMRIGHT", right, "BOTTOMRIGHT", 0, 164)
|
||||
local recentEmpty = UI.CreateLabel(recentScroll.child, L.LOOT_RECENT_EMPTY, { size = 12, color = "textDim" })
|
||||
recentEmpty:SetPoint("TOPLEFT", recentScroll.child, "TOPLEFT", 4, -6)
|
||||
|
||||
-- Protokoll
|
||||
local logTitle = UI.CreateLabel(right, L.LOOT_LOG_HEADER, { font = "heading", size = 14, color = "goldLight" })
|
||||
logTitle:SetPoint("BOTTOMLEFT", right, "BOTTOMLEFT", 0, 134)
|
||||
local logDivider = UI.CreateDivider(right)
|
||||
logDivider:SetPoint("BOTTOMLEFT", right, "BOTTOMLEFT", 0, 128)
|
||||
logDivider:SetPoint("BOTTOMRIGHT", right, "BOTTOMRIGHT", 0, 128)
|
||||
local logScroll = UI.CreateScrollFrame(right)
|
||||
logScroll:SetPoint("BOTTOMLEFT", right, "BOTTOMLEFT", 0, 0)
|
||||
logScroll:SetPoint("BOTTOMRIGHT", right, "BOTTOMRIGHT", 0, 0)
|
||||
logScroll:SetHeight(120)
|
||||
local logEmpty = UI.CreateLabel(logScroll.child, L.LOOT_LOG_EMPTY, { size = 12, color = "textDim" })
|
||||
logEmpty:SetPoint("TOPLEFT", logScroll.child, "TOPLEFT", 4, -6)
|
||||
|
||||
---------------- Aktualisieren ----------------
|
||||
local function RefreshList()
|
||||
local list = Loot:List()
|
||||
for i, entry in ipairs(list) do local entry = entry
|
||||
local row = listRows[i]
|
||||
if not row then
|
||||
row = ListRow(listScroll.child)
|
||||
listRows[i] = row
|
||||
end
|
||||
row:ClearAllPoints()
|
||||
local y = (i - 1) * (ROW_H + ROW_GAP)
|
||||
row:SetPoint("TOPLEFT", listScroll.child, "TOPLEFT", 0, -y)
|
||||
row:SetPoint("TOPRIGHT", listScroll.child, "TOPRIGHT", 0, -y)
|
||||
FillItem(row, entry.id, entry.name)
|
||||
row.idLabel:SetText(tostring(entry.id))
|
||||
row.remove:SetScript("OnClick", function()
|
||||
Loot:Remove(entry.id)
|
||||
end)
|
||||
row:Show()
|
||||
end
|
||||
for i = #list + 1, #listRows do
|
||||
listRows[i]:Hide()
|
||||
end
|
||||
listEmpty:SetShown(#list == 0)
|
||||
listScroll:SetContentHeight(#list * (ROW_H + ROW_GAP))
|
||||
local pending = Loot:PendingCount()
|
||||
pendingLabel:SetText(pending > 0 and string.format(FW.L.LOOT_PENDING, pending) or "")
|
||||
end
|
||||
|
||||
local function RefreshRecent()
|
||||
local recent = Loot.chardb.recent
|
||||
for i, entry in ipairs(recent) do local entry = entry
|
||||
local row = recentRows[i]
|
||||
if not row then
|
||||
row = UI.CreatePanel(recentScroll.child, "card", "bronze")
|
||||
row:SetHeight(SMALL_H)
|
||||
row.icon = row:CreateTexture(nil, "ARTWORK")
|
||||
row.icon:SetSize(22, 22)
|
||||
row.icon:SetPoint("LEFT", row, "LEFT", 5, 0)
|
||||
row.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
||||
row.name = UI.CreateLabel(row, "", { size = 12 })
|
||||
row.name:SetPoint("LEFT", row.icon, "RIGHT", 8, 0)
|
||||
row.name:SetWordWrap(false)
|
||||
row.add = UI.CreateButton(row, FW.L.LOOT_RECENT_ADD, 84, 22, nil, "default")
|
||||
row.add:SetPoint("RIGHT", row, "RIGHT", -4, 0)
|
||||
row.listed = UI.CreateLabel(row, FW.L.LOOT_RECENT_LISTED, { size = 10, color = "textDim", justify = "RIGHT" })
|
||||
row.listed:SetPoint("RIGHT", row, "RIGHT", -12, 0)
|
||||
row.name:SetPoint("RIGHT", row, "RIGHT", -96, 0)
|
||||
recentRows[i] = row
|
||||
end
|
||||
row:ClearAllPoints()
|
||||
local y = (i - 1) * (SMALL_H + 4)
|
||||
row:SetPoint("TOPLEFT", recentScroll.child, "TOPLEFT", 0, -y)
|
||||
row:SetPoint("TOPRIGHT", recentScroll.child, "TOPRIGHT", 0, -y)
|
||||
FillItem(row, entry.id)
|
||||
local listed = Loot:IsListed(entry.id)
|
||||
row.add:SetShown(not listed)
|
||||
row.listed:SetShown(listed)
|
||||
row.add:SetScript("OnClick", function()
|
||||
TryAdd(entry.id)
|
||||
end)
|
||||
row:Show()
|
||||
end
|
||||
for i = #recent + 1, #recentRows do
|
||||
recentRows[i]:Hide()
|
||||
end
|
||||
recentEmpty:SetShown(#recent == 0)
|
||||
recentScroll:SetContentHeight(#recent * (SMALL_H + 4))
|
||||
end
|
||||
|
||||
local function RefreshLog()
|
||||
local log = Loot.chardb.log
|
||||
for i, entry in ipairs(log) do
|
||||
local line = logRows[i]
|
||||
if not line then
|
||||
line = UI.CreateLabel(logScroll.child, "", { size = 11 })
|
||||
logRows[i] = line
|
||||
end
|
||||
line:ClearAllPoints()
|
||||
line:SetPoint("TOPLEFT", logScroll.child, "TOPLEFT", 4, -((i - 1) * 18 + 4))
|
||||
line:SetPoint("TOPRIGHT", logScroll.child, "TOPRIGHT", -4, -((i - 1) * 18 + 4))
|
||||
line:SetWordWrap(false)
|
||||
line:SetText(string.format(FW.L.LOOT_LOG_LINE, date("%H:%M", entry.t or 0), entry.name or "?", entry.count or 1))
|
||||
line:Show()
|
||||
end
|
||||
for i = #log + 1, #logRows do
|
||||
logRows[i]:Hide()
|
||||
end
|
||||
logEmpty:SetShown(#log == 0)
|
||||
logScroll:SetContentHeight(#log * 18 + 8)
|
||||
end
|
||||
|
||||
function f.Refresh()
|
||||
RefreshList()
|
||||
RefreshRecent()
|
||||
RefreshLog()
|
||||
end
|
||||
|
||||
local function IfShown(fn)
|
||||
return function()
|
||||
if f:IsShown() then
|
||||
fn()
|
||||
end
|
||||
end
|
||||
end
|
||||
FW:On("LOOT_LIST_CHANGED", IfShown(function() f.Refresh() end), f)
|
||||
FW:On("LOOT_PENDING_CHANGED", IfShown(RefreshList), f)
|
||||
FW:On("LOOT_RECENT_CHANGED", IfShown(RefreshRecent), f)
|
||||
FW:On("LOOT_LOG_CHANGED", IfShown(RefreshLog), f)
|
||||
|
||||
return f
|
||||
end
|
||||
|
||||
UI:RegisterTab("loot", {
|
||||
label = function()
|
||||
return FW.L.LOOT_TAB
|
||||
end,
|
||||
order = 70,
|
||||
build = Build,
|
||||
onShow = function(f)
|
||||
Loot:Scan()
|
||||
f.Refresh()
|
||||
end,
|
||||
})
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Einstellungen
|
||||
------------------------------------------------------------------------
|
||||
|
||||
if UI.RegisterSettingsSection then
|
||||
UI:RegisterSettingsSection("loot", {
|
||||
order = 110,
|
||||
height = 180,
|
||||
build = function(parent)
|
||||
local L = FW.L
|
||||
local f, stack = UI.CreateSection(parent, L.LOOT_SET_HEADER)
|
||||
|
||||
local boxes = {}
|
||||
local defs = {
|
||||
{ key = "enabled", label = L.LOOT_SET_ENABLED },
|
||||
{ key = "autoLoot", label = L.LOOT_SET_AUTOLOOT },
|
||||
{ key = "chat", label = L.LOOT_SET_CHAT },
|
||||
}
|
||||
for _, def in ipairs(defs) do local def = def
|
||||
local cb = UI.CreateCheckbox(f, def.label, function()
|
||||
return Loot.db.settings[def.key]
|
||||
end, function(value)
|
||||
Loot.db.settings[def.key] = value and true or false
|
||||
end)
|
||||
stack:Add(cb, { fit = true, gap = 4 })
|
||||
boxes[#boxes + 1] = cb
|
||||
end
|
||||
|
||||
local note = UI.CreateLabel(f, L.LOOT_SET_NOTE, { size = 11, color = "textDim", justifyV = "TOP" })
|
||||
stack:Add(note, { fit = true, gap = 10 })
|
||||
|
||||
function f.Refresh()
|
||||
for _, cb in ipairs(boxes) do
|
||||
cb:Refresh()
|
||||
end
|
||||
end
|
||||
stack:Layout()
|
||||
return f
|
||||
end,
|
||||
refresh = function(frame)
|
||||
frame.Refresh()
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Befehl
|
||||
------------------------------------------------------------------------
|
||||
|
||||
SLASH_FREEWOODLOOT1 = "/fwloot"
|
||||
SlashCmdList["FREEWOODLOOT"] = function(msg)
|
||||
msg = (msg or ""):lower():match("^%s*(.-)%s*$")
|
||||
if msg == "test" then
|
||||
Loot:RunTest()
|
||||
else
|
||||
UI:Toggle("loot")
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user