ItemRef.lua

ItemRef.lua (9.1.5.40906; unchanged since 9.1.5.40871)
  1. local DUNGEON_SCORE_LINK_INDEX_START = 9;
  2. local DUNGEON_SCORE_LINK_ITERATE = 3;
  3. local PVP_LINK_ITERATE = 3;
  4. local PVP_LINK_ITERATE_BRACKET = 4;
  5. local PVP_LINK_INDEX_START = 7;
  6. local function FormatLink(linkType, linkDisplayText, ...)
  7. local linkFormatTable = { ("|H%s"):format(linkType), ... };
  8. local returnLink = table.concat(linkFormatTable, ":");
  9. if linkDisplayText then
  10. return returnLink .. ("|h%s|h"):format(linkDisplayText);
  11. else
  12. return returnLink .. "|h";
  13. end
  14. end
  15. function SetItemRef(link, text, button, chatFrame)
  16. -- Going forward, use linkType and linkData instead of strsub and strsplit everywhere
  17. local linkType, linkData = ExtractLinkData(link);
  18. if ( strsub(link, 1, 6) == "player" ) then
  19. local namelink, isGMLink, isCommunityLink;
  20. if ( strsub(link, 7, 8) == "GM" ) then
  21. namelink = strsub(link, 10);
  22. isGMLink = true;
  23. elseif ( strsub(link, 7, 15) == "Community") then
  24. namelink = strsub(link, 17);
  25. isCommunityLink = true;
  26. else
  27. namelink = strsub(link, 8);
  28. end
  29. local name, lineID, chatType, chatTarget, communityClubID, communityStreamID, communityEpoch, communityPosition;
  30. if ( isCommunityLink ) then
  31. name, communityClubID, communityStreamID, communityEpoch, communityPosition = strsplit(":", namelink);
  32. else
  33. name, lineID, chatType, chatTarget = strsplit(":", namelink);
  34. end
  35. if ( name and (strlen(name) > 0) ) then
  36. if ( IsModifiedClick("CHATLINK") ) then
  37. local staticPopup;
  38. staticPopup = StaticPopup_Visible("ADD_IGNORE");
  39. if ( staticPopup ) then
  40. -- If add ignore dialog is up then enter the name into the editbox
  41. _G[staticPopup.."EditBox"]:SetText(name);
  42. return;
  43. end
  44. staticPopup = StaticPopup_Visible("ADD_FRIEND");
  45. if ( staticPopup ) then
  46. -- If add ignore dialog is up then enter the name into the editbox
  47. _G[staticPopup.."EditBox"]:SetText(name);
  48. return;
  49. end
  50. staticPopup = StaticPopup_Visible("ADD_GUILDMEMBER");
  51. if ( staticPopup ) then
  52. -- If add ignore dialog is up then enter the name into the editbox
  53. _G[staticPopup.."EditBox"]:SetText(name);
  54. return;
  55. end
  56. staticPopup = StaticPopup_Visible("CHANNEL_INVITE");
  57. if ( staticPopup ) then
  58. _G[staticPopup.."EditBox"]:SetText(name);
  59. return;
  60. end
  61. if ( ChatEdit_GetActiveWindow() ) then
  62. ChatEdit_InsertLink(name);
  63. else
  64. C_FriendList.SendWho(WHO_TAG_EXACT..name);
  65. end
  66. elseif ( button == "RightButton" and (not isGMLink) ) then
  67. FriendsFrame_ShowDropdown(name, 1, lineID, chatType, chatFrame, nil, nil, communityClubID, communityStreamID, communityEpoch, communityPosition);
  68. else
  69. ChatFrame_SendTell(name, chatFrame);
  70. end
  71. end
  72. return;
  73. elseif ( strsub(link, 1, 8) == "BNplayer" ) then
  74. local namelink, isCommunityLink;
  75. if ( strsub(link, 9, 17) == "Community" ) then
  76. namelink = strsub(link, 19);
  77. isCommunityLink = true;
  78. else
  79. namelink = strsub(link, 10);
  80. end
  81. local name, bnetIDAccount, lineID, chatType, chatTarget, communityClubID, communityStreamID, communityEpoch, communityPosition;
  82. if ( isCommunityLink ) then
  83. name, bnetIDAccount, communityClubID, communityStreamID, communityEpoch, communityPosition = strsplit(":", namelink);
  84. else
  85. name, bnetIDAccount, lineID, chatType, chatTarget = strsplit(":", namelink);
  86. end
  87. if ( name and (strlen(name) > 0) ) then
  88. if ( IsModifiedClick("CHATLINK") ) then
  89. -- Disable SHIFT-CLICK for battlenet friends, so we don't put an encoded bnetIDAccount in chat
  90. elseif ( button == "RightButton" ) then
  91. if ( isCommunityLink or not BNIsSelf(bnetIDAccount) ) then
  92. FriendsFrame_ShowBNDropdown(name, 1, nil, chatType, chatFrame, nil, bnetIDAccount, communityClubID, communityStreamID, communityEpoch, communityPosition);
  93. end
  94. else
  95. if ( BNIsFriend(bnetIDAccount)) then
  96. ChatFrame_SendBNetTell(name);
  97. else
  98. local displayName = BNGetDisplayName(bnetIDAccount);
  99. ChatFrame_SendBNetTell(displayName)
  100. end
  101. end
  102. end
  103. return;
  104. elseif ( strsub(link, 1, 7) == "channel" ) then
  105. if ( IsModifiedClick("CHATLINK") ) then
  106. local chanLink = strsub(link, 9);
  107. local chatType, chatTarget = strsplit(":", chanLink);
  108. ChannelFrame:Toggle();
  109. elseif ( button == "LeftButton" ) then
  110. local chanLink = strsub(link, 9);
  111. local chatType, chatTarget = strsplit(":", chanLink);
  112. if ( strupper(chatType) == "CHANNEL" ) then
  113. if ( GetChannelName(tonumber(chatTarget))~=0 ) then
  114. ChatFrame_OpenChat("/"..chatTarget, chatFrame);
  115. end
  116. elseif ( strupper(chatType) == "PET_BATTLE_COMBAT_LOG" or strupper(chatType) == "PET_BATTLE_INFO" ) then
  117. --Don't do anything
  118. else
  119. ChatFrame_OpenChat("/"..chatType, chatFrame);
  120. end
  121. elseif ( button == "RightButton" ) then
  122. local chanLink = strsub(link, 9);
  123. local chatType, chatTarget = strsplit(":", chanLink);
  124. if not ( (strupper(chatType) == "CHANNEL" and GetChannelName(tonumber(chatTarget)) == 0) ) then --Don't show the dropdown if this is a channel we are no longer in.
  125. ChatChannelDropDown_Show(chatFrame, strupper(chatType), chatTarget, Chat_GetColoredChatName(strupper(chatType), chatTarget));
  126. end
  127. end
  128. return;
  129. elseif ( strsub(link, 1, 6) == "GMChat" ) then
  130. GMChatStatusFrame_OnClick();
  131. return;
  132. elseif ( strsub(link, 1, 7) == "levelup" ) then
  133. local _, level, levelUpType, arg1 = strsplit(":", link);
  134. EventToastManagerSideDisplay:DisplayToastsByLevel(level);
  135. return;
  136. elseif ( strsub(link, 1, 6) == "pvpbgs" ) then
  137. TogglePVPUI();
  138. return;
  139. elseif ( strsub(link, 1, 12) == "battleground" ) then
  140. PVEFrame_ShowFrame("PVPUIFrame", HonorFrame);
  141. HonorFrame_SetType("specific");
  142. local _, bgID = strsplit(":", link);
  143. HonorFrameSpecificList_FindAndSelectBattleground(tonumber(bgID));
  144. return;
  145. elseif ( strsub(link, 1, 3) == "lfd" ) then
  146. ToggleLFDParentFrame();
  147. return;
  148. elseif ( strsub(link, 1, 8) == "specpane" ) then
  149. ToggleTalentFrame(SPECIALIZATION_TAB);
  150. return;
  151. elseif ( strsub(link, 1, 10) == "talentpane" ) then
  152. ToggleTalentFrame(TALENTS_TAB);
  153. return;
  154. elseif ( strsub(link, 1, 14) == "mountequipment" ) then
  155. ToggleCollectionsJournal(COLLECTIONS_JOURNAL_TAB_INDEX_MOUNTS);
  156. return;
  157. elseif ( strsub(link, 1, 11) == "honortalent" ) then
  158. ToggleTalentFrame(PVP_TALENTS_TAB);
  159. return;
  160. elseif ( strsub(link, 1, 10) == "worldquest" ) then
  161. OpenWorldMap();
  162. return;
  163. elseif ( strsub(link, 1, 7) == "journal" ) then
  164. if ( not HandleModifiedItemClick(GetFixedLink(text)) ) then
  165. if ( not EncounterJournal ) then
  166. EncounterJournal_LoadUI();
  167. end
  168. EncounterJournal_OpenJournalLink(strsplit(":", link));
  169. end
  170. return;
  171. elseif ( strsub(link, 1, 8) == "urlIndex" ) then
  172. local _, index = strsplit(":", link);
  173. LoadURLIndex(tonumber(index));
  174. return;
  175. elseif ( strsub(link, 1, 11) == "lootHistory" ) then
  176. local _, rollID = strsplit(":", link);
  177. LootHistoryFrame_ToggleWithRoll(LootHistoryFrame, tonumber(rollID), chatFrame);
  178. return;
  179. elseif ( strsub(link, 1, 13) == "battlePetAbil" ) then
  180. local _, abilityID, maxHealth, power, speed = strsplit(":", link);
  181. if ( IsModifiedClick() ) then
  182. local fixedLink = GetFixedLink(text);
  183. HandleModifiedItemClick(fixedLink);
  184. else
  185. FloatingPetBattleAbility_Show(tonumber(abilityID), tonumber(maxHealth), tonumber(power), tonumber(speed));
  186. end
  187. return;
  188. elseif ( strsub(link, 1, 9) == "battlepet" ) then
  189. local _, speciesID, level, breedQuality, maxHealth, power, speed, battlePetID = strsplit(":", link);
  190. if ( IsModifiedClick() ) then
  191. local fixedLink = GetFixedLink(text, tonumber(breedQuality));
  192. HandleModifiedItemClick(fixedLink);
  193. else
  194. FloatingBattlePet_Toggle(tonumber(speciesID), tonumber(level), tonumber(breedQuality), tonumber(maxHealth), tonumber(power), tonumber(speed), string.gsub(string.gsub(text, "^(.*)%[", ""), "%](.*)$", ""), battlePetID);
  195. end
  196. return;
  197. elseif ( strsub(link, 1, 19) == "garrfollowerability" ) then
  198. local _, garrFollowerAbilityID = strsplit(":", link);
  199. if ( IsModifiedClick() ) then
  200. local fixedLink = GetFixedLink(text);
  201. HandleModifiedItemClick(fixedLink);
  202. else
  203. FloatingGarrisonFollowerAbility_Toggle(tonumber(garrFollowerAbilityID));
  204. end
  205. return;
  206. elseif ( strsub(link, 1, 12) == "garrfollower" ) then
  207. local _, garrisonFollowerID, quality, level, itemLevel, ability1, ability2, ability3, ability4, trait1, trait2, trait3, trait4, spec1 = strsplit(":", link);
  208. if ( IsModifiedClick() ) then
  209. local fixedLink = GetFixedLink(text, tonumber(quality));
  210. HandleModifiedItemClick(fixedLink);
  211. else
  212. FloatingGarrisonFollower_Toggle(tonumber(garrisonFollowerID), tonumber(quality), tonumber(level), tonumber(itemLevel), tonumber(spec1), tonumber(ability1), tonumber(ability2), tonumber(ability3), tonumber(ability4), tonumber(trait1), tonumber(trait2), tonumber(trait3), tonumber(trait4));
  213. end
  214. return;
  215. elseif ( strsub(link, 1, 11) == "garrmission" ) then
  216. local _, garrMissionID = strsplit(":", link);
  217. local garrMissionID, garrMissionDBID = link:match("garrmission:(%d+):([0-9a-fA-F]+)")
  218. if (garrMissionID and garrMissionDBID and strlen(garrMissionDBID) == 16) then
  219. if ( IsModifiedClick() ) then
  220. local fixedLink = GetFixedLink(text);
  221. HandleModifiedItemClick(fixedLink);
  222. else
  223. FloatingGarrisonMission_Toggle(tonumber(garrMissionID), "0x"..(garrMissionDBID:upper()));
  224. end
  225. end
  226. return;
  227. elseif ( strsub(link, 1, 5) == "death" ) then
  228. local _, id = strsplit(":", link);
  229. OpenDeathRecapUI(id);
  230. return;
  231. elseif ( strsub(link, 1, 7) == "sharess" ) then
  232. local _, index = strsplit(":", link);
  233. SocialFrame_LoadUI();
  234. Social_ShowScreenshot(tonumber(index));
  235. return;
  236. elseif ( strsub(link, 1, 12) == "shareachieve" ) then
  237. local _, achievementID, earned = strsplit(":", link);
  238. SocialFrame_LoadUI();
  239. Social_ShowAchievement(tonumber(achievementID), StringToBoolean(earned));
  240. return;
  241. elseif ( strsub(link, 1, 9) == "shareitem" ) then
  242. local strippedItemLink, earned = link:match("^shareitem:(.-):(%d+)$");
  243. local itemLink = FormatLink("item", nil, strippedItemLink);
  244. SocialFrame_LoadUI();
  245. Social_ShowItem(itemLink, earned);
  246. return;
  247. elseif ( strsub(link, 1, 16) == "transmogillusion" ) then
  248. local fixedLink = GetFixedLink(text);
  249. if ( not HandleModifiedItemClick(fixedLink) ) then
  250. DressUpTransmogLink(link);
  251. end
  252. return;
  253. elseif ( strsub(link, 1, 18) == "transmogappearance" ) then
  254. local _, sourceID = strsplit(":", link);
  255. if ( IsModifiedClick("CHATLINK") ) then
  256. local itemLink = select(6, C_TransmogCollection.GetAppearanceSourceInfo(sourceID));
  257. HandleModifiedItemClick(itemLink);
  258. else
  259. TransmogUtil.OpenCollectionToItem(sourceID);
  260. end
  261. return;
  262. elseif ( strsub(link, 1, 11) == "transmogset" ) then
  263. local _, setID = strsplit(":", link);
  264. TransmogUtil.OpenCollectionToSet(setID);
  265. return;
  266. elseif ( strsub(link, 1, 6) == "outfit" ) then
  267. local fixedLink = GetFixedLink(text);
  268. if not HandleModifiedItemClick(fixedLink) then
  269. local itemTransmogInfoList = C_TransmogCollection.GetItemTransmogInfoListFromOutfitHyperlink(text);
  270. if itemTransmogInfoList then
  271. local showOutfitDetails = true;
  272. DressUpItemTransmogInfoList(itemTransmogInfoList, showOutfitDetails);
  273. end
  274. end
  275. return;
  276. elseif ( strsub(link, 1, 3) == "api" ) then
  277. APIDocumentation_LoadUI();
  278. local command = APIDocumentation.Commands.Default;
  279. if button == "RightButton" then
  280. command = APIDocumentation.Commands.CopyAPI;
  281. elseif IsModifiedClick("CHATLINK") then
  282. command = APIDocumentation.Commands.OpenDump;
  283. end
  284. APIDocumentation:HandleAPILink(link, command);
  285. return;
  286. elseif ( strsub(link, 1, 13) == "storecategory" ) then
  287. local _, category = strsplit(":", link);
  288. if category == "token" then
  289. StoreFrame_SetTokenCategory();
  290. ToggleStoreUI();
  291. elseif category == "games" then
  292. StoreFrame_OpenGamesCategory();
  293. elseif category == "services" then
  294. StoreFrame_SetServicesCategory();
  295. ToggleStoreUI();
  296. elseif category == "gametime" then
  297. StoreInterfaceUtil.OpenToSubscriptionProduct();
  298. end
  299. elseif ( strsub(link, 1, 4) == "item" ) then
  300. if ( IsModifiedClick("CHATLINK") and button == "LeftButton" ) then
  301. local name, link = GetItemInfo(text);
  302. if ChatEdit_InsertLink(link) then
  303. return;
  304. end
  305. end
  306. elseif ( strsub(link, 1, 10) == "clubTicket" ) then
  307. if ( IsModifiedClick("CHATLINK") and button == "LeftButton" ) then
  308. if ChatEdit_InsertLink(text) then
  309. return;
  310. end
  311. end
  312. local _, ticketId = strsplit(":", link);
  313. if ( CommunitiesFrame_IsEnabled() ) then
  314. Communities_LoadUI();
  315. CommunitiesHyperlink.OnClickLink(ticketId);
  316. end
  317. return;
  318. elseif ( strsub(link, 1, 13) == "calendarEvent" ) then
  319. local _, monthOffset, monthDay, index = strsplit(":", link);
  320. local dayEvent = C_Calendar.GetDayEvent(monthOffset, monthDay, index);
  321. if dayEvent then
  322. Calendar_LoadUI();
  323. if not CalendarFrame:IsShown() then
  324. Calendar_Toggle();
  325. end
  326. C_Calendar.OpenEvent(monthOffset, monthDay, index);
  327. end
  328. return;
  329. elseif ( strsub(link, 1, 9) == "community" ) then
  330. if ( CommunitiesFrame_IsEnabled() ) then
  331. local _, clubId = strsplit(":", link);
  332. clubId = tonumber(clubId);
  333. Communities_LoadUI();
  334. CommunitiesHyperlink.OnClickReference(clubId);
  335. end
  336. return;
  337. elseif ( strsub(link, 1, 9) == "azessence" ) then
  338. if ChatEdit_InsertLink(link) then
  339. return;
  340. end
  341. elseif ( strsub(link, 1, 10) == "clubFinder" ) then
  342. if ( IsModifiedClick("CHATLINK") and button == "LeftButton" ) then
  343. if ChatEdit_InsertLink(text) then
  344. return;
  345. end
  346. end
  347. Communities_LoadUI();
  348. local _, clubFinderId = strsplit(":", link);
  349. CommunitiesFrame:ClubFinderHyperLinkClicked(clubFinderId);
  350. return;
  351. elseif ( strsub(link, 1, 8) == "worldmap" ) then
  352. local waypoint = C_Map.GetUserWaypointFromHyperlink(link);
  353. if waypoint then
  354. C_Map.SetUserWaypoint(waypoint);
  355. OpenWorldMap(waypoint.uiMapID);
  356. end
  357. return;
  358. elseif ( strsub(link, 1, 12) == "dungeonScore" ) then
  359. DisplayDungeonScoreLink(link);
  360. return;
  361. elseif ( strsub(link, 1, 9) == "pvpRating" ) then
  362. DisplayPvpRatingLink(link);
  363. return;
  364. elseif ( strsub(link, 1, 14) == "aadcopenconfig" ) then
  365. ShowUIPanel(ChatConfigFrame);
  366. return;
  367. end
  368. if ( IsModifiedClick() ) then
  369. local fixedLink = GetFixedLink(text);
  370. HandleModifiedItemClick(fixedLink);
  371. else
  372. local itemName, itemLink = ItemRefTooltip:GetItem();
  373. if itemLink == GetFixedLink(text) then
  374. HideUIPanel(ItemRefTooltip);
  375. else
  376. ShowUIPanel(ItemRefTooltip);
  377. if ( not ItemRefTooltip:IsShown() ) then
  378. ItemRefTooltip:SetOwner(UIParent, "ANCHOR_PRESERVE");
  379. end
  380. ItemRefTooltip:ItemRefSetHyperlink(link);
  381. end
  382. end
  383. end
  384. function GetFixedLink(text, quality)
  385. local startLink = strfind(text, "|H");
  386. if ( not strfind(text, "|c") ) then
  387. if ( quality ) then
  388. return (gsub(text, "(|H.+|h.+|h)", ITEM_QUALITY_COLORS[quality].hex.."%1|r", 1));
  389. elseif ( strsub(text, startLink + 2, startLink + 6) == "quest" ) then
  390. --We'll always color it yellow. We really need to fix this for Cata. (It will appear the correct color in the chat log)
  391. return (gsub(text, "(|H.+|h.+|h)", "|cffffff00%1|r", 1));
  392. elseif ( strsub(text, startLink + 2, startLink + 12) == "achievement" ) then
  393. return (gsub(text, "(|H.+|h.+|h)", "|cffffff00%1|r", 1));
  394. elseif ( strsub(text, startLink + 2, startLink + 7) == "talent" ) then
  395. return (gsub(text, "(|H.+|h.+|h)", "|cff4e96f7%1|r", 1));
  396. elseif ( strsub(text, startLink + 2, startLink + 6) == "trade" ) then
  397. return (gsub(text, "(|H.+|h.+|h)", "|cffffd000%1|r", 1));
  398. elseif ( strsub(text, startLink + 2, startLink + 8) == "enchant" ) then
  399. return (gsub(text, "(|H.+|h.+|h)", "|cffffd000%1|r", 1));
  400. elseif ( strsub(text, startLink + 2, startLink + 13) == "instancelock" ) then
  401. return (gsub(text, "(|H.+|h.+|h)", "|cffff8000%1|r", 1));
  402. elseif ( strsub(text, startLink + 2, startLink + 8) == "journal" ) then
  403. return (gsub(text, "(|H.+|h.+|h)", "|cff66bbff%1|r", 1));
  404. elseif ( strsub(text, startLink + 2, startLink + 14) == "battlePetAbil" ) then
  405. return (gsub(text, "(|H.+|h.+|h)", "|cff4e96f7%1|r", 1));
  406. elseif ( strsub(text, startLink + 2, startLink + 10) == "battlepet" ) then
  407. return (gsub(text, "(|H.+|h.+|h)", "|cffffd200%1|r", 1)); -- s_defaultColorString (yellow)
  408. elseif ( strsub(text, startLink + 2, startLink + 12) == "garrmission" ) then
  409. return (gsub(text, "(|H.+|h.+|h)", "|cffffff00%1|r", 1));
  410. elseif ( strsub(text, startLink + 2, startLink + 17) == "transmogillusion" ) then
  411. return (gsub(text, "(|H.+|h.+|h)", "|cffff80ff%1|r", 1));
  412. elseif ( strsub(text, startLink + 2, startLink + 19) == "transmogappearance" ) then
  413. return (gsub(text, "(|H.+|h.+|h)", "|cffff80ff%1|r", 1));
  414. elseif ( strsub(text, startLink + 2, startLink + 12) == "transmogset" ) then
  415. return (gsub(text, "(|H.+|h.+|h)", "|cffff80ff%1|r", 1));
  416. elseif ( strsub(text, startLink + 2, startLink + 7) == "outfit" ) then
  417. return (gsub(text, "(|H.+|h.+|h)", "|cffff80ff%1|r", 1));
  418. elseif ( strsub(text, startLink + 2, startLink + 9) == "worldmap" ) then
  419. return (gsub(text, "(|H.+|h.+|h)", "|cffffff00%1|r", 1));
  420. end
  421. end
  422. --Nothing to change.
  423. return text;
  424. end
  425. function GetBattlePetAbilityHyperlink(abilityID, maxHealth, power, speed)
  426. local id, name = C_PetBattles.GetAbilityInfoByID(abilityID);
  427. if not name then
  428. GMError("Attempt to link ability when we don't have record.");
  429. return "";
  430. end
  431. local linkDisplayText = ("[%s]"):format(name);
  432. return ("|cff4e96f7%s|r"):format(FormatLink("battlePetAbil", linkDisplayText, abilityID, maxHealth or 100, power or 0, speed or 0));
  433. end
  434. function GetPlayerLink(characterName, linkDisplayText, lineID, chatType, chatTarget)
  435. -- Use simplified link if possible
  436. if lineID or chatType or chatTarget then
  437. return FormatLink("player", linkDisplayText, characterName, lineID or 0, chatType or 0, chatTarget or "");
  438. else
  439. return FormatLink("player", linkDisplayText, characterName);
  440. end
  441. end
  442. function GetBNPlayerLink(name, linkDisplayText, bnetIDAccount, lineID, chatType, chatTarget)
  443. return FormatLink("BNplayer", linkDisplayText, name, bnetIDAccount, lineID or 0, chatType, chatTarget);
  444. end
  445. function GetGMLink(gmName, linkDisplayText, lineID)
  446. if lineID then
  447. return FormatLink("playerGM", linkDisplayText, gmName, lineID or 0);
  448. else
  449. return FormatLink("playerGM", linkDisplayText, gmName);
  450. end
  451. end
  452. local function SanitizeCommunityData(clubId, streamId, epoch, position)
  453. if type(clubId) == "number" then
  454. clubId = ("%.f"):format(clubId);
  455. end
  456. if type(streamId) == "number" then
  457. streamId = ("%.f"):format(streamId);
  458. end
  459. epoch = ("%.f"):format(epoch);
  460. position = ("%.f"):format(position);
  461. return clubId, streamId, epoch, position;
  462. end
  463. function GetBNPlayerCommunityLink(playerName, linkDisplayText, bnetIDAccount, clubId, streamId, epoch, position)
  464. clubId, streamId, epoch, position = SanitizeCommunityData(clubId, streamId, epoch, position);
  465. return FormatLink("BNplayerCommunity", linkDisplayText, playerName, bnetIDAccount, clubId, streamId, epoch, position);
  466. end
  467. function GetPlayerCommunityLink(playerName, linkDisplayText, clubId, streamId, epoch, position)
  468. clubId, streamId, epoch, position = SanitizeCommunityData(clubId, streamId, epoch, position);
  469. return FormatLink("playerCommunity", linkDisplayText, playerName, clubId, streamId, epoch, position);
  470. end
  471. function GetClubTicketLink(ticketId, clubName, clubType)
  472. local link = FormatLink("clubTicket", CLUB_INVITE_HYPERLINK_TEXT:format(clubName), ticketId);
  473. if clubType == Enum.ClubType.BattleNet then
  474. return BATTLENET_FONT_COLOR:WrapTextInColorCode(link);
  475. else
  476. return NORMAL_FONT_COLOR:WrapTextInColorCode(link);
  477. end
  478. end
  479. function GetClubFinderLink(clubFinderId, clubName)
  480. local clubType = C_ClubFinder.GetClubTypeFromFinderGUID(clubFinderId);
  481. local fontColor = NORMAL_FONT_COLOR;
  482. local linkGlobalString;
  483. if(clubType == Enum.ClubFinderRequestType.Guild) then
  484. linkGlobalString = CLUB_FINDER_LINK_GUILD;
  485. elseif(clubType == Enum.ClubFinderRequestType.Community) then
  486. linkGlobalString = CLUB_FINDER_LINK_COMMUNITY;
  487. fontColor = BATTLENET_FONT_COLOR;
  488. else
  489. linkGlobalString = ""
  490. end
  491. return fontColor:WrapTextInColorCode(FormatLink("clubFinder", linkGlobalString:format(clubName), clubFinderId));
  492. end
  493. function DungeonScoreLinkAddDungeonsToTable()
  494. local dungeonScoreDungeonTable = { };
  495. local maps = C_ChallengeMode.GetMapScoreInfo();
  496. for _, scoreInfo in ipairs(maps) do
  497. table.insert(dungeonScoreDungeonTable, scoreInfo.mapChallengeModeID);
  498. table.insert(dungeonScoreDungeonTable, scoreInfo.completedInTime);
  499. table.insert(dungeonScoreDungeonTable, scoreInfo.level);
  500. end
  501. return dungeonScoreDungeonTable;
  502. end
  503. function DisplayPvpRatingLink(link)
  504. if ( not ItemRefTooltip:IsShown() ) then
  505. ItemRefTooltip:SetOwner(UIParent, "ANCHOR_PRESERVE");
  506. end
  507. local splits = StringSplitIntoTable(":", link);
  508. if(not splits) then
  509. return;
  510. end
  511. local playerName = splits[3];
  512. local playerClass = splits[4];
  513. local playerItemLevel = tonumber(splits[5]);
  514. local playerLevel = tonumber(splits[6]);
  515. local className, classFileName = GetClassInfo(playerClass);
  516. local classColor = C_ClassColor.GetClassColor(classFileName);
  517. if(not playerName or not playerClass or not playerItemLevel or not playerLevel) then
  518. return;
  519. end
  520. if(not className or not classFileName or not classColor) then
  521. return;
  522. end
  523. GameTooltip_SetTitle(ItemRefTooltip, classColor:WrapTextInColorCode(playerName));
  524. GameTooltip_AddColoredLine(ItemRefTooltip, PVP_LINK_LEVEL_CLASS_FORMAT_STRING:format(playerLevel, className), HIGHLIGHT_FONT_COLOR)
  525. GameTooltip_AddNormalLine(ItemRefTooltip, PVP_RATING_LINK_ITEM_LEVEL:format(playerItemLevel));
  526. for i = PVP_LINK_INDEX_START, (#splits), PVP_LINK_ITERATE_BRACKET do
  527. GameTooltip_AddBlankLineToTooltip(ItemRefTooltip);
  528. local bracket = tonumber(splits[i]);
  529. local rating = tonumber(splits[i + 1]);
  530. local tier = tonumber(splits[i + 2]);
  531. local seasonGamesPlayed = tonumber(splits[i + 3]);
  532. GameTooltip_AddNormalLine(ItemRefTooltip, PVPUtil.GetBracketName(bracket));
  533. GameTooltip_AddColoredLine(ItemRefTooltip, PVP_RATING_LINK_FORMAT_STRING:format(PVPUtil.GetTierName(tier), rating), HIGHLIGHT_FONT_COLOR);
  534. GameTooltip_AddColoredLine(ItemRefTooltip, PVP_LINK_SEASON_GAMES:format(seasonGamesPlayed), HIGHLIGHT_FONT_COLOR);
  535. end
  536. ShowUIPanel(ItemRefTooltip);
  537. ItemRefTooltip:SetPadding(30, 0);
  538. end
  539. function AddPvpRatingsToTable()
  540. local pvpLinkInfoTable = { };
  541. for i = 1, PVP_LINK_ITERATE do
  542. local bracketIndex = CONQUEST_BRACKET_INDEXES[i];
  543. local rating, seasonBest, weeklyBest, seasonPlayed, seasonWon, weeklyPlayed, weeklyWon, lastWeeksBest, hasWon, pvpTier, ranking = GetPersonalRatedInfo(bracketIndex);
  544. local tierInfo = C_PvP.GetPvpTierInfo(pvpTier);
  545. if(not tierInfo or not tierInfo.pvpTierEnum) then
  546. return;
  547. end
  548. table.insert(pvpLinkInfoTable, bracketIndex);
  549. table.insert(pvpLinkInfoTable, rating);
  550. table.insert(pvpLinkInfoTable, tierInfo.pvpTierEnum);
  551. table.insert(pvpLinkInfoTable, seasonPlayed);
  552. end
  553. return pvpLinkInfoTable;
  554. end
  555. function DisplayDungeonScoreLink(link)
  556. if ( not ItemRefTooltip:IsShown() ) then
  557. ItemRefTooltip:SetOwner(UIParent, "ANCHOR_PRESERVE");
  558. end
  559. local splits = StringSplitIntoTable(":", link);
  560. --Bad Link, Return.
  561. if(not splits) then
  562. return;
  563. end
  564. local dungeonScore = tonumber(splits[2]);
  565. local playerName = splits[4];
  566. local playerClass = splits[5];
  567. local playerItemLevel = tonumber(splits[6]);
  568. local playerLevel = tonumber(splits[7]);
  569. local className, classFileName = GetClassInfo(playerClass);
  570. local classColor = C_ClassColor.GetClassColor(classFileName);
  571. local runsThisSeason = tonumber(splits[8]);
  572. --Bad Link..
  573. if(not playerName or not playerClass or not playerItemLevel or not playerLevel) then
  574. return;
  575. end
  576. --Bad Link..
  577. if(not className or not classFileName or not classColor) then
  578. return;
  579. end
  580. GameTooltip_SetTitle(ItemRefTooltip, classColor:WrapTextInColorCode(playerName));
  581. GameTooltip_AddColoredLine(ItemRefTooltip, DUNGEON_SCORE_LINK_LEVEL_CLASS_FORMAT_STRING:format(playerLevel, className), HIGHLIGHT_FONT_COLOR)
  582. GameTooltip_AddNormalLine(ItemRefTooltip, DUNGEON_SCORE_LINK_ITEM_LEVEL:format(playerItemLevel));
  583. local color = C_ChallengeMode.GetDungeonScoreRarityColor(dungeonScore);
  584. if (not color) then
  585. color = HIGHLIGHT_FONT_COLOR;
  586. end
  587. GameTooltip_AddNormalLine(ItemRefTooltip, DUNGEON_SCORE_LINK_RATING:format(color:WrapTextInColorCode(dungeonScore)));
  588. GameTooltip_AddNormalLine(ItemRefTooltip, DUNGEON_SCORE_LINK_RUNS_SEASON:format(runsThisSeason));
  589. GameTooltip_AddBlankLineToTooltip(ItemRefTooltip);
  590. local sortTable = { };
  591. for i = DUNGEON_SCORE_LINK_INDEX_START, (#splits), DUNGEON_SCORE_LINK_ITERATE do
  592. local mapChallengeModeID = tonumber(splits[i]);
  593. local completedInTime = tonumber(splits[i + 1]);
  594. local level = tonumber(splits[i + 2]);
  595. local mapName = C_ChallengeMode.GetMapUIInfo(mapChallengeModeID);
  596. --If any of the maps don't exist.. this is a bad link
  597. if(not mapName) then
  598. return;
  599. end
  600. table.insert(sortTable, { mapName = mapName, completedInTime = completedInTime, level = level });
  601. end
  602. -- Sort Alphabetically.
  603. table.sort(sortTable, function(a, b) strcmputf8i(a.mapName, b.mapName); end);
  604. for i = 1, #sortTable do
  605. local textColor = sortTable[i].completedInTime and HIGHLIGHT_FONT_COLOR or GRAY_FONT_COLOR;
  606. GameTooltip_AddColoredDoubleLine(ItemRefTooltip, DUNGEON_SCORE_LINK_TEXT1:format(sortTable[i].mapName), (sortTable[i].level > 0 and DUNGEON_SCORE_LINK_TEXT2:format(sortTable[i].level) or DUNGEON_SCORE_LINK_NO_SCORE), NORMAL_FONT_COLOR, textColor);
  607. end
  608. ItemRefTooltip:SetPadding(0, 0);
  609. ShowUIPanel(ItemRefTooltip);
  610. end
  611. function GetDungeonScoreLink(dungeonScore, playerName)
  612. local _, _, class = UnitClass("player");
  613. local avgItemLevel, avgItemLevelEquipped, avgItemLevelPvP = GetAverageItemLevel();
  614. local runHistory = C_MythicPlus.GetRunHistory(true);
  615. local dungeonScoreTable = {C_ChallengeMode.GetOverallDungeonScore(), UnitGUID("player"), playerName, class, math.ceil(avgItemLevel), UnitLevel("player"), runHistory and #runHistory or 0, unpack(DungeonScoreLinkAddDungeonsToTable())};
  616. return NORMAL_FONT_COLOR:WrapTextInColorCode(FormatLink("dungeonScore", DUNGEON_SCORE_LINK, unpack(dungeonScoreTable)));
  617. end
  618. function GetPvpRatingLink(playerName)
  619. local fontColor = NORMAL_FONT_COLOR;
  620. local _, _, class = UnitClass("player");
  621. local avgItemLevel, avgItemLevelEquipped, avgItemLevelPvP = GetAverageItemLevel();
  622. local pvpRatingTable = { UnitGUID("player"), playerName, class, math.ceil(avgItemLevelPvP), UnitLevel("player"), unpack(AddPvpRatingsToTable())};
  623. return fontColor:WrapTextInColorCode(FormatLink("pvpRating", PVP_PERSONAL_RATING_LINK, unpack(pvpRatingTable)));
  624. end
  625. function GetCalendarEventLink(monthOffset, monthDay, index)
  626. local dayEvent = C_Calendar.GetDayEvent(monthOffset, monthDay, index);
  627. if dayEvent then
  628. return FormatLink("calendarEvent", dayEvent.title, monthOffset, monthDay, index);
  629. end
  630. return nil;
  631. end
  632. function GetCommunityLink(clubId)
  633. local clubInfo = C_Club.GetClubInfo(clubId);
  634. if clubInfo then
  635. local link = FormatLink("community", COMMUNITY_REFERENCE_FORMAT:format(clubInfo.name), clubId);
  636. if clubInfo.clubType == Enum.ClubType.BattleNet then
  637. return BATTLENET_FONT_COLOR:WrapTextInColorCode(link);
  638. else
  639. return NORMAL_FONT_COLOR:WrapTextInColorCode(link);
  640. end
  641. end
  642. return nil;
  643. end
  644. LinkUtil = {};
  645. function LinkUtil.SplitLink(link) -- returns linkText and displayText
  646. return link:match("^|H(.+)|h(.*)|h$");
  647. end
  648. -- Extract the first link from the text given, ignoring leading and trailing characters.
  649. -- returns linkType, linkOptions, displayText
  650. function LinkUtil.ExtractLink(text)
  651. -- linkType: |H([^:]*): matches everything that's not a colon, up to the first colon.
  652. -- linkOptions: ([^|]*)|h matches everything that's not a |, up to the first |h.
  653. -- displayText: ([^|]*)|h matches everything that's not a |, up to the second |h.
  654. -- Ex: |cffffffff|Htype:a:b:c:d|htext|h|r becomes type, a:b:c:d, text
  655. return string.match(text, [[|H([^:]*):([^|]*)|h([^|]*)|h]]);
  656. end
  657. function LinkUtil.IsLinkType(link, matchLinkType)
  658. local linkType, linkOptions, displayText = LinkUtil.ExtractLink(link);
  659. return linkType == matchLinkType;
  660. end
  661. ItemRefTooltipMixin = {};
  662. function ItemRefTooltipMixin:OnLoad()
  663. GameTooltip_OnLoad(self);
  664. self:RegisterForDrag("LeftButton");
  665. self.shoppingTooltips = { ItemRefShoppingTooltip1, ItemRefShoppingTooltip2 };
  666. self.updateTooltipTimer = 0;
  667. self.UpdateTooltip = function(self, elapsed)
  668. if ( IsModifiedClick("COMPAREITEMS") ) then
  669. self.updateTooltipTimer = self.updateTooltipTimer - elapsed;
  670. if ( self.updateTooltipTimer > 0 ) then
  671. return;
  672. end
  673. self.updateTooltipTimer = TOOLTIP_UPDATE_TIME;
  674. GameTooltip_ShowCompareItem(self);
  675. else
  676. for _, frame in pairs(self.shoppingTooltips) do
  677. frame:Hide();
  678. end
  679. self.needsReset = true;
  680. self.comparing = false;
  681. end
  682. end
  683. end
  684. function ItemRefTooltipMixin:OnTooltipSetItem()
  685. self.updateTooltipTimer = 0;
  686. if ( IsModifiedClick("COMPAREITEMS") and self:IsMouseOver() ) then
  687. GameTooltip_ShowCompareItem(self);
  688. end
  689. end
  690. function ItemRefTooltipMixin:OnDragStart()
  691. self:StartMoving();
  692. end
  693. function ItemRefTooltipMixin:OnDragStop()
  694. self:StopMovingOrSizing();
  695. ValidateFramePosition(self);
  696. if ( IsModifiedClick("COMPAREITEMS") ) then --We do this to choose where the comparison is shown
  697. GameTooltip_ShowCompareItem(self);
  698. end
  699. end
  700. function ItemRefTooltipMixin:OnEnter()
  701. self.updateTooltipTimer = 0;
  702. self:SetScript("OnUpdate", self.UpdateTooltip);
  703. end
  704. function ItemRefTooltipMixin:OnLeave()
  705. for _, frame in pairs(self.shoppingTooltips) do
  706. frame:Hide();
  707. end
  708. self:SetScript("OnUpdate", nil);
  709. end
  710. function ItemRefTooltipMixin:OnHide()
  711. GameTooltip_OnHide(self);
  712. --While it is true that OnUpdate won't fire while the frame is hidden, we don't want to have to check-and-unregister when we show it
  713. self:SetScript("OnUpdate", nil);
  714. end
  715. function ItemRefTooltipMixin:ItemRefSetHyperlink(link)
  716. self:SetPadding(0, 0);
  717. self:SetHyperlink(link);
  718. local title = _G[self:GetName().."TextLeft1"];
  719. if ( title and title:GetRight() - self.CloseButton:GetLeft() > 0 ) then
  720. local xPadding = 16;
  721. self:SetPadding(xPadding, 0);
  722. end
  723. end