Blizzard_GarrisonSharedTemplates.lua 91.1 KB
Newer Older
TOM_RUS's avatar
TOM_RUS committed
1
2
GARRISON_FOLLOWER_BUSY_COLOR = { 0, 0.06, 0.22, 0.44 };
GARRISON_FOLLOWER_INACTIVE_COLOR = { 0.22, 0.06, 0, 0.44 };
TOM_RUS's avatar
TOM_RUS committed
3

TOM_RUS's avatar
TOM_RUS committed
4
5
6
7
8
-- We default to item qualities if there is no description entry here.
GARRISON_FOLLOWER_QUALITY_DESC = {
	[6] = GARRISON_FOLLOWER_QUALITY6_DESC,
}

TOM_RUS's avatar
TOM_RUS committed
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
---------------------------------------------------------------------------------
--- Static Popup Dialogs                                                             ---
---------------------------------------------------------------------------------

StaticPopupDialogs["CONFIRM_FOLLOWER_UPGRADE"] = {
	text = "%s",
	button1 = YES,
	button2 = NO,
	OnAccept = function(self)
		C_Garrison.CastSpellOnFollower(self.data);
	end,
	showAlert = 1,
	timeout = 0,
	exclusive = 1,
	hideOnEscape = 1
};

StaticPopupDialogs["CONFIRM_FOLLOWER_ABILITY_UPGRADE"] = {
	text = "%s",
	button1 = YES,
	button2 = NO,
	OnAccept = function(self)
		C_Garrison.CastSpellOnFollowerAbility(self.data.followerID, self.data.abilityID);
	end,
	timeout = 0,
	exclusive = 1,
	hideOnEscape = 1
};

StaticPopupDialogs["CONFIRM_FOLLOWER_TEMPORARY_ABILITY"] = {
	text = CONFIRM_GARRISON_FOLLOWER_TEMPORARY_ABILITY,
	button1 = YES,
	button2 = NO,
	OnAccept = function(self)
		C_Garrison.CastSpellOnFollower(self.data);
	end,
	showAlert = 1,
	timeout = 0,
	exclusive = 1,
	hideOnEscape = 1
};

StaticPopupDialogs["CONFIRM_FOLLOWER_EQUIPMENT"] = {
	text = "%s",
	button1 = YES,
	button2 = NO,
	OnAccept = function(self)
		if (self.data.source == "spell") then
			C_Garrison.CastSpellOnFollowerAbility(self.data.followerID, self.data.abilityID);
		elseif (self.data.source == "item") then
			C_Garrison.CastItemSpellOnFollowerAbility(self.data.followerID, self.data.abilityID);
		end
	end,
	timeout = 0,
	exclusive = 1,
	hideOnEscape = 1
};

TOM_RUS's avatar
TOM_RUS committed
67
68
69
---------------------------------------------------------------------------------
--- Follower List                                                             ---
---------------------------------------------------------------------------------
TOM_RUS's avatar
TOM_RUS committed
70

TOM_RUS's avatar
TOM_RUS committed
71
72
73
74
75
76
local FOLLOWER_BUTTON_HEIGHT = 56;
local CATEGORY_BUTTON_HEIGHT = 20;
local FOLLOWER_LIST_BUTTON_OFFSET = -6;
local FOLLOWER_LIST_BUTTON_INITIAL_OFFSET = -7;
local GARRISON_FOLLOWER_LIST_BUTTON_FULL_XP_WIDTH = 205;

TOM_RUS's avatar
TOM_RUS committed
77
78
GarrisonFollowerList = {};

TOM_RUS's avatar
TOM_RUS committed
79
function GarrisonFollowerList:Initialize(followerType)
TOM_RUS's avatar
TOM_RUS committed
80
81
82
83
	self.followerTab = self:GetParent().FollowerTab;
	if (self.followerTab) then
		self.followerTab.followerList = self;
	end
TOM_RUS's avatar
TOM_RUS committed
84
	self:Setup(self:GetParent(), followerType, self.followerTemplate);
TOM_RUS's avatar
TOM_RUS committed
85
86
end

TOM_RUS's avatar
TOM_RUS committed
87
88
89
function GarrisonFollowerList:Setup(mainFrame, followerType, followerTemplate, initialOffsetX)
	self.followers = { };
	self.followersList = { };
TOM_RUS's avatar
TOM_RUS committed
90
	self:DirtyList();
TOM_RUS's avatar
TOM_RUS committed
91
	self.followerType = followerType;
TOM_RUS's avatar
TOM_RUS committed
92

TOM_RUS's avatar
TOM_RUS committed
93
94
	self.listScroll.update = function() self:UpdateData(); end;
	self.listScroll.dynamic = function(offset) return GarrisonFollowerList_GetTopButton(self, offset); end;
TOM_RUS's avatar
TOM_RUS committed
95

TOM_RUS's avatar
TOM_RUS committed
96
	if (not followerTemplate) then
TOM_RUS's avatar
TOM_RUS committed
97
		followerTemplate = "GarrisonMissionFollowerOrCategoryListButtonTemplate";
TOM_RUS's avatar
TOM_RUS committed
98
99
100
101
	end
	if (not initialOffsetX) then
		initialOffsetX = 7;
	end
TOM_RUS's avatar
TOM_RUS committed
102
	HybridScrollFrame_CreateButtons(self.listScroll, followerTemplate, initialOffsetX, FOLLOWER_LIST_BUTTON_INITIAL_OFFSET, nil, nil, nil, FOLLOWER_LIST_BUTTON_OFFSET);
TOM_RUS's avatar
TOM_RUS committed
103
	self.listScroll.followerFrame = mainFrame;
TOM_RUS's avatar
TOM_RUS committed
104

TOM_RUS's avatar
TOM_RUS committed
105
	self:UpdateFollowers();
TOM_RUS's avatar
TOM_RUS committed
106
107
end

TOM_RUS's avatar
TOM_RUS committed
108
function GarrisonFollowerList:OnShow()
TOM_RUS's avatar
TOM_RUS committed
109
110
	if (self.followerTab) then
		self.followerTab.lastUpdate = GetTime();
TOM_RUS's avatar
TOM_RUS committed
111
	end
TOM_RUS's avatar
TOM_RUS committed
112
	self:StopAnimations();
TOM_RUS's avatar
TOM_RUS committed
113

TOM_RUS's avatar
TOM_RUS committed
114
115
	self:DirtyList();
	self:UpdateFollowers();
TOM_RUS's avatar
TOM_RUS committed
116
	-- if there's no follower displayed in the tab, select the first one
TOM_RUS's avatar
TOM_RUS committed
117
118
119
120
121
122
123
124
	if (self.followerTab) then
		if (not self.followerTab.followerID or not self:HasFollower(self.followerTab.followerID)) then
			local index = self:FindFirstFollower();
			if (index and index ~= 0) then
				self:ShowFollower(self.followers[index].followerID);
			else
				-- empty page
				self:ShowFollower(0);
TOM_RUS's avatar
TOM_RUS committed
125
			end
TOM_RUS's avatar
TOM_RUS committed
126
127
128
		else
			-- refresh the shown follower
			self:ShowFollower(self.followerTab.followerID);
TOM_RUS's avatar
TOM_RUS committed
129
		end
TOM_RUS's avatar
TOM_RUS committed
130
	end
TOM_RUS's avatar
TOM_RUS committed
131
	if (C_Garrison.GetNumFollowers(self.followerType) >= GarrisonFollowerOptions[self.followerType].minFollowersForThreatCountersFrame) then
TOM_RUS's avatar
TOM_RUS committed
132
133
		self:ShowThreatCountersFrame();
	end
TOM_RUS's avatar
TOM_RUS committed
134
135
136
137
138
139
140
141

	self:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE");
	self:RegisterEvent("GARRISON_FOLLOWER_REMOVED");
	self:RegisterEvent("GARRISON_FOLLOWER_XP_CHANGED");
	self:RegisterEvent("GARRISON_FOLLOWER_UPGRADED");
	self:RegisterEvent("GARRISON_FOLLOWER_DURABILITY_CHANGED");
	self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED");
	self:RegisterEvent("CURSOR_UPDATE");
TOM_RUS's avatar
TOM_RUS committed
142
143
144
145
146
147
148
end

function GarrisonFollowerList:ShowThreatCountersFrame()
	GarrisonThreatCountersFrame:Show();
