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