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 |