Nenue@4: local wipe, tinsert, sort = table.wipe, tinsert, table.sort Nenue@2: local pairs, ipairs = pairs, ipairs Nenue@4: local floor, mod, time = floor, mod, time Nenue@32: local max, min = math.max, math.min Nenue@2: local GetTime = GetTime Nenue@3: local GI_currentTime = time() Nenue@32: local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop Nenue@3: Nenue@32: local CG_GetBuildings = C_Garrison.GetBuildings Nenue@32: local CG_GetFollowerShipments = C_Garrison.GetFollowerShipments Nenue@32: local CG_GetLooseShipments = C_Garrison.GetLooseShipments Nenue@32: local CG_GetTalentTrees = C_Garrison.GetTalentTrees Nenue@32: local CG_GetCompleteTalent = C_Garrison.GetCompleteTalent Nenue@32: local CG_GetLandingPageShipmentInfo = C_Garrison.GetLandingPageShipmentInfo Nenue@32: local CG_GetLandingPageShipmentInfoByContainerID = C_Garrison.GetLandingPageShipmentInfoByContainerID Nenue@32: Nenue@32: local CP_REPLACE_LANDINGPAGE = true Nenue@32: local CP_HEADER_SIZE = 24 Nenue@32: local CP_BACKGROUND_COLOR = { Nenue@32: inProgress = {0, 0, 0, 0.5}, Nenue@32: shipmentsReady = {0, 0, 0, 0.25}, Nenue@32: complete = {0.5, 0.5, 0.5, 0.5} Nenue@2: } Nenue@2: Nenue@4: local GetTimeLeftString = function(timeLeft) Nenue@4: local days = floor(timeLeft/(24*3600)) Nenue@4: local hours = floor(mod(timeLeft, (24*3600)) / 3600) Nenue@4: local minutes = floor(mod(timeLeft, 3600) / 60) Nenue@4: local seconds = mod(timeLeft, 60) Nenue@4: if days >= 1 then Nenue@6: return (days .. 'd' .. ' ') .. ((hours > 0) and (hours .. 'h') or '') Nenue@4: else Nenue@6: return ((hours > 0) and (hours .. 'h') or '') .. ((minutes > 0) and (' ' ..minutes .. ' min') or '') Nenue@4: end Nenue@4: end Nenue@3: Nenue@23: Nenue@32: ClassOrderPlanCore = { Nenue@32: events = {}, Nenue@32: freeBlocks = {}, Nenue@32: blocks = {}, Nenue@32: sortedItems = {}, Nenue@32: timers = {}, Nenue@32: shipments = {}, Nenue@32: playerFirst = false, Nenue@32: prototypes = {}, Nenue@32: Queued = {} Nenue@32: } Nenue@32: local MissionList = { Nenue@32: templateName = 'ClassPlanMissionEntry', Nenue@32: listKey = {'missions', 'available'}, Nenue@32: listTitle = {'In Progress', 'Available'}, Nenue@23: Nenue@32: point = 'TOPLEFT', Nenue@32: relativePoint ='TOPLEFT', Nenue@32: events = { Nenue@32: 'GARRISON_MISSION_LIST_UPDATE', Nenue@32: 'GARRISON_LANDINGPAGE_SHIPMENTS'}, Nenue@32: } Nenue@32: local ShipmentList = { Nenue@32: templateName = 'ClassPlanShipmentEntry', Nenue@32: listKey = {'shipments'}, Nenue@32: listTitle = {'Work Orders'}, Nenue@32: events = { Nenue@32: 'GARRISON_MISSION_LIST_UPDATE', Nenue@32: 'GARRISON_LANDINGPAGE_SHIPMENTS', Nenue@32: 'GARRISON_TALENT_UPDATE', Nenue@32: "GARRISON_TALENT_COMPLETE", Nenue@32: "GARRISON_SHIPMENT_RECEIVED", Nenue@32: 'GARRISON_FOLLOWER_LIST_UPDATE', Nenue@32: 'GARRISON_SHOW_LANDING_PAGE'}, Nenue@32: } Nenue@32: local SharedHandlers = { Nenue@32: numBlocks = 0, Nenue@32: isStale = true, Nenue@32: } Nenue@32: local SharedEntry = {} Nenue@32: local ShipmentEntry = {} Nenue@32: local MissionEntry = {} Nenue@1: Nenue@32: local ClassPlan = ClassOrderPlanCore Nenue@5: Nenue@32: function ClassPlan:OnLoad () Nenue@3: self:RegisterEvent('PLAYER_LOGIN') Nenue@3: self:RegisterEvent('ADDON_LOADED') Nenue@3: self:RegisterEvent('PLAYER_REGEN_ENABLED') Nenue@5: self:RegisterEvent('PLAYER_REGEN_DISABLED') Nenue@32: self:RegisterForDrag('LeftButton') Nenue@32: self:SetMovable(true) Nenue@32: self:SetToplevel(true) Nenue@32: Nenue@32: Nenue@32: SLASH_CLASSPLAN1 = "/classplan" Nenue@32: SLASH_CLASSPLAN2 = "/cp" Nenue@32: SlashCmdList.CLASSPLAN = function(args) Nenue@32: self:Toggle() Nenue@32: end Nenue@32: Nenue@4: end Nenue@19: Nenue@32: function ClassPlan:GetCurrentProfile() Nenue@32: WorldPlanData.OrderHall = WorldPlanData.OrderHall or {} Nenue@32: local db = WorldPlanData.OrderHall Nenue@32: self.data = db Nenue@4: Nenue@32: local characters = db.characters or {} Nenue@32: db.characters = characters Nenue@4: Nenue@32: local name, realm = UnitName('player') Nenue@32: realm = realm or GetRealmName() Nenue@32: local profileName = name .. '-' .. realm Nenue@4: Nenue@32: self.profile = characters[profileName] or {} Nenue@32: self.characters = characters Nenue@32: characters[profileName] = self.profile Nenue@32: Nenue@32: Nenue@32: local classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))] Nenue@32: local className = UnitClass('player') Nenue@32: Nenue@32: print('|cFFFFFF00Loaded:|r', classColor.hex, className, profileName) Nenue@32: self.Background:SetColorTexture(classColor.r, classColor.g, classColor.b, 0.5) Nenue@32: self.profile.classColor = classColor Nenue@32: self.profile.className = className Nenue@32: return self.profile Nenue@3: end Nenue@3: Nenue@32: function ClassPlan:SetupHandler(handler) Nenue@32: print('|cFF00FF00'..handler:GetName()..' loaded') Nenue@32: for i, event in ipairs(handler.events) do Nenue@32: print('|cFF00FF00 event', event) Nenue@32: handler:RegisterEvent(event) Nenue@1: end Nenue@32: for index, listKey in ipairs(handler.listKey) do Nenue@32: self.profile[listKey] = self.profile[listKey] or {} Nenue@32: local listTitle = handler.listTitle[index] Nenue@32: setmetatable(self.profile[listKey], { __tostring = listTitle }) Nenue@32: end Nenue@32: handler:SetList(1) Nenue@32: handler.sortedItems = {} Nenue@3: end Nenue@1: Nenue@32: function ClassPlan:OnEvent (event, arg) Nenue@32: print(event, arg) Nenue@5: if event == 'PLAYER_REGEN_DISABLED' then Nenue@6: if self:IsVisible() then Nenue@6: self.combatHide = true Nenue@6: self:SetShown(false) Nenue@6: end Nenue@6: Nenue@5: elseif event == 'PLAYER_REGEN_ENABLED' then Nenue@6: if self.combatHide == true then Nenue@6: self.combatHide = nil Nenue@6: self:SetShown(true) Nenue@6: end Nenue@32: elseif event == 'ADDON_LOADED' then Nenue@32: if arg == 'Blizzard_GarrisonUI' then Nenue@32: self:Reanchor() Nenue@32: end Nenue@3: elseif event == 'PLAYER_LOGIN' then Nenue@3: if not self.initialized then Nenue@4: self:Setup() Nenue@1: end Nenue@2: end Nenue@2: end Nenue@2: Nenue@32: function ClassPlan:Setup() Nenue@32: if IsLoggedIn() then Nenue@32: print('|cFFFFFF00'..self:GetName()..':Setup()|r') Nenue@32: Nenue@32: self:GetCurrentProfile() Nenue@32: for _, handler in ipairs(self.Handlers) do Nenue@32: self:SetupHandler(handler) Nenue@32: end Nenue@32: self.initialized = true Nenue@32: self:SetShown(self.data.IsShown) Nenue@32: end Nenue@3: end Nenue@3: Nenue@4: Nenue@32: --- Update space Nenue@4: Nenue@32: local max = math.max Nenue@32: function ClassPlan:Update() Nenue@32: print('|cFF00FFFFRefresh()|r') Nenue@32: self.currentHeight = 0 Nenue@32: for index, handler in pairs(self.Handlers) do Nenue@32: if handler.isStale then Nenue@32: print(' |cFF00FF00'..index..' '..handler:GetName()..'|r') Nenue@32: local sortedItems = handler.sortedItems Nenue@32: local activeKey = handler.activeKey Nenue@32: handler.profile = self.profile[handler.activeKey] Nenue@3: Nenue@32: wipe(sortedItems) Nenue@32: handler:GetPlayerData(self.profile) Nenue@32: for key, profile in pairs(self.data.characters) do Nenue@32: print('profile', key, activeKey) Nenue@32: local profileList = profile[activeKey] Nenue@32: if profileList and #profileList >= 1 then Nenue@32: local classColor = profile.classColor or defaultClassColor Nenue@32: local isMine = (profile == self.profile) Nenue@32: for index, data in ipairs(profileList) do Nenue@32: data.classColor = classColor Nenue@32: data.profileKey = key Nenue@32: data.isMine = isMine Nenue@32: if handler.OnGetItem then Nenue@32: handler.OnGetItem(data) Nenue@32: end Nenue@32: tinsert(sortedItems, data) Nenue@32: end Nenue@32: end Nenue@32: end Nenue@3: Nenue@32: if handler.SortHandler then Nenue@32: sort(sortedItems, handler.SortHandler) Nenue@23: end Nenue@23: Nenue@23: end Nenue@32: handler.isStale = nil Nenue@32: local itemsHeight = handler:UpdateItems() Nenue@32: self.currentHeight = max(itemsHeight, self.currentHeight) Nenue@23: Nenue@23: end Nenue@23: Nenue@32: self.isStale = nil Nenue@32: self:Reanchor() Nenue@32: self:SetHeight(self.currentHeight + CP_HEADER_SIZE) Nenue@3: end Nenue@3: Nenue@3: Nenue@32: function ClassPlan:Toggle() Nenue@5: if self:IsShown() then Nenue@3: self:Hide() Nenue@3: else Nenue@3: self:Show() Nenue@3: end Nenue@3: Nenue@3: if self.data then Nenue@5: self.data.IsShown = self:IsShown() Nenue@3: end Nenue@3: end Nenue@3: Nenue@32: function ClassPlan:OnUpdate() Nenue@18: if self.isStale then Nenue@32: print('|cFFFF4400An illusion! What are you hiding?|r') Nenue@32: self:Update() Nenue@18: end Nenue@3: end Nenue@3: Nenue@32: function ClassPlan:OnShow() Nenue@23: print('|cFF00FFFFShow()') Nenue@3: if self.isStale then Nenue@32: self:Update() Nenue@3: end Nenue@32: self:Reanchor() Nenue@3: end Nenue@3: Nenue@32: function ClassPlan:OnHide() Nenue@32: print('|cFF00FFFFHide()') Nenue@3: end Nenue@3: Nenue@32: function ClassPlan:Reanchor() Nenue@32: self:ClearAllPoints() Nenue@32: self:SetPoint('CENTER', self.data.positionX, self.data.positionY) Nenue@32: Nenue@32: for index, frame in ipairs(self.Handlers) do Nenue@32: frame:Reanchor() Nenue@32: end Nenue@2: end Nenue@2: Nenue@32: function ClassPlan:OnDragStart() Nenue@32: self:StartMoving() Nenue@32: end Nenue@32: function ClassPlan:OnDragStop() Nenue@32: Nenue@32: self:StopMovingOrSizing() Nenue@32: local x,y = self:GetCenter() Nenue@32: if x and y then Nenue@32: x = (x - GetScreenWidth()/2) Nenue@32: y = (y - GetScreenHeight()/2) * -1 Nenue@32: self.data.positionX, self.data.positionY = x,y Nenue@32: print('saving positions:', x, y) Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: function SharedHandlers:SetList(index) Nenue@32: if not index then Nenue@32: if self.currentListIndex == #self.listKey then Nenue@32: index = 1 Nenue@32: else Nenue@32: index = self.currentListIndex + 1 Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: print('|cFF0088FF'..self:GetName()..'|r:SetList()', index) Nenue@32: self.currentListIndex = index Nenue@32: self.activeKey = self.listKey[index] Nenue@32: self.activeTitle = self.listTitle[index] Nenue@32: Nenue@32: self.isStale = true Nenue@32: end Nenue@32: Nenue@32: function SharedHandlers:RequestData() Nenue@32: print('|cFF0088FF'..self:GetName()..':RequestData()') Nenue@32: self.isStale = true Nenue@32: end Nenue@32: Nenue@32: function SharedHandlers:OnEvent(event, arg) Nenue@32: if (event == 'GARRISON_MISSION_LIST_UPDATE') and (arg ~= LE_FOLLOWER_TYPE_GARRISON_7_0) then Nenue@32: -- ignore non-OrderHall updates Nenue@2: return Nenue@2: end Nenue@32: print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, arg) Nenue@32: if self:IsVisible() then Nenue@32: print('|cFF88FF00 frame visible; get busy') Nenue@32: self:RequestData() Nenue@6: else Nenue@32: if not self.NextData then Nenue@32: print('|cFF88FF00 setting timer') Nenue@32: self.NextData = C_Timer.NewTimer(0.25, function() Nenue@32: if self.initialized then Nenue@32: self:RequestData() Nenue@32: self.NextData:Cancel() Nenue@32: self.NextData = nil Nenue@32: print('|cFF88FF00'..self:GetName()..' clearing timer') Nenue@32: end Nenue@32: Nenue@32: end) Nenue@32: end Nenue@32: end Nenue@32: end Nenue@32: function SharedHandlers:OnUpdate() Nenue@32: if self.isStale then Nenue@32: self:GetParent():Update() Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: Nenue@32: -- Stuff set on every list item Nenue@32: function SharedHandlers:SetOwnerData (self, data) Nenue@32: local name, realm = string.match(data.profileKey, "(.+)%-(.+)") Nenue@32: local ownerText = '|c'.. data.classColor.colorStr .. name .. '|r' Nenue@32: self.Owner:SetText(ownerText) Nenue@32: self.Name:SetText(self.name) Nenue@32: self.Name:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b) Nenue@32: end Nenue@32: Nenue@32: function SharedHandlers:UpdateItems() Nenue@32: local sortedItems = self.sortedItems Nenue@32: Nenue@32: self.blocks = self.blocks or {} Nenue@32: local blocks = self.blocks Nenue@32: Nenue@32: local lastProfile Nenue@32: local numItems = #sortedItems Nenue@32: local totalHeight = 0 Nenue@32: self.lastBlock = nil Nenue@32: self.numActive = 0 Nenue@32: for i, data in ipairs(sortedItems) do Nenue@32: local block = blocks[i] Nenue@32: if not block then Nenue@32: block = CreateFrame('Button', nil, self, self.templateName) Nenue@32: block:SetID(i) Nenue@32: block.listType = self.activeKey Nenue@32: block.handler = self Nenue@32: self.numBlocks = self.numBlocks + 1 Nenue@32: blocks[i] = block Nenue@32: end Nenue@32: Nenue@32: print('RefreshItem', block) Nenue@32: self.numActive = self.numActive + 1 Nenue@32: Nenue@32: if self.lastBlock then Nenue@32: block:SetPoint('TOPLEFT', self.lastBlock, 'BOTTOMLEFT', 0, 0) Nenue@32: print('--', i, data.isComplete, data.missionEndTime, data.name) Nenue@32: else Nenue@32: block:SetPoint('TOPLEFT', 0, 0) Nenue@32: print('--top') Nenue@32: end Nenue@32: self.lastBlock = block Nenue@32: Nenue@32: totalHeight = totalHeight + block:GetHeight() Nenue@32: block.lastProfile = lastProfile Nenue@32: -- blot out arbitrary flags Nenue@32: block.offerEndTime = nil Nenue@32: block.missionEndTime = nil Nenue@32: block.creationTime = nil Nenue@32: block.duration = nil Nenue@32: block.throttle = 5 Nenue@32: Nenue@32: for k,v in pairs(data) do Nenue@32: if type(block[k]) ~= 'function' then Nenue@32: block[k] = v Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: block:Update() Nenue@32: self:SetOwnerData(block, data) Nenue@32: Nenue@32: block:Show() Nenue@32: lastProfile = data.profileKey Nenue@6: end Nenue@6: Nenue@32: for i = numItems + 1, self.numBlocks do Nenue@32: if blocks[i] then Nenue@32: blocks[i]:Hide() Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: self:Reanchor() Nenue@32: Nenue@32: return totalHeight Nenue@32: end Nenue@32: Nenue@32: Nenue@32: function ShipmentList:Reanchor() Nenue@32: print('|cFF00FFFF'..self:GetName()..':Reanchor|r') Nenue@32: self:SetPoint('TOPLEFT', 0, -24) Nenue@32: self:SetPoint('BOTTOMRIGHT', -ClassOrderPlan:GetWidth()/2, 0) Nenue@32: end Nenue@32: Nenue@32: function MissionList:Reanchor() Nenue@32: self:SetPoint('TOPRIGHT', 0, -24) Nenue@32: self:SetPoint('BOTTOMLEFT', ClassOrderPlan:GetWidth()/2, 0) Nenue@32: Nenue@32: self.ListTab:ClearAllPoints() Nenue@32: self.ListTab:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, CP_HEADER_SIZE) Nenue@32: self.ListTab:SetPoint('BOTTOMRIGHT', self, 'TOPRIGHT', 0, 0) Nenue@32: self.ListTab.Label:SetText(self.listTitle[self.currentListIndex]) Nenue@32: self.ListTab:Show() Nenue@32: print(self.ListTab:GetSize()) Nenue@32: end Nenue@32: Nenue@32: function MissionList:GetPlayerData (profile) Nenue@32: wipe(profile.missions) Nenue@32: wipe(profile.available) Nenue@32: Nenue@32: local items = C_Garrison.GetAvailableMissions(GetPrimaryGarrisonFollowerType(LE_GARRISON_TYPE_7_0)); Nenue@32: for i = 1, #items do Nenue@32: if (not items[i].isBuilding and items[i].isZoneSupport) then Nenue@32: else Nenue@32: Nenue@32: tinsert(profile.available, items[i]) Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: local items = C_Garrison.GetLandingPageItems(LE_GARRISON_TYPE_7_0) Nenue@32: for index, data in ipairs(items) do Nenue@32: print(' -',data.name, '|cFF00FF00'.. data.timeLeft .. '|r', date("%A %I:%m %p", data.missionEndTime)) Nenue@32: tinsert(profile.missions, data) Nenue@32: end Nenue@32: return true Nenue@32: end Nenue@32: Nenue@32: do Nenue@32: local ShipmentsInfo = {} Nenue@32: local AddShipmentInfo = function(shipmentType, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID, followerID) Nenue@32: -- early login queries may return empty tables, causing the sorter to compare nil Nenue@32: if not creationTime then Nenue@32: return Nenue@32: end Nenue@32: --print(shipmentType, name, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString) Nenue@32: tinsert(ShipmentsInfo, Nenue@32: { Nenue@32: shipmentType = shipmentType, Nenue@32: name = name, Nenue@32: icon = texture, Nenue@32: shipmentCapacity = shipmentCapacity, Nenue@32: shipmentsReady = shipmentsReady, Nenue@32: shipmentsTotal = shipmentsTotal, Nenue@32: creationTime = creationTime, Nenue@32: duration = duration, Nenue@32: timeleftString = timeleftString, Nenue@32: itemName = itemName, Nenue@32: itemIcon = itemIcon, Nenue@32: itemQuality = itemQuality, Nenue@32: itemID = itemID, Nenue@32: followerID = followerID, Nenue@32: }) Nenue@32: end Nenue@32: function ShipmentList:GetPlayerData (profile) Nenue@32: if not profile then Nenue@32: return false Nenue@32: end Nenue@32: local profileList = profile.shipments Nenue@32: wipe(ShipmentsInfo) Nenue@32: Nenue@32: local garrisonType = LE_GARRISON_TYPE_7_0 Nenue@32: local buildings = CG_GetBuildings(garrisonType); Nenue@32: local shipmentIndex = 0 Nenue@32: --print('Buildings:') Nenue@32: for i = 1, #buildings do Nenue@32: local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID = CG_GetLandingPageShipmentInfo(buildingID); Nenue@32: AddShipmentInfo('Building', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID) Nenue@32: end Nenue@32: Nenue@32: --print('Follower:') Nenue@32: local followerShipments = CG_GetFollowerShipments(garrisonType); Nenue@32: for i = 1, #followerShipments do Nenue@32: local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, _, _, _, _, followerID = CG_GetLandingPageShipmentInfoByContainerID(followerShipments[i]); Nenue@32: AddShipmentInfo('Follower', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, nil, nil, nil, nil, followerID) Nenue@32: end Nenue@32: Nenue@32: --print('Loose:') Nenue@32: local looseShipments = CG_GetLooseShipments(garrisonType) Nenue@32: for i = 1, #looseShipments do Nenue@32: local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString = CG_GetLandingPageShipmentInfoByContainerID(looseShipments[i]); Nenue@32: AddShipmentInfo('Misc', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString) Nenue@32: end Nenue@32: Nenue@32: local talentTrees = CG_GetTalentTrees(garrisonType, select(3, UnitClass("player"))); Nenue@32: -- this is a talent that has completed, but has not been seen in the talent UI yet. Nenue@32: local completeTalentID = CG_GetCompleteTalent(garrisonType); Nenue@32: --print('Talents:') Nenue@32: if (talentTrees) then Nenue@32: for treeIndex, tree in ipairs(talentTrees) do Nenue@32: for talentIndex, talent in ipairs(tree) do Nenue@32: local showTalent = false; Nenue@32: if (talent.isBeingResearched) or (talent.id == completeTalentID) then Nenue@32: AddShipmentInfo('Talent', talent.name, talent.icon, 1, (talent.isBeingResearched and 0 or 1), 1, talent.researchStartTime, talent.researchDuration, talent.timeleftString) Nenue@32: end Nenue@32: end Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: wipe(profileList) Nenue@32: for index, data in ipairs(ShipmentsInfo) do Nenue@32: --DEFAULT_CHAT_FRAME:AddMessage(data.shipmentType ..' '.. tostring(data.name) ..' '.. tostring(data.creationTime) ..' '.. tostring(data.duration)) Nenue@32: tinsert(profileList, data) Nenue@32: end Nenue@32: self.isStale = true Nenue@32: return true Nenue@32: end Nenue@32: end Nenue@32: MissionList.OnGetItem = function(data) Nenue@32: if data.missionEndTime and (data.missionEndTime < GI_currentTime) then Nenue@32: data.isComplete = true Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: MissionList.FreeBlock = function(self, block) Nenue@32: end Nenue@32: Nenue@32: MissionList.SortHandler = function (a,b) Nenue@32: local result = false Nenue@32: --if not a or not b then Nenue@32: -- return true Nenue@32: --else Nenue@32: --if (a.isMine ~= b.isMine) then Nenue@32: -- result = a.isMine Nenue@32: --else Nenue@32: --if (not b.missionEndTime) or (not a.missionEndTime) then Nenue@32: -- print('missing article', b.missionEndTime, a.missionEndTime) Nenue@32: --end Nenue@32: if b.isComplete ~= a.isComplete then Nenue@32: return a.isComplete Nenue@32: elseif b.isMine ~= a.isMine then Nenue@32: return a.isMine Nenue@32: elseif b.missionEndTime then Nenue@32: return ( b.missionEndTime > a.missionEndTime) Nenue@32: else Nenue@32: return ( b.offerEndTime > a.offerEndTime) Nenue@32: end Nenue@32: Nenue@32: --end Nenue@32: --end Nenue@32: end Nenue@32: Nenue@32: Nenue@32: function MissionList:OnShow() Nenue@32: print('|cFF00FF88'..self:GetName()..':OnShow()|r') Nenue@32: end Nenue@32: Nenue@32: function ShipmentList:OnLoad() Nenue@32: C_Garrison.RequestLandingPageShipmentInfo(); Nenue@32: end Nenue@32: function ShipmentList:OnShow() Nenue@32: print('|cFF00FF88'..self:GetName()..':OnShow()|r') Nenue@32: C_Garrison.RequestLandingPageShipmentInfo() Nenue@32: end Nenue@32: Nenue@32: -- Update shipment flags data Nenue@32: local SetActualShipmentTime = function(self) Nenue@32: Nenue@32: if self.isComplete then Nenue@32: print('|cFF00FF88isComplete '..self.name..'|r') Nenue@32: return true Nenue@32: end Nenue@32: Nenue@32: local timestamp = time() Nenue@32: local timeLeft = self.creationTime + self.duration - timestamp Nenue@32: local justFinished = false Nenue@32: while (self.shipmentsReady < self.shipmentsTotal) and (timeLeft <= 0) do Nenue@32: if not self.originalReady then Nenue@32: self.originalReady = self.shipmentsReady Nenue@32: self.originalCreationTime = self.creationTime Nenue@32: end Nenue@32: Nenue@32: Nenue@32: self.shipmentsReady = self.shipmentsReady + 1 Nenue@32: self.creationTime = self.creationTime + self.duration Nenue@32: timeLeft = timeLeft + self.duration Nenue@32: print('|cFF00FF88udpating '..self.name..'|r', 'timeLeft:', timeLeft, 'shipments:', self.shipmentsReady, self.shipmentsTotal) Nenue@32: end Nenue@32: Nenue@32: if (timeLeft <= 0) and (not self.isBeingResearched) then Nenue@32: self.isComplete = true Nenue@32: self.isStale = true Nenue@32: end Nenue@32: Nenue@32: return timeLeft Nenue@32: end Nenue@32: Nenue@32: ShipmentList.OnGetItem = function(data) Nenue@32: print('OnGetItem()') Nenue@32: if data.shipmentsTotal then Nenue@32: SetActualShipmentTime(data) Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: ShipmentList.SortHandler = function(a, b) Nenue@32: if b.isComplete ~= a.isComplete then Nenue@32: return a.isComplete and true or false Nenue@32: elseif a.shipmentsReady or b.shipmentsReady then Nenue@32: return (a.shipmentsReady or 0) > (b.shipmentsReady or 0) Nenue@32: else Nenue@32: return (a.creationTime) < (b.creationTime) Nenue@32: end Nenue@32: end Nenue@32: Nenue@32: Nenue@32: function MissionEntry:OnComplete() Nenue@32: print('flagging complete', self.name) Nenue@32: self:Update() Nenue@32: end Nenue@32: Nenue@32: function MissionEntry:OnUpdate(sinceLast) Nenue@32: self.throttle = (self.throttle or .5) + sinceLast Nenue@32: if self.throttle < .5 then Nenue@32: return Nenue@32: else Nenue@32: self.throttle = self.throttle - .5 Nenue@32: end Nenue@32: if self.offerEndTime then Nenue@32: local timeLeft = self.offerEndTime Nenue@32: self.TimeLeft:SetText(GetTimeLeftString(timeLeft)) Nenue@32: self.TimeLeft:SetTextColor(1,1,1) Nenue@32: elseif self.missionEndTime then Nenue@32: Nenue@32: if self.isComplete then Nenue@32: return Nenue@32: end Nenue@1: local timeLeft = self.missionEndTime - time() Nenue@1: if timeLeft < 0 then Nenue@2: self:OnComplete() Nenue@1: else Nenue@2: self.TimeLeft:SetText(GetTimeLeftString(timeLeft)) Nenue@2: if timeLeft > 3600 then Nenue@2: self.TimeLeft:SetTextColor(1,1,1) Nenue@2: else Nenue@2: self.TimeLeft:SetTextColor(1,1,0) Nenue@2: end Nenue@6: end Nenue@2: Nenue@6: if not self.isComplete then Nenue@18: local progress = (time() - (self.missionEndTime - self.durationSeconds)) / self.durationSeconds Nenue@6: local w = self.ProgressBG:GetWidth() Nenue@6: if progress >= 1 then Nenue@6: self.ProgressBar:SetWidth(w) Nenue@6: else Nenue@18: self.ProgressBar:SetWidth(progress * w) Nenue@18: local r, g = 1, 0 Nenue@18: if progress >= 0.5 then Nenue@18: g = 1 Nenue@18: r = 1-((progress-0.5)*2) Nenue@18: else Nenue@18: g = min(progress * 2, 1) Nenue@18: r = 1 Nenue@18: end Nenue@32: self.ProgressBar:SetColorTexture(r,g,0,.4) Nenue@18: self.ProgressBG:SetColorTexture(r,g,0,0.125) Nenue@6: end Nenue@6: self.ProgressBG:Show() Nenue@6: self.ProgressBar:Show() Nenue@6: else Nenue@6: self.ProgressBG:Hide() Nenue@6: self.ProgressBar:Hide() Nenue@1: end Nenue@1: else Nenue@1: self.TimeLeft:SetText(self.missionEndTime) Nenue@1: end Nenue@2: end Nenue@2: Nenue@32: function MissionEntry:OnLoad() Nenue@32: print('|cFFFF4400',self:GetName() or tostring(self), 'onload') Nenue@32: self.Count = self.Overlay.Count Nenue@32: self.Name = self.Overlay.Name Nenue@32: self.TimeLeft = self.Overlay.TimeLeft Nenue@32: self.Owner = self.Overlay.Owner Nenue@32: Nenue@32: self.Icon:SetDesaturated(false) Nenue@32: self.Done:Hide() Nenue@32: end Nenue@32: Nenue@32: function MissionEntry:Update() Nenue@2: local r,g,b = 1, 1, 1 Nenue@4: if self.isRare then Nenue@2: r,g,b = 0.1, 0.4, 1 Nenue@5: self.IconBorder:SetVertexColor(r, g, b, 1) Nenue@2: end Nenue@2: Nenue@2: --self.missionData = data Nenue@5: self.Name:SetText(self.name) Nenue@4: if #self.rewards >= 1 then Nenue@4: self.Icon:SetTexture(self.rewards[1].icon or GetItemIcon(self.rewards[1].itemID)) Nenue@4: self.rewardInfo = self.rewards[1] Nenue@2: else Nenue@4: self.Icon:SetAtlas(self.typeAtlas, false) Nenue@2: end Nenue@6: Nenue@32: Nenue@6: Nenue@18: if self.isComplete then Nenue@18: self.TimeLeft:SetText('Complete!') Nenue@18: self.Background:SetColorTexture(.25,.25,.25,1) Nenue@18: else Nenue@18: self.Background:SetColorTexture(0,0,0,0.5) Nenue@18: end Nenue@2: end Nenue@2: Nenue@32: function MissionEntry:OnEnter() Nenue@2: if self.rewardInfo and self.rewardInfo.itemID then Nenue@2: GameTooltip:SetOwner(self, 'ANCHOR_LEFT') Nenue@2: GameTooltip:SetItemByID(self.rewardInfo.itemID) Nenue@2: GameTooltip:Show() Nenue@2: end Nenue@2: end Nenue@19: Nenue@32: function MissionEntry:OnLeave() Nenue@2: if GameTooltip:IsOwned(self) then Nenue@2: GameTooltip:Hide() Nenue@2: end Nenue@2: end Nenue@2: Nenue@32: function ShipmentEntry:OnLoad() Nenue@32: MissionEntry.OnLoad(self) Nenue@32: end Nenue@3: Nenue@32: Nenue@32: function ShipmentEntry:Update() Nenue@32: print('|cFF0088FF'.. self.name..'|r:Update()') Nenue@4: self.Icon:SetTexture(self.icon) Nenue@4: self.Count:SetText(self.shipmentsReady) Nenue@4: self.Done:SetShown(self.shipmentsReady and (self.shipmentsReady >= 1)) Nenue@2: Nenue@3: -- flag as complete Nenue@32: Nenue@32: local bgColor = CP_BACKGROUND_COLOR.inProgress Nenue@6: if ( self.shipmentsReady >= self.shipmentsTotal ) and (not self.isBeingResearched) then Nenue@2: self.Swipe:SetCooldownUNIX(0, 0); Nenue@2: self.Done:Show(); Nenue@32: bgColor = CP_BACKGROUND_COLOR.complete Nenue@2: else Nenue@32: if (self.shipmentsReady >= 1) and (self.shipmentsReady < self.shipmentsTotal) then Nenue@32: bgColor = CP_BACKGROUND_COLOR.shipmentsReady Nenue@32: end Nenue@4: self.Swipe:SetCooldownUNIX(self.creationTime or 0 , self.duration or 0); Nenue@2: end Nenue@32: self.Background:SetColorTexture(unpack(bgColor)) Nenue@2: Nenue@32: SetActualShipmentTime(self) Nenue@32: Nenue@32: if self.originalReady then Nenue@32: print('|cFF00FF88'..self.name..'|r', 'starting ready:', self.originalReady, 'starting time:', self.originalCreationTime) Nenue@18: end Nenue@19: end Nenue@18: Nenue@32: function ShipmentEntry:OnUpdate(sinceLast) Nenue@18: self.throttle = (self.throttle or 1) + sinceLast Nenue@18: if self.throttle >= 1 then Nenue@18: self.throttle = self.throttle - 1 Nenue@18: else Nenue@18: return Nenue@18: end Nenue@2: Nenue@32: Nenue@6: if (self.shipmentsReady and self.shipmentsTotal) and (self.shipmentsReady < self.shipmentsTotal) then Nenue@32: local timeLeft = SetActualShipmentTime(self) Nenue@32: Nenue@32: if self.isComplete then Nenue@32: self.TimeLeft:SetText('Complete!') Nenue@32: self.TimeLeft:SetTextColor(0,0.5,1) Nenue@32: elseif self.shipmentsReady >= 1 then Nenue@6: self.TimeLeft:SetText(GetTimeLeftString(timeLeft)) Nenue@6: self.TimeLeft:SetTextColor(0,1,0) Nenue@6: else Nenue@6: self.TimeLeft:SetText(GetTimeLeftString(timeLeft)) Nenue@6: self.TimeLeft:SetTextColor(1,1,1) Nenue@6: end Nenue@32: Nenue@4: elseif self.isBeingResearched then Nenue@4: self.TimeLeft:SetText(GetTimeLeftString(self.researchStartTime + self.researchDuration - time())) Nenue@6: self.TimeLeft:SetTextColor(1,1,0) Nenue@2: else Nenue@2: self.TimeLeft:SetText('Complete!') Nenue@6: self.TimeLeft:SetTextColor(0,1,0) Nenue@2: end Nenue@2: Nenue@18: if not self.isComplete then Nenue@18: local progress = ((time() - self.creationTime) / self.duration) Nenue@18: local w = self.ProgressBG:GetWidth() Nenue@18: if progress >= 1 then Nenue@18: self.ProgressBar:SetWidth(w) Nenue@18: else Nenue@18: self.ProgressBar:SetWidth(progress * w) Nenue@18: end Nenue@18: Nenue@18: local r, g = 1, 0 Nenue@18: if progress >= 0.5 then Nenue@18: g = 1 Nenue@18: r = 1-((progress-0.5)*2) Nenue@18: else Nenue@18: g = min(progress * 2, 1) Nenue@18: r = 1 Nenue@18: end Nenue@32: self.ProgressBar:SetColorTexture(r, g, 0, .4) Nenue@18: self.ProgressBG:SetColorTexture(r, g, 0, .125) Nenue@18: self.ProgressBG:Show() Nenue@18: self.ProgressBar:Show() Nenue@18: else Nenue@18: self.ProgressBG:Hide() Nenue@18: self.ProgressBar:Hide() Nenue@18: end Nenue@2: end Nenue@2: Nenue@32: function ShipmentEntry:OnEnter() Nenue@4: if ( self.shipmentsReady and self.shipmentsTotal ) then Nenue@2: GameTooltip:SetOwner(self, 'ANCHOR_LEFT') Nenue@4: GameTooltip:AddLine(self.Owner:GetText(), self.Owner:GetTextColor()) Nenue@4: GameTooltip:AddLine(self.shipmentType) Nenue@4: GameTooltip:AddLine(self.shipmentsReady .. ' of '.. self.shipmentsTotal) Nenue@2: GameTooltip:Show() Nenue@2: end Nenue@2: end Nenue@2: Nenue@32: function ShipmentEntry:OnLeave() Nenue@2: if GameTooltip:IsOwned(self) then Nenue@2: GameTooltip:Hide() Nenue@2: end Nenue@2: end Nenue@2: Nenue@32: function ShipmentEntry:OnClick(button) Nenue@3: if button == 'RightButton' then Nenue@4: self.handler:FreeBlock(self) Nenue@3: end Nenue@32: end Nenue@32: Nenue@32: ClassPlanMissionHandler = Mixin(MissionList, SharedHandlers) Nenue@32: ClassPlanShipmentHandler = Mixin(ShipmentList, SharedHandlers) Nenue@32: ClassPlanMissionEntryMixin = Mixin(MissionEntry, SharedEntry) Nenue@32: ClassPlanShipmentEntryMixin = Mixin(ShipmentEntry,SharedEntry) Nenue@32: Nenue@32: ClassPlanHeaderMixin = { Nenue@32: OnClick = function(self) Nenue@32: self:GetParent():SetList() Nenue@32: self:GetParent().isStale = true Nenue@32: ClassOrderPlan:Update() Nenue@32: end Nenue@32: }