annotate ClassPlan.lua @ 33:be4db60219ca

WorldPlan: - Toggling a reward filter cancels out other types by default. Use right mouse to clear. - Fixed filter bar info falling out of sync after player-triggered world map updates. ClassPlan: - Available missions are now recorded; the mission list can be toggled between in-progress and available by clicking the heading.
author Nenue
date Wed, 02 Nov 2016 17:25:07 -0400
parents e8679ecb48d8
children 26dfa661daa7
rev   line source
Nenue@4 1 local wipe, tinsert, sort = table.wipe, tinsert, table.sort
Nenue@2 2 local pairs, ipairs = pairs, ipairs
Nenue@4 3 local floor, mod, time = floor, mod, time
Nenue@32 4 local max, min = math.max, math.min
Nenue@2 5 local GetTime = GetTime
Nenue@3 6 local GI_currentTime = time()
Nenue@32 7 local print = DEVIAN_WORKSPACE and function(...) print('ClassPlan', ...) end or nop
Nenue@3 8
Nenue@32 9 local CG_GetBuildings = C_Garrison.GetBuildings
Nenue@32 10 local CG_GetFollowerShipments = C_Garrison.GetFollowerShipments
Nenue@32 11 local CG_GetLooseShipments = C_Garrison.GetLooseShipments
Nenue@32 12 local CG_GetTalentTrees = C_Garrison.GetTalentTrees
Nenue@32 13 local CG_GetCompleteTalent = C_Garrison.GetCompleteTalent
Nenue@32 14 local CG_GetLandingPageShipmentInfo = C_Garrison.GetLandingPageShipmentInfo
Nenue@32 15 local CG_GetLandingPageShipmentInfoByContainerID = C_Garrison.GetLandingPageShipmentInfoByContainerID
Nenue@32 16
Nenue@32 17 local CP_REPLACE_LANDINGPAGE = true
Nenue@32 18 local CP_HEADER_SIZE = 24
Nenue@32 19 local CP_BACKGROUND_COLOR = {
Nenue@32 20 inProgress = {0, 0, 0, 0.5},
Nenue@32 21 shipmentsReady = {0, 0, 0, 0.25},
Nenue@32 22 complete = {0.5, 0.5, 0.5, 0.5}
Nenue@2 23 }
Nenue@2 24
Nenue@4 25 local GetTimeLeftString = function(timeLeft)
Nenue@4 26 local days = floor(timeLeft/(24*3600))
Nenue@4 27 local hours = floor(mod(timeLeft, (24*3600)) / 3600)
Nenue@4 28 local minutes = floor(mod(timeLeft, 3600) / 60)
Nenue@4 29 local seconds = mod(timeLeft, 60)
Nenue@4 30 if days >= 1 then
Nenue@6 31 return (days .. 'd' .. ' ') .. ((hours > 0) and (hours .. 'h') or '')
Nenue@4 32 else
Nenue@6 33 return ((hours > 0) and (hours .. 'h') or '') .. ((minutes > 0) and (' ' ..minutes .. ' min') or '')
Nenue@4 34 end
Nenue@4 35 end
Nenue@3 36
Nenue@23 37
Nenue@32 38 ClassOrderPlanCore = {
Nenue@32 39 events = {},
Nenue@32 40 freeBlocks = {},
Nenue@32 41 blocks = {},
Nenue@32 42 sortedItems = {},
Nenue@32 43 timers = {},
Nenue@32 44 shipments = {},
Nenue@32 45 playerFirst = false,
Nenue@32 46 prototypes = {},
Nenue@32 47 Queued = {}
Nenue@32 48 }
Nenue@32 49 local MissionList = {
Nenue@32 50 templateName = 'ClassPlanMissionEntry',
Nenue@32 51 listKey = {'missions', 'available'},
Nenue@32 52 listTitle = {'In Progress', 'Available'},
Nenue@23 53
Nenue@32 54 point = 'TOPLEFT',
Nenue@32 55 relativePoint ='TOPLEFT',
Nenue@32 56 events = {
Nenue@32 57 'GARRISON_MISSION_LIST_UPDATE',
Nenue@32 58 'GARRISON_LANDINGPAGE_SHIPMENTS'},
Nenue@32 59 }
Nenue@32 60 local ShipmentList = {
Nenue@32 61 templateName = 'ClassPlanShipmentEntry',
Nenue@32 62 listKey = {'shipments'},
Nenue@32 63 listTitle = {'Work Orders'},
Nenue@32 64 events = {
Nenue@32 65 'GARRISON_MISSION_LIST_UPDATE',
Nenue@32 66 'GARRISON_LANDINGPAGE_SHIPMENTS',
Nenue@32 67 'GARRISON_TALENT_UPDATE',
Nenue@32 68 "GARRISON_TALENT_COMPLETE",
Nenue@32 69 "GARRISON_SHIPMENT_RECEIVED",
Nenue@32 70 'GARRISON_FOLLOWER_LIST_UPDATE',
Nenue@32 71 'GARRISON_SHOW_LANDING_PAGE'},
Nenue@32 72 }
Nenue@32 73 local SharedHandlers = {
Nenue@32 74 numBlocks = 0,
Nenue@32 75 isStale = true,
Nenue@32 76 }
Nenue@32 77 local SharedEntry = {}
Nenue@32 78 local ShipmentEntry = {}
Nenue@32 79 local MissionEntry = {}
Nenue@1 80
Nenue@32 81 local ClassPlan = ClassOrderPlanCore
Nenue@5 82
Nenue@32 83 function ClassPlan:OnLoad ()
Nenue@3 84 self:RegisterEvent('PLAYER_LOGIN')
Nenue@3 85 self:RegisterEvent('ADDON_LOADED')
Nenue@3 86 self:RegisterEvent('PLAYER_REGEN_ENABLED')
Nenue@5 87 self:RegisterEvent('PLAYER_REGEN_DISABLED')
Nenue@32 88 self:RegisterForDrag('LeftButton')
Nenue@32 89 self:SetMovable(true)
Nenue@32 90 self:SetToplevel(true)
Nenue@32 91
Nenue@32 92
Nenue@32 93 SLASH_CLASSPLAN1 = "/classplan"
Nenue@32 94 SLASH_CLASSPLAN2 = "/cp"
Nenue@32 95 SlashCmdList.CLASSPLAN = function(args)
Nenue@32 96 self:Toggle()
Nenue@32 97 end
Nenue@32 98
Nenue@4 99 end
Nenue@19 100
Nenue@32 101 function ClassPlan:GetCurrentProfile()
Nenue@32 102 WorldPlanData.OrderHall = WorldPlanData.OrderHall or {}
Nenue@32 103 local db = WorldPlanData.OrderHall
Nenue@32 104 self.data = db
Nenue@4 105
Nenue@32 106 local characters = db.characters or {}
Nenue@32 107 db.characters = characters
Nenue@4 108
Nenue@32 109 local name, realm = UnitName('player')
Nenue@32 110 realm = realm or GetRealmName()
Nenue@32 111 local profileName = name .. '-' .. realm
Nenue@4 112
Nenue@32 113 self.profile = characters[profileName] or {}
Nenue@32 114 self.characters = characters
Nenue@32 115 characters[profileName] = self.profile
Nenue@32 116
Nenue@32 117
Nenue@32 118 local classColor = RAID_CLASS_COLORS[select(2, UnitClass('player'))]
Nenue@32 119 local className = UnitClass('player')
Nenue@32 120
Nenue@32 121 print('|cFFFFFF00Loaded:|r', classColor.hex, className, profileName)
Nenue@32 122 self.Background:SetColorTexture(classColor.r, classColor.g, classColor.b, 0.5)
Nenue@32 123 self.profile.classColor = classColor
Nenue@32 124 self.profile.className = className
Nenue@32 125 return self.profile
Nenue@3 126 end
Nenue@3 127
Nenue@32 128 function ClassPlan:SetupHandler(handler)
Nenue@32 129 print('|cFF00FF00'..handler:GetName()..' loaded')
Nenue@32 130 for i, event in ipairs(handler.events) do
Nenue@32 131 print('|cFF00FF00 event', event)
Nenue@32 132 handler:RegisterEvent(event)
Nenue@1 133 end
Nenue@32 134 for index, listKey in ipairs(handler.listKey) do
Nenue@32 135 self.profile[listKey] = self.profile[listKey] or {}
Nenue@32 136 local listTitle = handler.listTitle[index]
Nenue@32 137 setmetatable(self.profile[listKey], { __tostring = listTitle })
Nenue@32 138 end
Nenue@32 139 handler:SetList(1)
Nenue@32 140 handler.sortedItems = {}
Nenue@3 141 end
Nenue@1 142
Nenue@32 143 function ClassPlan:OnEvent (event, arg)
Nenue@32 144 print(event, arg)
Nenue@5 145 if event == 'PLAYER_REGEN_DISABLED' then
Nenue@6 146 if self:IsVisible() then
Nenue@6 147 self.combatHide = true
Nenue@6 148 self:SetShown(false)
Nenue@6 149 end
Nenue@6 150
Nenue@5 151 elseif event == 'PLAYER_REGEN_ENABLED' then
Nenue@6 152 if self.combatHide == true then
Nenue@6 153 self.combatHide = nil
Nenue@6 154 self:SetShown(true)
Nenue@6 155 end
Nenue@32 156 elseif event == 'ADDON_LOADED' then
Nenue@32 157 if arg == 'Blizzard_GarrisonUI' then
Nenue@32 158 self:Reanchor()
Nenue@32 159 end
Nenue@3 160 elseif event == 'PLAYER_LOGIN' then
Nenue@3 161 if not self.initialized then
Nenue@4 162 self:Setup()
Nenue@1 163 end
Nenue@2 164 end
Nenue@2 165 end
Nenue@2 166
Nenue@32 167 function ClassPlan:Setup()
Nenue@32 168 if IsLoggedIn() then
Nenue@32 169 print('|cFFFFFF00'..self:GetName()..':Setup()|r')
Nenue@32 170
Nenue@32 171 self:GetCurrentProfile()
Nenue@32 172 for _, handler in ipairs(self.Handlers) do
Nenue@32 173 self:SetupHandler(handler)
Nenue@32 174 end
Nenue@32 175 self.initialized = true
Nenue@32 176 self:SetShown(self.data.IsShown)
Nenue@32 177 end
Nenue@3 178 end
Nenue@3 179
Nenue@4 180
Nenue@32 181 --- Update space
Nenue@4 182
Nenue@32 183 local max = math.max
Nenue@32 184 function ClassPlan:Update()
Nenue@32 185 print('|cFF00FFFFRefresh()|r')
Nenue@32 186 self.currentHeight = 0
Nenue@32 187 for index, handler in pairs(self.Handlers) do
Nenue@32 188 if handler.isStale then
Nenue@32 189 print(' |cFF00FF00'..index..' '..handler:GetName()..'|r')
Nenue@32 190 local sortedItems = handler.sortedItems
Nenue@32 191 local activeKey = handler.activeKey
Nenue@32 192 handler.profile = self.profile[handler.activeKey]
Nenue@3 193
Nenue@32 194 wipe(sortedItems)
Nenue@32 195 handler:GetPlayerData(self.profile)
Nenue@32 196 for key, profile in pairs(self.data.characters) do
Nenue@32 197 print('profile', key, activeKey)
Nenue@32 198 local profileList = profile[activeKey]
Nenue@32 199 if profileList and #profileList >= 1 then
Nenue@32 200 local classColor = profile.classColor or defaultClassColor
Nenue@32 201 local isMine = (profile == self.profile)
Nenue@32 202 for index, data in ipairs(profileList) do
Nenue@32 203 data.classColor = classColor
Nenue@32 204 data.profileKey = key
Nenue@32 205 data.isMine = isMine
Nenue@32 206 if handler.OnGetItem then
Nenue@32 207 handler.OnGetItem(data)
Nenue@32 208 end
Nenue@32 209 tinsert(sortedItems, data)
Nenue@32 210 end
Nenue@32 211 end
Nenue@32 212 end
Nenue@3 213
Nenue@32 214 if handler.SortHandler then
Nenue@32 215 sort(sortedItems, handler.SortHandler)
Nenue@23 216 end
Nenue@23 217
Nenue@23 218 end
Nenue@32 219 handler.isStale = nil
Nenue@32 220 local itemsHeight = handler:UpdateItems()
Nenue@32 221 self.currentHeight = max(itemsHeight, self.currentHeight)
Nenue@23 222
Nenue@23 223 end
Nenue@23 224
Nenue@32 225 self.isStale = nil
Nenue@32 226 self:Reanchor()
Nenue@32 227 self:SetHeight(self.currentHeight + CP_HEADER_SIZE)
Nenue@3 228 end
Nenue@3 229
Nenue@3 230
Nenue@32 231 function ClassPlan:Toggle()
Nenue@5 232 if self:IsShown() then
Nenue@3 233 self:Hide()
Nenue@3 234 else
Nenue@3 235 self:Show()
Nenue@3 236 end
Nenue@3 237
Nenue@3 238 if self.data then
Nenue@5 239 self.data.IsShown = self:IsShown()
Nenue@3 240 end
Nenue@3 241 end
Nenue@3 242
Nenue@32 243 function ClassPlan:OnUpdate()
Nenue@18 244 if self.isStale then
Nenue@32 245 print('|cFFFF4400An illusion! What are you hiding?|r')
Nenue@32 246 self:Update()
Nenue@18 247 end
Nenue@3 248 end
Nenue@3 249
Nenue@32 250 function ClassPlan:OnShow()
Nenue@23 251 print('|cFF00FFFFShow()')
Nenue@3 252 if self.isStale then
Nenue@32 253 self:Update()
Nenue@3 254 end
Nenue@32 255 self:Reanchor()
Nenue@3 256 end
Nenue@3 257
Nenue@32 258 function ClassPlan:OnHide()
Nenue@32 259 print('|cFF00FFFFHide()')
Nenue@3 260 end
Nenue@3 261
Nenue@32 262 function ClassPlan:Reanchor()
Nenue@32 263 self:ClearAllPoints()
Nenue@32 264 self:SetPoint('CENTER', self.data.positionX, self.data.positionY)
Nenue@32 265
Nenue@32 266 for index, frame in ipairs(self.Handlers) do
Nenue@32 267 frame:Reanchor()
Nenue@32 268 end
Nenue@2 269 end
Nenue@2 270
Nenue@32 271 function ClassPlan:OnDragStart()
Nenue@32 272 self:StartMoving()
Nenue@32 273 end
Nenue@32 274 function ClassPlan:OnDragStop()
Nenue@32 275
Nenue@32 276 self:StopMovingOrSizing()
Nenue@32 277 local x,y = self:GetCenter()
Nenue@32 278 if x and y then
Nenue@32 279 x = (x - GetScreenWidth()/2)
Nenue@32 280 y = (y - GetScreenHeight()/2) * -1
Nenue@32 281 self.data.positionX, self.data.positionY = x,y
Nenue@32 282 print('saving positions:', x, y)
Nenue@32 283 end
Nenue@32 284 end
Nenue@32 285
Nenue@32 286 function SharedHandlers:SetList(index)
Nenue@32 287 if not index then
Nenue@32 288 if self.currentListIndex == #self.listKey then
Nenue@32 289 index = 1
Nenue@32 290 else
Nenue@32 291 index = self.currentListIndex + 1
Nenue@32 292 end
Nenue@32 293 end
Nenue@32 294
Nenue@32 295 print('|cFF0088FF'..self:GetName()..'|r:SetList()', index)
Nenue@32 296 self.currentListIndex = index
Nenue@32 297 self.activeKey = self.listKey[index]
Nenue@32 298 self.activeTitle = self.listTitle[index]
Nenue@32 299
Nenue@32 300 self.isStale = true
Nenue@32 301 end
Nenue@32 302
Nenue@32 303 function SharedHandlers:RequestData()
Nenue@32 304 print('|cFF0088FF'..self:GetName()..':RequestData()')
Nenue@32 305 self.isStale = true
Nenue@32 306 end
Nenue@32 307
Nenue@32 308 function SharedHandlers:OnEvent(event, arg)
Nenue@32 309 if (event == 'GARRISON_MISSION_LIST_UPDATE') and (arg ~= LE_FOLLOWER_TYPE_GARRISON_7_0) then
Nenue@32 310 -- ignore non-OrderHall updates
Nenue@2 311 return
Nenue@2 312 end
Nenue@32 313 print('|cFF00FF88'..self:GetName()..':OnEvent()|r', event, arg)
Nenue@32 314 if self:IsVisible() then
Nenue@32 315 print('|cFF88FF00 frame visible; get busy')
Nenue@32 316 self:RequestData()
Nenue@6 317 else
Nenue@32 318 if not self.NextData then
Nenue@32 319 print('|cFF88FF00 setting timer')
Nenue@32 320 self.NextData = C_Timer.NewTimer(0.25, function()
Nenue@32 321 if self.initialized then
Nenue@32 322 self:RequestData()
Nenue@32 323 self.NextData:Cancel()
Nenue@32 324 self.NextData = nil
Nenue@32 325 print('|cFF88FF00'..self:GetName()..' clearing timer')
Nenue@32 326 end
Nenue@32 327
Nenue@32 328 end)
Nenue@32 329 end
Nenue@32 330 end
Nenue@32 331 end
Nenue@32 332 function SharedHandlers:OnUpdate()
Nenue@32 333 if self.isStale then
Nenue@32 334 self:GetParent():Update()
Nenue@32 335 end
Nenue@32 336 end
Nenue@32 337
Nenue@32 338
Nenue@32 339 -- Stuff set on every list item
Nenue@32 340 function SharedHandlers:SetOwnerData (self, data)
Nenue@32 341 local name, realm = string.match(data.profileKey, "(.+)%-(.+)")
Nenue@32 342 local ownerText = '|c'.. data.classColor.colorStr .. name .. '|r'
Nenue@32 343 self.Owner:SetText(ownerText)
Nenue@32 344 self.Name:SetText(self.name)
Nenue@32 345 self.Name:SetTextColor(data.classColor.r, data.classColor.g, data.classColor.b)
Nenue@32 346 end
Nenue@32 347
Nenue@32 348 function SharedHandlers:UpdateItems()
Nenue@32 349 local sortedItems = self.sortedItems
Nenue@32 350
Nenue@32 351 self.blocks = self.blocks or {}
Nenue@32 352 local blocks = self.blocks
Nenue@32 353
Nenue@32 354 local lastProfile
Nenue@32 355 local numItems = #sortedItems
Nenue@32 356 local totalHeight = 0
Nenue@32 357 self.lastBlock = nil
Nenue@32 358 self.numActive = 0
Nenue@32 359 for i, data in ipairs(sortedItems) do
Nenue@32 360 local block = blocks[i]
Nenue@32 361 if not block then
Nenue@32 362 block = CreateFrame('Button', nil, self, self.templateName)
Nenue@32 363 block:SetID(i)
Nenue@32 364 block.listType = self.activeKey
Nenue@32 365 block.handler = self
Nenue@32 366 self.numBlocks = self.numBlocks + 1
Nenue@32 367 blocks[i] = block
Nenue@32 368 end
Nenue@32 369
Nenue@32 370 print('RefreshItem', block)
Nenue@32 371 self.numActive = self.numActive + 1
Nenue@32 372
Nenue@32 373 if self.lastBlock then
Nenue@32 374 block:SetPoint('TOPLEFT', self.lastBlock, 'BOTTOMLEFT', 0, 0)
Nenue@32 375 print('--', i, data.isComplete, data.missionEndTime, data.name)
Nenue@32 376 else
Nenue@32 377 block:SetPoint('TOPLEFT', 0, 0)
Nenue@32 378 print('--top')
Nenue@32 379 end
Nenue@32 380 self.lastBlock = block
Nenue@32 381
Nenue@32 382 totalHeight = totalHeight + block:GetHeight()
Nenue@32 383 block.lastProfile = lastProfile
Nenue@32 384 -- blot out arbitrary flags
Nenue@32 385 block.offerEndTime = nil
Nenue@32 386 block.missionEndTime = nil
Nenue@32 387 block.creationTime = nil
Nenue@32 388 block.duration = nil
Nenue@32 389 block.throttle = 5
Nenue@32 390
Nenue@32 391 for k,v in pairs(data) do
Nenue@32 392 if type(block[k]) ~= 'function' then
Nenue@32 393 block[k] = v
Nenue@32 394 end
Nenue@32 395 end
Nenue@32 396
Nenue@32 397 block:Update()
Nenue@32 398 self:SetOwnerData(block, data)
Nenue@32 399
Nenue@32 400 block:Show()
Nenue@32 401 lastProfile = data.profileKey
Nenue@6 402 end
Nenue@6 403
Nenue@32 404 for i = numItems + 1, self.numBlocks do
Nenue@32 405 if blocks[i] then
Nenue@32 406 blocks[i]:Hide()
Nenue@32 407 end
Nenue@32 408 end
Nenue@32 409
Nenue@32 410 self:Reanchor()
Nenue@32 411
Nenue@32 412 return totalHeight
Nenue@32 413 end
Nenue@32 414
Nenue@32 415
Nenue@32 416 function ShipmentList:Reanchor()
Nenue@32 417 print('|cFF00FFFF'..self:GetName()..':Reanchor|r')
Nenue@32 418 self:SetPoint('TOPLEFT', 0, -24)
Nenue@32 419 self:SetPoint('BOTTOMRIGHT', -ClassOrderPlan:GetWidth()/2, 0)
Nenue@32 420 end
Nenue@32 421
Nenue@32 422 function MissionList:Reanchor()
Nenue@32 423 self:SetPoint('TOPRIGHT', 0, -24)
Nenue@32 424 self:SetPoint('BOTTOMLEFT', ClassOrderPlan:GetWidth()/2, 0)
Nenue@32 425
Nenue@32 426 self.ListTab:ClearAllPoints()
Nenue@32 427 self.ListTab:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, CP_HEADER_SIZE)
Nenue@32 428 self.ListTab:SetPoint('BOTTOMRIGHT', self, 'TOPRIGHT', 0, 0)
Nenue@32 429 self.ListTab.Label:SetText(self.listTitle[self.currentListIndex])
Nenue@32 430 self.ListTab:Show()
Nenue@32 431 print(self.ListTab:GetSize())
Nenue@32 432 end
Nenue@32 433
Nenue@32 434 function MissionList:GetPlayerData (profile)
Nenue@32 435 wipe(profile.missions)
Nenue@32 436 wipe(profile.available)
Nenue@32 437
Nenue@32 438 local items = C_Garrison.GetAvailableMissions(GetPrimaryGarrisonFollowerType(LE_GARRISON_TYPE_7_0));
Nenue@32 439 for i = 1, #items do
Nenue@32 440 if (not items[i].isBuilding and items[i].isZoneSupport) then
Nenue@32 441 else
Nenue@32 442
Nenue@32 443 tinsert(profile.available, items[i])
Nenue@32 444 end
Nenue@32 445 end
Nenue@32 446
Nenue@32 447 local items = C_Garrison.GetLandingPageItems(LE_GARRISON_TYPE_7_0)
Nenue@32 448 for index, data in ipairs(items) do
Nenue@32 449 print(' -',data.name, '|cFF00FF00'.. data.timeLeft .. '|r', date("%A %I:%m %p", data.missionEndTime))
Nenue@32 450 tinsert(profile.missions, data)
Nenue@32 451 end
Nenue@32 452 return true
Nenue@32 453 end
Nenue@32 454
Nenue@32 455 do
Nenue@32 456 local ShipmentsInfo = {}
Nenue@32 457 local AddShipmentInfo = function(shipmentType, name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID, followerID)
Nenue@32 458 -- early login queries may return empty tables, causing the sorter to compare nil
Nenue@32 459 if not creationTime then
Nenue@32 460 return
Nenue@32 461 end
Nenue@32 462 --print(shipmentType, name, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
Nenue@32 463 tinsert(ShipmentsInfo,
Nenue@32 464 {
Nenue@32 465 shipmentType = shipmentType,
Nenue@32 466 name = name,
Nenue@32 467 icon = texture,
Nenue@32 468 shipmentCapacity = shipmentCapacity,
Nenue@32 469 shipmentsReady = shipmentsReady,
Nenue@32 470 shipmentsTotal = shipmentsTotal,
Nenue@32 471 creationTime = creationTime,
Nenue@32 472 duration = duration,
Nenue@32 473 timeleftString = timeleftString,
Nenue@32 474 itemName = itemName,
Nenue@32 475 itemIcon = itemIcon,
Nenue@32 476 itemQuality = itemQuality,
Nenue@32 477 itemID = itemID,
Nenue@32 478 followerID = followerID,
Nenue@32 479 })
Nenue@32 480 end
Nenue@32 481 function ShipmentList:GetPlayerData (profile)
Nenue@32 482 if not profile then
Nenue@32 483 return false
Nenue@32 484 end
Nenue@32 485 local profileList = profile.shipments
Nenue@32 486 wipe(ShipmentsInfo)
Nenue@32 487
Nenue@32 488 local garrisonType = LE_GARRISON_TYPE_7_0
Nenue@32 489 local buildings = CG_GetBuildings(garrisonType);
Nenue@32 490 local shipmentIndex = 0
Nenue@32 491 --print('Buildings:')
Nenue@32 492 for i = 1, #buildings do
Nenue@32 493 local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID = CG_GetLandingPageShipmentInfo(buildingID);
Nenue@32 494 AddShipmentInfo('Building', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, itemName, itemIcon, itemQuality, itemID)
Nenue@32 495 end
Nenue@32 496
Nenue@32 497 --print('Follower:')
Nenue@32 498 local followerShipments = CG_GetFollowerShipments(garrisonType);
Nenue@32 499 for i = 1, #followerShipments do
Nenue@32 500 local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, _, _, _, _, followerID = CG_GetLandingPageShipmentInfoByContainerID(followerShipments[i]);
Nenue@32 501 AddShipmentInfo('Follower', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString, nil, nil, nil, nil, followerID)
Nenue@32 502 end
Nenue@32 503
Nenue@32 504 --print('Loose:')
Nenue@32 505 local looseShipments = CG_GetLooseShipments(garrisonType)
Nenue@32 506 for i = 1, #looseShipments do
Nenue@32 507 local name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString = CG_GetLandingPageShipmentInfoByContainerID(looseShipments[i]);
Nenue@32 508 AddShipmentInfo('Misc', name, texture, shipmentCapacity, shipmentsReady, shipmentsTotal, creationTime, duration, timeleftString)
Nenue@32 509 end
Nenue@32 510
Nenue@32 511 local talentTrees = CG_GetTalentTrees(garrisonType, select(3, UnitClass("player")));
Nenue@32 512 -- this is a talent that has completed, but has not been seen in the talent UI yet.
Nenue@32 513 local completeTalentID = CG_GetCompleteTalent(garrisonType);
Nenue@32 514 --print('Talents:')
Nenue@32 515 if (talentTrees) then
Nenue@32 516 for treeIndex, tree in ipairs(talentTrees) do
Nenue@32 517 for talentIndex, talent in ipairs(tree) do
Nenue@32 518 local showTalent = false;
Nenue@32 519 if (talent.isBeingResearched) or (talent.id == completeTalentID) then
Nenue@32 520 AddShipmentInfo('Talent', talent.name, talent.icon, 1, (talent.isBeingResearched and 0 or 1), 1, talent.researchStartTime, talent.researchDuration, talent.timeleftString)
Nenue@32 521 end
Nenue@32 522 end
Nenue@32 523 end
Nenue@32 524 end
Nenue@32 525
Nenue@32 526 wipe(profileList)
Nenue@32 527 for index, data in ipairs(ShipmentsInfo) do
Nenue@32 528 --DEFAULT_CHAT_FRAME:AddMessage(data.shipmentType ..' '.. tostring(data.name) ..' '.. tostring(data.creationTime) ..' '.. tostring(data.duration))
Nenue@32 529 tinsert(profileList, data)
Nenue@32 530 end
Nenue@32 531 self.isStale = true
Nenue@32 532 return true
Nenue@32 533 end
Nenue@32 534 end
Nenue@32 535 MissionList.OnGetItem = function(data)
Nenue@32 536 if data.missionEndTime and (data.missionEndTime < GI_currentTime) then
Nenue@32 537 data.isComplete = true
Nenue@32 538 end
Nenue@32 539 end
Nenue@32 540
Nenue@32 541 MissionList.FreeBlock = function(self, block)
Nenue@32 542 end
Nenue@32 543
Nenue@32 544 MissionList.SortHandler = function (a,b)
Nenue@32 545 local result = false
Nenue@32 546 --if not a or not b then
Nenue@32 547 -- return true
Nenue@32 548 --else
Nenue@32 549 --if (a.isMine ~= b.isMine) then
Nenue@32 550 -- result = a.isMine
Nenue@32 551 --else
Nenue@32 552 --if (not b.missionEndTime) or (not a.missionEndTime) then
Nenue@32 553 -- print('missing article', b.missionEndTime, a.missionEndTime)
Nenue@32 554 --end
Nenue@32 555 if b.isComplete ~= a.isComplete then
Nenue@32 556 return a.isComplete
Nenue@32 557 elseif b.isMine ~= a.isMine then
Nenue@32 558 return a.isMine
Nenue@32 559 elseif b.missionEndTime then
Nenue@32 560 return ( b.missionEndTime > a.missionEndTime)
Nenue@32 561 else
Nenue@32 562 return ( b.offerEndTime > a.offerEndTime)
Nenue@32 563 end
Nenue@32 564
Nenue@32 565 --end
Nenue@32 566 --end
Nenue@32 567 end
Nenue@32 568
Nenue@32 569
Nenue@32 570 function MissionList:OnShow()
Nenue@32 571 print('|cFF00FF88'..self:GetName()..':OnShow()|r')
Nenue@32 572 end
Nenue@32 573
Nenue@32 574 function ShipmentList:OnLoad()
Nenue@32 575 C_Garrison.RequestLandingPageShipmentInfo();
Nenue@32 576 end
Nenue@32 577 function ShipmentList:OnShow()
Nenue@32 578 print('|cFF00FF88'..self:GetName()..':OnShow()|r')
Nenue@32 579 C_Garrison.RequestLandingPageShipmentInfo()
Nenue@32 580 end
Nenue@32 581
Nenue@32 582 -- Update shipment flags data
Nenue@32 583 local SetActualShipmentTime = function(self)
Nenue@32 584
Nenue@32 585 if self.isComplete then
Nenue@32 586 print('|cFF00FF88isComplete '..self.name..'|r')
Nenue@32 587 return true
Nenue@32 588 end
Nenue@32 589
Nenue@32 590 local timestamp = time()
Nenue@32 591 local timeLeft = self.creationTime + self.duration - timestamp
Nenue@32 592 local justFinished = false
Nenue@32 593 while (self.shipmentsReady < self.shipmentsTotal) and (timeLeft <= 0) do
Nenue@32 594 if not self.originalReady then
Nenue@32 595 self.originalReady = self.shipmentsReady
Nenue@32 596 self.originalCreationTime = self.creationTime
Nenue@32 597 end
Nenue@32 598
Nenue@32 599
Nenue@32 600 self.shipmentsReady = self.shipmentsReady + 1
Nenue@32 601 self.creationTime = self.creationTime + self.duration
Nenue@32 602 timeLeft = timeLeft + self.duration
Nenue@32 603 print('|cFF00FF88udpating '..self.name..'|r', 'timeLeft:', timeLeft, 'shipments:', self.shipmentsReady, self.shipmentsTotal)
Nenue@32 604 end
Nenue@32 605
Nenue@32 606 if (timeLeft <= 0) and (not self.isBeingResearched) then
Nenue@32 607 self.isComplete = true
Nenue@32 608 self.isStale = true
Nenue@32 609 end
Nenue@32 610
Nenue@32 611 return timeLeft
Nenue@32 612 end
Nenue@32 613
Nenue@32 614 ShipmentList.OnGetItem = function(data)
Nenue@32 615 print('OnGetItem()')
Nenue@32 616 if data.shipmentsTotal then
Nenue@32 617 SetActualShipmentTime(data)
Nenue@32 618 end
Nenue@32 619 end
Nenue@32 620
Nenue@32 621 ShipmentList.SortHandler = function(a, b)
Nenue@32 622 if b.isComplete ~= a.isComplete then
Nenue@32 623 return a.isComplete and true or false
Nenue@32 624 elseif a.shipmentsReady or b.shipmentsReady then
Nenue@32 625 return (a.shipmentsReady or 0) > (b.shipmentsReady or 0)
Nenue@32 626 else
Nenue@32 627 return (a.creationTime) < (b.creationTime)
Nenue@32 628 end
Nenue@32 629 end
Nenue@32 630
Nenue@32 631
Nenue@32 632 function MissionEntry:OnComplete()
Nenue@32 633 print('flagging complete', self.name)
Nenue@32 634 self:Update()
Nenue@32 635 end
Nenue@32 636
Nenue@32 637 function MissionEntry:OnUpdate(sinceLast)
Nenue@32 638 self.throttle = (self.throttle or .5) + sinceLast
Nenue@32 639 if self.throttle < .5 then
Nenue@32 640 return
Nenue@32 641 else
Nenue@32 642 self.throttle = self.throttle - .5
Nenue@32 643 end
Nenue@32 644 if self.offerEndTime then
Nenue@32 645 local timeLeft = self.offerEndTime
Nenue@32 646 self.TimeLeft:SetText(GetTimeLeftString(timeLeft))
Nenue@32 647 self.TimeLeft:SetTextColor(1,1,1)
Nenue@32 648 elseif self.missionEndTime then
Nenue@32 649
Nenue@32 650 if self.isComplete then
Nenue@32 651 return
Nenue@32 652 end
Nenue@1 653 local timeLeft = self.missionEndTime - time()
Nenue@1 654 if timeLeft < 0 then
Nenue@2 655 self:OnComplete()
Nenue@1 656 else
Nenue@2 657 self.TimeLeft:SetText(GetTimeLeftString(timeLeft))
Nenue@2 658 if timeLeft > 3600 then
Nenue@2 659 self.TimeLeft:SetTextColor(1,1,1)
Nenue@2 660 else
Nenue@2 661 self.TimeLeft:SetTextColor(1,1,0)
Nenue@2 662 end
Nenue@6 663 end
Nenue@2 664
Nenue@6 665 if not self.isComplete then
Nenue@18 666 local progress = (time() - (self.missionEndTime - self.durationSeconds)) / self.durationSeconds
Nenue@6 667 local w = self.ProgressBG:GetWidth()
Nenue@6 668 if progress >= 1 then
Nenue@6 669 self.ProgressBar:SetWidth(w)
Nenue@6 670 else
Nenue@18 671 self.ProgressBar:SetWidth(progress * w)
Nenue@18 672 local r, g = 1, 0
Nenue@18 673 if progress >= 0.5 then
Nenue@18 674 g = 1
Nenue@18 675 r = 1-((progress-0.5)*2)
Nenue@18 676 else
Nenue@18 677 g = min(progress * 2, 1)
Nenue@18 678 r = 1
Nenue@18 679 end
Nenue@32 680 self.ProgressBar:SetColorTexture(r,g,0,.4)
Nenue@18 681 self.ProgressBG:SetColorTexture(r,g,0,0.125)
Nenue@6 682 end
Nenue@6 683 self.ProgressBG:Show()
Nenue@6 684 self.ProgressBar:Show()
Nenue@6 685 else
Nenue@6 686 self.ProgressBG:Hide()
Nenue@6 687 self.ProgressBar:Hide()
Nenue@1 688 end
Nenue@1 689 else
Nenue@1 690 self.TimeLeft:SetText(self.missionEndTime)
Nenue@1 691 end
Nenue@2 692 end
Nenue@2 693
Nenue@32 694 function MissionEntry:OnLoad()
Nenue@32 695 print('|cFFFF4400',self:GetName() or tostring(self), 'onload')
Nenue@32 696 self.Count = self.Overlay.Count
Nenue@32 697 self.Name = self.Overlay.Name
Nenue@32 698 self.TimeLeft = self.Overlay.TimeLeft
Nenue@32 699 self.Owner = self.Overlay.Owner
Nenue@32 700
Nenue@32 701 self.Icon:SetDesaturated(false)
Nenue@32 702 self.Done:Hide()
Nenue@32 703 end
Nenue@32 704
Nenue@32 705 function MissionEntry:Update()
Nenue@2 706 local r,g,b = 1, 1, 1
Nenue@4 707 if self.isRare then
Nenue@2 708 r,g,b = 0.1, 0.4, 1
Nenue@5 709 self.IconBorder:SetVertexColor(r, g, b, 1)
Nenue@2 710 end
Nenue@2 711
Nenue@2 712 --self.missionData = data
Nenue@5 713 self.Name:SetText(self.name)
Nenue@4 714 if #self.rewards >= 1 then
Nenue@4 715 self.Icon:SetTexture(self.rewards[1].icon or GetItemIcon(self.rewards[1].itemID))
Nenue@4 716 self.rewardInfo = self.rewards[1]
Nenue@2 717 else
Nenue@4 718 self.Icon:SetAtlas(self.typeAtlas, false)
Nenue@2 719 end
Nenue@6 720
Nenue@32 721
Nenue@6 722
Nenue@18 723 if self.isComplete then
Nenue@18 724 self.TimeLeft:SetText('Complete!')
Nenue@18 725 self.Background:SetColorTexture(.25,.25,.25,1)
Nenue@18 726 else
Nenue@18 727 self.Background:SetColorTexture(0,0,0,0.5)
Nenue@18 728 end
Nenue@2 729 end
Nenue@2 730
Nenue@32 731 function MissionEntry:OnEnter()
Nenue@2 732 if self.rewardInfo and self.rewardInfo.itemID then
Nenue@2 733 GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
Nenue@2 734 GameTooltip:SetItemByID(self.rewardInfo.itemID)
Nenue@2 735 GameTooltip:Show()
Nenue@2 736 end
Nenue@2 737 end
Nenue@19 738
Nenue@32 739 function MissionEntry:OnLeave()
Nenue@2 740 if GameTooltip:IsOwned(self) then
Nenue@2 741 GameTooltip:Hide()
Nenue@2 742 end
Nenue@2 743 end
Nenue@2 744
Nenue@32 745 function ShipmentEntry:OnLoad()
Nenue@32 746 MissionEntry.OnLoad(self)
Nenue@32 747 end
Nenue@3 748
Nenue@32 749
Nenue@32 750 function ShipmentEntry:Update()
Nenue@32 751 print('|cFF0088FF'.. self.name..'|r:Update()')
Nenue@4 752 self.Icon:SetTexture(self.icon)
Nenue@4 753 self.Count:SetText(self.shipmentsReady)
Nenue@4 754 self.Done:SetShown(self.shipmentsReady and (self.shipmentsReady >= 1))
Nenue@2 755
Nenue@3 756 -- flag as complete
Nenue@32 757
Nenue@32 758 local bgColor = CP_BACKGROUND_COLOR.inProgress
Nenue@6 759 if ( self.shipmentsReady >= self.shipmentsTotal ) and (not self.isBeingResearched) then
Nenue@2 760 self.Swipe:SetCooldownUNIX(0, 0);
Nenue@2 761 self.Done:Show();
Nenue@32 762 bgColor = CP_BACKGROUND_COLOR.complete
Nenue@2 763 else
Nenue@32 764 if (self.shipmentsReady >= 1) and (self.shipmentsReady < self.shipmentsTotal) then
Nenue@32 765 bgColor = CP_BACKGROUND_COLOR.shipmentsReady
Nenue@32 766 end
Nenue@4 767 self.Swipe:SetCooldownUNIX(self.creationTime or 0 , self.duration or 0);
Nenue@2 768 end
Nenue@32 769 self.Background:SetColorTexture(unpack(bgColor))
Nenue@2 770
Nenue@32 771 SetActualShipmentTime(self)
Nenue@32 772
Nenue@32 773 if self.originalReady then
Nenue@32 774 print('|cFF00FF88'..self.name..'|r', 'starting ready:', self.originalReady, 'starting time:', self.originalCreationTime)
Nenue@18 775 end
Nenue@19 776 end
Nenue@18 777
Nenue@32 778 function ShipmentEntry:OnUpdate(sinceLast)
Nenue@18 779 self.throttle = (self.throttle or 1) + sinceLast
Nenue@18 780 if self.throttle >= 1 then
Nenue@18 781 self.throttle = self.throttle - 1
Nenue@18 782 else
Nenue@18 783 return
Nenue@18 784 end
Nenue@2 785
Nenue@32 786
Nenue@6 787 if (self.shipmentsReady and self.shipmentsTotal) and (self.shipmentsReady < self.shipmentsTotal) then
Nenue@32 788 local timeLeft = SetActualShipmentTime(self)
Nenue@32 789
Nenue@32 790 if self.isComplete then
Nenue@32 791 self.TimeLeft:SetText('Complete!')
Nenue@32 792 self.TimeLeft:SetTextColor(0,0.5,1)
Nenue@32 793 elseif self.shipmentsReady >= 1 then
Nenue@6 794 self.TimeLeft:SetText(GetTimeLeftString(timeLeft))
Nenue@6 795 self.TimeLeft:SetTextColor(0,1,0)
Nenue@6 796 else
Nenue@6 797 self.TimeLeft:SetText(GetTimeLeftString(timeLeft))
Nenue@6 798 self.TimeLeft:SetTextColor(1,1,1)
Nenue@6 799 end
Nenue@32 800
Nenue@4 801 elseif self.isBeingResearched then
Nenue@4 802 self.TimeLeft:SetText(GetTimeLeftString(self.researchStartTime + self.researchDuration - time()))
Nenue@6 803 self.TimeLeft:SetTextColor(1,1,0)
Nenue@2 804 else
Nenue@2 805 self.TimeLeft:SetText('Complete!')
Nenue@6 806 self.TimeLeft:SetTextColor(0,1,0)
Nenue@2 807 end
Nenue@2 808
Nenue@18 809 if not self.isComplete then
Nenue@18 810 local progress = ((time() - self.creationTime) / self.duration)
Nenue@18 811 local w = self.ProgressBG:GetWidth()
Nenue@18 812 if progress >= 1 then
Nenue@18 813 self.ProgressBar:SetWidth(w)
Nenue@18 814 else
Nenue@18 815 self.ProgressBar:SetWidth(progress * w)
Nenue@18 816 end
Nenue@18 817
Nenue@18 818 local r, g = 1, 0
Nenue@18 819 if progress >= 0.5 then
Nenue@18 820 g = 1
Nenue@18 821 r = 1-((progress-0.5)*2)
Nenue@18 822 else
Nenue@18 823 g = min(progress * 2, 1)
Nenue@18 824 r = 1
Nenue@18 825 end
Nenue@32 826 self.ProgressBar:SetColorTexture(r, g, 0, .4)
Nenue@18 827 self.ProgressBG:SetColorTexture(r, g, 0, .125)
Nenue@18 828 self.ProgressBG:Show()
Nenue@18 829 self.ProgressBar:Show()
Nenue@18 830 else
Nenue@18 831 self.ProgressBG:Hide()
Nenue@18 832 self.ProgressBar:Hide()
Nenue@18 833 end
Nenue@2 834 end
Nenue@2 835
Nenue@32 836 function ShipmentEntry:OnEnter()
Nenue@4 837 if ( self.shipmentsReady and self.shipmentsTotal ) then
Nenue@2 838 GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
Nenue@4 839 GameTooltip:AddLine(self.Owner:GetText(), self.Owner:GetTextColor())
Nenue@4 840 GameTooltip:AddLine(self.shipmentType)
Nenue@4 841 GameTooltip:AddLine(self.shipmentsReady .. ' of '.. self.shipmentsTotal)
Nenue@2 842 GameTooltip:Show()
Nenue@2 843 end
Nenue@2 844 end
Nenue@2 845
Nenue@32 846 function ShipmentEntry:OnLeave()
Nenue@2 847 if GameTooltip:IsOwned(self) then
Nenue@2 848 GameTooltip:Hide()
Nenue@2 849 end
Nenue@2 850 end
Nenue@2 851
Nenue@32 852 function ShipmentEntry:OnClick(button)
Nenue@3 853 if button == 'RightButton' then
Nenue@4 854 self.handler:FreeBlock(self)
Nenue@3 855 end
Nenue@32 856 end
Nenue@32 857
Nenue@32 858 ClassPlanMissionHandler = Mixin(MissionList, SharedHandlers)
Nenue@32 859 ClassPlanShipmentHandler = Mixin(ShipmentList, SharedHandlers)
Nenue@32 860 ClassPlanMissionEntryMixin = Mixin(MissionEntry, SharedEntry)
Nenue@32 861 ClassPlanShipmentEntryMixin = Mixin(ShipmentEntry,SharedEntry)
Nenue@32 862
Nenue@32 863 ClassPlanHeaderMixin = {
Nenue@32 864 OnClick = function(self)
Nenue@32 865 self:GetParent():SetList()
Nenue@32 866 self:GetParent().isStale = true
Nenue@32 867 ClassOrderPlan:Update()
Nenue@32 868 end
Nenue@32 869 }