end

function GarrisonFollowerList:StopAnimations()
TOM_RUS's avatar
TOM_RUS committed
149
	if (self.followerTab) then
TOM_RUS's avatar
TOM_RUS committed
150
151
152
153
154
		local abilities = self.followerTab.AbilitiesFrame.Abilities;
		if (abilities) then
		    for i, abilityFrame in ipairs(abilities) do
			    GarrisonFollowerPageAbility_StopAnimations(abilityFrame);
		    end
TOM_RUS's avatar
TOM_RUS committed
155
		end
TOM_RUS's avatar
TOM_RUS committed
156
	end
TOM_RUS's avatar
TOM_RUS committed
157
158
end

TOM_RUS's avatar
TOM_RUS committed
159
function GarrisonFollowerList:OnHide()
TOM_RUS's avatar
TOM_RUS committed
160
161
	self.followers = nil;

TOM_RUS's avatar
TOM_RUS committed
162
163
164
165
166
167
168
169
	self:UnregisterEvent("GARRISON_FOLLOWER_LIST_UPDATE");
	self:UnregisterEvent("GARRISON_FOLLOWER_REMOVED");
	self:UnregisterEvent("GARRISON_FOLLOWER_XP_CHANGED");
	self:UnregisterEvent("GARRISON_FOLLOWER_UPGRADED");
	self:UnregisterEvent("GARRISON_FOLLOWER_DURABILITY_CHANGED");
	self:UnregisterEvent("CURRENT_SPELL_CAST_CHANGED");
	self:UnregisterEvent("CURSOR_UPDATE");
end
TOM_RUS's avatar
TOM_RUS committed
170

TOM_RUS's avatar
TOM_RUS committed
171
172
173
174
function GarrisonFollowerList:FindFirstFollower(ignoreDBID)
	for i, index in ipairs(self.followersList) do
		if index ~= 0 and self.followers[self.followersList[i]].followerID ~= ignoreDBID then
			return index;
TOM_RUS's avatar
TOM_RUS committed
175
176
		end
	end
TOM_RUS's avatar
TOM_RUS committed
177
	return nil;
TOM_RUS's avatar
TOM_RUS committed
178
179
end

TOM_RUS's avatar
TOM_RUS committed
180
181
182
183
184
185
186
function GarrisonFollowerList:HasFollower(followerID)
	for i, index in ipairs(self.followersList) do
		if (index ~= 0 and (self.followers[index].followerID == followerID)) then
			return true;
		end
	end
	return false;
TOM_RUS's avatar
TOM_RUS committed
187
188
end

TOM_RUS's avatar
TOM_RUS committed
189
function GarrisonFollowerList:OnEvent(event, ...)
TOM_RUS's avatar
TOM_RUS committed
190
	if (event == "GARRISON_FOLLOWER_LIST_UPDATE" or event == "GARRISON_FOLLOWER_XP_CHANGED" or event == "GARRISON_FOLLOWER_DURABILITY_CHANGED") then
TOM_RUS's avatar
TOM_RUS committed
191
192
193
194
195
		local followerTypeID = ...;
		if (followerTypeID == self.followerType) then
			if (self.followerTab and self.followerTab.followerID and self.followerTab:IsVisible()) then
				self:ShowFollower(self.followerTab.followerID);
			end
TOM_RUS's avatar
TOM_RUS committed
196

TOM_RUS's avatar
TOM_RUS committed
197
			if (self:IsVisible()) then
TOM_RUS's avatar
TOM_RUS committed
198
199
				self:DirtyList();
				self:UpdateFollowers();
TOM_RUS's avatar
TOM_RUS committed
200
			end
TOM_RUS's avatar
TOM_RUS committed
201

TOM_RUS's avatar
TOM_RUS committed
202
			if (self.followerTab and self.followerTab.followerID and self.followerTab:IsVisible()) then
TOM_RUS's avatar
TOM_RUS committed
203
				if (C_Garrison.GetNumFollowers(self.followerType) >= GarrisonFollowerOptions[self.followerType].minFollowersForThreatCountersFrame) then
TOM_RUS's avatar
TOM_RUS committed
204
205
206
					self:ShowThreatCountersFrame();
				end
			end
TOM_RUS's avatar
TOM_RUS committed
207
		end
TOM_RUS's avatar
TOM_RUS committed
208
209
		return true;
	elseif (event == "GARRISON_FOLLOWER_REMOVED") then
TOM_RUS's avatar
TOM_RUS committed
210
		local followerTypeID = ...;
TOM_RUS's avatar
TOM_RUS committed
211
212
213
214
215
216
		if (followerTypeID == self.followerType) then
			if (self.followerTab and self.followerTab.followerID and self.followerTab:IsVisible() and not C_Garrison.GetFollowerInfo(self.followerTab.followerID) and self.followers) then
				-- viewed follower got removed, pick someone else
				local ignoreFollowerDBID = self.followerTab.followerID;
				local index = self:FindFirstFollower(ignoreFollowerDBID);
				if (index and index ~= 0) then
TOM_RUS's avatar
TOM_RUS committed
217
					self:ShowFollower(self.followers[index].followerID);
TOM_RUS's avatar
TOM_RUS committed
218
				else
TOM_RUS's avatar
TOM_RUS committed
219
					self:ShowFollower(0);
TOM_RUS's avatar
TOM_RUS committed
220
221
				end
			end
TOM_RUS's avatar
TOM_RUS committed
222
223
224
225
			if (self:IsVisible()) then
				self:DirtyList();
				self:UpdateFollowers();
			end
TOM_RUS's avatar
TOM_RUS committed
226
227
		end
		return true;
TOM_RUS's avatar
TOM_RUS committed
228
	elseif (event == "GARRISON_FOLLOWER_UPGRADED") then
TOM_RUS's avatar
TOM_RUS committed
229
		if ( self.followerTab and self.followerTab.followerID and self.followerTab:IsVisible() ) then
TOM_RUS's avatar
TOM_RUS committed
230
			local followerID = ...;
TOM_RUS's avatar
TOM_RUS committed
231
232
			if ( followerID == self.followerTab.followerID ) then
				self.followerTab.ModelCluster.Child.Model[1]:SetSpellVisualKit(6375);	-- level up visual;
TOM_RUS's avatar
TOM_RUS committed
233
				PlaySound(SOUNDKIT.UI_GARRISON_COMMAND_TABLE_FOLLOWER_LEVEL_UP);
TOM_RUS's avatar
TOM_RUS committed
234
235
			end
		end
TOM_RUS's avatar
TOM_RUS committed
236
	elseif (event == "CURRENT_SPELL_CAST_CHANGED" or event == "CURSOR_UPDATE") then
TOM_RUS's avatar
TOM_RUS committed
237
		if (self.followerTab and self.followerTab.followerID and self:IsVisible()) then
TOM_RUS's avatar
TOM_RUS committed
238
239
			local followerID = self.followerTab.followerID;
			local followerInfo = C_Garrison.GetFollowerInfo(followerID);
TOM_RUS's avatar
TOM_RUS committed
240
241
242
243
			if (followerInfo) then
				followerInfo.abilities = C_Garrison.GetFollowerAbilities(followerID);
				self:UpdateValidSpellHighlight(followerID, followerInfo);
			end
TOM_RUS's avatar
TOM_RUS committed
244
		end
TOM_RUS's avatar
TOM_RUS committed
245
246
247
248
249
	end

	return false;
end

TOM_RUS's avatar
TOM_RUS committed
250
251
252
253

GarrisonMissionFollowerDurabilityMixin = { }

function GarrisonMissionFollowerDurabilityMixin:SetDurability(durability, maxDurability, durabilityLoss)
TOM_RUS's avatar
TOM_RUS committed
254
	local heartWidth = 13;
TOM_RUS's avatar
TOM_RUS committed
255
256
	local spacing = 2;

TOM_RUS's avatar
TOM_RUS committed
257
258
259
260
	self.durabilityVal = durability;
	self.maxDurabilityVal = maxDurability;
	self.durabilityLossVal = durabilityLoss;

