Mercurial > wow > worldplan
view ClassPlan.lua @ 74:2ba11b25aa7f
flight map data handler adjustments
author | Nenue |
---|---|
date | Sat, 08 Apr 2017 17:07:58 -0400 |
parents | 79e5e96e5f18 |
children | b29b35cb8539 |
line wrap: on
line source
local _, db = ... local wipe, tinsert, sort = table.wipe, tinsert, table.sort local pairs, ipairs = pairs, ipairs local floor, mod, time = floor, mod, time local max, min = math.max, math.min local GetTime = GetTime local GI_currentTime = time() local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop local CP_REPLACE_LANDINGPAGE = true local CP_HEADER_SIZE = 24 db.ClassPlanDefaultType = { backgroundColor = {0, 0, 0, 0.5}, textColor = {1,1,1,1} } db.ClassPlanTypes = setmetatable({}, {__index = db.ClassPlanDefaultType}) db.ClassPlanTypes.inProgress = { backgroundColor = {0, 0, 0, 0.5}, textColor = {1,1,1} } db.ClassPlanTypes.shipmentsReady = { backgroundColor = {1, 1, 0, 0.25 }, textColor = {1, 1, 0} } db.ClassPlanTypes.complete = { backgroundColor = {0, 1, 0, 0.25 }, textColor = {0, 1, 0} } local GetTimeLeftString = function(timeLeft) local days = floor(timeLeft/(24*3600)) local hours = floor(mod(timeLeft, (24*3600)) / 3600) local minutes = floor(mod(timeLeft, 3600) / 60) local seconds = mod(timeLeft, 60) if days >= 1 then return (days .. 'd' .. ' ') .. ((hours > 0) and (hours .. 'h') or '') else return ((hours > 0) and (hours .. 'h') or '') .. ((minutes > 0) and (' ' ..minutes .. ' min') or '') end end ClassOrderPlanCore = { events = {}, freeBlocks = {}, characterButtons = {}, blocks = {}, sortedItems = {}, timers = {}, shipments = {}, playerFirst = false, prototypes = {}, Queued = {}, Timers = {}, ReportChunks = {}, } ClassPlanHandlerBase = { numBlocks = 0, isStale = true, maxItems = 10 } ClassPlanEntryBase = {} local ClassPlan = ClassOrderPlanCore local Embed = function(object, ...) for i = 1, select('#', ...) do local src = select(i, ...) for k,v in pairs(src) do if not object[k] then object[k] = v end end end return object end function ClassPlan:OnLoad () self:RegisterEvent('PLAYER_LOGIN') self:RegisterEvent('ADDON_LOADED') self:RegisterEvent('PLAYER_REGEN_ENABLED') self:RegisterEvent('PLAYER_REGEN_DISABLED') self:RegisterEvent('GARRISON_SHOW_LANDING_PAGE') self:RegisterForDrag('LeftButton') self:SetMovable(true) self:SetToplevel(true) SLASH_CLASSPLAN1 = "/classplan" SLASH_CLASSPLAN2 = "/cp" SlashCmdList.CLASSPLAN = function(args) self:Toggle() end local originalScript = GarrisonLandingPageMinimapButton:GetScript('OnClick') GarrisonLandingPageMinimapButton:SetScript("OnClick", function(minimap, button) if button == 'LeftButton' and (not IsShiftKeyDown()) then self:Toggle() else originalScript(minimap, button) end end) self.FadeOut:SetScript('OnFinished', function() self:Hide() self.data.IsShown = nil self.isAnimating = nil end) self.FadeIn:SetScript('OnPlay', function() self.isAnimating = true self:SetShown(true) end) --hooksecurefunc(C_Garrison, 'RequestLandingPageShipmentInfo', function() -- WorldPlan:print("Requesting shipments data.") --end) C_Garrison.RequestLandingPageShipmentInfo(); self.isStale = true end function ClassPlan:GetCurrentProfile() WorldPlanData.OrderHall = WorldPlanData.OrderHall or {} local db = WorldPlanData.OrderHall self.data = db local characters = db.characters or {} db.characters = characters local name, realm = UnitName('player') realm = realm or GetRealmName() local profileName = name .. '-' .. realm self.profile = characters[profileName] or { showItems = true } self.characters = characters characters[profileName] = self.profile local classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))] local className = UnitClass('player') print('|cFFFFFF00Loaded:|r', classColor.hex, className, profileName) self.profile.classColor = classColor self.profile.className = className self.profile.characterName = name self.profile.characterRealm = realm -- flip it on self.profile.showItems = true self.HeaderInset:SetHeight(CP_HEADER_SIZE) self.ClassStripe:SetColorTexture(classColor.r, classColor.g, classColor.b, 1) self.ClassStripe:SetPoint('TOPLEFT', self.HeaderInset, 'BOTTOMLEFT') return self.profile end function ClassPlan:AddHandler(frame) print('|cFF00FF00'..frame:GetName()..' loaded') for i, event in ipairs(frame.events) do print('|cFF00FF00 event', event) frame:RegisterEvent(event) end frame.sortedItems = {} for index, listKey in ipairs(frame.listKey) do frame.profile = self.profile frame.data = self.data self.profile[listKey] = self.profile[listKey] or {} local listTitle = frame.listTitle[index] setmetatable(self.profile[listKey], { __tostring = function() return listTitle end }) frame.sortedItems[listKey] = {} end frame.owningFrame = self frame:SetList(1) end function ClassPlan:OnEvent (event, arg) print(event, arg) if event == 'PLAYER_REGEN_DISABLED' then if self:IsVisible() then self.combatHide = true self:SetShown(false) end elseif event == 'PLAYER_REGEN_ENABLED' then if self.combatHide == true then self.combatHide = nil self:SetShown(true) end elseif event == 'ADDON_LOADED' then if arg == 'Blizzard_GarrisonUI' then self:Reanchor() end elseif event == 'PLAYER_LOGIN' then if not self.initialized then self:Setup() end elseif event == 'GARRISON_SHOW_LANDING_PAGE' then self:RefreshData() end end function ClassPlan:Setup() if IsLoggedIn() then print('|cFFFFFF00'..self:GetName()..':Setup()|r') self:GetCurrentProfile() for _, handler in ipairs(self.Handlers) do self:AddHandler(handler) handler.initialized = true end self.initialized = true self:SetShown(self.data.IsShown) GarrisonMinimap_HidePulse(GarrisonLandingPageMinimapButton, 1) -- buildings GarrisonMinimap_HidePulse(GarrisonLandingPageMinimapButton, 5) -- missions end end --- Update space local max = math.max function ClassPlan:RefreshData() local detailsFailed for index, handler in pairs(self.Handlers) do print(' |cFF00FF00'..handler:GetName()..' data update|r') handler:RefreshData() end if detailsFailed then db.print('Unable to obtain player details. Trying again later.') else self.requestingData = nil end end function ClassPlan:Update() print('|cFF00FFFF'..self:GetName()..'Refresh()|r') self.currentHeight = 0 for index, handler in ipairs(self.Handlers) do local itemsHeight = handler:UpdateItems() if itemsHeight then self.currentHeight = max(itemsHeight, self.currentHeight) end end local index = 1 for key, info in pairs(self.data.characters) do print('cbutton', key) if self.data[key] then print('|cFFFF4400remove legacy value', key) self.data[key] = nil end local button = self.characterButtons[index] if not button then button = CreateFrame('Button', nil, self, 'ClassOrderPlanCharacterButton') button:SetID(index) self.characterButtons[index] = button if not self.lastButton then button:SetPoint('TOPLEFT', self.HeaderInset, 'TOPLEFT', 0, 0) else button:SetPoint('TOPLEFT', self.lastButton, 'TOPRIGHT', 2, 0) end self.lastButton = button end if not info.characterName then info.characterName, info.characterRealm = key:match("%(.+)%-(.+)^") end print(info.characterName) button:SetSize(CP_HEADER_SIZE, CP_HEADER_SIZE) button.profileKey = key button.className = info.className button.classColor = info.classColor button.characterName = info.characterName button.characterRealm = info.characterRealm button.showItems = info.showItems button.isMine = (info == self.profile) button:Update() button:Show() index = index + 1 end self.HeaderInset:SetHeight(CP_HEADER_SIZE) self.HeaderInset:ClearAllPoints() self.HeaderInset:SetPoint('TOPLEFT' ,self, 'TOPLEFT') self.HeaderInset:SetPoint('RIGHT' ,self, 'RIGHT') self.ClassStripe:ClearAllPoints() self.ClassStripe:SetPoint('TOPLEFT', self.HeaderInset, 'BOTTOMLEFT', 0, 0) self.ClassStripe:SetPoint('RIGHT') self:Reanchor() self.isStale = nil end function ClassPlan:Toggle() if self:IsShown() then self.FadeOut:Play() else self.data.IsShown = true self.FadeIn:Play() end end function ClassPlan:OnUpdate() if self.requestingData then self:RefreshData() elseif self.isStale then -- shouldn't happen, usually self:Update() end if #self.ReportChunks >= 1 then db.print(table.concat(self.ReportChunks, ', ')) wipe(self.ReportChunks) end end function ClassPlan:OnShow() print('|cFF00FFFFShow()') self.isStale = true self:Reanchor() end function ClassPlan:OnHide() print('|cFF00FFFFHide()') end function ClassPlan:Reanchor() if not (self.data.positionX and self.data.positionY) then self.data.positionX = 0 self.data.positionY = -148 end self:ClearAllPoints() self:SetPoint('TOP', self.data.positionX, self.data.positionY) self.currentHeight = 0 for index, frame in ipairs(self.Handlers) do frame:Reanchor() local ListTab = frame.ListTab if ListTab then ListTab:ClearAllPoints() ListTab:SetPoint('TOPLEFT', frame, 'TOPLEFT', 0, 0) ListTab:SetPoint('BOTTOMRIGHT', frame, 'TOPRIGHT', 0, -CP_HEADER_SIZE) ListTab.Label:SetText(frame.listTitle[frame.currentListIndex]) ListTab:Show() print(ListTab:GetSize()) end self.currentHeight = max(self.currentHeight, frame.currentHeight or 0) end self:SetHeight(self.currentHeight + self.HeaderInset:GetHeight() + self.ClassStripe:GetHeight()) end function ClassPlan:OnDragStart() self:StartMoving() end function ClassPlan:OnDragStop() self:StopMovingOrSizing() local x,y = self:GetCenter() if x and y then x = (x - GetScreenWidth()/2) y = (y - GetScreenHeight()/2) * -1 self.data.positionX, self.data.positionY = x,y print('saving positions:', x, y) end end function ClassPlanHandlerBase:ScheduleUpdate(expires) -- value will occasionally lag so check here local duration = expires - time() self.Timers = self.Timers or {} if (duration > 0) and (not self.Timers[expires]) then print(' adding timer at', expires, 'c', duration) self.Timers[expires] = true C_Timer.After(duration, function() self.isStale = true self:UpdateItems() self.Timers[expires] = nil end) end end function ClassPlanHandlerBase:SetList(index) local prevIndex = self.currentListIndex if not index then if self.currentListIndex == #self.listKey then index = 1 else index = self.currentListIndex + 1 end end print('|cFF0088FF'..self:GetName()..'|r:SetList()', index, self.listKey[index]) self.currentListIndex = index self.activeKey = self.listKey[index] self.activeTitle = self.listTitle[index] self.ListTab.Label:SetText(self.listTitle[index]) self.isStale = true if self.OnSetList then self:OnSetList(self.currentListIndex, prevIndex) end end function ClassPlanHandlerBase:OnMouseWheel(delta) self.scrollOffset = (self.scrollOffset or 0) - ((delta > 0) and 1 or -1) self:UpdateItems() end function ClassPlanHandlerBase:RefreshData() print('|cFF0088FF'..self:GetName()..':RefreshData()') local activeKey = self.activeKey local detailsFailed self.truncatedItems = 0 self.currentTime = time() if self:GetParent().profile then self:GetPlayerData() else detailsFailed = true end for _, listKey in ipairs(self.listKey) do local sortedItems = self.sortedItems[listKey] wipe(sortedItems) for key, profile in pairs(self.data.characters) do local isMine = (profile == self.profile) print(key, listKey, isMine, profile.showItems) local profileList = profile[listKey] if profileList and #profileList >= 1 then local classColor = profile.classColor or RAID_CLASS_COLORS['HUNTER'] if profile.showItems then for index, data in ipairs(profileList) do data.classColor = classColor data.profileKey = key data.isMine = isMine if self.OnGetItem then self:OnGetItem(data) end tinsert(sortedItems, data) end else self.truncatedItems = self.truncatedItems + 1 end end end if self.SortHandler then sort(sortedItems, self.SortHandler) end end for k,v in pairs(self.sortedItems) do print(' ', k) end self.isStale = true end function ClassPlanHandlerBase:OnEvent(event, id) if (event == 'GARRISON_MISSION_LIST_UPDATE') then if (id == LE_FOLLOWER_TYPE_GARRISON_7_0) then print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, id) self:RefreshData() end else print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, id) end end function ClassPlanHandlerBase:OnUpdate() if self.isStale then print('|cFF00FF00'..self:GetName()..':OnUpdate()|r') self:UpdateItems() end end -- Stuff set on every list item function ClassPlanHandlerBase:SetOwnerData (self, data) local name, realm = string.match(data.profileKey, "(.+)%-(.+)") local ownerText = '|c'.. data.classColor.colorStr .. name .. '|r' self.Owner:SetText(ownerText) self.Name:SetText(self.name) self.Name:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b) end function ClassPlanHandlerBase:Acquire(id) end function ClassPlanHandlerBase:FreeBlock (block) end function ClassPlanHandlerBase:UpdateItems() print('|cFF0088FF '..self:GetName()..':UpdateItems()|r', self.activeKey) self.MoreItemsUp:Hide() self.MoreItemsDown:Hide() local sortedItems = self.sortedItems[self.activeKey] local scrollOffset = self.scrollOffset or 0 local numItems = #sortedItems if (not sortedItems[scrollOffset+1]) or (numItems <= self.maxItems) then scrollOffset = 0 elseif (numItems > self.maxItems) and (scrollOffset > (numItems - self.maxItems)) then scrollOffset = (numItems - self.maxItems) end self.ListTab.Count:SetText(numItems) self.blocks = self.blocks or {} local blocks = self.blocks local lastProfile local totalHeight = (self.ListTab:GetHeight() or 0) self.lastBlock = nil self.numActive = 0 for i = 1, self.maxItems do local index = scrollOffset + i local data = sortedItems[index] if not data then print('|cFFFF4400end of data') break end local block = blocks[i] if not block then block = CreateFrame('Button', self:GetName()..'ListItem'..i , self, self.templateName) block.listType = self.activeKey block.doAnimation = true block.handler = self self.numBlocks = self.numBlocks + 1 blocks[i] = block end block:SetID(index) self.numActive = self.numActive + 1 if self.lastBlock then block:SetPoint('TOPLEFT', self.lastBlock, 'BOTTOMLEFT', 0, 0) --print('--', index, data.isComplete, data.missionEndTime, data.name) else block:SetPoint('TOPLEFT', self.ListTab, 'BOTTOMLEFT', 0, 0) --print('--top') end self.lastBlock = block totalHeight = totalHeight + block:GetHeight() block.lastProfile = lastProfile -- blot out arbitrary flags block.offerEndTime = nil block.missionEndTime = nil block.creationTime = nil block.duration = nil block.throttle = 5 for k,v in pairs(data) do if type(block[k]) ~= 'function' then block[k] = v end end block:Update() self:SetOwnerData(block, data) block:Show() lastProfile = data.profileKey end if self.numActive < numItems then if scrollOffset < (numItems - self.maxItems) then self.MoreItemsDown:Show() end if scrollOffset > 0 then self.MoreItemsUp:Show() end end for i = self.numActive + 1, self.numBlocks do if blocks[i] then blocks[i]:Hide() end end self:Reanchor() if totalHeight ~= self.currentHeight then self.currentHeight = totalHeight self:SetHeight(self.currentHeight) self:GetParent():Reanchor() end self.scrollOffset = scrollOffset self.isStale = nil return totalHeight end function ClassPlanEntryBase:OnAnimFinished() end function ClassPlanEntryBase:OnShow() print('|cFF44FF00'..self:GetName()..':OnShow()') if self.doAnimation then self.doAnimation = nil if not ClassOrderPlan.isAnimating then self.NewBlockFade:Play() end end end function ClassPlanEntryBase:SetTimeLeft(expires, duration) self.ProgressBG:Hide() self.ProgressBar:Hide() if not expires then return end -- calculate here since time isn't available local timeLeft = expires - time() if timeLeft < 0 then -- handle being complete if self.shipmentsReady and (self.shipmentsReady < self.shipmentsTotal) then self.TimeLeft:SetText('Ready') else self.TimeLeft:SetText('Complete!') end else self.TimeLeft:SetText(GetTimeLeftString(timeLeft)) end if (timeLeft > 0) and duration then local progress = (duration - timeLeft) / duration local r = ((progress >= .5) and (progress/2)) or 1 local g = ((progress <= .5) and (progress*2)) or 1 self.ProgressBG:Show() self.ProgressBar:Show() self.ProgressBG:SetColorTexture(r,g,0,0.25) self.ProgressBar:SetColorTexture(r,g,0,0.5) self.ProgressBar:SetWidth(self.ProgressBG:GetWidth() * progress) end end ClassPlanHeaderMixin = {} function ClassPlanHeaderMixin:OnLoad() self:EnableMouse((#self:GetParent().listKey > 1)) self:RegisterForClicks('AnyUp') end function ClassPlanHeaderMixin:OnClick () local frame = self:GetParent() frame:SetList() if frame.OnHeaderClick then frame.OnHeaderClick(frame) end end ClassPlanCharacterButtonMixin = { } function ClassPlanCharacterButtonMixin:Update () --print(CLASS_ICON_TCOORDS[self.className:upper()]) if self.className and CLASS_ICON_TCOORDS[self.className:upper()] then self.Icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[self.className:upper()])) end self.Icon:SetDesaturated((not self.showItems)) self.SelectGlow:SetShown(self.isMine) end function ClassPlanCharacterButtonMixin:OnEnter() if not self.profileKey then return end GameTooltip:SetOwner(self, 'ANCHOR_RIGHT') local info = ClassOrderPlan.data.characters[self.profileKey] GameTooltip:AddLine(self.characterName, self.classColor.r, self.classColor.g, self.classColor.b) local numItems = 0 if info.missions then GameTooltip:AddLine(#info.missions .. ' mission'..((#info.missions == 1) and '' or 's')..' in progress') end if info.shipments then GameTooltip:AddLine(#info.shipments .. ' work order' .. ((#info.shipments == 1) and '' or 's')) end if info.available then GameTooltip:AddLine(#info.available .. ' mission'..((#info.available == 1) and '' or 's')..' available') end GameTooltip:Show() end function ClassPlanCharacterButtonMixin:OnLeave() if GameTooltip:IsOwned(self) then GameTooltip:Hide() end end function ClassPlanCharacterButtonMixin:OnClick(button, down) print('OnClick', self.profileKey) local clist = ClassOrderPlan.data.characters if button == 'RightButton' then for _, profile in pairs(clist) do profile.showItems = true end else if clist[self.profileKey].showItems then clist[self.profileKey].showItems = nil else clist[self.profileKey].showItems = true end end for i, handler in ipairs(ClassOrderPlan.Handlers) do handler.isStale = true end ClassOrderPlan:RefreshData() ClassOrderPlan:Update() print(clist[self.profileKey].showItems) end