local MX = LibStub("AceAddon-3.0"):NewAddon("MxW.Farm"); local L = LibStub("AceLocale-3.0"):GetLocale("MxW.Farm"); local date = C_DateAndTime.GetCurrentCalendarTime(); local weekday, month, day, year = date.weekday, date.month, date.monthDay, date.year; function MX:OnInitialize() if (LogicDay == nil) then LogicDay = day; end end -- 1. Data & Initialization FarmTrackerDB = FarmTrackerDB or { items = {2840, 2841, 2770}, milestone = 100, autoAdd = true, minValue = 1, goal = 0, minimzed = false, locked = false, scale = 1.0, pos = { y = 0, x = 0, point = "BOTTOMLEFT", relativePoint = "BOTTOMLEFT" } } local sessionStartCounts, itemRows = {}, {} local startTime = GetTime() local isInitialized, lastMilestoneReached, lastGoldValue = false, 0, 0 local currentGold = GetMoney() -- Initializing for tracking local CUSTOM_FONT = "Interface\\Addons\\MxW.Farm\\Media\\Font\\Consola.ttf" local mxwVersion = C_AddOns.GetAddOnMetadata("MxW.Farm", "Version") -- Ensure these are NOT nil local isPaused = false local sessionAccumulatedTime = 0 local pauseStartTime = 0 local function ApplyCustomFont(fs, size, style) if not fs or not fs.SetFont then return end local success = style and style ~= "" and pcall(fs.SetFont, fs, CUSTOM_FONT, size or 14, style) or pcall(fs.SetFont, fs, CUSTOM_FONT, size or 14) if not success then fs:SetFontObject("GameFontHighlightSmall") end end -- 2. Main Tracker Frame (Updated Styling) local f = CreateFrame("Frame", "FarmTrackerFrame", UIParent, "BackdropTemplate") f:SetSize(280, 120); f:SetFrameStrata("MEDIUM"); f:SetMovable(true); f:EnableMouse(true); f:RegisterForDrag("LeftButton") 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:SetScript("OnDragStart", f.StartMoving) f:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() local p, _, rp, x, y = self:GetPoint() FarmTrackerDB.pos = { point = p, relativePoint = rp, x = x, y = y } end) -- Label - Titleersion f.title = f:CreateFontString(nil, "ARTWORK"); f.title:SetFont("Interface\\Addons\\MxW\\Media\\Font\\Consola.ttf", 20); f.title:SetPoint("TOP", 0, -5); f.title:SetTextColor(1.00, 0.49, 0.04); f.title:SetText("MxW"); -- Label - Version f.version = f:CreateFontString(nil, "ARTWORK"); f.version:SetFont("Interface\\Addons\\MxW\\Media\\Font\\Consola.ttf", 12); f.version:SetPoint("TOP", 0, -22); f.version:SetTextColor(1.00, 0.49, 0.04); f.version:SetText(mxwVersion); -- f.title = f:CreateFontString(nil, "OVERLAY"); f.title:SetPoint("TOP", 0, -10); ApplyCustomFont(f.title, 14, "OUTLINE"); f.title:SetText("MxW") f.text = f:CreateFontString(nil, "OVERLAY"); f.text:SetPoint("TOPLEFT", 12, -35); f.text:SetJustifyH("LEFT"); ApplyCustomFont(f.text, 14) f.barBG = f:CreateTexture(nil, "BACKGROUND"); f.barBG:SetHeight(4); f.barBG:SetPoint("BOTTOMLEFT", 12, 75); f.barBG:SetPoint("BOTTOMRIGHT", -12, 75); f.barBG:SetColorTexture(0.1, 0.1, 0.1, 0.8) f.barFill = f:CreateTexture(nil, "ARTWORK"); f.barFill:SetHeight(4); f.barFill:SetPoint("LEFT", f.barBG, "LEFT") f.statsText = f:CreateFontString(nil, "OVERLAY"); f.statsText:SetPoint("BOTTOMLEFT", 12, 58); ApplyCustomFont(f.statsText, 13) f.invText = f:CreateFontString(nil, "OVERLAY"); f.invText:SetPoint("BOTTOMLEFT", 12, 42); ApplyCustomFont(f.invText, 13) -- New: MXW Style Global Tracking Section f.line = f:CreateTexture(nil, "ARTWORK"); f.line:SetHeight(1); f.line:SetPoint("BOTTOMLEFT", 10, 38); f.line:SetPoint("BOTTOMRIGHT", -10, 38); f.line:SetColorTexture(1, 1, 1, 0.2) f.dailyText = f:CreateFontString(nil, "OVERLAY"); f.dailyText:SetPoint("BOTTOMLEFT", 12, 22); ApplyCustomFont(f.dailyText, 14) f.monthlyText = f:CreateFontString(nil, "OVERLAY"); f.monthlyText:SetPoint("BOTTOMLEFT", 12, 8); ApplyCustomFont(f.monthlyText, 14) -- Pause/Play Button f.pauseBtn = CreateFrame("Button", nil, f) f.pauseBtn:SetSize(16, 16) f.pauseBtn:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up") -- Default Play look f.pauseBtn:GetNormalTexture():SetVertexColor(0, 1, 0) -- Green for Play f.pauseBtn:SetScript("OnClick", function() isPaused = not isPaused if isPaused then pauseStartTime = GetTime() f.pauseBtn:GetNormalTexture():SetVertexColor(1, 0, 0) -- Red for Paused f.pauseBtn:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Up") else -- Add the duration of the pause to the accumulated time sessionAccumulatedTime = sessionAccumulatedTime + (GetTime() - startTime) startTime = GetTime() -- Reset start reference to "now" f.pauseBtn:GetNormalTexture():SetVertexColor(0, 1, 0) -- Green for Play f.pauseBtn:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up") end MX:RefreshDisplay() end) -- Flash Animation f.flash = f:CreateAnimationGroup() local alpha1 = f.flash:CreateAnimation("Alpha") alpha1:SetFromAlpha(1); alpha1:SetToAlpha(0.5); alpha1:SetDuration(0.2); alpha1:SetOrder(1) local alpha2 = f.flash:CreateAnimation("Alpha") alpha2:SetFromAlpha(0.5); alpha2:SetToAlpha(1); alpha2:SetDuration(0.4); alpha2:SetOrder(2) local function FlashGreen() f:SetBackdropColor(0, 0.5, 0, 1) f.flash:Play() C_Timer.After(0.6, function() f:SetBackdropColor(0.20, 0.20, 0.20, 1) end) end -- 3. Management UI (Matching Styles) local m = CreateFrame("Frame", "FarmTrackerManager", UIParent, "BackdropTemplate") m:SetSize(340, 560); m:SetPoint("CENTER"); m:Hide(); m:SetMovable(true); m:EnableMouse(true); m:RegisterForDrag("LeftButton") m:SetBackdrop(f:GetBackdrop()) m:SetBackdropColor(0.1, 0.1, 0.1, 1) m:SetBackdropBorderColor(0, 0, 0, 1) m:SetScript("OnDragStart", m.StartMoving); m:SetScript("OnDragStop", m.StopMovingOrSizing) local function OnReceiveDragItem() local infoType, itemID = GetCursorInfo() if infoType == "item" then local id = tonumber(itemID) if id then local exists = false for _, v in ipairs(FarmTrackerDB.items) do if v == id then exists = true break end end if not exists then table.insert(FarmTrackerDB.items, id) sessionStartCounts[id] = GetItemCount(id, false) UpdateManagerList(); MX:RefreshDisplay() end end ClearCursor() end end m:SetScript("OnReceiveDrag", OnReceiveDragItem) m.title = m:CreateFontString(nil, "OVERLAY"); m.title:SetPoint("TOPLEFT", 15, -15); ApplyCustomFont(m.title, 16, "OUTLINE"); m.title:SetText("Manager") m.close = CreateFrame("Button", nil, m, "UIPanelCloseButton"); m.close:SetPoint("TOPRIGHT", -5, -5) m.mileLabel = m:CreateFontString(nil, "OVERLAY"); m.mileLabel:SetPoint("TOPLEFT", 15, -45); ApplyCustomFont(m.mileLabel, 12); m.mileLabel:SetText("Milestone (Gold):") m.mileEdit = CreateFrame("EditBox", nil, m, "InputBoxTemplate") m.mileEdit:SetSize(60, 20); m.mileEdit:SetPoint("LEFT", m.mileLabel, "RIGHT", 10, 0); m.mileEdit:SetAutoFocus(false) m.mileEdit:SetScript("OnEnterPressed", function(self) FarmTrackerDB.milestone = tonumber(self:GetText()) or 100; self:ClearFocus(); MX:RefreshDisplay() end) m.autoAddCheck = CreateFrame("CheckButton", "FTAutoAddCheck", m, "UICheckButtonTemplate") m.autoAddCheck:SetPoint("TOPLEFT", m.mileLabel, "BOTTOMLEFT", -5, -15) m.autoAddCheck.text = m:CreateFontString(nil, "OVERLAY"); m.autoAddCheck.text:SetPoint("LEFT", m.autoAddCheck, "RIGHT", 5, 0) ApplyCustomFont(m.autoAddCheck.text, 12); m.autoAddCheck.text:SetText("Auto-Add Materials") m.autoAddCheck:SetScript("OnClick", function(self) FarmTrackerDB.autoAdd = self:GetChecked() end) m.minValLabel = m:CreateFontString(nil, "OVERLAY"); m.minValLabel:SetPoint("LEFT", m.autoAddCheck.text, "RIGHT", 15, 0); ApplyCustomFont(m.minValLabel, 12); m.minValLabel:SetText("Min Gold:") m.minValEdit = CreateFrame("EditBox", nil, m, "InputBoxTemplate") m.minValEdit:SetSize(40, 20); m.minValEdit:SetPoint("LEFT", m.minValLabel, "RIGHT", 8, 0); m.minValEdit:SetAutoFocus(false) m.minValEdit:SetScript("OnEnterPressed", function(self) FarmTrackerDB.minValue = tonumber(self:GetText()) or 0; self:ClearFocus() end) m.summary = m:CreateFontString(nil, "OVERLAY"); m.summary:SetPoint("TOPLEFT", m.autoAddCheck, "BOTTOMLEFT", 5, -5); ApplyCustomFont(m.summary, 12) local scrollFrame = CreateFrame("ScrollFrame", "FTScroll", m, "UIPanelScrollFrameTemplate") scrollFrame:SetPoint("TOPLEFT", 10, -140); scrollFrame:SetPoint("BOTTOMRIGHT", -30, 20) local scrollChild = CreateFrame("Frame"); scrollChild:SetSize(280, 1) -- Height updated in UpdateManagerList scrollFrame:SetScrollChild(scrollChild) function UpdateManagerList() for _, row in ipairs(itemRows) do row:Hide() end local listCount = #FarmTrackerDB.items scrollChild:SetHeight(math.max(1, listCount * 28)) for i, id in ipairs(FarmTrackerDB.items or {}) do if not itemRows[i] then local row = CreateFrame("Frame", nil, scrollChild); row:SetSize(280, 28) -- Item Name Text row.text = row:CreateFontString(nil, "OVERLAY"); row.text:SetPoint("LEFT", 5, 0); row.text:SetWidth(170); -- Slightly narrowed to make room for buttons row.text:SetJustifyH("LEFT"); ApplyCustomFont(row.text, 11) -- Delete Button row.del = CreateFrame("Button", nil, row); row.del:SetSize(16, 16); row.del:SetPoint("RIGHT", -5, 0); row.del:SetNormalTexture("Interface\\Buttons\\UI-GroupLoot-Pass-Up") -- Down Button row.down = CreateFrame("Button", nil, row); row.down:SetSize(16, 16); row.down:SetPoint("RIGHT", row.del, "LEFT", -4, 0); row.down:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up") -- Up Button row.up = CreateFrame("Button", nil, row); row.up:SetSize(16, 16); row.up:SetPoint("RIGHT", row.down, "LEFT", -4, 0); row.up:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollUpButton-Up") itemRows[i] = row end local _, link = GetItemInfo(id); local row = itemRows[i] row.text:SetText(link or "Loading...") -- Logic for Delete row.del:SetScript("OnClick", function() table.remove(FarmTrackerDB.items, i); UpdateManagerList(); MX:RefreshDisplay() end) -- Logic for Move Up row.up:SetEnabled(i > 1) row.up:GetNormalTexture():SetDesaturated(i == 1) 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(); MX:RefreshDisplay() end end) -- Logic for Move Down row.down:SetEnabled(i < listCount) row.down:GetNormalTexture():SetDesaturated(i == listCount) row.down:SetScript("OnClick", function() if i < listCount then local temp = FarmTrackerDB.items[i+1] FarmTrackerDB.items[i+1] = FarmTrackerDB.items[i] FarmTrackerDB.items[i] = temp UpdateManagerList(); MX:RefreshDisplay() end end) row:SetPoint("TOPLEFT", 0, -(i - 1) * 28); row:Show() end end -- 4. Logic: Refresh Display & Dynamic Height function MX:RefreshDisplay() if not isInitialized then return end local displayString, totalSess, totalInv, itemCount = "", 0, 0, 0 local maxWidth = 260 for _, id in ipairs(FarmTrackerDB.items or {}) do local name, link, _, _, _, _, _, _, _, icon = GetItemInfo(id) if name and link then local truncatedName = link:sub(1, 25) local quality = C_TradeSkillUI.GetItemReagentQualityByItemInfo(link) local qualityIcon = "" if quality then qualityIcon = CreateAtlasMarkup("Professions-Icon-Quality-Tier" .. quality, 14, 14) else qualityIcon = "|TInterface\\Buttons\\UI-EmptySlot-White:14:14:0:0:64:64:0:0:0:0|t"; end local count = GetItemCount(id, false) local countString = "" local gain = count - (sessionStartCounts[id] or count) local gainString = "" local price = ((_G.TSM_API and TSM_API.GetCustomPriceValue("DBMinBuyout", "i:" .. id)) or 0) / 10000 local priceCopper = ((_G.TSM_API and TSM_API.GetCustomPriceValue("DBMinBuyout", "i:" .. id)) or 0) totalSess, totalInv = totalSess + (gain * price), totalInv + (count * price) if count > 0 or gain > 0 then -- displayString = displayString .. string.format("|T%s:16:16:0:0|t %s: %d |cFF00FF00(+%d)|r\n", icon or "", name or "...", count, gain) -- displayString = displayString .. string.format("|T%s:16:16:0:0|t %s: %d |cFF00FF00(+%d)|r\n", icon or "", name or "...", count, gain) if count < 10 then countString = string.format(" %d", count) elseif count >= 10 and count < 100 then countString = string.format(" %d", count) elseif count >= 100 then countString = string.format("%d", count) end if gain < 10 then gainString = string.format(" %d", gain) elseif gain > 10 and gain < 100 then gainString = string.format(" %d", gain) elseif gain > 100 then gainString = string.format("%d", gain) end local unitDiv = priceCopper / 1000 local unitString = "" if unitDiv < 10 then unitString = string.format(" %s", MX:FormatMoneyGoldOnly(priceCopper)) elseif unitDiv >= 10 and unitDiv < 100 then unitString = string.format(" %s", MX:FormatMoneyGoldOnly(priceCopper)) elseif unitDiv >= 100 and unitDiv < 1000 then unitString = string.format(" %s", MX:FormatMoneyGoldOnly(priceCopper)) elseif unitDiv >= 1000 and unitDiv < 10000 then unitString = string.format(" %s", MX:FormatMoneyGoldOnly(priceCopper)) elseif unitDiv >= 10000 and unitDiv < 100000 then unitString = string.format(" %s", MX:FormatMoneyGoldOnly(priceCopper)) elseif unitDiv >= 100000 then unitString = string.format("%s", MX:FormatMoneyGoldOnly(priceCopper)) end local totalDiv = (count * priceCopper) / 1000 local totalString = "" if totalDiv < 10 then totalString = string.format(" %s", MX:FormatMoneyGoldOnly(count * priceCopper)) elseif totalDiv >= 10 and totalDiv < 100 then totalString = string.format(" %s", MX:FormatMoneyGoldOnly(count * priceCopper)) elseif totalDiv >= 100 and totalDiv < 1000 then totalString = string.format(" %s", MX:FormatMoneyGoldOnly(count * priceCopper)) elseif totalDiv >= 1000 and totalDiv < 10000 then totalString = string.format(" %s", MX:FormatMoneyGoldOnly(count * priceCopper)) elseif totalDiv >= 10000 and totalDiv < 100000 then totalString = string.format(" %s", MX:FormatMoneyGoldOnly(count * priceCopper)) elseif totalDiv >= 100000 then totalString = string.format("%s", MX:FormatMoneyGoldOnly(count * priceCopper)) end -- displayString = displayString .. string.format("|T%s:14:14:0:0|t |cFF00FFFFB%s|r |cFF00FF00S%s|r %s/u %s/t %s %s\n", icon or "", countString, gainString, MX:FormatMoneyGoldOnly(priceCopper), MX:FormatMoneyGoldOnly(count * priceCopper), qualityIcon or "n", name or "...") displayString = displayString .. string.format("|T%s:14:14:0:0|t |cFF00FFFF%s|r |cFF00FF00%s|r %s/u %s/t %s\n", icon or "", countString, gainString, unitString, totalString, link or "...") itemCount = itemCount + 1 maxWidth = math.max(maxWidth, f.text:GetStringWidth() + 40) end end end local ms = math.max(1, FarmTrackerDB.milestone or 100) local progress = (totalSess % ms) / ms -- Calculate active time local currentActiveSession = isPaused and 0 or (GetTime() - startTime) local totalActiveSeconds = sessionAccumulatedTime + currentActiveSession local elapsedHours = totalActiveSeconds / 3600 local gph = elapsedHours > 0.005 and (totalSess / elapsedHours) or 0 local timerStr = string.format("[%02d:%02d]", math.floor(totalActiveSeconds / 60), math.floor(totalActiveSeconds % 60)) if FarmTrackerDB.minimized then f:SetSize(200, 55); f.text:SetText(""); f.line:Hide(); f.dailyText:Hide(); f.monthlyText:Hide(); f.barBG:Hide() f.statsText:SetPoint("BOTTOMLEFT", 12, 22); f.statsText:SetText(string.format("|cFF00FF00S: %.2fg|r %s", totalSess, timerStr)) f.invText:SetPoint("BOTTOMLEFT", 12, 8); f.invText:SetText(string.format("|cFF00FFFFI: %.2fg|r", totalInv)) else f.text:SetText(displayString) if displayString then f.barBG:Show() end f.line:Show(); f.dailyText:Show(); f.monthlyText:Show(); -- Anchor elements from the bottom up to prevent overlapping f.dailyText:SetText(string.format(L["MxW_MainForm_Day"], MX:FormatMoneyGoldOnly(MxW_DailyGlobal))) f.monthlyText:SetText(string.format(L["MxW_MainForm_Month"], MX:FormatMoneyGoldOnly(MxW_MonthlyGlobal))) f.line:SetPoint("BOTTOMLEFT", 10, 44); f.line:SetPoint("BOTTOMRIGHT", -10, 44) f.invText:SetPoint("BOTTOMLEFT", 12, 50); f.invText:SetText(string.format(L["MxW_MainForm_Bag"], totalInv, totalInv - (totalInv * 0.05))) f.statsText:SetPoint("BOTTOMLEFT", 12, 66); f.statsText:SetText(string.format(L["MxW_MainForm_Live"], totalSess, gph, timerStr)) f.barBG:SetPoint("BOTTOMLEFT", 12, 84); f.barBG:SetPoint("BOTTOMRIGHT", -12, 84) f.barFill:SetWidth(math.max(1, f.barBG:GetWidth() * progress)) f.barFill:SetColorTexture(progress < 0.5 and 1 or (progress < 0.8 and 1 or 0), progress < 0.5 and 0 or 1, 0) f.pauseBtn:SetPoint("LEFT", f.statsText, "RIGHT", 5, 0); f.pauseBtn:Show() f:SetSize(maxWidth, 120 + (itemCount * 20)) -- Dynamic Height calculation end end -- 5. Buttons & Tickers f.minBtn = CreateFrame("Button", nil, f); f.minBtn:SetSize(18, 18); f.minBtn:SetPoint("TOPRIGHT", -8, -8); f.minBtn:SetNormalTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Up") f.minBtn:SetScript("OnClick", function() FarmTrackerDB.minimized = not FarmTrackerDB.minimized; RefreshDisplay() end) f.configBtn = CreateFrame("Button", nil, f); f.configBtn:SetSize(18, 18); f.configBtn:SetPoint("TOPRIGHT", f.minBtn, "TOPLEFT", -2, 0); f.configBtn:SetNormalTexture("Interface\\Buttons\\UI-OptionsButton") f.configBtn:SetScript("OnClick", function() if m:IsShown() then m:Hide() else m.mileEdit:SetText(tostring(FarmTrackerDB.milestone or 100)) m.minValEdit:SetText(tostring(FarmTrackerDB.minValue or 1)) m.autoAddCheck:SetChecked(FarmTrackerDB.autoAdd) UpdateManagerList(); m:Show() end end) f.resetBtn = CreateFrame("Button", nil, f); f.resetBtn:SetSize(18, 18); f.resetBtn:SetPoint("BOTTOMRIGHT", -10, 10); f.resetBtn:SetNormalTexture("Interface\\Buttons\\UI-RefreshButton") f.resetBtn:SetScript("OnClick", function() StaticPopup_Show("FARMTRACKER_RESET") end) StaticPopupDialogs["FARMTRACKER_RESET"] = { text = "Reset session?", button1 = "Yes", button2 = "No", OnAccept = function() for _, id in ipairs(FarmTrackerDB.items) do sessionStartCounts[id] = GetItemCount(id, false) end startTime, lastMilestoneReached, lastGoldValue = GetTime(), 0, 0 MX:RefreshDisplay() end, timeout = 0, whileDead = true, hideOnEscape = true } -- 6. Events f:RegisterEvent("ADDON_LOADED"); f:RegisterEvent("PLAYER_LOGIN"); f:RegisterEvent("CHAT_MSG_LOOT"); f:RegisterEvent("PLAYER_ENTERING_WORLD") f:SetScript("OnEvent", function(self, event, arg1) if event == "ADDON_LOADED" and arg1 == "MxW.Farm" then FarmTrackerDB = FarmTrackerDB or { items = {2840, 2841, 2770}, milestone = 100, autoAdd = true, minValue = 1 } if FarmTrackerDB.pos then f:ClearAllPoints(); f:SetPoint(FarmTrackerDB.pos.point, UIParent, FarmTrackerDB.pos.relativePoint, FarmTrackerDB.pos.x, FarmTrackerDB.pos.y) end elseif event == "PLAYER_LOGIN" then -- nothing elseif event == "CHAT_MSG_LOOT" and isInitialized and FarmTrackerDB.autoAdd then local itemLink = arg1:match("|H(item:%d+:.-)|h") if itemLink then -- Use a ItemMixin to ensure data is loaded before processing local item = Item:CreateFromItemLink(itemLink) item:ContinueOnItemLoad(function() local id = item:GetItemID() local _, _, _, _, _, _, classID = GetItemInfo(id) -- Check if it's a Crafting Material (Class 7) if classID == 7 then -- Get price from TSM local priceCopper = (_G.TSM_API and TSM_API.GetCustomPriceValue("DBMinBuyout", "i:" .. id)) or 0 local priceGold = priceCopper / 10000 -- Check threshold if priceGold >= (FarmTrackerDB.minValue or 0) then local exists = false for _, v in ipairs(FarmTrackerDB.items) do if v == id then exists = true break end end if not exists then table.insert(FarmTrackerDB.items, id) -- Set start count to current - 1 so the (+1) shows immediately sessionStartCounts[id] = GetItemCount(id, false) - 1 -- Call the correct function name MX:RefreshDisplay() if m:IsShown() then UpdateManagerList() end end end end end) end elseif event == "PLAYER_ENTERING_WORLD" then if (day ~= 0 and LogicDay ~= day) then MxW_DailyGlobal = 0; LogicDay = day; end C_Timer.After(5, function() for _, id in ipairs(FarmTrackerDB.items or {}) do sessionStartCounts[id] = GetItemCount(id, false) end isInitialized = true; f:Show(); MX:RefreshDisplay() end) CurrentGold = GetMoney() end end) C_Timer.NewTicker(1, function() if isInitialized then MX:RefreshDisplay() end end) -- 7. 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 f:Show() -- Default to showing manager if no command end end