Advertisement
Guest User

Blizzard_GarrisonSharedTemplates.lua

a guest
Apr 17th, 2015
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 46.39 KB | None | 0 0
  1. GARRISON_FOLLOWER_BUSY_COLOR = { 0, 0.06, 0.22, 0.44 };
  2. GARRISON_FOLLOWER_INACTIVE_COLOR = { 0.22, 0.06, 0, 0.44 };
  3.  
  4. local minFollowersForThreatCountersFrame = 10;
  5.  
  6. ---------------------------------------------------------------------------------
  7. --- Follower List ---
  8. ---------------------------------------------------------------------------------
  9.  
  10. function GarrisonFollowerList_ScrollListUpdate(self)
  11. self.followerFrame.FollowerList:UpdateData();
  12. end
  13.  
  14. GarrisonFollowerList = {};
  15.  
  16. function GarrisonFollowerList:Load(followerType)
  17. self.minFollowersForThreatCountersFrame = minFollowersForThreatCountersFrame;
  18. self.followerCountString = GARRISON_FOLLOWER_COUNT;
  19. self:Setup(self:GetParent(), followerType);
  20. end
  21.  
  22. function GarrisonFollowerList:Setup(mainFrame, followerType, followerTemplate, initialOffsetX)
  23. self.followers = { };
  24. self.followersList = { };
  25. GarrisonFollowerList_DirtyList(self);
  26. self.followerType = followerType;
  27.  
  28. self.listScroll.update = GarrisonFollowerList_ScrollListUpdate;
  29. self.listScroll.dynamic = function(offset) return GarrisonFollowerList_GetTopButton(mainFrame, offset); end;
  30.  
  31. if (not followerTemplate) then
  32. followerTemplate = "GarrisonMissionFollowerButtonTemplate";
  33. end
  34. if (not initialOffsetX) then
  35. initialOffsetX = 7;
  36. end
  37. HybridScrollFrame_CreateButtons(self.listScroll, followerTemplate, initialOffsetX, -7, nil, nil, nil, -6);
  38. self.listScroll.followerFrame = mainFrame;
  39.  
  40. self:UpdateData();
  41.  
  42. mainFrame:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE");
  43. mainFrame:RegisterEvent("GARRISON_FOLLOWER_REMOVED");
  44. mainFrame:RegisterEvent("GARRISON_FOLLOWER_XP_CHANGED");
  45. mainFrame:RegisterEvent("GARRISON_FOLLOWER_UPGRADED");
  46. mainFrame:RegisterEvent("CURRENT_SPELL_CAST_CHANGED");
  47. end
  48.  
  49. function GarrisonFollowerList:OnShow()
  50. local followerTab = self:GetParent().FollowerTab;
  51. followerTab.lastUpdate = GetTime();
  52. self:StopAnimations();
  53.  
  54. GarrisonFollowerList_DirtyList(self);
  55. GarrisonFollowerList_UpdateFollowers(self);
  56. -- if there's no follower displayed in the tab, select the first one
  57. if (followerTab and not followerTab.followerID) then
  58. local index = self.followersList[1];
  59. if (index) then
  60. self:ShowFollower(self.followers[index].followerID);
  61. else
  62. -- empty page
  63. self:ShowFollower(0);
  64. end
  65. end
  66. if (C_Garrison.GetNumFollowers(self.followerType) >= self.minFollowersForThreatCountersFrame) then
  67. self:ShowThreatCountersFrame();
  68. end
  69. end
  70.  
  71. function GarrisonFollowerList:ShowThreatCountersFrame()
  72. GarrisonThreatCountersFrame:Show();
  73. end
  74.  
  75. function GarrisonFollowerList:StopAnimations()
  76. local followerFrame = self:GetParent().FollowerTab;
  77. for i = 1, #followerFrame.AbilitiesFrame.Abilities do
  78. GarrisonFollowerPageAbility_StopAnimations(followerFrame.AbilitiesFrame.Abilities[i]);
  79. end
  80. end
  81.  
  82. function GarrisonFollowerList:OnHide()
  83. self.followers = nil;
  84. end
  85.  
  86. function GarrisonFollowerList_OnEvent(self, event, ...)
  87. if (event == "GARRISON_FOLLOWER_LIST_UPDATE" or event == "GARRISON_FOLLOWER_XP_CHANGED") then
  88. if (self.FollowerTab and self.FollowerTab.followerID) then
  89. self.FollowerList:ShowFollower(self.FollowerTab.followerID);
  90. end
  91.  
  92. GarrisonFollowerList_DirtyList(self.FollowerList);
  93. GarrisonFollowerList_UpdateFollowers(self.FollowerList);
  94.  
  95. local minFollowers = self.minFollowersForThreatCountersFrame or minFollowersForThreatCountersFrame;
  96. if (C_Garrison.GetNumFollowers(self.followerType) >= minFollowers) then
  97. self.FollowerList:ShowThreatCountersFrame();
  98. end
  99.  
  100. return true;
  101. elseif (event == "GARRISON_FOLLOWER_REMOVED") then
  102. if (self.FollowerTab and self.FollowerTab.followerID and not C_Garrison.GetFollowerInfo(self.FollowerTab.followerID) and self.FollowerList.followers) then
  103. -- viewed follower got removed, pick someone else
  104. local index = self.FollowerList.followersList[1];
  105. if (index and self.FollowerList.followers[index].followerID ~= self.FollowerTab.followerID) then
  106. self.FollowerList:ShowFollower(self.FollowerList.followers[index].followerID);
  107. else
  108. -- try the 2nd follower
  109. index = self.FollowerList.followersList[2];
  110. if (index) then
  111. self.FollowerList:ShowFollower(self.FollowerList.followers[index].followerID);
  112. else
  113. -- empty page
  114. self.FollowerList:ShowFollower(0);
  115. end
  116. end
  117. end
  118. GarrisonFollowerList_DirtyList(self.FollowerList);
  119. return true;
  120. elseif (event == "GARRISON_FOLLOWER_UPGRADED") then
  121. if ( self.FollowerTab and self.FollowerTab.Model and self.FollowerTab:IsVisible() ) then
  122. local followerID = ...;
  123. if ( followerID == self.FollowerTab.Model.followerID ) then
  124. self.FollowerTab.Model:SetSpellVisualKit(6375); -- level up visual
  125. PlaySound("UI_Garrison_CommandTable_Follower_LevelUp");
  126. end
  127. end
  128. elseif (event == "CURRENT_SPELL_CAST_CHANGED") then
  129. if (self.FollowerTab and self.FollowerTab.followerID and self:IsShown()) then
  130. self.FollowerList:ShowFollower(self.FollowerTab.followerID);
  131. end
  132. end
  133.  
  134. return false;
  135. end
  136.  
  137. function GarrisonFollowListEditBox_OnTextChanged(self)
  138. SearchBoxTemplate_OnTextChanged(self);
  139. GarrisonFollowerList_UpdateFollowers(self:GetParent());
  140. end
  141.  
  142. function GarrisonFollowerList_UpdateFollowers(self)
  143. local followerList = self;
  144. if ( followerList.dirtyList ) then
  145. followerList.followers = C_Garrison.GetFollowers(self.followerType);
  146. followerList.dirtyList = nil;
  147. end
  148.  
  149. if ( not followerList.followers ) then
  150. return;
  151. end
  152.  
  153. followerList.followersList = { };
  154.  
  155. local searchString = followerList.SearchBox:GetText();
  156.  
  157. for i = 1, #followerList.followers do
  158. if ( (self.followers[i].isCollected or self.showUncollected) and (searchString == "" or C_Garrison.SearchForFollower(self.followers[i].followerID, searchString)) ) then
  159. tinsert(self.followersList, i);
  160. end
  161. end
  162.  
  163. local followerTab = self:GetParent().FollowerTab;
  164. if ( followerTab ) then
  165. local maxFollowers = C_Garrison.GetFollowerSoftCap(self.followerType);
  166. local numActiveFollowers = C_Garrison.GetNumActiveFollowers(self.followerType);
  167. if ( self.isLandingPage ) then
  168. local countColor = HIGHLIGHT_FONT_COLOR_CODE;
  169. if ( numActiveFollowers > maxFollowers ) then
  170. countColor = RED_FONT_COLOR_CODE;
  171. end
  172. self:GetParent().FollowerTab.NumFollowers:SetText(countColor..numActiveFollowers.."/"..maxFollowers..FONT_COLOR_CODE_CLOSE);
  173. else
  174. local countColor = NORMAL_FONT_COLOR_CODE;
  175. if ( numActiveFollowers > maxFollowers ) then
  176. countColor = RED_FONT_COLOR_CODE;
  177. end
  178. self:GetParent().FollowerTab.NumFollowers:SetText(format(self.followerCountString, countColor, numActiveFollowers, maxFollowers, FONT_COLOR_CODE_CLOSE));
  179. end
  180. end
  181.  
  182. GarrisonFollowerList_SortFollowers(self);
  183. self:UpdateData();
  184. end
  185.  
  186. function GarrisonFollowerList_GetTopButton(self, offset)
  187. local followerFrame = self.FollowerList;
  188. local buttonHeight = followerFrame.listScroll.buttonHeight;
  189. local expandedFollower = followerFrame.expandedFollower;
  190. local followers = followerFrame.followers;
  191. local sortedList = followerFrame.followersList;
  192. local totalHeight = 0;
  193. for i = 1, #sortedList do
  194. local height;
  195. if ( followers[sortedList[i]].followerID == expandedFollower ) then
  196. height = followerFrame.expandedFollowerHeight;
  197. else
  198. height = buttonHeight;
  199. end
  200. totalHeight = totalHeight + height;
  201. if ( totalHeight > offset ) then
  202. return i - 1, height + offset - totalHeight;
  203. end
  204. end
  205.  
  206. --We're scrolled completely off the bottom
  207. return #followers, 0;
  208. end
  209.  
  210. function GarrisonFollowerList:UpdateData()
  211. local followerFrame = self:GetParent();
  212. local followers = self.followers;
  213. local followersList = self.followersList;
  214. local numFollowers = #followersList;
  215. local scrollFrame = self.listScroll;
  216. local offset = HybridScrollFrame_GetOffset(scrollFrame);
  217. local buttons = scrollFrame.buttons;
  218. local numButtons = #buttons;
  219. local showCounters = self.showCounters;
  220. local canExpand = self.canExpand;
  221. local mentorLevel = GarrisonMissionFrame and GarrisonMissionFrame.MissionTab.MissionPage.mentorLevel or 0;
  222. local mentorItemLevel = GarrisonMissionFrame and GarrisonMissionFrame.MissionTab.MissionPage.mentorItemLevel or 0;
  223.  
  224. for i = 1, numButtons do
  225. local button = buttons[i];
  226. local index = offset + i; -- adjust index
  227. if ( index <= numFollowers ) then
  228. local follower = followers[followersList[index]];
  229. button.id = follower.followerID;
  230. button.info = follower;
  231. button.Name:SetText(follower.name);
  232. button.Class:SetAtlas(follower.classAtlas);
  233. button.Status:SetText(follower.status);
  234. if ( follower.status == GARRISON_FOLLOWER_INACTIVE ) then
  235. button.Status:SetTextColor(1, 0.1, 0.1);
  236. else
  237. button.Status:SetTextColor(0.698, 0.941, 1);
  238. end
  239. local color = ITEM_QUALITY_COLORS[follower.quality];
  240. button.PortraitFrame.LevelBorder:SetVertexColor(color.r, color.g, color.b);
  241. button.PortraitFrame.Level:SetText(follower.level);
  242. GarrisonFollowerPortrait_Set(button.PortraitFrame.Portrait, follower.portraitIconID);
  243. if ( follower.isCollected ) then
  244. -- have this follower
  245. button.isCollected = true;
  246. button.Name:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
  247. button.Class:SetDesaturated(false);
  248. button.Class:SetAlpha(0.2);
  249. button.PortraitFrame.PortraitRingQuality:Show();
  250. button.PortraitFrame.PortraitRingQuality:SetVertexColor(color.r, color.g, color.b);
  251. button.PortraitFrame.Portrait:SetDesaturated(false);
  252. if ( follower.status == GARRISON_FOLLOWER_INACTIVE ) then
  253. button.PortraitFrame.PortraitRingCover:Show();
  254. button.PortraitFrame.PortraitRingCover:SetAlpha(0.5);
  255. button.BusyFrame:Show();
  256. button.BusyFrame.Texture:SetTexture(unpack(GARRISON_FOLLOWER_INACTIVE_COLOR));
  257. elseif ( follower.status ) then
  258. button.PortraitFrame.PortraitRingCover:Show();
  259. button.PortraitFrame.PortraitRingCover:SetAlpha(0.5);
  260. button.BusyFrame:Show();
  261. button.BusyFrame.Texture:SetTexture(unpack(GARRISON_FOLLOWER_BUSY_COLOR));
  262. -- get time remaining for follower
  263. if ( follower.status == GARRISON_FOLLOWER_ON_MISSION ) then
  264. if (follower.level == GARRISON_FOLLOWER_MAX_LEVEL) then
  265. button.Status:SetText(C_Garrison.GetFollowerMissionTimeLeft(follower.followerID));
  266. else
  267. button.Status:SetFormattedText(GARRISON_FOLLOWER_ON_MISSION_WITH_DURATION, C_Garrison.GetFollowerMissionTimeLeft(follower.followerID));
  268. end
  269. end
  270. else
  271. button.PortraitFrame.PortraitRingCover:Hide();
  272. button.BusyFrame:Hide();
  273. end
  274. if ( canExpand ) then
  275. button.DownArrow:SetAlpha(1);
  276. else
  277. button.DownArrow:SetAlpha(0);
  278. end
  279. -- adjust text position if we have additional text to show below name
  280. if (follower.level == GARRISON_FOLLOWER_MAX_LEVEL or follower.status) then
  281. button.Name:SetPoint("LEFT", button.PortraitFrame, "LEFT", 66, 8);
  282. else
  283. button.Name:SetPoint("LEFT", button.PortraitFrame, "LEFT", 66, 0);
  284. end
  285. -- show iLevel for max level followers
  286. if (follower.level == GARRISON_FOLLOWER_MAX_LEVEL) then
  287. button.ILevel:SetText(ITEM_LEVEL_ABBR.." "..follower.iLevel);
  288. button.Status:SetPoint("TOPLEFT", button.ILevel, "TOPRIGHT", 4, 0);
  289. else
  290. button.ILevel:SetText(nil);
  291. button.Status:SetPoint("TOPLEFT", button.ILevel, "TOPRIGHT", 0, 0);
  292. end
  293. if (follower.xp == 0 or follower.levelXP == 0) then
  294. button.XPBar:Hide();
  295. else
  296. button.XPBar:Show();
  297. button.XPBar:SetWidth((follower.xp/follower.levelXP) * GARRISON_FOLLOWER_LIST_BUTTON_FULL_XP_WIDTH);
  298. end
  299. else
  300. -- don't have this follower
  301. button.isCollected = nil;
  302. button.Name:SetTextColor(0.25, 0.25, 0.25);
  303. button.ILevel:SetText(nil);
  304. button.Status:SetPoint("TOPLEFT", button.ILevel, "TOPRIGHT", 0, 0);
  305. button.Class:SetDesaturated(true);
  306. button.Class:SetAlpha(0.1);
  307. button.PortraitFrame.PortraitRingQuality:Hide();
  308. button.PortraitFrame.Portrait:SetDesaturated(true);
  309. button.PortraitFrame.PortraitRingCover:Show();
  310. button.PortraitFrame.PortraitRingCover:SetAlpha(0.6);
  311. button.XPBar:Hide();
  312. button.DownArrow:SetAlpha(0);
  313. button.BusyFrame:Hide();
  314. end
  315.  
  316. GarrisonFollowerButton_UpdateCounters(self:GetParent(), button, follower, showCounters, followerFrame.lastUpdate);
  317.  
  318. if (canExpand and button.id == self.expandedFollower and button.id == followerFrame.selectedFollower) then
  319. GarrisonFollowerButton_Expand(button, self);
  320. else
  321. GarrisonFollowerButton_Collapse(button);
  322. end
  323. if ( button.id == followerFrame.selectedFollower ) then
  324. button.Selection:Show();
  325. else
  326. button.Selection:Hide();
  327. end
  328. button:Show();
  329. else
  330. button:Hide();
  331. end
  332. end
  333.  
  334. local extraHeight = 0;
  335. if ( self.expandedFollower ) then
  336. extraHeight = self.expandedFollowerHeight - scrollFrame.buttonHeight;
  337. else
  338. extraHeight = 0;
  339. end
  340. local totalHeight = numFollowers * scrollFrame.buttonHeight + extraHeight;
  341. local displayedHeight = numButtons * scrollFrame.buttonHeight;
  342. HybridScrollFrame_Update(scrollFrame, totalHeight, displayedHeight);
  343.  
  344. followerFrame.lastUpdate = GetTime();
  345. end
  346.  
  347. function GarrisonFollowerButton_UpdateCounters(frame, button, follower, showCounters, lastUpdate)
  348. local numShown = 0;
  349. if ( showCounters and button.isCollected and follower.status ~= GARRISON_FOLLOWER_INACTIVE ) then
  350. --if a mission is being viewed, show mechanics this follower can counter
  351. --for followers you have, show counters if they are or could be on the mission
  352. local counters = frame.followerCounters and frame.followerCounters[follower.followerID];
  353. if ( counters ) then
  354. for i = 1, #counters do
  355. -- max of 4 icons
  356. if ( numShown == 4 ) then
  357. break;
  358. end
  359. numShown = numShown + 1;
  360. GarrisonFollowerButton_SetCounterButton(button, follower.followerID, numShown, counters[i], lastUpdate);
  361. end
  362. end
  363. local traits = frame.followerTraits and frame.followerTraits[follower.followerID];
  364. if ( traits ) then
  365. for i = 1, #traits do
  366. -- max of 4 icons
  367. if ( numShown == 4 ) then
  368. break;
  369. end
  370. numShown = numShown + 1;
  371. GarrisonFollowerButton_SetCounterButton(button, follower.followerID, numShown, traits[i], lastUpdate);
  372. end
  373. end
  374. end
  375. if ( numShown == 1 or numShown == 2 ) then
  376. button.Counters[1]:SetPoint("TOPRIGHT", -8, -16);
  377. else
  378. button.Counters[1]:SetPoint("TOPRIGHT", -8, -4);
  379. end
  380. for i = numShown + 1, #button.Counters do
  381. button.Counters[i].info = nil;
  382. button.Counters[i]:Hide();
  383. end
  384. end
  385.  
  386. function GarrisonFollowerButton_SetCounterButton(button, followerID, index, info, lastUpdate)
  387. local counter = button.Counters[index];
  388. if ( not counter ) then
  389. button.Counters[index] = CreateFrame("Frame", nil, button, "GarrisonMissionAbilityCounterTemplate");
  390. if (index % 2 == 0) then
  391. button.Counters[index]:SetPoint("RIGHT", button.Counters[index-1], "LEFT", -6, 0);
  392. else
  393. button.Counters[index]:SetPoint("TOP", button.Counters[index-2], "BOTTOM", 0, -6);
  394. end
  395. counter = button.Counters[index];
  396. end
  397. counter.info = info;
  398. counter.Icon:SetTexture(info.icon);
  399. if ( info.traitID ) then
  400. counter.tooltip = nil;
  401. counter.info.showCounters = false;
  402. counter.Border:Hide();
  403.  
  404. if ( GarrisonFollowerAbilities_IsNew(lastUpdate, followerID, info.traitID, GARRISON_FOLLOWER_ABILITY_TYPE_TRAIT ) ) then
  405. counter.AbilityFeedbackGlowAnim.traitID = info.traitID;
  406. counter.AbilityFeedbackGlowAnim:Play();
  407. elseif ( counter.AbilityFeedbackGlowAnim.traitID ~= info.traitID ) then
  408. counter.AbilityFeedbackGlowAnim.traitID = nil;
  409. counter.AbilityFeedbackGlowAnim:Stop();
  410. end
  411. else
  412. counter.tooltip = info.name;
  413. counter.info.showCounters = true;
  414. counter.Border:Show();
  415.  
  416. counter.AbilityFeedbackGlowAnim.traitID = nil;
  417. counter.AbilityFeedbackGlowAnim:Stop();
  418. end
  419. counter:Show();
  420. end
  421.  
  422. function GarrisonFollowerButton_Expand(self, followerListFrame)
  423. if ( not self.isCollected ) then
  424. return;
  425. end
  426.  
  427. self.UpArrow:Show();
  428. self.DownArrow:Hide();
  429. local abHeight = 0;
  430. if (not self.info.abilities) then
  431. self.info.abilities = C_Garrison.GetFollowerAbilities(self.info.followerID);
  432. end
  433.  
  434. local buttonCount = 0;
  435. -- abilities
  436. for i=1, #self.info.abilities do
  437. if ( not self.info.abilities[i].isTrait ) then
  438. buttonCount = buttonCount + 1;
  439. abHeight = abHeight + GarrisonFollowerButton_AddAbility(self, buttonCount, self.info.abilities[i]);
  440. end
  441. end
  442. -- traits
  443. for i=1, #self.info.abilities do
  444. if ( self.info.abilities[i].isTrait ) then
  445. buttonCount = buttonCount + 1;
  446. abHeight = abHeight + GarrisonFollowerButton_AddAbility(self, buttonCount, self.info.abilities[i]);
  447. end
  448. end
  449.  
  450. for i=(#self.info.abilities + 1), #self.Abilities do
  451. self.Abilities[i]:Hide();
  452. end
  453. if (abHeight > 0) then
  454. abHeight = abHeight + 8;
  455. self.AbilitiesBG:Show();
  456. self.AbilitiesBG:SetHeight(abHeight);
  457. else
  458. self.AbilitiesBG:Hide();
  459. end
  460. self:SetHeight(51 + abHeight);
  461. followerListFrame.expandedFollowerHeight = 51 + abHeight + 6;
  462. end
  463.  
  464. function GarrisonFollowerButton_AddAbility(self, index, ability)
  465. if (not self.Abilities[index]) then
  466. self.Abilities[index] = CreateFrame("Frame", nil, self, "GarrisonFollowerListButtonAbilityTemplate");
  467. self.Abilities[index]:SetPoint("TOPLEFT", self.Abilities[index-1], "BOTTOMLEFT", 0, -2);
  468. end
  469. local Ability = self.Abilities[index];
  470. Ability.abilityID = ability.id;
  471. Ability.Name:SetText(ability.name);
  472. Ability.Icon:SetTexture(ability.icon);
  473. Ability.tooltip = ability.description;
  474. Ability:Show();
  475. return Ability:GetHeight() + 3;
  476. end
  477.  
  478. function GarrisonFollowerButton_Collapse(self)
  479. self.UpArrow:Hide();
  480. self.DownArrow:Show();
  481. self.AbilitiesBG:Hide();
  482. for i=1, #self.Abilities do
  483. self.Abilities[i]:Hide();
  484. end
  485. self:SetHeight(56);
  486. end
  487.  
  488. function GarrisonFollowerListButton_OnClick(self, button)
  489. local followerFrame = self:GetParent():GetParent().followerFrame;
  490. if ( button == "LeftButton" ) then
  491. PlaySound("UI_Garrison_CommandTable_SelectFollower");
  492. followerFrame.selectedFollower = self.id;
  493.  
  494. if ( self.isCollected and followerFrame.FollowerList.canCastSpellsOnFollowers and SpellCanTargetGarrisonFollower() ) then
  495. GarrisonFollower_DisplayUpgradeConfirmation(self.id);
  496. end
  497.  
  498. if ( followerFrame.FollowerList.canExpand ) then
  499. if ( self.isCollected ) then
  500. if (followerFrame.FollowerList.expandedFollower == self.id) then
  501. followerFrame.FollowerList.expandedFollower = nil;
  502. PlaySound("UI_Garrison_CommandTable_FollowerAbilityClose");
  503. else
  504. followerFrame.FollowerList.expandedFollower = self.id;
  505. -- expand button now to get height
  506. GarrisonFollowerButton_Expand(self, followerFrame.FollowerList);
  507. PlaySound("UI_Garrison_CommandTable_FollowerAbilityOpen");
  508. end
  509. else
  510. followerFrame.FollowerList.expandedFollower = nil;
  511. PlaySound("UI_Garrison_CommandTable_FollowerAbilityClose");
  512. end
  513. else
  514. if ( not followerFrame.FollowerList.canExpand and followerFrame.FollowerList.expandedFollower ~= self.id ) then
  515. followerFrame.FollowerList.expandedFollower = nil;
  516. end
  517. end
  518. followerFrame.FollowerList:UpdateData();
  519. if ( followerFrame.FollowerTab ) then
  520. followerFrame.FollowerList:ShowFollower(self.id);
  521. end
  522. CloseDropDownMenus();
  523. -- Don't show right click follower menu in landing page
  524. elseif ( button == "RightButton" and not self:GetParent():GetParent():GetParent().isLandingPage) then
  525. if ( self.isCollected ) then
  526. if ( GarrisonFollowerOptionDropDown.followerID ~= self.id ) then
  527. CloseDropDownMenus();
  528. end
  529. GarrisonFollowerOptionDropDown.followerID = self.id;
  530. ToggleDropDownMenu(1, nil, GarrisonFollowerOptionDropDown, "cursor", 0, 0);
  531. else
  532. GarrisonFollowerOptionDropDown.followerID = nil;
  533. CloseDropDownMenus();
  534. end
  535. end
  536. end
  537.  
  538. function GarrisonFollowerListButton_OnModifiedClick(self, button)
  539. if ( IsModifiedClick("CHATLINK") ) then
  540. local followerLink;
  541. if (self.info.isCollected) then
  542. followerLink = C_Garrison.GetFollowerLink(self.info.followerID);
  543. else
  544. followerLink = C_Garrison.GetFollowerLinkByID(self.info.followerID);
  545. end
  546.  
  547. if ( followerLink ) then
  548. ChatEdit_InsertLink(followerLink);
  549. end
  550. end
  551. end
  552.  
  553. ---------------------------------------------------------------------------------
  554. --- Follower filtering and searching ---
  555. ---------------------------------------------------------------------------------
  556. function GarrisonFollowerList_DirtyList(self)
  557. self.dirtyList = true;
  558. end
  559.  
  560. local statusPriority = {
  561. [GARRISON_FOLLOWER_IN_PARTY] = 1,
  562. [GARRISON_FOLLOWER_WORKING] = 2,
  563. [GARRISON_FOLLOWER_ON_MISSION] = 3,
  564. [GARRISON_FOLLOWER_EXHAUSTED] = 4,
  565. [GARRISON_FOLLOWER_INACTIVE] = 5,
  566. }
  567.  
  568. function GarrisonFollowerList_SortFollowers(self)
  569. local followers = self.followers;
  570. local followerCounters = GarrisonMissionFrame.followerCounters;
  571. local followerTraits = GarrisonMissionFrame.followerTraits;
  572. local checkAbilities = followerCounters and followerTraits and GarrisonMissionFrame.MissionTab:IsVisible();
  573. local mentorLevel, mentorItemLevel = 0, 0;
  574. if ( checkAbilities ) then
  575. mentorLevel = GarrisonMissionFrame.MissionTab.MissionPage.mentorLevel or 0;
  576. mentorItemLevel = GarrisonMissionFrame.MissionTab.MissionPage.mentorItemLevel or 0;
  577. end
  578. local comparison = function(index1, index2)
  579. local follower1 = followers[index1];
  580. local follower2 = followers[index2];
  581.  
  582. if ( follower1.isCollected ~= follower2.isCollected ) then
  583. return follower1.isCollected;
  584. end
  585.  
  586. -- treat IN_PARTY status as no status
  587. local status1 = follower1.status;
  588. if ( status1 == GARRISON_FOLLOWER_IN_PARTY ) then
  589. status1 = nil;
  590. end
  591. local status2 = follower2.status;
  592. if ( status2 == GARRISON_FOLLOWER_IN_PARTY ) then
  593. status2 = nil;
  594. end
  595. if ( status1 and not status2 ) then
  596. return false;
  597. elseif ( not status1 and status2 ) then
  598. return true;
  599. end
  600.  
  601. if ( status1 ~= status2 ) then
  602. return statusPriority[status1] < statusPriority[status2];
  603. end
  604.  
  605. -- sorting: level > item level > (num counters for mission) > (num traits for mission) > quality > name
  606. local follower1Level = max(follower1.level, mentorLevel);
  607. local follower2Level = max(follower2.level, mentorLevel);
  608. if ( follower1Level ~= follower2Level ) then
  609. return follower1Level > follower2Level;
  610. end
  611. local follower1ItemLevel = max(follower1.iLevel, mentorItemLevel);
  612. local follower2ItemLevel = max(follower2.iLevel, mentorItemLevel);
  613. if ( follower1Level == GARRISON_FOLLOWER_MAX_LEVEL and follower1ItemLevel ~= follower2ItemLevel ) then -- only checking follower 1 because follower 2 has same level at this point
  614. return follower1ItemLevel > follower2ItemLevel;
  615. end
  616. if ( checkAbilities and not status1 and follower1.isCollected ) then -- only checking follower 1 because follower 2 has same status and collected-ness at this point
  617. local numCounters1 = followerCounters[follower1.followerID] and #followerCounters[follower1.followerID] or 0;
  618. local numCounters2 = followerCounters[follower2.followerID] and #followerCounters[follower2.followerID] or 0;
  619. if ( numCounters1 ~= numCounters2 ) then
  620. return numCounters1 > numCounters2;
  621. end
  622. local numTraits1 = followerTraits[follower1.followerID] and #followerTraits[follower1.followerID] or 0;
  623. local numTraits2 = followerTraits[follower2.followerID] and #followerTraits[follower2.followerID] or 0;
  624. if ( numTraits1 ~= numTraits2 ) then
  625. return numTraits1 > numTraits2;
  626. end
  627. end
  628. if ( follower1.quality ~= follower2.quality ) then
  629. return follower1.quality > follower2.quality;
  630. end
  631. return strcmputf8i(follower1.name, follower2.name) < 0;
  632. end
  633.  
  634. table.sort(self.followersList, comparison);
  635. end
  636.  
  637. ---------------------------------------------------------------------------------
  638. --- Models ---
  639. ---------------------------------------------------------------------------------
  640. function GarrisonMission_SetFollowerModel(modelFrame, followerID, displayID)
  641. if ( not displayID or displayID == 0 ) then
  642. modelFrame:ClearModel();
  643. modelFrame:Hide();
  644. modelFrame.followerID = nil;
  645. else
  646. modelFrame:Show();
  647. modelFrame:SetDisplayInfo(displayID);
  648. modelFrame.followerID = followerID;
  649. GarrisonMission_SetFollowerModelItems(modelFrame);
  650. end
  651. end
  652.  
  653. function GarrisonMission_SetFollowerModelItems(modelFrame)
  654. if ( modelFrame.followerID ) then
  655. modelFrame:UnequipItems();
  656. local follower = C_Garrison.GetFollowerInfo(modelFrame.followerID);
  657. if ( follower and follower.isCollected ) then
  658. local modelItems = C_Garrison.GetFollowerModelItems(modelFrame.followerID);
  659. for i = 1, #modelItems do
  660. modelFrame:EquipItem(modelItems[i]);
  661. end
  662. end
  663. end
  664. end
  665.  
  666. function GarrisonCinematicModelBase_OnLoad(self)
  667. self:RegisterEvent("UI_SCALE_CHANGED");
  668. self:RegisterEvent("DISPLAY_SIZE_CHANGED");
  669. end
  670.  
  671. function GarrisonCinematicModelBase_OnEvent(self)
  672. self:RefreshCamera();
  673. end
  674.  
  675. ---------------------------------------------------------------------------------
  676. --- Follower Page ---
  677. ---------------------------------------------------------------------------------
  678. GARRISON_FOLLOWER_PAGE_HEIGHT_MULTIPLIER = .65;
  679. GARRISON_FOLLOWER_PAGE_SCALE_MULTIPLIER = 1.3
  680.  
  681. function GarrisonFollowerPageItemButton_OnEvent(self, event)
  682. if ( not self:IsShown() and self.itemID ) then
  683. GarrisonFollowerPage_SetItem(self, self.itemID, self.itemLevel);
  684. end
  685. end
  686.  
  687. function GarrisonFollowerPage_SetItem(itemFrame, itemID, itemLevel)
  688. if ( itemID and itemID > 0 ) then
  689. itemFrame.itemID = itemID;
  690. itemFrame.itemLevel = itemLevel;
  691. local itemName, _, itemQuality, _, _, _, _, _, _, itemTexture = GetItemInfo(itemID);
  692. if ( itemName ) then
  693. itemFrame.Icon:SetTexture(itemTexture);
  694. itemFrame.Name:SetTextColor(GetItemQualityColor(itemQuality));
  695. itemFrame.ItemLevel:SetFormattedText(GARRISON_FOLLOWER_ITEM_LEVEL, itemLevel);
  696. itemFrame:Show();
  697. return;
  698. end
  699. else
  700. itemFrame.itemID = nil;
  701. itemFrame.itemLevel = nil;
  702. end
  703. itemFrame:Hide();
  704. end
  705.  
  706. function GarrisonFollowerList:ShowFollower(followerID)
  707. local self = self:GetParent().FollowerTab;
  708. local lastUpdate = self.lastUpdate;
  709. local followerInfo = C_Garrison.GetFollowerInfo(followerID);
  710.  
  711. if (followerInfo) then
  712. self.followerID = followerID;
  713. self.NoFollowersLabel:Hide();
  714. self.PortraitFrame:Show();
  715. self.Model:SetAlpha(0);
  716. GarrisonMission_SetFollowerModel(self.Model, followerInfo.followerID, followerInfo.displayID);
  717. if (followerInfo.displayHeight) then
  718. self.Model:SetHeightFactor(followerInfo.displayHeight);
  719. end
  720. if (followerInfo.displayScale) then
  721. self.Model:InitializeCamera(followerInfo.displayScale);
  722. end
  723. else
  724. self.followerID = nil;
  725. self.NoFollowersLabel:Show();
  726. followerInfo = { };
  727. followerInfo.quality = 1;
  728. followerInfo.abilities = { };
  729. self.PortraitFrame:Hide();
  730. self.Model:ClearModel();
  731. end
  732.  
  733. GarrisonFollowerPageModelUpgrade_Update(self.Model.UpgradeFrame);
  734. GarrisonMissionFrame_SetFollowerPortrait(self.PortraitFrame, followerInfo);
  735. self.Name:SetText(followerInfo.name);
  736. local color = ITEM_QUALITY_COLORS[followerInfo.quality];
  737. self.Name:SetVertexColor(color.r, color.g, color.b);
  738. self.ClassSpec:SetText(followerInfo.className);
  739. self.Class:SetAtlas(followerInfo.classAtlas);
  740. if ( followerInfo.isCollected ) then
  741. -- Follower cannot be upgraded anymore
  742. if (followerInfo.level == GARRISON_FOLLOWER_MAX_LEVEL and followerInfo.quality >= GARRISON_FOLLOWER_MAX_UPGRADE_QUALITY) then
  743. self.XPLabel:Hide();
  744. self.XPBar:Hide();
  745. self.XPText:Hide();
  746. self.XPText:SetText("");
  747. else
  748. if (followerInfo.level == GARRISON_FOLLOWER_MAX_LEVEL) then
  749. self.XPLabel:SetText(GARRISON_FOLLOWER_XP_UPGRADE_STRING);
  750. else
  751. self.XPLabel:SetText(GARRISON_FOLLOWER_XP_STRING);
  752. end
  753. self.XPLabel:SetWidth(0);
  754. self.XPLabel:SetFontObject("GameFontHighlight");
  755. self.XPLabel:SetPoint("TOPRIGHT", self.XPText, "BOTTOMRIGHT", 0, -4);
  756. self.XPLabel:Show();
  757. -- If the XPLabel text does not fit within 100 pixels, shrink the font. If it wraps to 2 lines, move the text up.
  758. if (self.XPLabel:GetWidth() > 100) then
  759. self.XPLabel:SetWidth(100);
  760. self.XPLabel:SetFontObject("GameFontWhiteSmall");
  761. if (self.XPLabel:GetNumLines() > 1) then
  762. self.XPLabel:SetPoint("TOPRIGHT", self.XPText, "BOTTOMRIGHT", -1, 0);
  763. end
  764. end
  765. self.XPBar:Show();
  766. self.XPBar:SetMinMaxValues(0, followerInfo.levelXP);
  767. self.XPBar.Label:SetFormattedText(GARRISON_FOLLOWER_XP_BAR_LABEL, BreakUpLargeNumbers(followerInfo.xp), BreakUpLargeNumbers(followerInfo.levelXP));
  768. self.XPBar:SetValue(followerInfo.xp);
  769. local xpLeft = followerInfo.levelXP - followerInfo.xp;
  770. self.XPText:SetText(format(GARRISON_FOLLOWER_XP_LEFT, xpLeft));
  771. self.XPText:Show();
  772. end
  773. else
  774. self.XPText:Hide();
  775. self.XPLabel:Hide();
  776. self.XPBar:Hide();
  777. end
  778. GarrisonTruncationFrame_Check(self.Name);
  779.  
  780. if ( ENABLE_COLORBLIND_MODE == "1" ) then
  781. self.QualityFrame:Show();
  782. self.QualityFrame.Text:SetText(_G["ITEM_QUALITY"..followerInfo.quality.."_DESC"]);
  783. else
  784. self.QualityFrame:Hide();
  785. end
  786.  
  787. self.AbilitiesFrame.TraitsText:ClearAllPoints();
  788. if (not followerInfo.abilities) then
  789. followerInfo.abilities = C_Garrison.GetFollowerAbilities(followerID);
  790. end
  791. local lastAbilityAnchor, lastTraitAnchor;
  792. local numCounters = 0;
  793.  
  794. for i=1, #followerInfo.abilities do
  795. local ability = followerInfo.abilities[i];
  796.  
  797. local abilityFrame = self.AbilitiesFrame.Abilities[i];
  798. if ( not abilityFrame ) then
  799. abilityFrame = CreateFrame("Frame", nil, self.AbilitiesFrame, "GarrisonFollowerPageAbilityTemplate");
  800. self.AbilitiesFrame.Abilities[i] = abilityFrame;
  801. end
  802.  
  803. if ( self.isLandingPage ) then
  804. abilityFrame.Category:SetText("");
  805. abilityFrame.Name:SetFontObject("GameFontHighlightMed2");
  806. abilityFrame.Name:ClearAllPoints();
  807. abilityFrame.Name:SetPoint("LEFT", abilityFrame.IconButton, "RIGHT", 8, 0);
  808. abilityFrame.Name:SetWidth(150);
  809. else
  810. local categoryText = "";
  811. if ( ability.isTrait ) then
  812. if ( ability.temporary ) then
  813. categoryText = GARRISON_TEMPORARY_CATEGORY_FORMAT:format(ability.category or "");
  814. else
  815. categoryText = ability.category or "";
  816. end
  817. end
  818. abilityFrame.Category:SetText(categoryText);
  819. abilityFrame.Name:SetFontObject("GameFontNormalLarge2");
  820. abilityFrame.Name:ClearAllPoints();
  821. abilityFrame.Name:SetPoint("TOPLEFT", abilityFrame.IconButton, "TOPRIGHT", 8, 0);
  822. abilityFrame.Name:SetWidth(240);
  823. end
  824. if ( followerInfo.isCollected and GarrisonFollowerAbilities_IsNew(lastUpdate, followerInfo.followerID, ability.id, GARRISON_FOLLOWER_ABILITY_TYPE_TRAIT) ) then
  825. if ( ability.temporary ) then
  826. abilityFrame.LargeAbilityFeedbackGlowAnim:Play();
  827. else
  828. abilityFrame.IconButton.Icon:SetAlpha(0);
  829. abilityFrame.IconButton.OldIcon:SetAlpha(1);
  830. abilityFrame.AbilityOverwriteAnim:Play();
  831. end
  832. else
  833. GarrisonFollowerPageAbility_StopAnimations(abilityFrame);
  834. end
  835. abilityFrame.Name:SetText(ability.name);
  836. abilityFrame.IconButton.Icon:SetTexture(ability.icon);
  837. abilityFrame.IconButton.abilityID = ability.id;
  838. if ( followerInfo and followerInfo.isCollected and followerInfo.status ~= GARRISON_FOLLOWER_WORKING and followerInfo.status ~= GARRISON_FOLLOWER_IN_PARTY and SpellCanTargetGarrisonFollowerAbility(followerInfo.followerID, ability.id) ) then
  839. abilityFrame.IconButton.ValidSpellHighlight:Show();
  840. if ( not ability.temporary ) then
  841. abilityFrame.IconButton.OldIcon:SetTexture(ability.icon);
  842. abilityFrame.IconButton.OldIcon:SetAlpha(0);
  843. end
  844. else
  845. abilityFrame.IconButton.ValidSpellHighlight:Hide();
  846. end
  847.  
  848. local hasCounters = false;
  849. if ( ability.counters and not ability.isTrait and not self.isLandingPage ) then
  850. for id, counter in pairs(ability.counters) do
  851. numCounters = numCounters + 1;
  852. local counterFrame = self.AbilitiesFrame.Counters[numCounters];
  853. if ( not counterFrame ) then
  854. counterFrame = CreateFrame("Frame", nil, self.AbilitiesFrame, "GarrisonMissionMechanicTemplate");
  855. self.AbilitiesFrame.Counters[numCounters] = counterFrame;
  856. end
  857. counterFrame.mainFrame = self:GetParent();
  858. counterFrame.Icon:SetTexture(counter.icon);
  859. counterFrame.tooltip = counter.name;
  860. counterFrame:ClearAllPoints();
  861. if ( hasCounters ) then
  862. counterFrame:SetPoint("LEFT", self.AbilitiesFrame.Counters[numCounters - 1], "RIGHT", 10, 0);
  863. else
  864. counterFrame:SetPoint("LEFT", abilityFrame.CounterString, "RIGHT", 2, -2);
  865. end
  866. counterFrame:Show();
  867. counterFrame.info = counter;
  868. hasCounters = true;
  869. end
  870. end
  871. if ( hasCounters ) then
  872. abilityFrame.CounterString:Show();
  873. else
  874. abilityFrame.CounterString:Hide();
  875. end
  876. -- anchor ability
  877. if ( ability.isTrait ) then
  878. lastTraitAnchor = GarrisonFollowerPage_AnchorAbility(abilityFrame, lastTraitAnchor, self.AbilitiesFrame.TraitsText, self.isLandingPage);
  879. else
  880. lastAbilityAnchor = GarrisonFollowerPage_AnchorAbility(abilityFrame, lastAbilityAnchor, self.AbilitiesFrame.AbilitiesText, self.isLandingPage);
  881. end
  882. abilityFrame:Show();
  883. end
  884.  
  885. if ( lastAbilityAnchor ) then
  886. self.AbilitiesFrame.AbilitiesText:Show();
  887. else
  888. self.AbilitiesFrame.AbilitiesText:Hide();
  889. end
  890. if ( lastTraitAnchor ) then
  891. self.AbilitiesFrame.TraitsText:Show();
  892. if ( lastAbilityAnchor ) then
  893. self.AbilitiesFrame.TraitsText:SetPoint("LEFT", self.AbilitiesFrame.AbilitiesText, "LEFT");
  894. if ( self.isLandingPage ) then
  895. self.AbilitiesFrame.TraitsText:SetPoint("TOP", lastAbilityAnchor, "BOTTOM", 0, 0);
  896. else
  897. self.AbilitiesFrame.TraitsText:SetPoint("TOP", lastAbilityAnchor, "BOTTOM", 0, -16);
  898. end
  899. else
  900. self.AbilitiesFrame.TraitsText:SetPoint("TOPLEFT", self.AbilitiesFrame.AbilitiesText, "TOPLEFT");
  901. end
  902. else
  903. self.AbilitiesFrame.TraitsText:Hide();
  904. end
  905.  
  906. for i = #followerInfo.abilities + 1, #self.AbilitiesFrame.Abilities do
  907. self.AbilitiesFrame.Abilities[i]:Hide();
  908. end
  909. for i = numCounters + 1, #self.AbilitiesFrame.Counters do
  910. self.AbilitiesFrame.Counters[i]:Hide();
  911. end
  912.  
  913. -- gear / source
  914. if ( followerInfo.isCollected and not self.isLandingPage ) then
  915. local weaponItemID, weaponItemLevel, armorItemID, armorItemLevel = C_Garrison.GetFollowerItems(followerInfo.followerID);
  916. GarrisonFollowerPage_SetItem(self.ItemWeapon, weaponItemID, weaponItemLevel);
  917. GarrisonFollowerPage_SetItem(self.ItemArmor, armorItemID, armorItemLevel);
  918. if ( followerInfo.level == GARRISON_FOLLOWER_MAX_LEVEL ) then
  919. self.ItemAverageLevel.Level:SetText(ITEM_LEVEL_ABBR .. " " .. followerInfo.iLevel);
  920. self.ItemAverageLevel.Level:Show();
  921. else
  922. self.ItemWeapon:Hide();
  923. self.ItemArmor:Hide();
  924. self.ItemAverageLevel.Level:Hide();
  925. end
  926. self.Source.SourceText:Hide();
  927. else
  928. self.ItemWeapon:Hide();
  929. self.ItemArmor:Hide();
  930. self.ItemAverageLevel.Level:Hide();
  931.  
  932. self.Source.SourceText:SetText(C_Garrison.GetFollowerSourceTextByID(followerID));
  933. self.Source.SourceText:Show();
  934. end
  935.  
  936. self.lastUpdate = self:IsShown() and GetTime() or nil;
  937. end
  938.  
  939. function GarrisonFollowerPage_AnchorAbility(abilityFrame, lastAnchor, headerString, isLandingPage)
  940. abilityFrame:ClearAllPoints();
  941. if ( lastAnchor ) then
  942. abilityFrame:SetPoint("LEFT", lastAnchor);
  943. abilityFrame:SetPoint("TOP", lastAnchor, "BOTTOM", 0, isLandingPage and 13 or 0);
  944. else
  945. abilityFrame:SetPoint("TOPLEFT", headerString, "BOTTOMLEFT", 2, isLandingPage and -5 or -12);
  946. end
  947. return abilityFrame;
  948. end
  949.  
  950. function GarrisonFollowerPageModel_OnMouseDown(self, button)
  951. local followerList = self:GetParent():GetParent().FollowerList;
  952. if ( button == "LeftButton" and followerList.canCastSpellsOnFollowers and SpellCanTargetGarrisonFollower() ) then
  953. -- no rotation if you can upgrade this follower
  954. local followerID = self.followerID;
  955. local followerInfo = followerID and C_Garrison.GetFollowerInfo(followerID);
  956. if ( followerInfo and followerInfo.isCollected and followerInfo.status ~= GARRISON_FOLLOWER_ON_MISSION ) then
  957. return;
  958. end
  959. end
  960. Model_OnMouseDown(self, button);
  961. end
  962.  
  963. function GarrisonFollowerPageModel_OnMouseUp(self, button)
  964. local followerList = self:GetParent():GetParent().FollowerList;
  965. if ( button == "LeftButton" and followerList.canCastSpellsOnFollowers and SpellCanTargetGarrisonFollower() ) then
  966. -- no rotation if you can upgrade this follower, bring up confirmation dialog
  967. if ( GarrisonFollower_DisplayUpgradeConfirmation(self.followerID) ) then
  968. return;
  969. end
  970. end
  971. Model_OnMouseUp(self, button);
  972. end
  973.  
  974. function GarrisonFollowerPageModelUpgrade_OnLoad(self)
  975. self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED");
  976. end
  977.  
  978. function GarrisonFollowerPageModelUpgrade_OnEvent(self, event)
  979. GarrisonFollowerPageModelUpgrade_Update(self);
  980. end
  981.  
  982. function GarrisonFollowerPageModelUpgrade_Update(self)
  983. if ( SpellCanTargetGarrisonFollower() ) then
  984. local followerID = self:GetParent().followerID;
  985. local followerInfo = followerID and C_Garrison.GetFollowerInfo(followerID);
  986. if ( followerInfo and followerInfo.isCollected and followerInfo.status ~= GARRISON_FOLLOWER_ON_MISSION and (not C_Garrison.TargetSpellHasFollowerTemporaryAbility() or C_Garrison.CanSpellTargetFollowerIDWithAddAbility(followerID)) ) then
  987. local isValidTarget = (followerInfo.level == GARRISON_FOLLOWER_MAX_LEVEL or not C_Garrison.TargetSpellHasFollowerItemLevelUpgrade());
  988. self.Text:SetShown(isValidTarget);
  989. self.Icon:SetShown(isValidTarget);
  990. self.TextInvalid:SetShown(not isValidTarget);
  991. self:Show();
  992. return;
  993. end
  994. end
  995. self:Hide();
  996. end
  997.  
  998. function GarrisionFollowerPageUpgradeTarget_OnLoad(self)
  999. self:SetFrameLevel(self:GetParent():GetFrameLevel() + 5);
  1000. self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED");
  1001. end
  1002.  
  1003. function GarrisionFollowerPageUpgradeTarget_OnEvent(self, event)
  1004. if (event == "CURRENT_SPELL_CAST_CHANGED") then
  1005. if ( SpellCanTargetGarrisonFollower() ) then
  1006. local followerID = self:GetParent().followerID;
  1007. local followerInfo = followerID and C_Garrison.GetFollowerInfo(followerID);
  1008. if ( followerInfo and followerInfo.isCollected and followerInfo.status ~= GARRISON_FOLLOWER_ON_MISSION and (followerInfo.level == GARRISON_FOLLOWER_MAX_LEVEL or not C_Garrison.TargetSpellHasFollowerItemLevelUpgrade()) ) then
  1009. if ( not C_Garrison.TargetSpellHasFollowerTemporaryAbility() or C_Garrison.CanSpellTargetFollowerIDWithAddAbility(followerID) ) then
  1010. self:Show();
  1011. return;
  1012. end
  1013. end
  1014. end
  1015. self:Hide();
  1016. end
  1017. end
  1018.  
  1019. function GarrisonFollower_DisplayUpgradeConfirmation(followerID)
  1020. local followerInfo = followerID and C_Garrison.GetFollowerInfo(followerID);
  1021. if ( followerInfo and followerInfo.isCollected and followerInfo.status ~= GARRISON_FOLLOWER_ON_MISSION and (followerInfo.level == GARRISON_FOLLOWER_MAX_LEVEL or not C_Garrison.TargetSpellHasFollowerItemLevelUpgrade()) ) then
  1022. local name = ITEM_QUALITY_COLORS[followerInfo.quality].hex..followerInfo.name..FONT_COLOR_CODE_CLOSE;
  1023. if ( C_Garrison.TargetSpellHasFollowerTemporaryAbility() ) then
  1024. if ( C_Garrison.CanSpellTargetFollowerIDWithAddAbility(followerID) ) then
  1025. StaticPopup_Show("CONFIRM_FOLLOWER_TEMPORARY_ABILITY", name, nil, followerID);
  1026. return true;
  1027. end
  1028. else
  1029. StaticPopup_Show("CONFIRM_FOLLOWER_UPGRADE", name, nil, followerID);
  1030. return true;
  1031. end
  1032. end
  1033. return false;
  1034. end
  1035.  
  1036. function GarrisionFollowerPageUpgradeTarget_OnClick(self, button)
  1037. GarrisonFollower_DisplayUpgradeConfirmation(self:GetParent().followerID);
  1038. end
  1039.  
  1040. function GarrisonFollowerPageAbility_OnClick(self, button)
  1041. if ( IsModifiedClick("CHATLINK") ) then
  1042. local abilityLink = C_Garrison.GetFollowerAbilityLink(self.abilityID);
  1043. if (abilityLink) then
  1044. ChatEdit_InsertLink(abilityLink);
  1045. end
  1046. else
  1047. local followerList = self:GetParent():GetParent():GetParent():GetParent().FollowerList;
  1048. if ( button == "LeftButton" and followerList.canCastSpellsOnFollowers and SpellCanTargetGarrisonFollowerAbility(self.abilityID) ) then
  1049. local followerID = self:GetParent():GetParent():GetParent().followerID;
  1050. local followerInfo = followerID and C_Garrison.GetFollowerInfo(followerID);
  1051. if ( not followerInfo or not followerInfo.isCollected or followerInfo.status == GARRISON_FOLLOWER_ON_MISSION or followerInfo.status == GARRISON_FOLLOWER_WORKING ) then
  1052. return;
  1053. end
  1054.  
  1055. local popupData = {};
  1056. popupData.followerID = followerID;
  1057. popupData.abilityID = self.abilityID;
  1058. GarrisonConfirmFollowerAbilityUpgradeFrame.Name:SetText(C_Garrison.GetFollowerAbilityName(self.abilityID));
  1059. GarrisonConfirmFollowerAbilityUpgradeFrame.Icon:SetTexture(C_Garrison.GetFollowerAbilityIcon(self.abilityID));
  1060. local text = CONFIRM_GARRISON_FOLLOWER_ABILITY_REPLACE;
  1061. if ( C_Garrison.GetFollowerAbilityIsTrait(self.abilityID) ) then
  1062. text = CONFIRM_GARRISON_FOLLOWER_TRAIT_REPLACE;
  1063. end
  1064. StaticPopup_Show("CONFIRM_FOLLOWER_ABILITY_UPGRADE", NORMAL_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE, nil, popupData, GarrisonConfirmFollowerAbilityUpgradeFrame);
  1065. end
  1066. end
  1067. end
  1068.  
  1069. function GarrisonFollowerPageAbility_StopAnimations(self)
  1070. self.LargeAbilityFeedbackGlowAnim:Stop();
  1071. if ( self.AbilityOverwriteAnim:IsPlaying() ) then
  1072. self.AbilityOverwriteAnim:Stop();
  1073. self.IconButton.Icon:SetAlpha(1);
  1074. self.IconButton.OldIcon:SetAlpha(0);
  1075. end
  1076. end
  1077.  
  1078. ---------------------------------------------------------------------------------
  1079. --- Mission Sorting ---
  1080. ---------------------------------------------------------------------------------
  1081.  
  1082. function Garrison_SortMissions(missionsList)
  1083. local comparison = function(mission1, mission2)
  1084. if ( mission1.level ~= mission2.level ) then
  1085. return mission1.level > mission2.level;
  1086. end
  1087.  
  1088. if ( mission1.level == GARRISON_FOLLOWER_MAX_LEVEL ) then -- mission 2 level is same as 1's at this point
  1089. if ( mission1.iLevel ~= mission2.iLevel ) then
  1090. return mission1.iLevel > mission2.iLevel;
  1091. end
  1092. end
  1093.  
  1094. if ( mission1.durationSeconds ~= mission2.durationSeconds ) then
  1095. return mission1.durationSeconds < mission2.durationSeconds;
  1096. end
  1097.  
  1098. if ( mission1.isRare ~= mission2.isRare ) then
  1099. return mission1.isRare;
  1100. end
  1101.  
  1102. return strcmputf8i(mission1.name, mission2.name) < 0;
  1103. end
  1104.  
  1105. table.sort(missionsList, comparison);
  1106. end
  1107.  
  1108. ---------------------------------------------------------------------------------
  1109. --- Truncation ---
  1110. ---------------------------------------------------------------------------------
  1111.  
  1112. function GarrisonTruncationFrame_Check(fontString)
  1113. local self = GarrisonTruncationFrame;
  1114. -- force a resize so IsTruncated will be correct, otherwise it might change a frame later depending on pending resizes
  1115. fontString:GetRect();
  1116. if ( fontString:IsTruncated() ) then
  1117. self:SetParent(fontString:GetParent());
  1118. self:SetPoint("TOPLEFT", fontString);
  1119. self:SetPoint("BOTTOMRIGHT", fontString);
  1120. self:Show();
  1121. self.tooltip = fontString:GetText();
  1122. else
  1123. self:Hide();
  1124. self.tooltip = nil;
  1125. end
  1126. end
  1127.  
  1128. function GarrisonTruncationFrame_OnEnter(self)
  1129. if ( self.tooltip ) then
  1130. GameTooltip:SetOwner(self, "ANCHOR_TOP");
  1131. GameTooltip:SetText(self.tooltip);
  1132. end
  1133. end
  1134.  
  1135. function GarrisonTruncationFrame_OnLeave(self)
  1136. GameTooltip:Hide();
  1137. end
  1138.  
  1139. ---------------------------------------------------------------------------------
  1140. --- Threat Counters ---
  1141. ---------------------------------------------------------------------------------
  1142.  
  1143. function GarrisonThreatCountersFrame_OnLoad(self, followerType, tooltipString)
  1144. if (followerType == nil) then
  1145. followerType = LE_FOLLOWER_TYPE_GARRISON_6_0;
  1146. end
  1147. if (tooltipString == nil) then
  1148. tooltipString = GARRISON_THREAT_COUNTER_TOOLTIP;
  1149. end
  1150. self.tooltipString = tooltipString;
  1151. local mechanics = C_Garrison.GetAllEncounterThreats(followerType);
  1152. -- sort reverse alphabetical because we'll be anchoring buttons right to left
  1153. table.sort(mechanics, function(m1, m2) return strcmputf8i(m1.name, m2.name) > 0; end);
  1154. for i = 1, #mechanics do
  1155. local frame = self.ThreatsList[i];
  1156. if ( not frame ) then
  1157. frame = CreateFrame("Button", nil, self, "GarrisonThreatCounterTemplate");
  1158. frame:SetPoint("RIGHT", self.ThreatsList[i-1], "LEFT", -14, 0);
  1159. self.ThreatsList[i] = frame;
  1160. end
  1161. frame.Icon:SetTexture(mechanics[i].icon);
  1162. frame.name = mechanics[i].name;
  1163. frame.id = mechanics[i].id;
  1164. end
  1165. self:RegisterEvent("GARRISON_FOLLOWER_LIST_UPDATE");
  1166. end
  1167.  
  1168. function GarrisonThreatCountersFrame_OnEvent(self, event, ...)
  1169. if ( self:IsVisible() ) then
  1170. GarrisonThreatCountersFrame_Update(self);
  1171. end
  1172. end
  1173.  
  1174. function GarrisonThreatCountersFrame_Update(self)
  1175. for i = 1, #self.ThreatsList do
  1176. self.ThreatsList[i].Count:SetText(C_Garrison.GetNumFollowersForMechanic(self.ThreatsList[i].id));
  1177. end
  1178. end
  1179.  
  1180. function GarrisonThreatCounter_OnEnter(self)
  1181. GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
  1182. local text = string.format(self:GetParent().tooltipString, C_Garrison.GetNumFollowersForMechanic(self.id), self.name);
  1183. GameTooltip:SetText(text, nil, nil, nil, nil, true);
  1184. end
  1185.  
  1186. ---------------------------------------------------------------------------------
  1187. --- Follower Abilities ---
  1188. ---------------------------------------------------------------------------------
  1189.  
  1190. GARRISON_FOLLOWER_ABILITY_TYPE_ABILITY = 1;
  1191. GARRISON_FOLLOWER_ABILITY_TYPE_TRAIT = 2;
  1192. GARRISON_FOLLOWER_ABILITY_TYPE_EITHER = 3;
  1193.  
  1194. local function IsNewHelper(lastUpdate, abilityIdToTest, ...)
  1195. for i = 1, select("#", ...), 2 do
  1196. local abilityID = select(i, ...);
  1197. local timeGained = select(i + 1, ...);
  1198. if ( timeGained >= lastUpdate and abilityIdToTest == abilityID ) then
  1199. return true;
  1200. end
  1201. end
  1202. return false;
  1203. end
  1204.  
  1205. function GarrisonFollowerAbilities_IsNew(lastUpdate, followerID, abilityIdToTest, abilityType)
  1206. if ( lastUpdate and followerID and followerID ~= "" ) then
  1207. abilityType = abilityType or GARRISON_FOLLOWER_ABILITY_TYPE_EITHER;
  1208.  
  1209. if ( abilityType == GARRISON_FOLLOWER_ABILITY_TYPE_ABILITY or abilityType == GARRISON_FOLLOWER_ABILITY_TYPE_EITHER ) then
  1210. if ( IsNewHelper(lastUpdate, abilityIdToTest, C_Garrison.GetFollowerRecentlyGainedAbilityIDs(followerID)) ) then
  1211. return true;
  1212. end
  1213. end
  1214.  
  1215. if ( abilityType == GARRISON_FOLLOWER_ABILITY_TYPE_TRAIT or abilityType == GARRISON_FOLLOWER_ABILITY_TYPE_EITHER ) then
  1216. if ( IsNewHelper(lastUpdate, abilityIdToTest, C_Garrison.GetFollowerRecentlyGainedTraitIDs(followerID)) ) then
  1217. return true;
  1218. end
  1219. end
  1220. end
  1221.  
  1222. return false;
  1223. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement