annotate ClassPlan.lua @ 35:26dfa661daa7

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