421 lines
14 KiB
Lua
421 lines
14 KiB
Lua
-- 1. Persistent Data & Session Initialization
|
|
FarmTrackerDB = FarmTrackerDB or {
|
|
items = {2840, 2841, 2770},
|
|
locked = false,
|
|
goal = 0,
|
|
pos = nil,
|
|
scale = 1.0
|
|
}
|
|
local sessionStartCounts = {}
|
|
local startTime = GetTime()
|
|
local isInitialized = false
|
|
local hoverButtons = {}
|
|
local goalReachedSoundPlayed = false
|
|
|
|
-- 2. Create the Main Tracker Frame
|
|
local f = CreateFrame("Frame", "FarmTrackerFrame", UIParent, "BackdropTemplate")
|
|
f:SetSize(280, 100)
|
|
f:SetFrameStrata("MEDIUM")
|
|
f:SetMovable(true)
|
|
f:EnableMouse(true)
|
|
f:RegisterForDrag("LeftButton")
|
|
|
|
local function SavePosition(self)
|
|
local point, _, relativePoint, xOfs, yOfs = self:GetPoint()
|
|
FarmTrackerDB.pos = {
|
|
point = point,
|
|
relativePoint = relativePoint,
|
|
x = xOfs,
|
|
y = yOfs
|
|
}
|
|
end
|
|
|
|
f:SetScript("OnDragStart", f.StartMoving)
|
|
f:SetScript("OnDragStop", function(self)
|
|
self:StopMovingOrSizing()
|
|
SavePosition(self)
|
|
end)
|
|
|
|
f:SetBackdrop({
|
|
bgFile = "Interface/Tooltips/UI-Tooltip-Background",
|
|
edgeFile = "Interface/Buttons/WHITE8x8",
|
|
tile = true,
|
|
tileSize = 16,
|
|
edgeSize = 1,
|
|
insets = {
|
|
left = 2,
|
|
right = 2,
|
|
top = 2,
|
|
bottom = 2
|
|
}
|
|
})
|
|
f:SetBackdropColor(0.20,0.20,0.20,1);
|
|
|
|
f.title = f:CreateFontString(nil, "OVERLAY")
|
|
f.title:SetFont("Interface\\Addons\\MxW\\Media\\Font\\Consola.ttf", 14);
|
|
f.title:SetPoint("TOP", f, "TOP", 0, -10)
|
|
f.title:SetTextColor(1.00,0.49,0.04);
|
|
f.title:SetText("MxW.Farm")
|
|
|
|
f.statsText = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
|
f.statsText:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 12, 12)
|
|
f.statsText:SetJustifyH("LEFT")
|
|
|
|
f.text = f:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
|
|
f.text:SetPoint("BOTTOMLEFT", f.statsText, "TOPLEFT", 0, 10)
|
|
f.text:SetJustifyH("LEFT")
|
|
|
|
-- Buttons: Reset & Manager Toggle
|
|
f.resetBtn = CreateFrame("Button", nil, f)
|
|
f.resetBtn:SetSize(18, 18)
|
|
f.resetBtn:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -10, 10)
|
|
f.resetBtn:SetNormalTexture("Interface\\Buttons\\UI-RefreshButton")
|
|
f.resetBtn:SetScript("OnClick", function()
|
|
for _, id in ipairs(FarmTrackerDB.items) do
|
|
sessionStartCounts[id] = GetItemCount(id, true)
|
|
end
|
|
startTime = GetTime()
|
|
goalReachedSoundPlayed = false
|
|
RefreshDisplay()
|
|
print("|cFF00FF00MxW.Farm:|r Session reset for " .. UnitName("player"))
|
|
end)
|
|
|
|
f.configBtn = CreateFrame("Button", nil, f)
|
|
f.configBtn:SetSize(18, 18)
|
|
f.configBtn:SetPoint("TOPRIGHT", f, "TOPRIGHT", -8, -8)
|
|
f.configBtn:SetNormalTexture("Interface\\Buttons\\UI-OptionsButton")
|
|
f.configBtn:SetScript("OnClick", function()
|
|
if FarmTrackerManager:IsShown() then
|
|
FarmTrackerManager:Hide()
|
|
else
|
|
FarmTrackerManager:Show()
|
|
end
|
|
end)
|
|
|
|
-- 3. The SCROLLABLE Management UI (Drag & Drop)
|
|
local m = CreateFrame("Frame", "FarmTrackerManager", UIParent, "BackdropTemplate")
|
|
m:SetSize(320, 420)
|
|
m:SetPoint("CENTER")
|
|
m:SetFrameStrata("HIGH")
|
|
m:SetMovable(true)
|
|
m:EnableMouse(true)
|
|
m:RegisterForDrag("LeftButton")
|
|
m:SetScript("OnDragStart", m.StartMoving)
|
|
m:SetScript("OnDragStop", m.StopMovingOrSizing)
|
|
m:SetBackdrop(f:GetBackdrop())
|
|
m:SetBackdropColor(0, 0, 0, 1)
|
|
m:Hide()
|
|
|
|
local function AddItemToList(id)
|
|
if not id then
|
|
return
|
|
end
|
|
local found = false
|
|
for _, existing in ipairs(FarmTrackerDB.items) do
|
|
if existing == id then
|
|
found = true
|
|
end
|
|
end
|
|
if not found then
|
|
table.insert(FarmTrackerDB.items, id)
|
|
sessionStartCounts[id] = GetItemCount(id, true)
|
|
C_Item.RequestLoadItemDataByID(id)
|
|
UpdateManagerList()
|
|
RefreshDisplay()
|
|
end
|
|
end
|
|
|
|
m:SetScript("OnReceiveDrag", function()
|
|
local infoType, itemID = GetCursorInfo()
|
|
if infoType == "item" then
|
|
AddItemToList(itemID)
|
|
ClearCursor()
|
|
end
|
|
end)
|
|
|
|
m:SetScript("OnUpdate", function(self)
|
|
if GetCursorInfo() == "item" and MouseIsOver(self) then
|
|
self:SetBackdropBorderColor(0, 1, 0, 1)
|
|
else
|
|
self:SetBackdropBorderColor(1, 1, 1, 1)
|
|
end
|
|
end)
|
|
|
|
m.title = m:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
|
m.title:SetPoint("TOPLEFT", m, "TOPLEFT", 15, -15)
|
|
m.title:SetText("Manage Materials")
|
|
|
|
m.desc = m:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
|
|
m.desc:SetPoint("TOPLEFT", m.title, "BOTTOMLEFT", 0, -2)
|
|
m.desc:SetText("Drag & drop items here to add them")
|
|
|
|
m.close = CreateFrame("Button", nil, m, "UIPanelCloseButton")
|
|
m.close:SetPoint("TOPRIGHT", m, "TOPRIGHT", -5, -5)
|
|
|
|
local scrollFrame = CreateFrame("ScrollFrame", "FTManagerScrollFrame", m, "UIPanelScrollFrameTemplate")
|
|
scrollFrame:SetPoint("TOPLEFT", m, "TOPLEFT", 10, -60)
|
|
scrollFrame:SetPoint("BOTTOMRIGHT", m, "BOTTOMRIGHT", -30, 60)
|
|
|
|
local scrollChild = CreateFrame("Frame")
|
|
scrollChild:SetSize(270, 1)
|
|
scrollFrame:SetScrollChild(scrollChild)
|
|
|
|
local itemRows = {}
|
|
|
|
function UpdateManagerList()
|
|
for _, row in ipairs(itemRows) do
|
|
row:Hide()
|
|
end
|
|
|
|
for i, id in ipairs(FarmTrackerDB.items) do
|
|
if not itemRows[i] then
|
|
local row = CreateFrame("Frame", nil, scrollChild)
|
|
row:SetSize(270, 26)
|
|
|
|
-- Item Text
|
|
row.text = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
|
|
row.text:SetPoint("LEFT", row, "LEFT", 45, 0) -- Pushed right to fit arrows
|
|
row.text:SetWidth(180)
|
|
row.text:SetJustifyH("LEFT")
|
|
|
|
-- Remove Button
|
|
row.remove = CreateFrame("Button", nil, row)
|
|
row.remove:SetSize(16, 16)
|
|
row.remove:SetPoint("RIGHT", row, "RIGHT", -2, 0)
|
|
row.remove:SetNormalTexture("Interface\\Buttons\\UI-GroupLoot-Pass-Up")
|
|
|
|
-- UP Arrow
|
|
row.up = CreateFrame("Button", nil, row)
|
|
row.up:SetSize(16, 16)
|
|
row.up:SetPoint("LEFT", row, "LEFT", 5, 0)
|
|
row.up:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollUpButton-Up")
|
|
|
|
-- DOWN Arrow
|
|
row.down = CreateFrame("Button", nil, row)
|
|
row.down:SetSize(16, 16)
|
|
row.down:SetPoint("LEFT", row.up, "RIGHT", 2, 0)
|
|
row.down:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up")
|
|
|
|
itemRows[i] = row
|
|
end
|
|
|
|
local _, link = GetItemInfo(id)
|
|
local row = itemRows[i]
|
|
row.text:SetText(link or "Loading ID: " .. id)
|
|
|
|
-- Logic: Move Up
|
|
row.up:SetScript("OnClick", function()
|
|
if i > 1 then
|
|
local temp = FarmTrackerDB.items[i - 1]
|
|
FarmTrackerDB.items[i - 1] = FarmTrackerDB.items[i]
|
|
FarmTrackerDB.items[i] = temp
|
|
UpdateManagerList()
|
|
RefreshDisplay()
|
|
end
|
|
end)
|
|
|
|
-- Logic: Move Down
|
|
row.down:SetScript("OnClick", function()
|
|
if i < #FarmTrackerDB.items then
|
|
local temp = FarmTrackerDB.items[i + 1]
|
|
FarmTrackerDB.items[i + 1] = FarmTrackerDB.items[i]
|
|
FarmTrackerDB.items[i] = temp
|
|
UpdateManagerList()
|
|
RefreshDisplay()
|
|
end
|
|
end)
|
|
|
|
-- Logic: Remove
|
|
row.remove:SetScript("OnClick", function()
|
|
table.remove(FarmTrackerDB.items, i)
|
|
UpdateManagerList()
|
|
RefreshDisplay()
|
|
end)
|
|
|
|
-- Visibility of arrows (disable first up and last down)
|
|
row.up:SetAlpha(i == 1 and 0.3 or 1)
|
|
row.down:SetAlpha(i == #FarmTrackerDB.items and 0.3 or 1)
|
|
|
|
row:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, -(i - 1) * 26)
|
|
row:Show()
|
|
end
|
|
scrollChild:SetHeight(#FarmTrackerDB.items * 26)
|
|
end
|
|
|
|
m.editBox = CreateFrame("EditBox", nil, m, "InputBoxTemplate")
|
|
m.editBox:SetSize(180, 20)
|
|
m.editBox:SetPoint("BOTTOMLEFT", m, "BOTTOMLEFT", 20, 20)
|
|
m.editBox:SetAutoFocus(false)
|
|
m.editBox:SetText("Paste link/ID here...")
|
|
m.editBox:SetScript("OnEditFocusGained", function(self)
|
|
if self:GetText() == "Paste link/ID here..." then
|
|
self:SetText("")
|
|
end
|
|
end)
|
|
|
|
m.addBtn = CreateFrame("Button", nil, m, "UIPanelButtonTemplate")
|
|
m.addBtn:SetSize(80, 22)
|
|
m.addBtn:SetPoint("LEFT", m.editBox, "RIGHT", 5, 0)
|
|
m.addBtn:SetText("Add Item")
|
|
m.addBtn:SetScript("OnClick", function()
|
|
local text = m.editBox:GetText()
|
|
local id = tonumber(text) or tonumber(text:match("item:(%d+)"))
|
|
if id then
|
|
AddItemToList(id)
|
|
m.editBox:SetText("")
|
|
end
|
|
end)
|
|
|
|
m:SetScript("OnShow", UpdateManagerList)
|
|
|
|
-- 4. Logic: Refresh Display
|
|
local function GetOrCreateButton(index)
|
|
if not hoverButtons[index] then
|
|
local b = CreateFrame("Button", nil, f)
|
|
b:SetHeight(28)
|
|
b:SetScript("OnEnter", function(self)
|
|
if self.itemID and not FarmTrackerDB.locked then
|
|
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
|
GameTooltip:SetItemByID(self.itemID)
|
|
GameTooltip:Show()
|
|
end
|
|
end)
|
|
b:SetScript("OnLeave", function()
|
|
GameTooltip:Hide()
|
|
end)
|
|
hoverButtons[index] = b
|
|
end
|
|
return hoverButtons[index]
|
|
end
|
|
|
|
function RefreshDisplay()
|
|
if not FarmTrackerDB then
|
|
return
|
|
end
|
|
local displayString, totalInv, totalSess, activeIndex = "", 0, 0, 0
|
|
local elapsed = (GetTime() - startTime) / 3600
|
|
for _, btn in ipairs(hoverButtons) do
|
|
btn:Hide()
|
|
end
|
|
|
|
for _, id in ipairs(FarmTrackerDB.items) do
|
|
local name, link, _, _, _, _, _, _, _, icon = GetItemInfo(id)
|
|
local count = GetItemCount(id, true)
|
|
local gain = count - (sessionStartCounts[id] or count)
|
|
|
|
if count > 0 or gain > 0 then
|
|
activeIndex = activeIndex + 1
|
|
local price = (_G.TSM_API and TSM_API.GetCustomPriceValue("dbmarket", "i:" .. id)) or 0
|
|
totalInv = totalInv + (count * price / 10000)
|
|
totalSess = totalSess + (gain * price / 10000)
|
|
|
|
local rank = ""
|
|
if link then
|
|
local q = C_TradeSkillUI.GetItemReagentQualityByItemInfo(link)
|
|
if q and q > 0 then
|
|
rank = " " .. CreateAtlasMarkup(("Professions-Icon-Quality-Tier%d-Small"):format(q), 14, 14)
|
|
end
|
|
end
|
|
|
|
displayString = string.format(
|
|
"|T%s:14:14:0:0|t |cFFFFD100%s%s:|r %d |cFF00FF00(+%d)|r\n|cFF808080Inv: %.2fg|r\n\n", icon or "",
|
|
name or "Loading...", rank, count, gain, (count * price / 10000)) .. displayString
|
|
|
|
local btn = GetOrCreateButton(activeIndex)
|
|
btn.itemID = id
|
|
btn:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 10,
|
|
55 + (activeIndex - 1) * 32 + (FarmTrackerDB.goal > 0 and 15 or 0))
|
|
btn:SetWidth(f:GetWidth() - 20)
|
|
if not FarmTrackerDB.locked then
|
|
btn:Show()
|
|
end
|
|
end
|
|
end
|
|
|
|
local gph = elapsed > 0 and (totalSess / elapsed) or 0
|
|
local goalBar = ""
|
|
if FarmTrackerDB.goal > 0 then
|
|
local p = math.min(totalSess / FarmTrackerDB.goal, 1)
|
|
goalBar = string.format("\nGoal: |cFF00FF00%s|r|cFF555555%s|r %.1f%%", string.rep("■", math.floor(p * 20)),
|
|
string.rep("■", 20 - math.floor(p * 20)), p * 100)
|
|
if p >= 1 and not goalReachedSoundPlayed then
|
|
PlaySound(888, "Master")
|
|
goalReachedSoundPlayed = true
|
|
end
|
|
end
|
|
|
|
f.statsText:SetText(string.format("|cFF00FF00Sess: %.2fg|r |cFFFFFF00Total: %.2fg|r\n|cFF55AAFFGPH: %.2fg/hr|r%s",
|
|
totalSess, totalInv, gph, goalBar))
|
|
f.text:SetText(displayString)
|
|
f:SetHeight(f.text:GetStringHeight() + f.statsText:GetStringHeight() + 60)
|
|
end
|
|
|
|
-- 5. Init & Events
|
|
f:RegisterEvent("ADDON_LOADED")
|
|
f:RegisterEvent("BAG_UPDATE")
|
|
f:RegisterEvent("PLAYER_LOGIN")
|
|
|
|
f:SetScript("OnEvent", function(self, event, arg1)
|
|
if event == "ADDON_LOADED" and (arg1 == "MxW.Farm" or arg1 == "FarmTracker") then
|
|
FarmTrackerDB = FarmTrackerDB or {}
|
|
FarmTrackerDB.items = FarmTrackerDB.items or {2840, 2841, 2770}
|
|
FarmTrackerDB.scale = FarmTrackerDB.scale or 1.0
|
|
f:SetScale(FarmTrackerDB.scale)
|
|
if FarmTrackerDB.pos then
|
|
f:ClearAllPoints()
|
|
f:SetPoint(FarmTrackerDB.pos.point, UIParent, FarmTrackerDB.pos.relativePoint, FarmTrackerDB.pos.x,
|
|
FarmTrackerDB.pos.y)
|
|
else
|
|
f:SetPoint("BOTTOM", UIParent, "CENTER")
|
|
end
|
|
if FarmTrackerDB.locked then
|
|
f:EnableMouse(false)
|
|
f:SetMovable(false)
|
|
f.resetBtn:Hide()
|
|
end
|
|
elseif event == "PLAYER_LOGIN" then
|
|
C_Timer.After(2, function()
|
|
for _, id in ipairs(FarmTrackerDB.items) do
|
|
sessionStartCounts[id] = GetItemCount(id, true)
|
|
C_Item.RequestLoadItemDataByID(id)
|
|
end
|
|
isInitialized = true
|
|
f:Show()
|
|
RefreshDisplay()
|
|
end)
|
|
elseif event == "BAG_UPDATE" and isInitialized then
|
|
RefreshDisplay()
|
|
end
|
|
end)
|
|
|
|
-- 6. Slash Commands
|
|
SLASH_FARMTRACKER1 = "/ft"
|
|
SlashCmdList["FARMTRACKER"] = function(msg)
|
|
local cmd, arg = msg:match("^(%S*)%s*(.-)$")
|
|
if cmd == "lock" then
|
|
FarmTrackerDB.locked = not FarmTrackerDB.locked
|
|
f:EnableMouse(not FarmTrackerDB.locked)
|
|
f:SetMovable(not FarmTrackerDB.locked)
|
|
if FarmTrackerDB.locked then
|
|
f.resetBtn:Hide()
|
|
else
|
|
f.resetBtn:Show()
|
|
end
|
|
RefreshDisplay()
|
|
elseif cmd == "goal" then
|
|
FarmTrackerDB.goal = tonumber(arg) or 0
|
|
goalReachedSoundPlayed = false
|
|
RefreshDisplay()
|
|
elseif cmd == "scale" then
|
|
local s = tonumber(arg)
|
|
if s and s >= 0.5 and s <= 3.0 then
|
|
FarmTrackerDB.scale = s
|
|
f:SetScale(s)
|
|
end
|
|
elseif cmd == "manage" then
|
|
m:Show()
|
|
else
|
|
m:Show() -- Default to showing manager if no command
|
|
end
|
|
end
|