Mercurial > wow > worldplan
changeset 2:b8a19781f79b
shipment logging
author | Nenue |
---|---|
date | Thu, 13 Oct 2016 09:08:38 -0400 |
parents | 232617b8bcd5 |
children | c006ce87a147 |
files | ClassPlan.lua ClassPlan.xml |
diffstat | 2 files changed, 545 insertions(+), 100 deletions(-) [+] |
line wrap: on
line diff
--- a/ClassPlan.lua Thu Oct 13 05:32:43 2016 -0400 +++ b/ClassPlan.lua Thu Oct 13 09:08:38 2016 -0400 @@ -1,3 +1,11 @@ +local wipe = table.wipe +local pairs, ipairs = pairs, ipairs +local GetTime = GetTime +local blockTemplate = { + point = 'TOPLEFT', + relativePoint ='TOPLEFT', +} + SLASH_CLASSPLAN1 = "/classplan" SLASH_CLASSPLAN2 = "/cp" SlashCmdList.CLASSPLAN = function(args) @@ -10,27 +18,85 @@ end ClassOrderPlanCore = { + freeBlocks = {}, blocks = {}, - playerFirst = true, - timers = {} + shipmentBlocks = {}, + freeShipmentBlocks = {}, + sortedShipments = {}, + sortedMissions = {}, + timers = {}, + shipments = {}, + playerFirst = false, + templates = setmetatable({}, { + __newindex = function(t,k ,v) + if type(v) == 'table' then + setmetatable(v, {__index = blockTemplate}) + rawset(t,k,v) + end + end + }) } -ClassPlanBlockMixin = { - followers = {}, - blocks = {}, -} -local core, block = ClassOrderPlanCore, ClassPlanBlockMixin +ClassPlanBlockMixin = {} +ClassPlanShipmentMixin = setmetatable({}, {__index = ClassPlanBlockMixin}) +local core, block, shipment = ClassOrderPlanCore, ClassPlanBlockMixin, ClassPlanShipmentMixin local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop + + function core:OnLoad () self:RegisterUnitEvent('UNIT_PORTRAIT_UPDATE', 'player') - self:RegisterEvent('GARRISON_MISSION_STARTED') - self:RegisterEvent('GARRISON_MISSION_FINISHED') self:RegisterEvent('PLAYER_LOGIN') self:RegisterEvent('PLAYER_ENTERING_WORLD') + self:RegisterEvent('PLAYER_REGEN_ENABLED') + + self:RegisterEvent('GARRISON_MISSION_LIST_UPDATE') + self:RegisterEvent('GARRISON_MISSION_FINISHED') + self:RegisterEvent("GARRISON_LANDINGPAGE_SHIPMENTS"); + self:RegisterEvent("GARRISON_SHIPMENT_RECEIVED"); + self:RegisterEvent("GARRISON_TALENT_UPDATE"); + self:RegisterEvent("GARRISON_TALENT_COMPLETE"); end +core.templates.ClassPlanBlock = { + SetItemData = function(block, data) + block.isComplete = data.isComplete + block.missionEndTime = data.missionEndTime + end +} + +core.templates.ClassPlanShipment = { + + parent = false, + point = 'TOPRIGHT', + relativePoint ='TOPRIGHT', + SetItemData = function(block, data) + block.icon = data.icon + block.shipmentCapacity = data.shipmentCapacity + block.shipmentsReady = data.shipmentsReady + block.shipmentsTotal = data.shipmentsTotal + block.creationTime = data.creationTime + block.duration = data.duration + block.itemID = data.itemID + block.itemQuality = data.itemQuality + --[[ + icon = texture, + shipmentCapacity = shipmentCapacity, + shipmentsReady = shipmentsReady, + shipmentsTotal = shipmentsTotal, + creationTime = creationTime, + duration = duration, + timeleftString = timeleftString, + itemName = itemName, + itemIcon = itemIcon, + itemQuality = itemQuality, + itemID = itemID + + --]] + end +} function core:OnEvent (event, ...) + print(event) if event == 'UNIT_PORTRAIT_UPDATE' then SetPortraitTexture(self.portrait, 'player') elseif event == 'PLAYER_LOGIN' then @@ -48,166 +114,461 @@ end self.profile = self.data[self.profileKey] + self.profile.shipments = self.profile.shipments or {} + self.profile.missions = self.profile.missions or {} + self.profile.classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))] + + C_Garrison.RequestLandingPageShipmentInfo(); self.initialized = true - print('initialized') end end + elseif event == 'GARRISON_LANDINGPAGE_SHIPMENTS' or event == 'GARRISON_TALENT_UPDATE' then + self:UpdateShipments() + elseif event == 'PLAYER_REGEN_ENABLED' or event == 'GARRISON_MISSION_FINISHED' or event == 'GARRISON_TALENT_COMPLETE' or event == 'GARRISON_SHIPMENT_RECEIVED' then + self:UpdateNotifications() else - self:Refresh () + self:UpdateItems () end end -function core:UpdateList() - self.sortedMissions = self.sortedMissions or {} - table.wipe(self.sortedMissions) +function core:UpdateNotifications() +end +function core:RefreshItems(sortedItems, templateName) + self.blocks[templateName] = self.blocks[templateName] or {} + local blocks = self.blocks[templateName] + local template = self.templates[templateName] or { + parent = self.portrait, + point = 'TOPLEFT', + relativePoint ='TOPRIGHT', + } + + local lastProfile + local numItems = #sortedItems + for i, data in ipairs(sortedItems) do + local block = blocks[i] + + if not block then + block = CreateFrame('Frame', nil, self, templateName) + block:SetID(i) + template.numBlocks = (template.numBlocks or 0) + 1 + + if template.lastBlock then + block:SetPoint('TOPLEFT', template.lastBlock, 'BOTTOMLEFT', 0, 0) + else + block:SetPoint(template.point, self[template.parent] or self, template.relativePoint, 0, 0) + end + template.lastBlock = block + blocks[i] = block + end + + if template.SetItemData then + template.SetItemData(block, data) + end + + + block.lastProfile = lastProfile + block:Refresh(data) + block:Show() + lastProfile = data.profileKey + end + + for i = numItems + 1, template.numBlocks do + if blocks[i] then + blocks[i]:Hide() + end + end +end + +function core:Refresh() + if self.isStale then + self:SortLists() + end + self.isStale = nil + + self:RefreshItems(self.sortedMissions, 'ClassPlanBlock') + self:RefreshItems(self.sortedShipments, 'ClassPlanShipment') + + + local posX = self.data.posX or 0 + local posY = self.data.posY or -24 + local point = self.point or 'TOP' + local relativePoint = self.point or 'TOP' + self:SetPoint(point, UIParent, relativePoint, posX, posY) + + +end + +function core:OnUpdate() + if self.fadeTimer and self.fadeTimer < GetTime() then + self:Hide() + end +end + +function core:OnShow() + if self.isStale then + print('updating items on show') + self:Refresh() + end + +end + +function core:SortLists() + + wipe(self.sortedShipments) + wipe(self.sortedMissions) for name, profile in pairs(self.data) do local isMine = (profile == self.profile) for index, data in pairs(profile.missions) do data.classColor = profile.classColor or {r = 0.7, g = 0.7, b =0.7} - data.profileKey = name data.isMine = (profile == self.profile) tinsert(self.sortedMissions, data) end + + if not profile.shipments then + profile.shipments = {} + profile.shipment = nil + end + + for index, data in pairs(profile.shipments) do + data.classColor = profile.classColor or {r = 0.7, g = 0.7, b =0.7} + data.profileKey = name + data.isMine = (profile == self.profile) + tinsert(self.sortedShipments, data) + end end - for i, v in ipairs(self.sortedMissions) do - print(i, v.missionEndTime, v.name) - end - - - table.sort(self.sortedMissions, function(a,b) + table.sort(self.sortedMissions, function (a,b) local result = false if not a or not b then result = true else - if (a.isMine ~= b.isMine) and self.playerFirst then result = a.isMine else if (not b.missionEndTime) or (not a.missionEndTime) then print('missing article', b.missionEndTime, a.missionEndTime) end - result = ( b.missionEndTime > a.missionEndTime) end end - print('cmp', (b and (b.missionEndTime .. ' ' .. tostring(b.isMine)) or '-'), '>', (a and (a.missionEndTime .. ' ' .. tostring(a.isMine)) or '-'), result, n) + --print('cmp', (b and (b.missionEndTime .. ' ' .. tostring(b.isMine)) or '-'), '>', (a and (a.missionEndTime .. ' ' .. tostring(a.isMine)) or '-'), result, n) return result end) - self.isStale = nil - local lastProfile - local numItems = #self.sortedMissions - for i, data in ipairs(self.sortedMissions) do - local block = self.blocks[i] - if not block then - block = CreateFrame('Frame', nil, self, 'ClassPlanBlock') - block:SetID(i) - self.numBlocks = (self.numBlocks or 0) + 1 +end - if self.lastBlock then - block:SetPoint('TOPLEFT', self.lastBlock, 'BOTTOMLEFT', 0, 0) - else - block:SetPoint('TOPLEFT', self.portrait, 'TOPRIGHT', 0, 0) +function core:UpdateShipments() + print('|cFF0088FFShipments|r:', self.profileKey) + if not self.profile then + return + end + wipe(self.shipments) + + + local garrisonType = LE_GARRISON_TYPE_7_0 + local buildings = C_Garrison.GetBuildings(garrisonType); + local shipmentIndex = 0 + print('Buildings:') + for i = 1, #buildings do + local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID = C_Garrison.GetLandingPageShipmentInfo(buildingID); + print(buildings[i], name, creationTime, duration) + tinsert(self.shipments, + { + shipmentType = 'Work Order', + name = name, + icon = texture, + shipmentCapacity = shipmentCapacity, + shipmentsReady = shipmentsReady, + shipmentsTotal = shipmentsTotal, + creationTime = creationTime, + duration = duration, + timeleftString = timeleftString, + itemName = itemName, + itemIcon = itemIcon, + itemQuality = itemQuality, + itemID = itemID + }) + end + + print('Follower:') + local followerShipments = C_Garrison.GetFollowerShipments(garrisonType); + for i = 1, #followerShipments do + local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, _, _, _, _, followerID = C_Garrison.GetLandingPageShipmentInfoByContainerID(followerShipments[i]); + print(followerShipments[i], name, creationTime, duration) + tinsert(self.shipments, + { + shipmentType = '', + name = name, + icon = texture, + shipmentCapacity = shipmentCapacity, + shipmentsReady = shipmentsReady, + shipmentsTotal = shipmentsTotal, + creationTime = creationTime, + duration = duration, + timeleftString = timeleftString, + followerID = followerID, + }) + end + + print('Loose:') + local looseShipments = C_Garrison.GetLooseShipments(garrisonType) + for i = 1, #looseShipments do + local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString = C_Garrison.GetLandingPageShipmentInfoByContainerID(looseShipments[i]); + print(looseShipments[i], name, creationTime, duration) + tinsert(self.shipments, + { + shipmentType = '', + name = name, + icon = texture, + shipmentCapacity = shipmentCapacity, + shipmentsReady = shipmentsReady, + shipmentsTotal = shipmentsTotal, + creationTime = creationTime, + duration = duration, + timeleftString = timeleftString, + }) + end + + local talentTrees = C_Garrison.GetTalentTrees(garrisonType, select(3, UnitClass("player"))); + -- this is a talent that has completed, but has not been seen in the talent UI yet. + local completeTalentID = C_Garrison.GetCompleteTalent(garrisonType); + print('Talents:') + if (talentTrees) then + for treeIndex, tree in ipairs(talentTrees) do + for talentIndex, talent in ipairs(tree) do + local showTalent = false; + if (talent.isBeingResearched) then + showTalent = true; + end + if (talent.id == completeTalentID) then + showTalent = true; + end + if (showTalent) then + print(talent.name) + talent.creationTime = talent.researchStartTime + talent.duration = talent.researchDuration + talent.shipmentType = 'Talent: ' + tinsert(self.shipments, talent) + end end - self.lastBlock = block - self.blocks[i] = block end + end - local r,g,b = 1, 1, 1 - if data.isRare then - r,g,b = 0.1, 0.4, 1 + self.profile.shipments = self.profile.shipments or {} + if #self.shipments >= 1 then + + wipe(self.profile.shipments) + for index, shipment in ipairs(self.shipments) do + tinsert(self.profile.shipments, shipment) end - if data.isMine then - block.Icon:SetVertexColor(0,1,0,1) - else - block.Icon:SetVertexColor(1,1,1) - end + self.isStale = true + end - - --block.missionData = data - block.missionID = data.missionID - block.missionEndTime = data.missionEndTime - block.Icon:SetAtlas(data.typeAtlas, false) - block.Label:SetText(data.name) - block.Label:SetTextColor(r, g, b) - - if lastProfile ~= data.profileKey then - block.Owner:SetText(data.profileKey) - block.Owner:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b) - else - block.Owner:SetText(nil) - end - block.Background:SetColorTexture(data.classColor.r, data.classColor.g, data.classColor.b, 0.5) - - block:Show() - lastProfile = data.profileKey - end - for i = numItems + 1, self.numBlocks do - if self.blocks[i] then - self.blocks[i]:Hide() - end + if self:IsVisible() then + self:Refresh() end end -function core:OnShow() - if self.isStale then - print('updating items on show') - self:UpdateList() - end -end - -function core:Refresh () +function core:UpdateItems () if not self.profile then return end - self.items = C_Garrison.GetLandingPageItems(LE_GARRISON_TYPE_7_0) - self.profile.missions = self.profile.missions or {} - self.profile.classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))] - print('|cFF0088FFLocal Scoop|r:', self.profileKey) + print('|cFF0088FFLandingPageItems|r:', self.profileKey) if #self.items >= 1 then - table.wipe(self.profile.missions) + wipe(self.profile.missions) for index, data in ipairs(self.items) do print('', data.name) print(' |cFF00FF00', data.timeLeft .. '|r', date("%A %I:%m %p", data.missionEndTime)) tinsert(self.profile.missions, data) end + print('items update pending') + self.isStale = true end if self:IsVisible() then - self:UpdateList() + self:Refresh() + end +end + +function block:OnComplete() + self.isComplete = true + self:Refresh() +end + +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 - print('items update pending') - self.isStale = true + return ((hours > 0) and (hours .. 'h ') or '') .. ((minutes > 0) and (minutes .. ' min') or '') end end function block:OnUpdate() + if self.isComplete then + return + end + if self.missionEndTime then local timeLeft = self.missionEndTime - time() if timeLeft < 0 then - self.TimeLeft:SetText('Complete!') + self:OnComplete() else - 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) - self.TimeLeft:SetText( - ((days > 0) and (days .. ' d') or '') .. - ((hours > 0) and (' '.. hours .. ' hr') or '').. - ((minutes > 0) and (' ' .. minutes .. ' min' or '')) - , 1,1,1) + self.TimeLeft:SetText(GetTimeLeftString(timeLeft)) + + if timeLeft > 3600 then + self.TimeLeft:SetTextColor(1,1,1) + else + self.TimeLeft:SetTextColor(1,1,0) + end + end else self.TimeLeft:SetText(self.missionEndTime) end +end + +local SetClassColors = function(self, data) + + if self.lastProfile ~= data.profileKey then + self.Owner:SetText(data.profileKey) + self.Owner:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b) + else + self.Owner:SetText(nil) + end + self.Background:SetColorTexture(data.classColor.r, data.classColor.g, data.classColor.b, + (data.isComplete and 0.5 or 0.1)) +end + +function block:Refresh(data) + data = data or self.data + self.data = data + + local r,g,b = 1, 1, 1 + if data.isRare then + r,g,b = 0.1, 0.4, 1 + end + + + --self.missionData = data + self.Label:SetText(data.name) + self.Label:SetTextColor(r, g, b) + + if #data.rewards >= 1 then + self.Icon:SetTexture(data.rewards[1].icon or GetItemIcon(data.rewards[1].itemID)) + self.rewardInfo = data.rewards[1] + else + self.Icon:SetAtlas(data.typeAtlas, false) + end + + SetClassColors(self, data) + + if self.isComplete then + self.TimeLeft:SetText('Complete!') + end +end + + +function block:OnEnter() + if self.rewardInfo and self.rewardInfo.itemID then + GameTooltip:SetOwner(self, 'ANCHOR_LEFT') + GameTooltip:SetItemByID(self.rewardInfo.itemID) + GameTooltip:Show() + end +end +function block:OnLeave() + if GameTooltip:IsOwned(self) then + GameTooltip:Hide() + end +end + + + +function shipment:Refresh(data) + data = data or self.data + self.Icon:SetTexture(data.icon) + self.data = data + + self.Name:SetText(data.shipmentType .. data.name) + self.Count:SetText(data.shipmentsReady) + + self.Done:SetShown(data.shipmentsReady and (data.shipmentsReady >= 1)) + + if ( data.shipmentsReady == data.shipmentsTotal ) then + self.Swipe:SetCooldownUNIX(0, 0); + self.Done:Show(); + if not data.isBeingResearched then + data.isComplete = true + end + else + self.Swipe:SetCooldownUNIX(data.creationTime or 0 , data.duration or 0); + end + + + + SetClassColors(self, data) +end +function shipment:UpdateShipment() + + local data = self.data + if data.shipmentsTotal then + local timeLeft = data.creationTime + data.duration - time() + if timeLeft < 0 then + local numReady = floor((1*timeLeft) / data.duration) + data.shipmentsReady = data.shipmentsReady + numReady + data.creationTime = data.creationTime + (numReady * data.duration) + self:Refresh() + end + end +end +function shipment:OnUpdate() + local data = self.data + if (data.shipmentsReady and data.shipmentsTotal) and (data.shipmentsReady ~= data.shipmentsTotal) then + local timeLeft = data.creationTime + data.duration - time() + if timeLeft < 0 then + self:UpdateShipment() + return + end + + self.TimeLeft:SetText('Next: '.. GetTimeLeftString(timeLeft) .. ' |cFFFFFF00'..data.shipmentsTotal..' orders|r') + + + elseif data.isBeingResearched then + self.TimeLeft:SetText(GetTimeLeftString(data.researchStartTime + data.researchDuration - time())) + else + self.TimeLeft:SetText('Complete!') + end + +end + +function shipment:OnEnter() + local data = self.data + if ( data.shipmentsReady and data.shipmentsTotal ) then + GameTooltip:SetOwner(self, 'ANCHOR_LEFT') + GameTooltip:AddLine(data.shipmentsReady .. ' of '.. data.shipmentsTotal) + GameTooltip:Show() + end +end + +function shipment:OnLeave() + if GameTooltip:IsOwned(self) then + GameTooltip:Hide() + end +end + +function shipment:OnClick(button) + --todo: trigger cleanup script for dead shipment data end \ No newline at end of file
--- a/ClassPlan.xml Thu Oct 13 05:32:43 2016 -0400 +++ b/ClassPlan.xml Thu Oct 13 09:08:38 2016 -0400 @@ -3,8 +3,11 @@ <Script file="ClassPlan.lua" /> + <Font name="ClassPlanFont" font="Interface\AddOns\Veneer\Font\ArchivoNarrow-Regular.ttf" height="14" outline="NORMAL" virtual="true" /> + <Font name="ClassPlanNumberFont" font="Interface\AddOns\Veneer\Font\ArchivoNarrow-Bold.ttf" height="14" outline="NORMAL" virtual="true" /> + <Frame name="ClassOrderPlan" mixin="ClassOrderPlanCore" parent="UIParent" hidden="true"> - <Size x="500" y="40" /> + <Size x="600" y="40" /> <Anchors> <Anchor point="TOP" /> </Anchors> @@ -31,6 +34,8 @@ <Scripts> <OnUpdate method="OnUpdate" /> <OnShow method="OnShow" /> + <OnEnter method="OnEnter" /> + <OnLeave method="OnLeave" /> </Scripts> <Layers> <Layer level="BACKGROUND"> @@ -47,22 +52,101 @@ </Texture> </Layer> <Layer level="OVERLAY"> - <FontString name="$parentLabel" inherits="GameFontNormal" parentKey="Label" text="base text"> + <FontString name="$parentLabel" inherits="ClassPlanFont" parentKey="Label" text="base text"> <Anchors> <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeKey="$parent.Icon" x="4" y="0" /> </Anchors> </FontString> - <FontString name="$parentTimeLeft" inherits="GameFontNormalSmall" parentKey="TimeLeft" text="base text"> + <FontString name="$parentTimeLeft" inherits="ClassPlanNumberFont" parentKey="TimeLeft" text="base text"> <Anchors> <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.Label" x="4" y="-2" /> </Anchors> </FontString> - <FontString name="$parentOwner" inherits="GameFontNormalSmall" parentKey="Owner" text="base text"> + <FontString name="$parentOwner" inherits="ClassPlanFont" parentKey="Owner" text="base text"> + <Anchors> + <Anchor point="TOPRIGHT" /> + </Anchors> + </FontString> + </Layer> + <Layer level="HIGHLIGHT"> + <Texture setAllPoints="true" alphaMode="ADD"> + <Color a="1" r="0.1" g="0.1" b="0.1" /> + </Texture> + </Layer> + </Layers> + </Frame> + + <Frame name="ClassPlanShipment" mixin="ClassPlanShipmentMixin" virtual="true"> + <Scripts> + <OnUpdate method="OnUpdate" /> + <OnShow method="OnShow" /> + <OnEnter method="OnEnter" /> + <OnLeave method="OnLeave" /> + </Scripts> + <Size x="200" y="32" /> + <Layers> + <Layer level="BACKGROUND"> + <Texture parentKey="Background" setAllPoints="true" /> + </Layer> + <Layer level="BACKGROUND" textureSubLevel="1"> + <Texture parentKey="Icon" alpha="0.5" desaturated="true"> + <Size x="30" y="30"/> + <Anchors> + <Anchor point="LEFT"/> + </Anchors> + </Texture> + </Layer> + <Layer level="BORDER"> + <Texture parentKey="Done" atlas="GarrLanding-ShipmentCompleteGlow"> + <Size x="32" y="32" /> + <Anchors> + <Anchor point="LEFT"/> + </Anchors> + </Texture> + </Layer> + <Layer level="ARTWORK"> + <FontString parentKey="Name" inherits="ClassPlanFont" justifyV="TOP" justifyH="CENTER"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeKey="$parent.Icon" x="2" y="-2"/> + </Anchors> + <Color r=".75" g=".75" b=".73"/> + </FontString> + </Layer> + <Layer level="OVERLAY"> + <FontString parentKey="TimeLeft" inherits="ClassPlanFont" justifyH="CENTER"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.Name" x="0" y="-2"/> + </Anchors> + </FontString> + <FontString parentKey="Count" inherits="WorldPlanFont" justifyH="CENTER"> + <Anchors> + <Anchor point="BOTTOM" relativeKey="$parent.Icon" x="0" y="0"/> + </Anchors> + </FontString> + <FontString name="$parentOwner" inherits="WorldPlanFont" parentKey="Owner" text="base text"> <Anchors> <Anchor point="TOPRIGHT" /> </Anchors> </FontString> </Layer> </Layers> + <Frames> + <Cooldown parentKey="Swipe" reverse="true" hideCountdownNumbers="true"> + <Size x="32" y="32"/> + <Anchors> + <Anchor point="LEFT"/> + </Anchors> + <SwipeTexture file="Interface\Garrison\GarrLanding-TradeskillTimerFill"/> + <Scripts> + <OnCooldownStart> + self:Show() + </OnCooldownStart> + <OnCoolDownDone> + -- update via event + C_Garrison.RequestLandingPageShipmentInfo(); + </OnCoolDownDone> + </Scripts> + </Cooldown> + </Frames> </Frame> </Ui> \ No newline at end of file