TOM_RUS's avatar
TOM_RUS committed
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
	durability = Clamp(durability, 0, maxDurability);
	durabilityLoss = Clamp(durabilityLoss or 0, 0, durability);
	durability = durability - durabilityLoss;
	while ((self.durability and #self.durability or 0) < maxDurability) do
		local durabilityTexture = self:CreateTexture(nil, "ARTWORK", "GarrisonMissionFollowerButtonDurabilityTemplate");
		durabilityTexture:ClearAllPoints();
		if (#self.durability == 1) then
			durabilityTexture:SetPoint("TOPLEFT");
		else
			durabilityTexture:SetPoint("TOPLEFT", self.durability[#self.durability - 1], "TOPRIGHT", spacing, 0);
		end
	end

	for i = 1, durability do
		self.durability[i]:Show();
		self.durability[i]:SetAtlas("GarrisonTroops-Health");
		self.durability[i]:SetDesaturated(false);
	end
	for i = durability + 1, durability + durabilityLoss do
		self.durability[i]:Show();
		self.durability[i]:SetAtlas("GarrisonTroops-Health-Consume");
		self.durability[i]:SetDesaturated(false);
	end
	for i = durability + durabilityLoss + 1, maxDurability do
		self.durability[i]:Show();
		self.durability[i]:SetAtlas("GarrisonTroops-Health");
		self.durability[i]:SetDesaturated(true);
	end
	for i = maxDurability + 1, (self.durability and #self.durability or 0) do
		self.durability[i]:Hide();
	end

TOM_RUS's avatar
TOM_RUS committed
293
	local width = max(1, maxDurability * (heartWidth + spacing));
TOM_RUS's avatar
TOM_RUS committed
294
295
296
	self:SetWidth(width);
end

TOM_RUS's avatar
TOM_RUS committed
297
298
299
300
function GarrisonMissionFollowerDurabilityMixin:GetDurability()
	return self.durabilityVal, self.maxDurabilityVal, self.durabilityLossVal;
end

TOM_RUS's avatar
TOM_RUS committed
301
302
303
304
305
306
GarrisonFollowerListButton = { };

function GarrisonFollowerListButton:GetFollowerList()
	return self:GetParent():GetParent():GetParent();
end

TOM_RUS's avatar
TOM_RUS committed
307
308
309
310
311
312
313
314
315
316
317
318
319
320
function GarrisonFollowerListButton_OnDragStart(self, button)
	local mainFrame = self:GetFollowerList():GetParent();
	if (mainFrame.OnDragStartFollowerButton) then
		mainFrame:OnDragStartFollowerButton(GarrisonFollowerPlacer, self, 24);
	end
end

function GarrisonFollowerListButton_OnDragStop(self)
	local mainFrame = self:GetFollowerList():GetParent();
	if (mainFrame.OnDragStopFollowerButton) then
		mainFrame:OnDragStopFollowerButton(GarrisonFollowerPlacer);
	end
end

TOM_RUS's avatar
TOM_RUS committed
321
322
323
324
325
326
GarrisonMissionFollowerOrCategoryListButtonMixin = { }

function GarrisonMissionFollowerOrCategoryListButtonMixin:GetFollowerList()
	return self:GetParent():GetParent():GetParent():GetParent();
end

TOM_RUS's avatar
TOM_RUS committed
327
function GarrisonFollowListEditBox_OnTextChanged(self)
TOM_RUS's avatar
TOM_RUS committed
328
	SearchBoxTemplate_OnTextChanged(self);
TOM_RUS's avatar
TOM_RUS committed
329
	self:GetParent():UpdateFollowers();
TOM_RUS's avatar
TOM_RUS committed
330
331
end

TOM_RUS's avatar
TOM_RUS committed
332
333
334
335
336
337
338
339
340
341
342
343
344
345
function GarrisonFollowerList:DoesFollowerMatchFilters(follower, searchString)
	if (not follower.isCollected and not self.showUncollected) then
		return false;
	end
	if (searchString ~= "" and not C_Garrison.SearchForFollower(follower.followerID, searchString)) then
		return false;
	end
	if (self.filter and not self.filter(follower)) then
		return false;
	end

	return true;
end

TOM_RUS's avatar
TOM_RUS committed
346
function GarrisonFollowerList:UpdateFollowers()
TOM_RUS's avatar
TOM_RUS committed
347
348

	if ( self.dirtyList ) then
TOM_RUS's avatar
TOM_RUS committed
349
		self.followers = C_Garrison.GetFollowers(self.followerType) or {};
TOM_RUS's avatar
TOM_RUS committed
350
		self.dirtyList = nil;
TOM_RUS's avatar
TOM_RUS committed
351
	end
TOM_RUS's avatar
TOM_RUS committed
352

TOM_RUS's avatar
TOM_RUS committed
353
	if ( not self.followers ) then
TOM_RUS's avatar
TOM_RUS committed
354
355
356
		return;
	end

TOM_RUS's avatar
TOM_RUS committed
357
358
359
360
361
362
363
	--TODO: Tagify GetFollowers and condense this into it
	for i = 1, #self.followers do
		if (self.followers[i].garrFollowerID) then
			self.followers[i].autoCombatSpells = C_Garrison.GetFollowerAutoCombatSpells(self.followers[i].garrFollowerID);
		end
	end

TOM_RUS's avatar
TOM_RUS committed
364
365
	self.followersList = { };
	self.followersLabels = { };
TOM_RUS's avatar
TOM_RUS committed
366

TOM_RUS's avatar
TOM_RUS committed
367
	local searchString = "";
TOM_RUS's avatar
TOM_RUS committed
368
369
	if ( self.SearchBox ) then
		searchString = self.SearchBox:GetText();
TOM_RUS's avatar
TOM_RUS committed
370
	end
TOM_RUS's avatar
TOM_RUS committed
371

TOM_RUS's avatar
TOM_RUS committed
372
373
374
375
376
	local numActive = 0;
	local numTroops = 0;
	local numInactive = 0;
	local numUncollected = 0;
	for i = 1, #self.followers do
TOM_RUS's avatar
TOM_RUS committed
377
		if self:DoesFollowerMatchFilters(self.followers[i], searchString) then
TOM_RUS's avatar
TOM_RUS committed
378
			tinsert(self.followersList, i);
TOM_RUS's avatar
TOM_RUS committed
379
380
381
382
383
384
385
386
387
			if (not self.followers[i].isCollected) then
				numUncollected = numUncollected + 1;
			elseif (self.followers[i].isTroop) then
				numTroops = numTroops + 1;
			elseif (self.followers[i].status == GARRISON_FOLLOWER_INACTIVE) then
				numInactive = numInactive + 1;
			else
				numActive = numActive + 1;
			end
TOM_RUS's avatar
TOM_RUS committed
388
389
390
		end
	end

TOM_RUS's avatar
TOM_RUS committed
391
	if ( self.followerTab and GarrisonFollowerOptions[self.followerType].showNumFollowers) then
TOM_RUS's avatar
TOM_RUS committed
392
		local maxFollowers = C_Garrison.GetFollowerSoftCap(self.followerType);
TOM_RUS's avatar
TOM_RUS committed
393
		local numActiveFollowers = C_Garrison.GetNumActiveFollowers(self.followerType) or 0;
TOM_RUS's avatar
TOM_RUS committed
394
395
		if ( self.isLandingPage ) then
			local countColor = HIGHLIGHT_FONT_COLOR_CODE;
TOM_RUS's avatar
TOM_RUS committed
396
			if ( numActiveFollowers > maxFollowers ) then
TOM_RUS's avatar
TOM_RUS committed
397
398
				countColor = RED_FONT_COLOR_CODE;
			end
TOM_RUS's avatar
TOM_RUS committed
399
			self.followerTab.NumFollowers:SetText(countColor..numActiveFollowers.."/"..maxFollowers..FONT_COLOR_CODE_CLOSE);
TOM_RUS's avatar
TOM_RUS committed
400
			self.followerTab.FollowerText:SetText(GarrisonFollowerOptions[self.followerType].strings.FOLLOWER_COUNT_LABEL);
TOM_RUS's avatar
TOM_RUS committed
401
402
		else
			local countColor = NORMAL_FONT_COLOR_CODE;
TOM_RUS's avatar
TOM_RUS committed
403
			if ( numActiveFollowers > maxFollowers ) then
TOM_RUS's avatar
TOM_RUS committed
404
405
				countColor = RED_FONT_COLOR_CODE;
			end
TOM_RUS's avatar
TOM_RUS committed
406
			self.followerTab.NumFollowers:SetText(format(GarrisonFollowerOptions[self.followerType].strings.FOLLOWER_COUNT_STRING, countColor, numActiveFollowers, maxFollowers, FONT_COLOR_CODE_CLOSE));
TOM_RUS's avatar
TOM_RUS committed
407
408
409
410
		end
	end

	GarrisonFollowerList_SortFollowers(self);
TOM_RUS's avatar
TOM_RUS committed
411

TOM_RUS's avatar
TOM_RUS committed
412
413
414
415
	if (GarrisonFollowerOptions[self.followerType].showCategoriesInFollowerList) then
		-- The sort above will yield the following sort order: Active followers, troops, inactive followers. Insert new entries for the appropriate
		-- category labels at the correct locations. Category labels will have "followerID" set to 0.

TOM_RUS's avatar
TOM_RUS committed
416
	    local additionalOffset = 0;
TOM_RUS's avatar
TOM_RUS committed
417
418
419
420
421
422
423
424
425

		additionalOffset = additionalOffset + 1;
		tinsert(self.followersList, 0 + additionalOffset, 0);
		self.followersLabels[0 + additionalOffset] = FOLLOWERLIST_LABEL_CHAMPIONS;

		additionalOffset = additionalOffset + 1;
		tinsert(self.followersList, numActive + additionalOffset, 0);
		self.followersLabels[numActive + additionalOffset] = FOLLOWERLIST_LABEL_TROOPS;

TOM_RUS's avatar
TOM_RUS committed
426
427
428
429
430
431
432
433
434
435
436
	    if ( numInactive > 0 ) then
		    additionalOffset = additionalOffset + 1;
		    tinsert(self.followersList, numActive + numTroops + additionalOffset, 0);
		    self.followersLabels[numActive + numTroops + additionalOffset] = FOLLOWERLIST_LABEL_INACTIVE;
	    end
		if ( numUncollected > 0 ) then
		    additionalOffset = additionalOffset + 1;
			tinsert(self.followersList, numActive + numTroops + numInactive + additionalOffset, 0)
		    self.followersLabels[numActive + numTroops + numInactive + additionalOffset] = FOLLOWERLIST_LABEL_UNCOLLECTED;
		end
	end
TOM_RUS's avatar
TOM_RUS committed
437
	self:UpdateData();
TOM_RUS's avatar
TOM_RUS committed
438
439
end

TOM_RUS's avatar
TOM_RUS committed
440
function GarrisonFollowerList_GetTopButton(self, offset)
TOM_RUS's avatar
TOM_RUS committed
441
	local followerFrame = self;
TOM_RUS's avatar
TOM_RUS committed
442
443
444
445
446
447
448
	local buttonHeight = followerFrame.listScroll.buttonHeight;
	local expandedFollower = followerFrame.expandedFollower;
	local followers = followerFrame.followers;
	local sortedList = followerFrame.followersList;
	local totalHeight = 0;
	for i = 1, #sortedList do
		local height;
TOM_RUS's avatar
TOM_RUS committed
449
450
451
		if ( sortedList[i] == 0 ) then
			height = CATEGORY_BUTTON_HEIGHT - FOLLOWER_LIST_BUTTON_OFFSET;
		elseif ( followers[sortedList[i]].followerID == expandedFollower ) then
TOM_RUS's avatar
TOM_RUS committed
452
453
			height = followerFrame.expandedFollowerHeight;
		else
TOM_RUS's avatar
TOM_RUS committed
454
			height = FOLLOWER_BUTTON_HEIGHT - FOLLOWER_LIST_BUTTON_OFFSET;
TOM_RUS's avatar
TOM_RUS committed
455
456
457
458
459
460
461
462
463
464
465
		end
		totalHeight = totalHeight + height;
		if ( totalHeight > offset ) then
			return i - 1, height + offset - totalHeight;
		end
	end

	--We're scrolled completely off the bottom
	return #followers, 0;
end

TOM_RUS's avatar
TOM_RUS committed
466
467
function GarrisonFollowerList_SetButtonMode(followerList, button, mode)
	if (mode == "CATEGORY") then
TOM_RUS's avatar
TOM_RUS committed
468
		followerList:CollapseButton(button.Follower);
TOM_RUS's avatar
TOM_RUS committed
469
		button:SetHeight(CATEGORY_BUTTON_HEIGHT);
TOM_RUS's avatar
TOM_RUS committed
470
	else
TOM_RUS's avatar
TOM_RUS committed
471
472
473
474
		button:SetHeight(FOLLOWER_BUTTON_HEIGHT);
	end

	button.mode = mode;
TOM_RUS's avatar
TOM_RUS committed
475
476
	button.Follower:SetShown(mode == "FOLLOWER");
	button.Category:SetShown(mode == "CATEGORY");
TOM_RUS's avatar
TOM_RUS committed
477
478
end

TOM_RUS's avatar
TOM_RUS committed
479
480
481
482
function GarrisonFollowerList:UpdateData()
	local followerFrame = self:GetParent();
	local followers = self.followers;
	local followersList = self.followersList;
TOM_RUS's avatar
TOM_RUS committed
483
	local categoryLabels = self.followersLabels;
TOM_RUS's avatar
TOM_RUS committed
484
	local numFollowers = #followersList;
TOM_RUS's avatar
TOM_RUS committed
485
	local scrollFrame = self.listScroll;
TOM_RUS's avatar
TOM_RUS committed
486
487
488
	local offset = HybridScrollFrame_GetOffset(scrollFrame);
	local buttons = scrollFrame.buttons;
	local numButtons = #buttons;
TOM_RUS's avatar
TOM_RUS committed
489
490
	local showCounters = self.showCounters;
	local canExpand = self.canExpand;
TOM_RUS's avatar
TOM_RUS committed
491
492
	local totalHeight = -FOLLOWER_LIST_BUTTON_INITIAL_OFFSET;

TOM_RUS's avatar
TOM_RUS committed
493
494
495
	for i = 1, numButtons do
		local button = buttons[i];
		local index = offset + i; -- adjust index
TOM_RUS's avatar
TOM_RUS committed
496
497
		if ( index <= numFollowers and followersList[index] == 0 ) then
			GarrisonFollowerList_SetButtonMode(self, button, "CATEGORY");
TOM_RUS's avatar
TOM_RUS committed
498
			button.Category:SetText(categoryLabels[index]);
TOM_RUS's avatar
TOM_RUS committed
499
500
			button:Show();
		elseif ( index <= numFollowers ) then
TOM_RUS's avatar
TOM_RUS committed
501
			local follower = followers[followersList[index]];
TOM_RUS's avatar
TOM_RUS committed
502

TOM_RUS's avatar
TOM_RUS committed
503
504
			GarrisonFollowerList_SetButtonMode(self, button, "FOLLOWER");
			button.Follower.DurabilityFrame:SetShown(follower.isTroop);
TOM_RUS's avatar
TOM_RUS committed
505

TOM_RUS's avatar
TOM_RUS committed
506
507
508
			button.Follower.id = follower.followerID;
			button.Follower.info = follower;
			button.Follower.Name:SetText(follower.name);
TOM_RUS's avatar
TOM_RUS committed
509
510
511
			if ( button.Follower.Class) then
				button.Follower.Class:SetAtlas(follower.classAtlas);
			end
TOM_RUS's avatar
TOM_RUS committed
512
			button.Follower.Status:SetText(follower.status);
TOM_RUS's avatar
TOM_RUS committed
513
			if ( follower.status == GARRISON_FOLLOWER_INACTIVE ) then
TOM_RUS's avatar
TOM_RUS committed
514
				button.Follower.Status:SetTextColor(1, 0.1, 0.1);
TOM_RUS's avatar
TOM_RUS committed
515
			else
TOM_RUS's avatar
TOM_RUS committed
516
				button.Follower.Status:SetTextColor(0.698, 0.941, 1);
TOM_RUS's avatar
TOM_RUS committed
517
			end
TOM_RUS's avatar
TOM_RUS committed
518
			button.Follower.PortraitFrame:SetupPortrait(follower);
TOM_RUS's avatar
TOM_RUS committed
519

TOM_RUS's avatar
TOM_RUS committed
520
521
522
523
524
			local abilityGridAreaWidth = GarrisonFollowerButton_UpdateCounters(self:GetParent(), button.Follower, follower, showCounters, followerFrame.lastUpdate);
			if not showCounters then 
				--This should be used to replace counter width, as they're currently exclusive sets.
				abilityGridAreaWidth = GarrisonFollowerButton_UpdateAutoSpells(self:GetParent(), button.Follower, follower);
			end
TOM_RUS's avatar
TOM_RUS committed
525

TOM_RUS's avatar
TOM_RUS committed
526
527
			if ( follower.isCollected ) then
				-- have this follower
TOM_RUS's avatar
TOM_RUS committed
528
529
				button.Follower.isCollected = true;
				button.Follower.Name:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
TOM_RUS's avatar
TOM_RUS committed
530
531
532
533
534
				if( button.Follower.Class ) then
					button.Follower.Class:SetDesaturated(false);
					button.Follower.Class:SetAlpha(0.2);
				end
				if button.Follower.PortraitFrame.quality ~= Enum.GarrFollowerQuality.Title then
TOM_RUS's avatar
TOM_RUS committed
535
536
					button.Follower.PortraitFrame.PortraitRingQuality:Show();
				end
TOM_RUS's avatar
TOM_RUS committed
537
				button.Follower.PortraitFrame.Portrait:SetDesaturated(false);
TOM_RUS's avatar
TOM_RUS committed
538
				if ( follower.status == GARRISON_FOLLOWER_INACTIVE ) then
TOM_RUS's avatar
TOM_RUS committed
539
540
541
542
					button.Follower.PortraitFrame.PortraitRingCover:Show();
					button.Follower.PortraitFrame.PortraitRingCover:SetAlpha(0.5);
					button.Follower.BusyFrame:Show();
					button.Follower.BusyFrame.Texture:SetColorTexture(unpack(GARRISON_FOLLOWER_INACTIVE_COLOR));
TOM_RUS's avatar
TOM_RUS committed
543
				elseif ( follower.status ) then
TOM_RUS's avatar
TOM_RUS committed
544
545
546
547
					button.Follower.PortraitFrame.PortraitRingCover:Show();
					button.Follower.PortraitFrame.PortraitRingCover:SetAlpha(0.5);
					button.Follower.BusyFrame:Show();
					button.Follower.BusyFrame.Texture:SetColorTexture(unpack(GARRISON_FOLLOWER_BUSY_COLOR));
TOM_RUS's avatar
TOM_RUS committed
548
549
					-- get time remaining for follower
					if ( follower.status == GARRISON_FOLLOWER_ON_MISSION ) then
TOM_RUS's avatar
TOM_RUS committed
550
						if (follower.isMaxLevel) then
TOM_RUS's avatar
TOM_RUS committed
551
							button.Follower.Status:SetText(C_Garrison.GetFollowerMissionTimeLeft(follower.followerID));
TOM_RUS's avatar
TOM_RUS committed
552
						else
TOM_RUS's avatar
TOM_RUS committed
553
							button.Follower.Status:SetFormattedText(GARRISON_FOLLOWER_ON_MISSION_WITH_DURATION, C_Garrison.GetFollowerMissionTimeLeft(follower.followerID));
TOM_RUS's avatar
TOM_RUS committed
554
						end
TOM_RUS's avatar
TOM_RUS committed
555
					end
TOM_RUS's avatar
TOM_RUS committed
556
				else
TOM_RUS's avatar
TOM_RUS committed
557
558
					button.Follower.PortraitFrame.PortraitRingCover:Hide();
					button.Follower.BusyFrame:Hide();
TOM_RUS's avatar
TOM_RUS committed
559
				end
TOM_RUS's avatar
TOM_RUS committed
560
561
562
563
564
565
				if( button.Follower.DownArrow ) then
					if ( canExpand ) then
						button.Follower.DownArrow:SetAlpha(1);
					else
						button.Follower.DownArrow:SetAlpha(0);
					end
TOM_RUS's avatar
TOM_RUS committed
566
				end
TOM_RUS's avatar
TOM_RUS committed
567
				-- adjust text position if we have additional text to show below name
TOM_RUS's avatar
TOM_RUS committed
568
569
570
				local nameOffsetY = 0;
				if (follower.status) then
					nameOffsetY = nameOffsetY + 8;
TOM_RUS's avatar
TOM_RUS committed
571
				end
TOM_RUS's avatar
TOM_RUS committed
572
				-- show iLevel for max level followers
TOM_RUS's avatar
TOM_RUS committed
573
				if (ShouldShowILevelInFollowerList(follower)) then
TOM_RUS's avatar
TOM_RUS committed
574
575
576
577
					nameOffsetY = nameOffsetY + 9;
					if (COLLAPSE_ORDER_HALL_FOLLOWER_ITEM_LEVEL_DISPLAY) then
						button.Follower.ILevel:SetPoint("TOPLEFT", button.Follower.Name, "BOTTOMLEFT", 0, -1);
						button.Follower.Status:SetPoint("TOPLEFT", button.Follower.ILevel, "BOTTOMLEFT", -1, 1);
TOM_RUS's avatar
TOM_RUS committed
578
					else
TOM_RUS's avatar
TOM_RUS committed
579
580
						button.Follower.ILevel:SetPoint("TOPLEFT", button.Follower.Name, "BOTTOMLEFT", 0, -4);
						button.Follower.Status:SetPoint("TOPLEFT", button.Follower.ILevel, "BOTTOMLEFT", -1, -2);
TOM_RUS's avatar
TOM_RUS committed
581
					end
TOM_RUS's avatar
TOM_RUS committed
582
					button.Follower.ILevel:SetText(POWER_LEVEL_ABBR.." "..follower.iLevel);
TOM_RUS's avatar
TOM_RUS committed
583
					button.Follower.ILevel:Show();
TOM_RUS's avatar
TOM_RUS committed
584
				else
TOM_RUS's avatar
TOM_RUS committed
585
					button.Follower.ILevel:SetText(nil);
TOM_RUS's avatar
TOM_RUS committed
586
					button.Follower.ILevel:Hide();
TOM_RUS's avatar
TOM_RUS committed
587
588
					button.Follower.Status:SetPoint("TOPLEFT", button.Follower.Name, "BOTTOMLEFT", 0, -2);
				end
TOM_RUS's avatar
TOM_RUS committed
589

TOM_RUS's avatar
TOM_RUS committed
590
591
				if (button.Follower.DurabilityFrame:IsShown()) then
					nameOffsetY = nameOffsetY + 9;
TOM_RUS's avatar
TOM_RUS committed
592

TOM_RUS's avatar
TOM_RUS committed
593
594
595
596
					if (follower.status) then
						button.Follower.DurabilityFrame:SetPoint("TOPLEFT", button.Follower.Status, "BOTTOMLEFT", 0, -4);
					elseif (ShouldShowILevelInFollowerList(follower)) then
						button.Follower.DurabilityFrame:SetPoint("TOPLEFT", button.Follower.ILevel, "BOTTOMLEFT", 0, -6);
TOM_RUS's avatar
TOM_RUS committed
597
					else
TOM_RUS's avatar
TOM_RUS committed
598
						button.Follower.DurabilityFrame:SetPoint("TOPLEFT", button.Follower.Name, "BOTTOMLEFT", 0, -6);
TOM_RUS's avatar
TOM_RUS committed
599
					end
TOM_RUS's avatar
TOM_RUS committed
600
				end
TOM_RUS's avatar
TOM_RUS committed
601
				button.Follower.Name:SetPoint("LEFT", button.Follower.PortraitFrame, "LEFT", 66, nameOffsetY);
TOM_RUS's avatar
TOM_RUS committed
602
				button.Follower.Status:SetPoint("RIGHT", -abilityGridAreaWidth, 0);
TOM_RUS's avatar
TOM_RUS committed
603

TOM_RUS's avatar
TOM_RUS committed
604
605
606
607
608
609
610
				if ( button.Follower.XPBar ) then
					if (follower.xp == 0 or follower.levelXP == 0) then
						button.Follower.XPBar:Hide();
					else
						button.Follower.XPBar:Show();
						button.Follower.XPBar:SetWidth((follower.xp/follower.levelXP) * GARRISON_FOLLOWER_LIST_BUTTON_FULL_XP_WIDTH);
					end
TOM_RUS's avatar
TOM_RUS committed
611
612
613
				end
			else
				-- don't have this follower
TOM_RUS's avatar
TOM_RUS committed
614
615
616
				button.Follower.isCollected = nil;
				button.Follower.Name:SetTextColor(0.25, 0.25, 0.25);
				button.Follower.ILevel:SetText(nil);
TOM_RUS's avatar
TOM_RUS committed
617
				button.Follower.Status:SetPoint("TOPLEFT", button.Follower.ILevel, "TOPRIGHT", 0, 0);
TOM_RUS's avatar
TOM_RUS committed
618
619
620
621
				if( button.Follower.Class ) then
					button.Follower.Class:SetDesaturated(true);
					button.Follower.Class:SetAlpha(0.1);
				end
TOM_RUS's avatar
TOM_RUS committed
622
623
624
625
626
				button.Follower.PortraitFrame.PortraitRingQuality:Hide();
				button.Follower.PortraitFrame.Portrait:SetDesaturated(true);
				button.Follower.PortraitFrame.PortraitRingCover:Show();
				button.Follower.PortraitFrame.PortraitRingCover:SetAlpha(0.6);
				button.Follower.PortraitFrame:SetQuality(0);
TOM_RUS's avatar
TOM_RUS committed
627
628
629
				if ( button.Follower.XPBar ) then
					button.Follower.XPBar:Hide();
				end
TOM_RUS's avatar
TOM_RUS committed
630
631
				button.Follower.DownArrow:SetAlpha(0);
				button.Follower.BusyFrame:Hide();
TOM_RUS's avatar
TOM_RUS committed
632
633
			end

TOM_RUS's avatar
TOM_RUS committed
634
635
			if (canExpand and button.Follower.id == self.expandedFollower and button.Follower.id == followerFrame.selectedFollower) then
				self:ExpandButton(button.Follower, self);
TOM_RUS's avatar
TOM_RUS committed
636
			else
TOM_RUS's avatar
TOM_RUS committed
637
				self:CollapseButton(button.Follower);
TOM_RUS's avatar
TOM_RUS committed
638
			end
TOM_RUS's avatar
TOM_RUS committed
639

TOM_RUS's avatar
TOM_RUS committed
640
641
642
			button:SetHeight(button.Follower:GetHeight());
			if ( button.Follower.id == followerFrame.selectedFollower ) then
				button.Follower.Selection:Show();
TOM_RUS's avatar
TOM_RUS committed
643
			else
TOM_RUS's avatar
TOM_RUS committed
644
				button.Follower.Selection:Hide();
TOM_RUS's avatar
TOM_RUS committed
645
646
647
			end

			if (follower.isTroop) then
TOM_RUS's avatar
TOM_RUS committed
648
				button.Follower.DurabilityFrame:SetDurability(follower.durability, follower.maxDurability);
TOM_RUS's avatar
TOM_RUS committed
649
			end
TOM_RUS's avatar
TOM_RUS committed
650

TOM_RUS's avatar
TOM_RUS committed
651
652
653
654
655
			button:Show();
		else
			button:Hide();
		end
	end
TOM_RUS's avatar
TOM_RUS committed
656

TOM_RUS's avatar
TOM_RUS committed
657
658
659
660
661
662
663
	-- calculate the total height to pass to the HybridScrollFrame
	for i = 1, numFollowers do
		if (followersList[i] == 0) then
			totalHeight = totalHeight + CATEGORY_BUTTON_HEIGHT - FOLLOWER_LIST_BUTTON_OFFSET;
		else
			totalHeight = totalHeight + FOLLOWER_BUTTON_HEIGHT - FOLLOWER_LIST_BUTTON_OFFSET;
		end
TOM_RUS's avatar
TOM_RUS committed
664
	end
TOM_RUS's avatar
TOM_RUS committed
665
666
667
668
	if (self.expandedFollower) then
		totalHeight = totalHeight + self.expandedFollowerHeight - (FOLLOWER_BUTTON_HEIGHT - FOLLOWER_LIST_BUTTON_OFFSET);
	end

TOM_RUS's avatar
TOM_RUS committed
669
670
	local displayedHeight = numButtons * scrollFrame.buttonHeight;
	HybridScrollFrame_Update(scrollFrame, totalHeight, displayedHeight);
TOM_RUS's avatar
TOM_RUS committed
671
672

	followerFrame.lastUpdate = GetTime();
TOM_RUS's avatar
TOM_RUS committed
673
674
end

TOM_RUS's avatar
TOM_RUS committed
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
function GarrisonFollowerButton_AddCounterButtons(button, follower, numShown, counters, lastUpdate)
	if (not counters) then
		return numShown;
	end
	for i = 1, min(4 - numShown, #counters) do	-- max of 4 icons
		numShown = numShown + 1;
		GarrisonFollowerButton_SetCounterButton(button, follower.followerID, numShown, counters[i], lastUpdate, follower.followerTypeID);
	end

	return numShown;
end

local function GetFollowerButtonCounterSpacings(followerTypeID)
	local options = GarrisonFollowerOptions[followerTypeID];
	local numPerRow = options.followerListCounterNumPerRow;
	local innerSpacing = options.followerListCounterInnerSpacing;
	local outerSpacingX = options.followerListCounterOuterSpacingX;
	local outerSpacingY = options.followerListCounterOuterSpacingY;
	local scale = options.followerListCounterScale;

	return numPerRow, innerSpacing, outerSpacingX, outerSpacingY, scale;
end

TOM_RUS's avatar
TOM_RUS committed
698
function GarrisonFollowerButton_UpdateCounters(frame, button, follower, showCounters, lastUpdate)
TOM_RUS's avatar
TOM_RUS committed
699
	local numShown = 0;
TOM_RUS's avatar
TOM_RUS committed
700
	if ( showCounters and follower.isCollected and follower.status ~= GARRISON_FOLLOWER_INACTIVE ) then
TOM_RUS's avatar
TOM_RUS committed
701
702
		--if a mission is being viewed, show mechanics this follower can counter
		--for followers you have, show counters if they are or could be on the mission
TOM_RUS's avatar
TOM_RUS committed
703
		local counters = frame.followerCounters and frame.followerCounters[follower.followerID];
TOM_RUS's avatar
TOM_RUS committed
704
		if ( counters ) then
TOM_RUS's avatar
TOM_RUS committed
705
			if ( follower.followerTypeID == Enum.GarrisonFollowerType.FollowerType_6_2 ) then
TOM_RUS's avatar
TOM_RUS committed
706
707
				table.sort(counters, function(left, right) return left.factor > right.factor; end);
			end
TOM_RUS's avatar
TOM_RUS committed
708
		end
TOM_RUS's avatar
TOM_RUS committed
709
710
711

		numShown = GarrisonFollowerButton_AddCounterButtons(button, follower, numShown, counters, lastUpdate);

TOM_RUS's avatar
TOM_RUS committed
712
		local traits = frame.followerTraits and frame.followerTraits[follower.followerID];
TOM_RUS's avatar
TOM_RUS committed
713
714
715
716
717
		numShown = GarrisonFollowerButton_AddCounterButtons(button, follower, numShown, traits, lastUpdate);

		local spells = frame.followerSpells and frame.followerSpells[follower.followerID];
		numShown = GarrisonFollowerButton_AddCounterButtons(button, follower, numShown, spells, lastUpdate);

TOM_RUS's avatar
TOM_RUS committed
718
	end
TOM_RUS's avatar
TOM_RUS committed
719
720
721
722
723
	local numPerRow, innerSpacing, outerSpacingX, outerSpacingY, scale = GetFollowerButtonCounterSpacings(follower.followerTypeID);
	button.Counters[1]:ClearAllPoints();
	if ( numShown <= numPerRow ) then
		local collapsedButtonHeight = 46;
		button.Counters[1]:SetPoint("RIGHT", button.Counters[1]:GetParent(), "TOPRIGHT", -outerSpacingX, -collapsedButtonHeight/2);
TOM_RUS's avatar
TOM_RUS committed
724
	else
TOM_RUS's avatar
TOM_RUS committed
725
		button.Counters[1]:SetPoint("TOPRIGHT", -outerSpacingX, -outerSpacingY);
TOM_RUS's avatar
TOM_RUS committed
726
727
728
729
730
	end
	for i = numShown + 1, #button.Counters do
		button.Counters[i].info = nil;
		button.Counters[i]:Hide();
	end
TOM_RUS's avatar
TOM_RUS committed
731
732
733
734
735
736
737
738
739

	-- return the counters area width
	if (numShown == 0) then
		return 0;
	elseif (numShown == 1) then
		return 2 * outerSpacingX + button.Counters[1]:GetWidth() * scale;
	else
		return 2 * outerSpacingX + innerSpacing + (2 * button.Counters[1]:GetWidth() * scale);
	end
TOM_RUS's avatar
TOM_RUS committed
740
741
end

TOM_RUS's avatar
TOM_RUS committed
742
function GarrisonFollowerButton_SetCounterButton(button, followerID, index, info, lastUpdate, followerTypeID)
TOM_RUS's avatar
TOM_RUS committed
743
744
745
746
747
	local counter = button.Counters[index];
	if ( not counter ) then
		button.Counters[index] = CreateFrame("Frame", nil, button, "GarrisonMissionAbilityCounterTemplate");
		counter = button.Counters[index];
	end
TOM_RUS's avatar
TOM_RUS committed
748
	local numPerRow, innerSpacing, outerSpacingX, outerSpacingY, scale = GetFollowerButtonCounterSpacings(followerTypeID);
TOM_RUS's avatar
TOM_RUS committed
749
750
751
752
753
754
	if index > 1 then
		if ((index - 1) % numPerRow ~= 0) then
			counter:SetPoint("RIGHT", button.Counters[index-1], "LEFT", -innerSpacing, 0);
		else
			counter:SetPoint("TOP", button.Counters[index-numPerRow], "BOTTOM", 0, -innerSpacing);
		end
TOM_RUS's avatar
TOM_RUS committed
755
756
	end
	counter:SetScale(scale);
TOM_RUS's avatar
TOM_RUS committed
757
	counter.info = info;
TOM_RUS's avatar
TOM_RUS committed
758

TOM_RUS's avatar
TOM_RUS committed
759
	counter.followerTypeID = followerTypeID;
TOM_RUS's avatar
TOM_RUS committed
760
761
762
	if ( info.traitID ) then
		counter.tooltip = nil;
		counter.info.showCounters = false;
TOM_RUS's avatar
TOM_RUS committed
763
		counter.Icon:SetTexture(info.icon);
TOM_RUS's avatar
TOM_RUS committed
764
		counter.Border:Hide();
TOM_RUS's avatar
TOM_RUS committed
765
766
767
768
769
770
771
772

		if ( GarrisonFollowerAbilities_IsNew(lastUpdate, followerID, info.traitID, GARRISON_FOLLOWER_ABILITY_TYPE_TRAIT ) ) then
			counter.AbilityFeedbackGlowAnim.traitID = info.traitID;
			counter.AbilityFeedbackGlowAnim:Play();
		elseif ( counter.AbilityFeedbackGlowAnim.traitID ~= info.traitID ) then
			counter.AbilityFeedbackGlowAnim.traitID = nil;
			counter.AbilityFeedbackGlowAnim:Stop();
		end
TOM_RUS's avatar
TOM_RUS committed
773
774
775
776
777
778
	elseif (info.spellID) then
		counter.tooltip = nil;
		counter.info.showCounters = false;
		counter.Icon:SetTexture(select(3, GetSpellInfo(info.spellID)));
		counter.AbilityFeedbackGlowAnim:Stop();
		counter.Border:Hide();
TOM_RUS's avatar
TOM_RUS committed
779
780
781
	else
		counter.tooltip = info.name;
		counter.info.showCounters = true;
TOM_RUS's avatar
TOM_RUS committed
782
783
784
785
		if (GarrisonFollowerOptions[followerTypeID].displayCounterAbilityInPlaceOfMechanic and info.counterID) then
			local abilityInfo = C_Garrison.GetFollowerAbilityInfo(info.counterID);
			counter.Icon:SetTexture(abilityInfo.icon);
			counter.Border:SetShown(ShouldShowFollowerAbilityBorder(followerTypeID, abilityInfo));
TOM_RUS's avatar
TOM_RUS committed
786
		else
TOM_RUS's avatar
TOM_RUS committed
787
788
789
			counter.Icon:SetTexture(info.icon);
			counter.Border:Show();

TOM_RUS's avatar
TOM_RUS committed
790
			if ( counter.info.factor <= GARRISON_HIGH_THREAT_VALUE and followerTypeID == Enum.GarrisonFollowerType.FollowerType_6_2 ) then
TOM_RUS's avatar
TOM_RUS committed
791
792
793
				counter.Border:SetAtlas("GarrMission_WeakEncounterAbilityBorder");
			else
				counter.Border:SetAtlas("GarrMission_EncounterAbilityBorder");
TOM_RUS's avatar
TOM_RUS committed
794
			end
TOM_RUS's avatar
TOM_RUS committed
795
		end
TOM_RUS's avatar
TOM_RUS committed
796

TOM_RUS's avatar
TOM_RUS committed
797
798
		counter.AbilityFeedbackGlowAnim.traitID = nil;
		counter.AbilityFeedbackGlowAnim:Stop();
TOM_RUS's avatar
TOM_RUS committed
799
800
801
802
	end
	counter:Show();
end

TOM_RUS's avatar
TOM_RUS committed
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
function GarrisonFollowerButton_UpdateAutoSpells(frame, button, follower)
	local numShown = 0;

	if follower.autoCombatSpells then 
		numShown = #follower.autoCombatSpells;
	end

	if numShown == 0 then 
		return numShown;
	end

	if ( follower.isCollected and follower.status ~= GARRISON_FOLLOWER_INACTIVE ) then
		GarrisonFollowerButton_AddAutoSpellButtons(button, follower);
	end
	local numPerRow, innerSpacing, outerSpacingX, outerSpacingY, scale = GetFollowerButtonCounterSpacings(follower.followerTypeID);
	button.Counters[1]:ClearAllPoints();
	
	if ( numShown <= numPerRow ) then
		local collapsedButtonHeight = 46;
		button.Counters[1]:SetPoint("RIGHT", button.Counters[1]:GetParent(), "TOPRIGHT", -outerSpacingX, -collapsedButtonHeight/2);
	else
		button.Counters[1]:SetPoint("TOPRIGHT", -outerSpacingX, -outerSpacingY);
	end
	for i = numShown + 1, #button.Counters do
		button.Counters[i].info = nil;
		button.Counters[i]:Hide();
	end

	if (numShown == 1) then
		return 2 * outerSpacingX + button.Counters[1]:GetWidth() * scale;
	else
		return 2 * outerSpacingX + innerSpacing + (2 * button.Counters[1]:GetWidth() * scale);
	end
end

function GarrisonFollowerButton_AddAutoSpellButtons(button, follower)
	for i = 1, math.min(3, #follower.autoCombatSpells) do	-- max of 3 abilities 
		GarrisonFollowerButton_SetAutoSpellButton(button, follower.followerID, i, follower.autoCombatSpells[i], follower.followerTypeID);
	end
end

function GarrisonFollowerButton_SetAutoSpellButton(button, followerID, index, info, followerTypeID)
	local abilityFrame = button.Counters[index];
	if ( not abilityFrame ) then
		button.Counters[index] = CreateFrame("Frame", nil, button, "GarrisonMissionAbilityCounterTemplate");
		abilityFrame = button.Counters[index];
	end
	local numPerRow, innerSpacing, outerSpacingX, outerSpacingY, scale = GetFollowerButtonCounterSpacings(followerTypeID);
	if index > 1 then
		if ((index - 1) % numPerRow ~= 0) then
			abilityFrame:SetPoint("RIGHT", button.Counters[index-1], "LEFT", -innerSpacing, 0);
		else
			abilityFrame:SetPoint("TOP", button.Counters[index-numPerRow], "BOTTOM", 0, -innerSpacing);
		end
	end
	abilityFrame:SetScale(scale);
	abilityFrame.info = info;
	abilityFrame.followerTypeID = followerTypeID;
	abilityFrame.tooltip = nil;
	abilityFrame.info.showCounters = false;
	abilityFrame.Icon:SetTexture(info.icon);
	abilityFrame.Border:Hide();
	abilityFrame:Show();
end

TOM_RUS's avatar
TOM_RUS committed
868
869
870
function GarrisonFollowerList:ExpandButton(button, followerListFrame)
	local abHeight = self:ExpandButtonAbilities(button, false);
	if (abHeight == -1) then
TOM_RUS's avatar
TOM_RUS committed
871
872
		return;
	end
TOM_RUS's avatar
TOM_RUS committed
873

TOM_RUS's avatar
TOM_RUS committed
874
875
876
877
878
879
880
881
882
883
	button.UpArrow:Show();
	button.DownArrow:Hide();
	button:SetHeight(51 + abHeight);
	followerListFrame.expandedFollowerHeight = 51 + abHeight + 6;
end

function GarrisonFollowerList:ExpandButtonAbilities(button, traitsFirst)
	if ( not button.isCollected ) then
		return -1;
	end
TOM_RUS's avatar
TOM_RUS committed
884
885

	local abHeight = 0;
TOM_RUS's avatar
TOM_RUS committed
886
887
	if (not button.info.abilities) then
		button.info.abilities = C_Garrison.GetFollowerAbilities(button.info.followerID);
TOM_RUS's avatar
TOM_RUS committed
888
	end
TOM_RUS's avatar
TOM_RUS committed
889
890

	local buttonCount = 0;
TOM_RUS's avatar
TOM_RUS committed
891
892
	for i=1, #button.info.abilities do
		if ( traitsFirst == button.info.abilities[i].isTrait and button.info.abilities[i].icon ) then
TOM_RUS's avatar
TOM_RUS committed
893
			buttonCount = buttonCount + 1;
TOM_RUS's avatar
TOM_RUS committed
894
			abHeight = abHeight + GarrisonFollowerButton_AddAbility(button, buttonCount, button.info.abilities[i], self.followerType);
TOM_RUS's avatar
TOM_RUS committed
895
896
		end
	end
TOM_RUS's avatar
TOM_RUS committed
897
898
	for i=1, #button.info.abilities do
		if ( traitsFirst ~= button.info.abilities[i].isTrait and button.info.abilities[i].icon ) then
TOM_RUS's avatar
TOM_RUS committed
899
			buttonCount = buttonCount + 1;
TOM_RUS's avatar
TOM_RUS committed
900
			abHeight = abHeight + GarrisonFollowerButton_AddAbility(button, buttonCount, button.info.abilities[i], self.followerType);
TOM_RUS's avatar
TOM_RUS committed
901
		end
TOM_RUS's avatar
TOM_RUS committed
902
	end
TOM_RUS's avatar
TOM_RUS committed
903

TOM_RUS's avatar
TOM_RUS committed
904
905
	for i=(#button.info.abilities + 1), #button.Abilities do
		button.Abilities[i]:Hide();
TOM_RUS's avatar
TOM_RUS committed
906
907
908
	end
	if (abHeight > 0) then
		abHeight = abHeight + 8;
TOM_RUS's avatar
TOM_RUS committed
909
910
		button.AbilitiesBG:Show();
		button.AbilitiesBG:SetHeight(abHeight);
TOM_RUS's avatar
TOM_RUS committed
911
	else
TOM_RUS's avatar
TOM_RUS committed
912
		button.AbilitiesBG:Hide();
TOM_RUS's avatar
TOM_RUS committed
913
	end
TOM_RUS's avatar
TOM_RUS committed
914
	return abHeight;
TOM_RUS's avatar
TOM_RUS committed
915
916
end

TOM_RUS's avatar
TOM_RUS committed
917
function GarrisonFollowerButton_AddAbility(self, index, ability, followerType)
TOM_RUS's avatar
TOM_RUS committed
918
919
920
921
922
	if (not self.Abilities[index]) then
		self.Abilities[index] = CreateFrame("Frame", nil, self, "GarrisonFollowerListButtonAbilityTemplate");
		self.Abilities[index]:SetPoint("TOPLEFT", self.Abilities[index-1], "BOTTOMLEFT", 0, -2);
	end
	local Ability = self.Abilities[index];
TOM_RUS's avatar
TOM_RUS committed
923
	Ability.followerTypeID = followerType;
TOM_RUS's avatar
TOM_RUS committed
924
925
926
927
928
929
930
931
	Ability.abilityID = ability.id;
	Ability.Name:SetText(ability.name);
	Ability.Icon:SetTexture(ability.icon);
	Ability.tooltip = ability.description;
	Ability:Show();
	return Ability:GetHeight() + 3;
end

TOM_RUS's avatar
TOM_RUS committed
932
933
function GarrisonFollowerList:CollapseButton(button)
	self:CollapseButtonAbilities(button);
TOM_RUS's avatar
TOM_RUS committed
934
935
936
937
938
939
	if(button.UpArrow) then
		button.UpArrow:Hide();
	end
	if  (button.DownArrow) then
		button.DownArrow:Show();
	end
TOM_RUS's avatar
TOM_RUS committed
940
	button:SetHeight(FOLLOWER_BUTTON_HEIGHT);
TOM_RUS's avatar
TOM_RUS committed
941
942
943
944
945
946
end

function GarrisonFollowerList:CollapseButtonAbilities(button)
	button.AbilitiesBG:Hide();
	for i=1, #button.Abilities do
		button.Abilities[i]:Hide();
TOM_RUS's avatar
TOM_RUS committed
947
948
949
950
	end
end

function GarrisonFollowerListButton_OnClick(self, button)
TOM_RUS's avatar
TOM_RUS committed
951
952
953
954
955
	if (self.mode == "CATEGORY") then
		return;
	end

	local followerList = self:GetFollowerList();
TOM_RUS's avatar
TOM_RUS committed
956
	local followerFrame = followerList.listScroll.followerFrame;
TOM_RUS's avatar
TOM_RUS committed
957
	if ( button == "LeftButton" ) then
TOM_RUS's avatar
TOM_RUS committed
958
		if ( followerFrame.selectedFollower ~= self.id ) then
TOM_RUS's avatar
TOM_RUS committed
959
			PlaySound(SOUNDKIT.UI_GARRISON_COMMAND_TABLE_SELECT_FOLLOWER);
TOM_RUS's avatar
TOM_RUS committed
960
961
			followerFrame.selectedFollower = self.id;
		end
TOM_RUS's avatar
TOM_RUS committed
962

TOM_RUS's avatar
TOM_RUS committed
963
964
		if ( followerList.canCastSpellsOnFollowers and SpellCanTargetGarrisonFollower(self.id) ) then
			GarrisonFollower_AttemptUpgrade(self.id);
TOM_RUS's avatar
TOM_RUS committed
965
		end
TOM_RUS's avatar
TOM_RUS committed
966

TOM_RUS's avatar
TOM_RUS committed
967
		if ( followerList.canExpand ) then
TOM_RUS's avatar
TOM_RUS committed
968
			if ( self.isCollected ) then
TOM_RUS's avatar
TOM_RUS committed
969
970
				if (followerList.expandedFollower == self.id) then
					followerList.expandedFollower = nil;
TOM_RUS's avatar
TOM_RUS committed
971
					PlaySound(SOUNDKIT.UI_GARRISON_COMMAND_TABLE_FOLLOWER_ABILITY_CLOSE);
TOM_RUS's avatar
TOM_RUS committed
972
				else
TOM_RUS's avatar
TOM_RUS committed
973
					followerList.expandedFollower = self.id;
TOM_RUS's avatar
TOM_RUS committed
974
					PlaySound(SOUNDKIT.UI_GARRISON_COMMAND_TABLE_FOLLOWER_ABILITY_OPEN);
TOM_RUS's avatar
TOM_RUS committed
975
				end
TOM_RUS's avatar
TOM_RUS committed
976
			else
TOM_RUS's avatar
TOM_RUS committed
977
				followerList.expandedFollower = nil;
TOM_RUS's avatar
TOM_RUS committed
978
				PlaySound(SOUNDKIT.UI_GARRISON_COMMAND_TABLE_FOLLOWER_ABILITY_CLOSE);
TOM_RUS's avatar
TOM_RUS committed
979
			end
TOM_RUS's avatar
TOM_RUS committed
980
		else
TOM_RUS's avatar
TOM_RUS committed
981
982
			if ( not followerList.canExpand and followerList.expandedFollower ~= self.id ) then
				followerList.expandedFollower = nil;
TOM_RUS's avatar
TOM_RUS committed
983
			end
TOM_RUS's avatar
TOM_RUS committed
984
		end
TOM_RUS's avatar
TOM_RUS committed
985
986
987
		followerList:UpdateData();
		if ( followerList.