Advertisement
Arborus

NickTag-1.0.lua

Sep 28th, 2018
217
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 48.29 KB | None | 0 0
  1. --> Library NickTag is a small library for share individual nicknames and avatars.
  2.  
  3. --> Basic Functions:
  4. -- NickTag:SetNickname (name) -> set the player nick name, after set nicktag will broadcast the nick over addon guild channel.
  5. --
  6.  
  7. local major, minor = "NickTag-1.0", 10
  8. local NickTag, oldminor = LibStub:NewLibrary (major, minor)
  9.  
  10. if (not NickTag) then
  11. return
  12. end
  13.  
  14. --> fix for old nicktag version
  15. if (_G.NickTag) then
  16. if (_G.NickTag.OnEvent) then
  17. _G.NickTag:UnregisterComm ("NickTag")
  18. _G.NickTag.OnEvent = nil
  19. end
  20. end
  21.  
  22. ------------------------------------------------------------------------------------------------------------------------------------------------------
  23. --> constants
  24.  
  25. local CONST_INDEX_NICKNAME = 1
  26. local CONST_INDEX_AVATAR_PATH = 2
  27. local CONST_INDEX_AVATAR_TEXCOORD = 3
  28. local CONST_INDEX_BACKGROUND_PATH = 4
  29. local CONST_INDEX_BACKGROUND_TEXCOORD = 5
  30. local CONST_INDEX_BACKGROUND_COLOR = 6
  31. local CONST_INDEX_REVISION = 7
  32.  
  33. local CONST_COMM_FULLPERSONA = 1
  34. local CONST_COMM_LOGONREVISION = 2
  35. local CONST_COMM_REQUESTPERSONA = 3
  36.  
  37. --[[global]] NICKTAG_DEFAULT_AVATAR = [[Interface\EncounterJournal\UI-EJ-BOSS-Default]]
  38. --[[global]] NICKTAG_DEFAULT_BACKGROUND = [[Interface\PetBattles\Weather-ArcaneStorm]]
  39. --[[global]] NICKTAG_DEFAULT_BACKGROUND_CORDS = {0.129609375, 1, 1, 0}
  40.  
  41. ------------------------------------------------------------------------------------------------------------------------------------------------------
  42. --> library stuff
  43.  
  44. _G.NickTag = NickTag --> nicktag object over global container
  45.  
  46. local pool = {default = true} --> pointer to the cache pool and the default pool if no cache
  47. local queue_request = {}
  48. local queue_send = {}
  49. local last_queue = 0
  50. local is_updating = false
  51. NickTag.debug = false
  52.  
  53. local GetGuildRosterInfo = GetGuildRosterInfo
  54.  
  55. LibStub:GetLibrary ("AceComm-3.0"):Embed (NickTag)
  56. LibStub:GetLibrary ("AceSerializer-3.0"):Embed (NickTag)
  57. LibStub:GetLibrary ("AceTimer-3.0"):Embed (NickTag)
  58. local CallbackHandler = LibStub:GetLibrary ("CallbackHandler-1.0")
  59. NickTag.callbacks = NickTag.callbacks or CallbackHandler:New (NickTag)
  60.  
  61. NickTag.embeds = NickTag.embeds or {}
  62. local embed_functions = {
  63. "SetNickname",
  64. "SetNicknameAvatar",
  65. "SetNicknameBackground",
  66. "GetNickname",
  67. "GetNicknameAvatar",
  68. "GetNicknameBackground",
  69. "GetNicknameTable",
  70. "NickTagSetCache"
  71. }
  72. function NickTag:Embed (target)
  73. for k, v in pairs (embed_functions) do
  74. target[v] = self[v]
  75. end
  76. self.embeds [target] = true
  77. return target
  78. end
  79.  
  80. function NickTag:Msg (...)
  81. if (NickTag.debug) then
  82. print ("|cFFFFFF00NickTag:|r", ...)
  83. end
  84. end
  85.  
  86. local enUS = LibStub("AceLocale-3.0"):NewLocale ("NickTag-1.0", "enUS", true)
  87. if (enUS) then
  88. enUS ["STRING_ERROR_1"] = "Your nickname is too long, max of 12 characters is allowed."
  89. enUS ["STRING_ERROR_2"] = "Only letters and two spaces are allowed."
  90. enUS ["STRING_ERROR_3"] = "You can't use the same letter three times consecutively, two spaces consecutively or more then two spaces."
  91. enUS ["STRING_ERROR_4"] = "Name isn't a valid string."
  92. enUS ["STRING_INVALID_NAME"] = "Invalid Name"
  93. end
  94.  
  95. local ptBR = LibStub("AceLocale-3.0"):NewLocale ("NickTag-1.0", "ptBR")
  96. if (ptBR) then
  97. ptBR ["STRING_ERROR_1"] = "Seu apelido esta muito longo, o maximo permitido sao 12 caracteres."
  98. ptBR ["STRING_ERROR_2"] = "Apenas letras, numeros e espacos sao permitidos no apelido."
  99. ptBR ["STRING_ERROR_3"] = "Voce nao pode usar a mesma letra mais de 2 vezes consecutivas, dois espacos consecutivos ou mais de 2 espacos."
  100. ptBR ["STRING_ERROR_4"] = "Nome nao eh uma string valida."
  101. ptBR ["STRING_INVALID_NAME"] = "Nome Invalido"
  102. end
  103.  
  104. NickTag.background_pool = {
  105. {[[Interface\PetBattles\Weather-ArcaneStorm]], "Arcane Storm", {0.129609375, 1, 1, 0}},
  106. {[[Interface\PetBattles\Weather-Blizzard]], "Blizzard", {0.068704154, 1, 1, 0}},
  107. {[[Interface\PetBattles\Weather-BurntEarth]], "Burnt Earth", {0.087890625, 0.916015625, 1, 0}},
  108. {[[Interface\PetBattles\Weather-Darkness]], "Darkness", {0.080078125, 0.931640625, 1, 0}},
  109. {[[Interface\PetBattles\Weather-Moonlight]], "Moonlight", {0.02765625, 0.94359375, 1, 0}},
  110. {[[Interface\PetBattles\Weather-Moonlight]], "Moonlight (reverse)", {0.94359375, 0.02765625, 1, 0}},
  111. {[[Interface\PetBattles\Weather-Mud]], "Mud", {0.068359375, 0.94359375, 1, 0}},
  112. {[[Interface\PetBattles\Weather-Rain]], "Rain", {0.078125, 0.970703125, 1, 0}},
  113. {[[Interface\PetBattles\Weather-Sandstorm]], "Sand Storm", {0.048828125, 0.947265625, 1, 0}},
  114. {[[Interface\PetBattles\Weather-StaticField]], "Static Field", {0.1171875, 0.953125, 1, 0}},
  115. {[[Interface\PetBattles\Weather-Sunlight]], "Sun Light", {0.1772721, 0.953125, 1, 0}},
  116. {[[Interface\PetBattles\Weather-Windy]], "Windy", {0.9453125, 0.07421875, 0.8203125, 0}}
  117. }
  118.  
  119. NickTag.avatar_pool = {
  120. {[[Interface\EncounterJournal\UI-EJ-BOSS-Arcanist Doan]], "Arcanist Doan"},
  121. {[[Interface\EncounterJournal\UI-EJ-BOSS-Archbishop Benedictus]], "Archbishop Benedictus"},
  122. {[[Interface\EncounterJournal\UI-EJ-BOSS-Argent Confessor Paletress]], "Argent Confessor Paletress"},
  123. {[[Interface\EncounterJournal\UI-EJ-BOSS-Armsmaster Harlan]], "Armsmaster Harlan"},
  124. {[[Interface\EncounterJournal\UI-EJ-BOSS-Asira Dawnslayer]], "Asira Dawnslayer"},
  125. {[[Interface\EncounterJournal\UI-EJ-BOSS-Baelog]], "Baelog"},
  126. {[[Interface\EncounterJournal\UI-EJ-BOSS-Baron Ashbury]], "Baron Ashbury"},
  127. {[[Interface\EncounterJournal\UI-EJ-BOSS-Baron Silverlaine]], "Baron Silverlaine"},
  128. {[[Interface\EncounterJournal\UI-EJ-BOSS-Blood Guard Porung]], "Blood Guard Porung"},
  129. {[[Interface\EncounterJournal\UI-EJ-BOSS-Bronjahm]], "Bronjahm"},
  130. {[[Interface\EncounterJournal\UI-EJ-BOSS-Brother Korloff]], "Brother Korloff"},
  131. {[[Interface\EncounterJournal\UI-EJ-BOSS-Captain Skarloc]], "Captain Skarloc"},
  132. {[[Interface\EncounterJournal\UI-EJ-BOSS-Chief Ukorz Sandscalp]], "Chief Ukorz Sandscalp"},
  133. {[[Interface\EncounterJournal\UI-EJ-BOSS-Commander Kolurg]], "Commander Kolurg"},
  134. {[[Interface\EncounterJournal\UI-EJ-BOSS-Commander Malor]], "Commander Malor"},
  135. {[[Interface\EncounterJournal\UI-EJ-BOSS-Commander Sarannis]], "Commander Sarannis"},
  136. {[[Interface\EncounterJournal\UI-EJ-BOSS-Commander Springvale]], "Commander Springvale"},
  137. {[[Interface\EncounterJournal\UI-EJ-BOSS-Commander Stoutbeard]], "Commander Stoutbeard"},
  138. {[[Interface\EncounterJournal\UI-EJ-BOSS-Corla, Herald of Twilight]], "Corla, Herald of Twilight"},
  139. {[[Interface\EncounterJournal\UI-EJ-BOSS-Cyanigosa]], "Cyanigosa"},
  140. {[[Interface\EncounterJournal\UI-EJ-BOSS-Darkmaster Gandling]], "Darkmaster Gandling"},
  141. {[[Interface\EncounterJournal\UI-EJ-BOSS-Doctor Theolen Krastinov]], "Doctor Theolen Krastinov"},
  142. {[[Interface\EncounterJournal\UI-EJ-BOSS-DoomRel]], "DoomRel"},
  143. {[[Interface\EncounterJournal\UI-EJ-BOSS-Eadric the Pure]], "Eadric the Pure"},
  144. {[[Interface\EncounterJournal\UI-EJ-BOSS-Emperor Thaurissan]], "Emperor Thaurissan"},
  145. {[[Interface\EncounterJournal\UI-EJ-BOSS-Empyreal Queens]], "Lu'lin"},
  146. {[[Interface\EncounterJournal\UI-EJ-BOSS-Exarch Maladaar]], "Exarch Maladaar"},
  147. {[[Interface\EncounterJournal\UI-EJ-BOSS-Fineous Darkvire]], "Fineous Darkvire"},
  148. {[[Interface\EncounterJournal\UI-EJ-BOSS-Galdarah]], "Galdarah"},
  149. {[[Interface\EncounterJournal\UI-EJ-BOSS-Garajal the Spiritbinder]], "Garajal the Spiritbinder"},
  150. {[[Interface\EncounterJournal\UI-EJ-BOSS-Garrosh Hellscream]], "Garrosh Hellscream"},
  151. {[[Interface\EncounterJournal\UI-EJ-BOSS-General Nazgrim]], "General Nazgrim"},
  152. {[[Interface\EncounterJournal\UI-EJ-BOSS-Grand Champions-Alliance]], "Grand Champions-Alliance"},
  153. {[[Interface\EncounterJournal\UI-EJ-BOSS-Grand Champions-Horde]], "Grand Champions-Horde"},
  154. {[[Interface\EncounterJournal\UI-EJ-BOSS-Grand Magus Telestra]], "Grand Magus Telestra"},
  155. {[[Interface\EncounterJournal\UI-EJ-BOSS-HateRel]], "HateRel"},
  156. {[[Interface\EncounterJournal\UI-EJ-BOSS-Hazzarah]], "Hazzarah"},
  157. {[[Interface\EncounterJournal\UI-EJ-BOSS-Hearthsinger Forresten]], "Hearthsinger Forresten"},
  158. {[[Interface\EncounterJournal\UI-EJ-BOSS-Helix Gearbreaker]], "Helix Gearbreaker"},
  159. {[[Interface\EncounterJournal\UI-EJ-BOSS-High Botanist Freywinn]], "High Botanist Freywinn"},
  160. {[[Interface\EncounterJournal\UI-EJ-BOSS-High Inquisitor Whitemane]], "High Inquisitor Whitemane"},
  161. {[[Interface\EncounterJournal\UI-EJ-BOSS-High Interrogator Gerstahn]], "High Interrogator Gerstahn"},
  162. {[[Interface\EncounterJournal\UI-EJ-BOSS-High Justice Grimstone]], "High Justice Grimstone"},
  163. {[[Interface\EncounterJournal\UI-EJ-BOSS-Houndmaster Braun]], "Houndmaster Braun"},
  164. {[[Interface\EncounterJournal\UI-EJ-BOSS-Houndmaster Loksey]], "Houndmaster Loksey"},
  165. {[[Interface\EncounterJournal\UI-EJ-BOSS-Hydromancer Velratha]], "Hydromancer Velratha"},
  166. {[[Interface\EncounterJournal\UI-EJ-BOSS-Illyanna Ravenoak]], "Illyanna Ravenoak"},
  167. {[[Interface\EncounterJournal\UI-EJ-BOSS-Ingvar the Plunderer]], "Ingvar the Plunderer"},
  168. {[[Interface\EncounterJournal\UI-EJ-BOSS-Instructor Galford]], "Instructor Galford"},
  169. {[[Interface\EncounterJournal\UI-EJ-BOSS-Instructor Malicia]], "Instructor Malicia"},
  170. {[[Interface\EncounterJournal\UI-EJ-BOSS-Interrogator Vishas]], "Interrogator Vishas"},
  171. {[[Interface\EncounterJournal\UI-EJ-BOSS-Isiset]], "Isiset"},
  172. {[[Interface\EncounterJournal\UI-EJ-BOSS-JainaProudmoore]], "Jaina Proudmoore"},
  173. {[[Interface\EncounterJournal\UI-EJ-BOSS-Jandice Barov]], "Jandice Barov"},
  174. {[[Interface\EncounterJournal\UI-EJ-BOSS-Kaelthas Sunstrider]], "Kaelthas Sunstrider"},
  175. {[[Interface\EncounterJournal\UI-EJ-BOSS-Kelidan the Breaker]], "Kelidan the Breaker"},
  176. {[[Interface\EncounterJournal\UI-EJ-BOSS-Krick]], "Krick"},
  177. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lady Anacondra]], "Lady Anacondra"},
  178. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lady Illucia Barov]], "Lady Illucia Barov"},
  179. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lethtendris]], "Lethtendris"},
  180. {[[Interface\EncounterJournal\UI-EJ-BOSS-Loken]], "Loken"},
  181. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lord Alexei Barov]], "Lord Alexei Barov"},
  182. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lord Aurius Rivendare]], "Lord Aurius Rivendare"},
  183. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lord Cobrahn]], "Lord Cobrahn"},
  184. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lord Pythas]], "Lord Pythas"},
  185. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lord Serpentis]], "Lord Serpentis"},
  186. {[[Interface\EncounterJournal\UI-EJ-BOSS-Lorgus Jett]], "Lorgus Jett"},
  187. {[[Interface\EncounterJournal\UI-EJ-BOSS-Mage Lord Urom]], "Mage Lord Urom"},
  188. {[[Interface\EncounterJournal\UI-EJ-BOSS-Magister Kalendris]], "Magister Kalendris"},
  189. {[[Interface\EncounterJournal\UI-EJ-BOSS-Magistrate Barthilas]], "Magistrate Barthilas"},
  190. {[[Interface\EncounterJournal\UI-EJ-BOSS-Maiden of Grief]], "Maiden of Grief"},
  191. {[[Interface\EncounterJournal\UI-EJ-BOSS-Maleki the Pallid]], "Maleki the Pallid"},
  192. {[[Interface\EncounterJournal\UI-EJ-BOSS-Nethermancer Sepethrea]], "Nethermancer Sepethrea"},
  193. {[[Interface\EncounterJournal\UI-EJ-BOSS-Olaf]], "Olaf"},
  194. {[[Interface\EncounterJournal\UI-EJ-BOSS-Pathaleon the Calculator]], "Pathaleon the Calculator"},
  195. {[[Interface\EncounterJournal\UI-EJ-BOSS-Prince Tortheldrin]], "Prince Tortheldrin"},
  196. {[[Interface\EncounterJournal\UI-EJ-BOSS-Princess Moira Bronzebeard]], "Princess Moira Bronzebeard"},
  197. {[[Interface\EncounterJournal\UI-EJ-BOSS-QueenAzshara]], "Queen Azshara"},
  198. {[[Interface\EncounterJournal\UI-EJ-BOSS-Randolph Moloch]], "Randolph Moloch"},
  199. {[[Interface\EncounterJournal\UI-EJ-BOSS-Renataki]], "Renataki"},
  200. {[[Interface\EncounterJournal\UI-EJ-BOSS-Ribbly Screwspigot]], "Ribbly Screwspigot"},
  201. {[[Interface\EncounterJournal\UI-EJ-BOSS-Scarlet Commander Mograine]], "Scarlet Commander Mograine"},
  202. {[[Interface\EncounterJournal\UI-EJ-BOSS-Selin Fireheart]], "Selin Fireheart"},
  203. {[[Interface\EncounterJournal\UI-EJ-BOSS-Siegecrafter Blackfuse]], "Siegecrafter Blackfuse"},
  204. {[[Interface\EncounterJournal\UI-EJ-BOSS-Skarvald the Constructor]], "Skarvald the Constructor"},
  205. {[[Interface\EncounterJournal\UI-EJ-BOSS-Tribunal of the Ages]], "Tribunal of the Ages"},
  206. {[[Interface\EncounterJournal\UI-EJ-BOSS-TyrandeWhisperwind]], "Tyrande Whisperwind"},
  207. {[[Interface\EncounterJournal\UI-EJ-BOSS-Twilight Lord Kelris]], "Twilight Lord Kelris"},
  208. {[[Interface\EncounterJournal\UI-EJ-BOSS-Vanessa VanCleef]], "Vanessa VanCleef"},
  209. {[[Interface\EncounterJournal\UI-EJ-BOSS-Vazruden]], "Vazruden"},
  210. {[[Interface\EncounterJournal\UI-EJ-BOSS-Warchief Rend Blackhand]], "Warchief Rend Blackhand"},
  211. {[[Interface\EncounterJournal\UI-EJ-BOSS-Willey Hopebreaker]], "Willey Hopebreaker"},
  212. {[[Interface\EncounterJournal\UI-EJ-BOSS-Witch Doctor Zumrah]], "Witch Doctor Zumrah"},
  213. }
  214. ------------------------------------------------------------------------------------------------------------------------------------------------------
  215. --> send and receive functions
  216.  
  217. function NickTag:OnReceiveComm (prefix, data, channel, source)
  218.  
  219. if (not source) then
  220. return
  221. end
  222.  
  223. local _type, serial, arg3, name, realm, version = select (2, NickTag:Deserialize (data))
  224.  
  225. --> 0x1: received a full persona
  226. if (_type == CONST_COMM_FULLPERSONA) then
  227. local receivedPersona = arg3
  228. version = name
  229.  
  230. if (not receivedPersona or type (receivedPersona) ~= "table") then
  231. NickTag:Msg ("FULLPERSONA received but it's invalid ", source)
  232. return
  233. end
  234.  
  235. if (source ~= UnitName ("player") and (version and version == minor) and receivedPersona) then
  236.  
  237. local storedPersona = NickTag:GetNicknameTable (source)
  238. if (not storedPersona) then
  239. storedPersona = NickTag:Create (source)
  240. end
  241.  
  242. if (storedPersona [CONST_INDEX_REVISION] < receivedPersona [CONST_INDEX_REVISION]) then
  243. storedPersona [CONST_INDEX_REVISION] = receivedPersona [CONST_INDEX_REVISION]
  244.  
  245. --> we need to check if the received nickname fit in our rules.
  246. local allowNickName = NickTag:CheckName (receivedPersona [CONST_INDEX_NICKNAME])
  247. if (allowNickName) then
  248. storedPersona [CONST_INDEX_NICKNAME] = receivedPersona [CONST_INDEX_NICKNAME]
  249. else
  250. storedPersona [CONST_INDEX_NICKNAME] = LibStub ("AceLocale-3.0"):GetLocale ("NickTag-1.0")["STRING_INVALID_NAME"]
  251. end
  252.  
  253. storedPersona [CONST_INDEX_NICKNAME] = receivedPersona [CONST_INDEX_NICKNAME]
  254.  
  255. --> update the rest
  256. --avatar path
  257. storedPersona [CONST_INDEX_AVATAR_PATH] = type (receivedPersona [CONST_INDEX_AVATAR_PATH]) == "string" and receivedPersona [CONST_INDEX_AVATAR_PATH] or ""
  258.  
  259. --avatar texcoord
  260. if (type (receivedPersona [CONST_INDEX_AVATAR_TEXCOORD]) == "boolean") then
  261. storedPersona [CONST_INDEX_AVATAR_TEXCOORD] = {0, 1, 0, 1}
  262.  
  263. elseif (type (receivedPersona [CONST_INDEX_AVATAR_TEXCOORD]) == "table") then
  264. storedPersona [CONST_INDEX_AVATAR_TEXCOORD] = storedPersona [CONST_INDEX_AVATAR_TEXCOORD] or {}
  265. storedPersona [CONST_INDEX_AVATAR_TEXCOORD][1] = type (receivedPersona [CONST_INDEX_AVATAR_TEXCOORD][1]) == "number" and receivedPersona [CONST_INDEX_AVATAR_TEXCOORD][1] or 0
  266. storedPersona [CONST_INDEX_AVATAR_TEXCOORD][2] = type (receivedPersona [CONST_INDEX_AVATAR_TEXCOORD][2]) == "number" and receivedPersona [CONST_INDEX_AVATAR_TEXCOORD][2] or 1
  267. storedPersona [CONST_INDEX_AVATAR_TEXCOORD][3] = type (receivedPersona [CONST_INDEX_AVATAR_TEXCOORD][3]) == "number" and receivedPersona [CONST_INDEX_AVATAR_TEXCOORD][3] or 0
  268. storedPersona [CONST_INDEX_AVATAR_TEXCOORD][4] = type (receivedPersona [CONST_INDEX_AVATAR_TEXCOORD][4]) == "number" and receivedPersona [CONST_INDEX_AVATAR_TEXCOORD][4] or 1
  269. else
  270. storedPersona [CONST_INDEX_AVATAR_TEXCOORD] = {0, 1, 0, 1}
  271. end
  272.  
  273. --background texcoord
  274. if (type (receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD]) == "boolean") then
  275. storedPersona [CONST_INDEX_BACKGROUND_TEXCOORD] = {0, 1, 0, 1}
  276.  
  277. elseif (type (receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD]) == "table") then
  278. storedPersona [CONST_INDEX_BACKGROUND_TEXCOORD] = storedPersona [CONST_INDEX_BACKGROUND_TEXCOORD] or {}
  279. storedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][1] = type (receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][1]) == "number" and receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][1] or 0
  280. storedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][2] = type (receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][2]) == "number" and receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][2] or 1
  281. storedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][3] = type (receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][3]) == "number" and receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][3] or 0
  282. storedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][4] = type (receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][4]) == "number" and receivedPersona [CONST_INDEX_BACKGROUND_TEXCOORD][4] or 1
  283. else
  284. storedPersona [CONST_INDEX_BACKGROUND_TEXCOORD] = {0, 1, 0, 1}
  285. end
  286.  
  287. --background path
  288. storedPersona [CONST_INDEX_BACKGROUND_PATH] = type (receivedPersona [CONST_INDEX_BACKGROUND_PATH]) == "string" and receivedPersona [CONST_INDEX_BACKGROUND_PATH] or ""
  289.  
  290. --background color
  291. if (type (receivedPersona [CONST_INDEX_BACKGROUND_COLOR]) == "table") then
  292. storedPersona [CONST_INDEX_BACKGROUND_COLOR] = storedPersona [CONST_INDEX_BACKGROUND_COLOR] or {}
  293. storedPersona [CONST_INDEX_BACKGROUND_COLOR][1] = type (receivedPersona [CONST_INDEX_BACKGROUND_COLOR][1]) == "number" and receivedPersona [CONST_INDEX_BACKGROUND_COLOR][1] or 1
  294. storedPersona [CONST_INDEX_BACKGROUND_COLOR][2] = type (receivedPersona [CONST_INDEX_BACKGROUND_COLOR][2]) == "number" and receivedPersona [CONST_INDEX_BACKGROUND_COLOR][2] or 1
  295. storedPersona [CONST_INDEX_BACKGROUND_COLOR][3] = type (receivedPersona [CONST_INDEX_BACKGROUND_COLOR][3]) == "number" and receivedPersona [CONST_INDEX_BACKGROUND_COLOR][3] or 1
  296. else
  297. storedPersona [CONST_INDEX_BACKGROUND_COLOR] = {1, 1, 1}
  298. end
  299.  
  300. NickTag:Msg ("FULLPERSONA received and updated for character: ", source, "new nickname: ", receivedPersona [CONST_INDEX_NICKNAME])
  301. end
  302. end
  303.  
  304. --> 0x2: received a revision version from a guy which logon in the game
  305. elseif (_type == CONST_COMM_LOGONREVISION) then
  306.  
  307. if (UnitName ("player") == source) then
  308. return
  309. end
  310.  
  311. local receivedRevision = arg3
  312. local storedPersona = NickTag:GetNicknameTable (source)
  313.  
  314. NickTag:Msg ("LOGONREVISION rev: ", receivedRevision, " source: ", source)
  315.  
  316. if (type (version) ~= "number" or version ~= minor) then
  317. return
  318. end
  319.  
  320. if (not storedPersona or storedPersona [CONST_INDEX_REVISION] < receivedRevision) then
  321. --> put in queue our request for receive a updated persona
  322. NickTag:ScheduleTimer ("QueueRequest", math.random (10, 60), source)
  323.  
  324. NickTag:Msg ("LOGONREVISION from: " .. source .. " |cFFFF0000is out of date|r, queueing a request persona.")
  325. else
  326. NickTag:Msg ("LOGONREVISION from: " .. source .. " |cFF00FF00is up to date.")
  327. end
  328.  
  329. --> 0x3: someone requested my persona, so i need to send to him
  330. elseif (_type == CONST_COMM_REQUESTPERSONA) then
  331. if (type (version) ~= "number" or version ~= minor) then
  332. return
  333. end
  334.  
  335. --> queue to send our persona for requested person
  336. NickTag:Msg ("REQUESTPERSONA from: " .. source .. ", the request has been placed in queue.")
  337.  
  338. NickTag:QueueSend (source)
  339. end
  340.  
  341. end
  342.  
  343. NickTag:RegisterComm ("NickTag", "OnReceiveComm")
  344.  
  345. function NickTag:UpdateRoster()
  346. --> do not update roster if is in combat
  347. if (not UnitAffectingCombat ("player")) then
  348. GuildRoster()
  349. end
  350. end
  351.  
  352. function NickTag:IsOnline (name)
  353.  
  354. local isShownOffline = GetGuildRosterShowOffline()
  355. if (isShownOffline) then
  356. SetGuildRosterShowOffline (false)
  357. end
  358.  
  359. local _, numOnlineMembers = GetNumGuildMembers()
  360.  
  361. NickTag:Msg ("IsOnline(): " .. numOnlineMembers .. " online members.")
  362.  
  363. for i = 1, numOnlineMembers do
  364. local player_name = GetGuildRosterInfo (i)
  365. if (player_name:find (name)) then
  366. if (isShownOffline) then
  367. SetGuildRosterShowOffline (true)
  368. end
  369. return true
  370. end
  371. end
  372. if (isShownOffline) then
  373. SetGuildRosterShowOffline (true)
  374. end
  375. return false
  376. end
  377.  
  378. local event_frame = CreateFrame ("frame", nil, UIParent)
  379. event_frame:Hide()
  380. event_frame:SetScript ("OnEvent", function (_, _, local_update)
  381. if (not local_update) then
  382.  
  383. --> roster was been updated
  384. if (last_queue < time()) then
  385. last_queue = time()+11
  386. else
  387. return
  388. end
  389.  
  390. --> do not share if we are in combat
  391. if (UnitAffectingCombat ("player")) then
  392. return
  393. end
  394.  
  395. --> start with send requested personas
  396. if (#queue_send > 0) then
  397.  
  398. local name = queue_send [1]
  399. table.remove (queue_send, 1)
  400.  
  401. NickTag:Msg ("QUEUE -> ready to send persona to " .. name)
  402.  
  403. --> check if the player is online
  404. if (NickTag:IsOnline (name)) then
  405. NickTag:Msg ("QUEUE -> " .. name .. " is online, running SendPersona().")
  406. NickTag:SendPersona (name)
  407. else
  408. NickTag:Msg ("QUEUE -> " .. name .. " is offline, cant request his persona.")
  409. end
  410.  
  411. if (#queue_send == 0 and #queue_request == 0) then
  412. NickTag:StopRosterUpdates()
  413. end
  414.  
  415. elseif (#queue_request > 0) then
  416.  
  417. local name = queue_request [1]
  418. table.remove (queue_request, 1)
  419.  
  420. NickTag:Msg ("QUEUE -> ready to request the persona of " .. name)
  421.  
  422. --> check if the player is online
  423. if (NickTag:IsOnline (name)) then
  424. NickTag:Msg ("QUEUE -> " .. name .. " is online, running RequestPersona().")
  425. NickTag:RequestPersona (name)
  426. else
  427. NickTag:Msg ("QUEUE -> " .. name .. " is offline, cant request his persona.")
  428. end
  429.  
  430. if (#queue_request == 0 and #queue_request == 0) then
  431. NickTag:StopRosterUpdates()
  432. end
  433.  
  434. else
  435. NickTag:StopRosterUpdates()
  436. end
  437. end
  438. end)
  439.  
  440. function NickTag:StopRosterUpdates()
  441. NickTag:Msg ("ROSTER -> updates has been stopped")
  442. if (NickTag.UpdateRosterTimer) then
  443. NickTag:CancelTimer (NickTag.UpdateRosterTimer)
  444. end
  445. NickTag.UpdateRosterTimer = nil
  446. event_frame:UnregisterEvent ("GUILD_ROSTER_UPDATE")
  447. is_updating = false
  448. end
  449.  
  450. function NickTag:StartRosterUpdates()
  451. NickTag:Msg ("ROSTER -> updates has been actived")
  452. event_frame:RegisterEvent ("GUILD_ROSTER_UPDATE")
  453. if (not NickTag.UpdateRosterTimer) then
  454. NickTag.UpdateRosterTimer = NickTag:ScheduleRepeatingTimer ("UpdateRoster", 12)
  455. NickTag:Msg ("ROSTER -> new update thread created.")
  456. else
  457. NickTag:Msg ("ROSTER -> a update thread already exists.")
  458. end
  459. is_updating = true
  460. end
  461.  
  462. --> we queue data for roster update and also check for combat
  463. function NickTag:QueueRequest (name)
  464. table.insert (queue_request, name)
  465. if (not is_updating) then
  466. NickTag:StartRosterUpdates()
  467. end
  468. end
  469. function NickTag:QueueSend (name)
  470. table.insert (queue_send, name)
  471. if (not is_updating) then
  472. NickTag:StartRosterUpdates()
  473. end
  474. end
  475.  
  476. --> after logon, we send our revision, who needs update my persona will send 0x3 (request persona) to me and i send back 0x1 (send persona)
  477. function NickTag:SendRevision()
  478. local playerName = UnitName ("player")
  479. local myPersona = NickTag:GetNicknameTable (playerName)
  480. if (myPersona) then
  481. NickTag:Msg ("SendRevision() -> SENT")
  482. if (IsInGuild()) then
  483. NickTag:SendCommMessage ("NickTag", NickTag:Serialize (CONST_COMM_LOGONREVISION, 0, myPersona [CONST_INDEX_REVISION], UnitName ("player"), GetRealmName(), minor), "GUILD")
  484. end
  485. end
  486. end
  487.  
  488. --> i received 0x2 and his persona is out of date here, so i need to send 0x3 to him and him will send 0x1.
  489. function NickTag:RequestPersona (target)
  490. NickTag:Msg ("RequestPersona() -> requesting of " .. target)
  491. if (IsInGuild()) then
  492. NickTag:SendCommMessage ("NickTag", NickTag:Serialize (CONST_COMM_REQUESTPERSONA, 0, 0, UnitName ("player"), GetRealmName(), minor), "WHISPER", target)
  493. end
  494. end
  495.  
  496. --> this broadcast my persona to entire guild when i update my persona or send my persona to someone who doesn't have it or need to update.
  497. function NickTag:SendPersona (target)
  498. if (target) then
  499. NickTag:Msg ("SendPersona() -> sent to " .. target)
  500. else
  501. NickTag:Msg ("SendPersona() -> broadcast")
  502. end
  503.  
  504. --> auto change nickname if we have a invalid nickname
  505. if (NickTag:GetNickname (UnitName ("player")) == LibStub ("AceLocale-3.0"):GetLocale ("NickTag-1.0")["STRING_INVALID_NAME"]) then
  506. local nickTable = NickTag:GetNicknameTable (UnitName ("player"))
  507. if (nickTable) then
  508. nickTable [CONST_INDEX_NICKNAME] = UnitName ("player")
  509. end
  510. end
  511.  
  512. if (target) then
  513. --> was requested
  514. if (IsInGuild()) then
  515. NickTag:SendCommMessage ("NickTag", NickTag:Serialize (CONST_COMM_FULLPERSONA, 0, NickTag:GetNicknameTable (UnitName ("player")), minor), "WHISPER", target)
  516. end
  517. else
  518. --> updating my own persona
  519. NickTag.send_scheduled = false
  520. --> broadcast only happen when something has changed on the local player persona, it needs to increase the revision before sending
  521. NickTag:IncRevision()
  522. --> broadcast over guild channel
  523. if (IsInGuild()) then
  524. NickTag:SendCommMessage ("NickTag", NickTag:Serialize (CONST_COMM_FULLPERSONA, 0, NickTag:GetNicknameTable (UnitName ("player")), minor), "GUILD")
  525. end
  526. end
  527. end
  528.  
  529. ------------------------------------------------------------------------------------------------------------------------------------------------------
  530. --> on logon stuff
  531.  
  532. --> reset cache
  533. function NickTag:ResetCache()
  534.  
  535. local playerName = UnitName ("player")
  536.  
  537. if (playerName) then
  538. local player = NickTag:GetNicknameTable (playerName)
  539. if (player and pool.last_version == minor) then
  540. for thisPlayerName, _ in pairs (pool) do
  541. if (thisPlayerName ~= playerName) then
  542. pool [thisPlayerName] = nil
  543. end
  544. end
  545. --vardump (pool)
  546. else
  547. table.wipe (pool)
  548. end
  549.  
  550. pool.nextreset = time() + (60*60*24*15) --> 15 days or 1296000 seconds
  551. pool.last_version = minor
  552. else
  553. --> sometimes player guid isn't available right after logon, so, just schedule until it become available.
  554. NickTag:ScheduleTimer ("ResetCache", 0.3)
  555. end
  556. end
  557.  
  558. function NickTag:NickTagSetCache (_table)
  559. if (not pool.default) then
  560. return table.wipe (_table)
  561. end
  562.  
  563. pool = _table
  564.  
  565. if (not pool.nextreset) then
  566. pool.nextreset = time() + (60*60*24*15)
  567. end
  568. if (not pool.last_version) then
  569. pool.last_version = minor
  570. end
  571. if (pool.last_version < minor) then
  572. pool.nextreset = 1
  573. end
  574. if (time() > pool.nextreset) then
  575. NickTag:ResetCache()
  576. end
  577.  
  578. NickTag:ScheduleTimer ("SendRevision", 30)
  579. end
  580.  
  581. ------------------------------------------------------------------------------------------------------------------------------------------------------
  582. --> basic functions
  583.  
  584. --> trim from from http://lua-users.org/wiki/StringTrim
  585. function trim (s)
  586. local from = s:match"^%s*()"
  587. return from > #s and "" or s:match(".*%S", from)
  588. end
  589. --
  590. local titlecase = function (first, rest)
  591. return first:upper()..rest:lower()
  592. end
  593. --
  594. local have_repeated = false
  595. local count_spaces = 0
  596. local check_repeated = function (char)
  597. if (char == " ") then
  598. have_repeated = true
  599. elseif (string.len (char) > 2) then
  600. have_repeated = true
  601. elseif (char == " ") then
  602. count_spaces = count_spaces + 1
  603. end
  604. end
  605.  
  606. --> we need to keep game smooth checking and formating nicknames.
  607. --> SetNickname and names comming from other player need to be check.
  608. function NickTag:CheckName (name)
  609.  
  610. --> as nicktag only work internally in the guild, we think that is not necessary a work filter to avoid people using bad language.
  611.  
  612. if (type (name) ~= "string") then
  613. return false, LibStub ("AceLocale-3.0"):GetLocale ("NickTag-1.0")["STRING_ERROR_4"] --> error 4 = name isn't a valid string
  614. end
  615.  
  616. name = trim (name)
  617.  
  618. --> limit nickname to 12 characters, same as wow.
  619. local len = string.len (name)
  620. if (len > 25) then
  621. return false, LibStub ("AceLocale-3.0"):GetLocale ("NickTag-1.0")["STRING_ERROR_1"] --> error 1 = nickname is too long, max of 12 characters.
  622. end
  623.  
  624. --> check if contain any non allowed characters, by now only accpet letters, numbers and spaces.
  625. --> by default wow do not accetp spaces, but here will allow.
  626. --> tested over lua 5.2 and this capture was okey with accents, not sure why inside wow this doesn't work.
  627. local notallow = string.find (name, "[^a-zA-Z�������%s]")
  628. if (notallow) then
  629. return false, LibStub ("AceLocale-3.0"):GetLocale ("NickTag-1.0")["STRING_ERROR_2"] --> error 2 = nickname only support letters, numbers and spaces.
  630. end
  631.  
  632. --> check if there is sequencial repeated characters, like "Jasooon" were repeats 3 times the "o" character.
  633. --> got this from http://stackoverflow.com/questions/15608299/lua-pattern-matching-repeating-character
  634. have_repeated = false
  635. count_spaces = 0
  636. string.gsub (name, '.', '\0%0%0'):gsub ('(.)%z%1','%1'):gsub ('%z.([^%z]+)', check_repeated)
  637. if (count_spaces > 2) then
  638. have_repeated = true
  639. end
  640. if (have_repeated) then
  641. return false, LibStub ("AceLocale-3.0"):GetLocale ("NickTag-1.0")["STRING_ERROR_3"] --> error 3 = cant use the same letter three times consecutively, 2 spaces consecutively or 3 or more spaces.
  642. end
  643.  
  644. return true
  645. end
  646.  
  647. --> set the "player" nickname and schedule for send updated persona
  648. function NickTag:SetNickname (name)
  649.  
  650. --> check data before
  651. assert (type (name) == "string", "NickTag 'SetNickname' expects a string on #1 argument.")
  652.  
  653. --> check if the nickname is okey to allowed to use.
  654. local okey, errortype = NickTag:CheckName (name)
  655. if (not okey) then
  656. NickTag:Msg ("SetNickname() invalid name ", name)
  657. return false, errortype
  658. end
  659.  
  660. --> here we format the text to match titles, e.g converts name like "JASON NICKSHOW" into "Jason Nickshow".
  661.  
  662.  
  663. local playerName = UnitName ("player")
  664.  
  665. --> get the full nick table.
  666. local nickTable = NickTag:GetNicknameTable (playerName)
  667. if (not nickTable) then
  668. nickTable = NickTag:Create (playerName, true)
  669. end
  670.  
  671. --> change the nickname for the player nick table.
  672. if (nickTable [CONST_INDEX_NICKNAME] ~= name) then
  673. nickTable [CONST_INDEX_NICKNAME] = name
  674.  
  675. --> send the update for script which need it.
  676. NickTag.callbacks:Fire ("NickTag_Update", CONST_INDEX_NICKNAME)
  677.  
  678. --> schedule a update for revision and broadcast full persona.
  679. --> this is a kind of protection for scripts which call SetNickname, SetColor and SetAvatar one after other, so scheduling here avoid three revisions upgrades and 3 broadcasts to the guild.
  680. if (not NickTag.send_scheduled) then
  681. NickTag.send_scheduled = true
  682. NickTag:ScheduleTimer ("SendPersona", 1)
  683. end
  684.  
  685. else
  686. NickTag:Msg ("SetNickname() name is the same on the pool ", name, nickTable [CONST_INDEX_NICKNAME])
  687. end
  688.  
  689. return true
  690. end
  691.  
  692. function NickTag:SetNicknameAvatar (texture, l, r, t, b)
  693.  
  694. if (l == nil) then
  695. l, r, t, b = 0, 1, 0, 1
  696. elseif (type (l) == "table") then
  697. l, r, t, b = unpack (l)
  698. end
  699.  
  700. --> check data before
  701. assert (texture and l and r and t and b, "NickTag 'SetNicknameAvatar' bad format. Usage NickTag:SetAvatar (texturepath [, L, R, T, B] or texturepath [, {L, R, T, B}])")
  702.  
  703. local playerName = UnitName ("player")
  704.  
  705. local nickTable = NickTag:GetNicknameTable (playerName)
  706. if (not nickTable) then
  707. nickTable = NickTag:Create (playerName, true)
  708. end
  709.  
  710. if (nickTable [CONST_INDEX_AVATAR_PATH] ~= texture) then
  711. nickTable [CONST_INDEX_AVATAR_PATH] = texture
  712.  
  713. --> by default, CONST_INDEX_AVATAR_TEXCOORD comes as boolean false
  714. if (type (nickTable [CONST_INDEX_AVATAR_TEXCOORD]) == "boolean") then
  715. nickTable [CONST_INDEX_AVATAR_TEXCOORD] = {}
  716. end
  717.  
  718. nickTable [CONST_INDEX_AVATAR_TEXCOORD][1] = l
  719. nickTable [CONST_INDEX_AVATAR_TEXCOORD][2] = r
  720. nickTable [CONST_INDEX_AVATAR_TEXCOORD][3] = t
  721. nickTable [CONST_INDEX_AVATAR_TEXCOORD][4] = b
  722.  
  723. NickTag.callbacks:Fire ("NickTag_Update", CONST_INDEX_AVATAR_PATH)
  724.  
  725. if (not NickTag.send_scheduled) then
  726. NickTag.send_scheduled = true
  727. NickTag:ScheduleTimer ("SendPersona", 1)
  728. end
  729. end
  730.  
  731. return true
  732. end
  733.  
  734. --> set the background
  735. function NickTag:SetNicknameBackground (path, texcoord, color, silent)
  736.  
  737. if (not silent) then
  738. assert (type (path) == "string", "NickTag 'SetNicknameBackground' expects a string on #1 argument.")
  739. else
  740. if (type (path) ~= "string") then
  741. return
  742. end
  743. end
  744.  
  745. if (not texcoord) then
  746. texcoord = {0, 1, 0, 1}
  747. end
  748.  
  749. if (not color) then
  750. color = {1, 1, 1}
  751. end
  752.  
  753. local playerName = UnitName ("player")
  754.  
  755. local nickTable = NickTag:GetNicknameTable (playerName)
  756. if (not nickTable) then
  757. nickTable = NickTag:Create (playerName, true)
  758. end
  759.  
  760. local need_sync = false
  761. if (nickTable [CONST_INDEX_BACKGROUND_PATH] ~= path) then
  762. nickTable [CONST_INDEX_BACKGROUND_PATH] = path
  763. need_sync = true
  764. end
  765.  
  766. if (nickTable [CONST_INDEX_BACKGROUND_TEXCOORD] ~= texcoord) then
  767. nickTable [CONST_INDEX_BACKGROUND_TEXCOORD] = texcoord
  768. need_sync = true
  769. end
  770.  
  771. if (nickTable [CONST_INDEX_BACKGROUND_COLOR] ~= color) then
  772. nickTable [CONST_INDEX_BACKGROUND_COLOR] = color
  773. need_sync = true
  774. end
  775.  
  776. if (need_sync) then
  777. NickTag.callbacks:Fire ("NickTag_Update", CONST_INDEX_BACKGROUND_PATH)
  778.  
  779. if (not NickTag.send_scheduled) then
  780. NickTag.send_scheduled = true
  781. NickTag:ScheduleTimer ("SendPersona", 1)
  782. end
  783. end
  784.  
  785. return true
  786. end
  787.  
  788. function NickTag:GetNickname (playerName, default, silent)
  789. if (not silent) then
  790. assert (type (playerName) == "string", "NickTag 'GetNickname' expects a string or string on #1 argument.")
  791. end
  792.  
  793. local _table = pool [playerName]
  794. if (not _table) then
  795. return default or nil
  796. end
  797. return _table [CONST_INDEX_NICKNAME] or default or nil
  798. end
  799.  
  800. --> return the avatar and the texcoord.
  801. function NickTag:GetNicknameAvatar (playerName, default, silent)
  802. if (not silent) then
  803. assert (type (playerName) == "string", "NickTag 'GetNicknameAvatar' expects a string or string on #1 argument.")
  804. end
  805.  
  806. local _table = pool [playerName]
  807.  
  808. if (not _table and default) then
  809. return default, {0, 1, 0, 1}
  810. elseif (not _table) then
  811. return "", {0, 1, 0, 1}
  812. end
  813. return _table [CONST_INDEX_AVATAR_PATH] or default or "", _table [CONST_INDEX_AVATAR_TEXCOORD] or {0, 1, 0, 1}
  814. end
  815.  
  816. function NickTag:GetNicknameBackground (playerName, default_path, default_texcoord, default_color, silent)
  817. if (not silent) then
  818. assert (type (playerName) == "string", "NickTag 'GetNicknameBackground' expects a string or string on #1 argument.")
  819. end
  820.  
  821. local _table = pool [playerName]
  822. if (not _table) then
  823. return default_path, default_texcoord, default_color
  824. end
  825. return _table [CONST_INDEX_BACKGROUND_PATH] or default_path, _table [CONST_INDEX_BACKGROUND_TEXCOORD] or default_texcoord, _table [CONST_INDEX_BACKGROUND_COLOR] or default_color
  826. end
  827.  
  828. --> get the full nicktag table
  829. function NickTag:GetNicknameTable (playerName, silent)
  830. --> check data before
  831. if (not silent) then
  832. assert (type (playerName) == "string", "NickTag 'GetNicknameTable' expects a string on #1 argument.")
  833. else
  834. if (not playerName or type (playerName) ~= "string") then
  835. return
  836. end
  837. end
  838.  
  839. return pool [playerName]
  840. end
  841.  
  842. ------------------------------------------------------------------------------------------------------------------------------------------------------
  843. --> internal functions
  844.  
  845. --> create a empty nick table for the player
  846. function NickTag:Create (playerName, isSelf)
  847. --> check data before
  848. assert (type (playerName) == "string", "NickTag 'Create' expects a string on #1 argument.")
  849.  
  850. --> check if alredy exists
  851. local alredyHave = pool [playerName]
  852. if (alredyHave) then
  853. return alredyHave
  854. end
  855.  
  856. --> create the table:
  857. local newTable = {
  858. UnitName ("player"), --[1] player nickname
  859. false, --[2] avatar texture path
  860. false, --[3] avatar texture coord
  861. false, --[4] background texture path
  862. false, --[5] background texcoord
  863. false, --[6] background color
  864. 1 --[7] revision
  865. }
  866.  
  867. --> if not my persona, set revision to 0, this make always get update after creation
  868. if (not isSelf) then
  869. newTable [CONST_INDEX_REVISION] = 0
  870. end
  871.  
  872. pool [playerName] = newTable
  873. return newTable
  874. end
  875.  
  876. --> inc the revision of the player persona after update nick or avatar
  877. function NickTag:IncRevision()
  878. local playerName = UnitName ("player")
  879. local nickTable = NickTag:GetNicknameTable (playerName)
  880. if (not nickTable) then
  881. nickTable = NickTag:Create (playerName, true)
  882. end
  883.  
  884. nickTable [CONST_INDEX_REVISION] = nickTable [CONST_INDEX_REVISION] + 1
  885.  
  886. return true
  887. end
  888.  
  889. --> convert GUID into serial number (deprecated, it uses player name - realm name)
  890. function NickTag:GetSerial (serial, silent)
  891. return 0
  892. end
  893.  
  894. --> choose avatar window
  895. do
  896. local avatar_pick_frame = CreateFrame ("frame", "AvatarPickFrame", UIParent)
  897. avatar_pick_frame:SetFrameStrata ("DIALOG")
  898. avatar_pick_frame:SetBackdrop ({bgFile = [[Interface\FrameGeneral\UI-Background-Marble]], edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]], tile = true, tileSize = 256, edgeSize = 32, insets = {left = 11, right = 12, top = 12, bottom = 11}})
  899. avatar_pick_frame:SetBackdropColor (.3, .3, .3, .9)
  900. avatar_pick_frame:SetWidth (460)
  901. avatar_pick_frame:SetHeight (240)
  902.  
  903. avatar_pick_frame.selected_avatar = 1
  904. avatar_pick_frame.selected_background = 1
  905. avatar_pick_frame.selected_color = {1, 1, 1}
  906. avatar_pick_frame.selected_texcoord = {0, 1, 0, 1}
  907.  
  908. avatar_pick_frame:SetPoint ("center", UIParent, "center", 200, 0)
  909. ---
  910. local avatar_texture = avatar_pick_frame:CreateTexture ("AvatarPickFrameAvatarPreview", "overlay")
  911. avatar_texture:SetPoint ("topleft", avatar_pick_frame, "topleft", 167, -10)
  912. avatar_texture:SetTexture ([[Interface\EncounterJournal\UI-EJ-BOSS-Default]])
  913. --
  914. local background_texture = avatar_pick_frame:CreateTexture ("AvatarPickFrameBackgroundPreview", "artwork")
  915. background_texture:SetPoint ("topleft", avatar_pick_frame, "topleft", 167, 2)
  916. background_texture:SetWidth (290)
  917. background_texture:SetHeight (75)
  918. background_texture:SetTexture (NickTag.background_pool[1][1])
  919. background_texture:SetTexCoord (unpack (NickTag.background_pool[1][3]))
  920. --
  921. local name = avatar_pick_frame:CreateFontString ("AvatarPickFrameName", "overlay", "GameFontHighlightHuge")
  922. name:SetPoint ("left", avatar_texture, "right", -11, -17)
  923. name:SetText (UnitName ("player"))
  924. ---
  925.  
  926. local OnClickFunction = function (button)
  927. if (button.isAvatar) then
  928. local avatar = NickTag.avatar_pool [button.IconID]
  929. _G.AvatarPickFrameAvatarPreview:SetTexture ( avatar [1] )
  930. avatar_pick_frame.selected_avatar = avatar [1]
  931. elseif (button.isBackground) then
  932. local background = NickTag.background_pool [button.IconID]
  933. _G.AvatarPickFrameBackgroundPreview:SetTexture ( background [1] )
  934. _G.AvatarPickFrameBackgroundPreview:SetTexCoord (unpack (background [3]))
  935. avatar_pick_frame.selected_background = background [1]
  936. avatar_pick_frame.selected_texcoord = background [3]
  937. end
  938. end
  939.  
  940. local selectedColor = function()
  941. local r, g, b = ColorPickerFrame:GetColorRGB()
  942. background_texture:SetVertexColor (r, g, b)
  943. avatar_pick_frame.selected_color[1] = r
  944. avatar_pick_frame.selected_color[2] = g
  945. avatar_pick_frame.selected_color[3] = b
  946. end
  947.  
  948. local okey = CreateFrame ("button", "AvatarPickFrameAccept", avatar_pick_frame, "OptionsButtonTemplate")
  949. okey:SetPoint ("bottomright", avatar_pick_frame, "bottomright", -37, 12)
  950. okey:SetText ("Accept")
  951. okey:SetFrameLevel (avatar_pick_frame:GetFrameLevel()+2)
  952. okey:SetScript ("OnClick", function (self)
  953. avatar_pick_frame:Hide()
  954. if (avatar_pick_frame.callback) then
  955. avatar_pick_frame.callback (avatar_pick_frame.selected_avatar, {0, 1, 0, 1}, avatar_pick_frame.selected_background, avatar_pick_frame.selected_texcoord, avatar_pick_frame.selected_color)
  956. end
  957. end)
  958. local change_color = CreateFrame ("button", "AvatarPickFrameColor", avatar_pick_frame, "OptionsButtonTemplate")
  959. change_color:SetPoint ("bottomright", avatar_pick_frame, "bottomright", -205, 12)
  960. change_color:SetText ("Color")
  961. change_color:SetFrameLevel (avatar_pick_frame:GetFrameLevel()+2)
  962.  
  963. change_color:SetScript ("OnClick", function (self)
  964. ColorPickerFrame.func = selectedColor
  965. ColorPickerFrame.hasOpacity = false
  966. ColorPickerFrame:SetParent (avatar_pick_frame)
  967. ColorPickerFrame:SetColorRGB (_G.AvatarPickFrameBackgroundPreview:GetVertexColor())
  968. ColorPickerFrame:ClearAllPoints()
  969. ColorPickerFrame:SetPoint ("left", avatar_pick_frame, "right", 0, -10)
  970. ColorPickerFrame:Show()
  971. end)
  972.  
  973. local buttons = {}
  974. for i = 0, 2 do
  975. local newbutton = CreateFrame ("button", "AvatarPickFrameAvatarScrollButton"..i+1, avatar_pick_frame)
  976. newbutton:SetScript ("OnClick", OnClickFunction)
  977. newbutton:SetWidth (128)
  978. newbutton:SetHeight (64)
  979. newbutton:SetPoint ("topleft", avatar_pick_frame, "topleft", 15, (i*70*-1) - 20)
  980. newbutton:SetID (i+1)
  981. newbutton.isAvatar = true
  982. buttons [#buttons+1] = newbutton
  983. end
  984.  
  985. local buttonsbg = {}
  986. for i = 0, 2 do
  987. local newbutton = CreateFrame ("button", "AvatarPickFrameBackgroundScrollButton"..i+1, avatar_pick_frame)
  988. newbutton:SetScript ("OnClick", OnClickFunction)
  989. newbutton:SetWidth (275)
  990. newbutton:SetHeight (60)
  991. newbutton:SetPoint ("topleft", avatar_pick_frame, "topleft", 157, (i*50*-1) - 80)
  992. newbutton:SetID (i+1)
  993. newbutton.isBackground = true
  994. buttonsbg [#buttonsbg+1] = newbutton
  995. end
  996.  
  997. local avatar_list = CreateFrame ("ScrollFrame", "AvatarPickFrameAvatarScroll", avatar_pick_frame, "ListScrollFrameTemplate")
  998. avatar_list:SetPoint ("topleft", avatar_pick_frame, "topleft", 10, -10)
  999. local background_list = CreateFrame ("ScrollFrame", "AvatarPickFrameBackgroundScroll", avatar_pick_frame, "ListScrollFrameTemplate")
  1000. background_list:SetPoint ("topleft", avatar_pick_frame, "topleft", 147, -85)
  1001.  
  1002. avatar_list:SetWidth (128)
  1003. avatar_list:SetHeight (220)
  1004. background_list:SetWidth (275)
  1005. background_list:SetHeight (140)
  1006.  
  1007. local avatar_scroll_update = function (self)
  1008. local numMacroIcons = #NickTag.avatar_pool
  1009. local macroPopupIcon, macroPopupButton, index, texture
  1010. local macroPopupOffset = FauxScrollFrame_GetOffset (avatar_list)
  1011.  
  1012. for i = 1, 3 do
  1013. macroPopupIcon = _G ["AvatarPickFrameAvatarScrollButton"..i]
  1014. macroPopupButton = _G ["AvatarPickFrameAvatarScrollButton"..i]
  1015. index = (macroPopupOffset * 1) + i
  1016.  
  1017. texture = NickTag.avatar_pool [index][1]
  1018. if ( index <= numMacroIcons and texture ) then
  1019. macroPopupButton:SetNormalTexture (texture)
  1020. macroPopupButton:SetPushedTexture (texture)
  1021. macroPopupButton:SetDisabledTexture (texture)
  1022. macroPopupButton:SetHighlightTexture (texture, "ADD")
  1023. macroPopupButton.IconID = index
  1024. macroPopupButton:Show()
  1025. else
  1026. macroPopupButton:Hide()
  1027. end
  1028. end
  1029. FauxScrollFrame_Update (avatar_list, numMacroIcons , 3, 64)
  1030. end
  1031. local background_scroll_update = function (self)
  1032. local numMacroIcons = #NickTag.background_pool
  1033. local macroPopupIcon, macroPopupButton, index, texture
  1034. local macroPopupOffset = FauxScrollFrame_GetOffset (background_list)
  1035.  
  1036. for i = 1, 3 do
  1037. macroPopupIcon = _G ["AvatarPickFrameBackgroundScrollButton"..i]
  1038. macroPopupButton = _G ["AvatarPickFrameBackgroundScrollButton"..i]
  1039. index = (macroPopupOffset * 1) + i
  1040.  
  1041. texture = NickTag.background_pool [index][1]
  1042. if ( index <= numMacroIcons and texture ) then
  1043. macroPopupButton:SetNormalTexture (texture)
  1044. macroPopupButton:SetPushedTexture (texture)
  1045. macroPopupButton:SetDisabledTexture (texture)
  1046. macroPopupButton:SetHighlightTexture (texture, "ADD")
  1047. macroPopupButton.IconID = index
  1048. macroPopupButton:Show()
  1049. else
  1050. macroPopupButton:Hide()
  1051. end
  1052. end
  1053. FauxScrollFrame_Update (background_list, numMacroIcons , 3, 40)
  1054. end
  1055.  
  1056. avatar_list:SetScript ("OnVerticalScroll", function (self, offset)
  1057. FauxScrollFrame_OnVerticalScroll (avatar_list, offset, 64, avatar_scroll_update)
  1058. end)
  1059. background_list:SetScript ("OnVerticalScroll", function (self, offset)
  1060. FauxScrollFrame_OnVerticalScroll (background_list, offset, 40, background_scroll_update)
  1061. end)
  1062.  
  1063. avatar_scroll_update (avatar_list)
  1064. background_scroll_update (background_list)
  1065.  
  1066. function avatar_pick_frame:SetAvatar (n)
  1067. if (type (n) ~= "number") then
  1068. n = 1
  1069. end
  1070. if (n > #NickTag.avatar_pool) then
  1071. n = 1
  1072. end
  1073. local avatar = NickTag.avatar_pool [n]
  1074. _G.AvatarPickFrameAvatarPreview:SetTexture ( avatar [1] )
  1075. avatar_pick_frame.selected_avatar = avatar [1]
  1076. end
  1077. function avatar_pick_frame:SetBackground (n)
  1078. if (type (n) ~= "number") then
  1079. n = 1
  1080. end
  1081. if (n > #NickTag.background_pool) then
  1082. n = 1
  1083. end
  1084. local background = NickTag.background_pool [n]
  1085. _G.AvatarPickFrameBackgroundPreview:SetTexture ( background [1] )
  1086. _G.AvatarPickFrameBackgroundPreview:SetTexCoord (unpack (background [3]))
  1087. _G.AvatarPickFrameBackgroundPreview:SetVertexColor (unpack (avatar_pick_frame.selected_color))
  1088. avatar_pick_frame.selected_background = background [1]
  1089. end
  1090. function avatar_pick_frame:SetColor (r, g, b)
  1091. if (type (r) ~= "number" or r > 1) then
  1092. r = 1
  1093. end
  1094. if (type (g) ~= "number" or g > 1) then
  1095. g = 1
  1096. end
  1097. if (type (b) ~= "number" or b > 1) then
  1098. b = 1
  1099. end
  1100. _G.AvatarPickFrameBackgroundPreview:SetVertexColor (r, g, b)
  1101. avatar_pick_frame.selected_color[1] = r
  1102. avatar_pick_frame.selected_color[2] = g
  1103. avatar_pick_frame.selected_color[3] = b
  1104. end
  1105.  
  1106. local CONST_INDEX_NICKNAME = 1
  1107. local CONST_INDEX_AVATAR_PATH = 2
  1108. local CONST_INDEX_AVATAR_TEXCOORD = 3
  1109. local CONST_INDEX_BACKGROUND_PATH = 4
  1110. local CONST_INDEX_BACKGROUND_TEXCOORD = 5
  1111. local CONST_INDEX_BACKGROUND_COLOR = 6
  1112.  
  1113. avatar_pick_frame:SetScript ("OnShow", function()
  1114. --get player avatar
  1115. local avatar = NickTag:GetNicknameTable (UnitGUID ("player"))
  1116. if (avatar) then
  1117. _G.AvatarPickFrameName:SetText ( avatar [1] or UnitName ("player"))
  1118.  
  1119. _G.AvatarPickFrameAvatarPreview:SetTexture ( avatar [CONST_INDEX_AVATAR_PATH] or [[Interface\EncounterJournal\UI-EJ-BOSS-Default]] )
  1120. avatar_pick_frame.selected_avatar = avatar [CONST_INDEX_AVATAR_PATH] or [[Interface\EncounterJournal\UI-EJ-BOSS-Default]]
  1121.  
  1122. _G.AvatarPickFrameAvatarPreview:SetTexCoord ( 0, 1, 0, 1 ) --> always
  1123.  
  1124. _G.AvatarPickFrameBackgroundPreview:SetTexture ( avatar [CONST_INDEX_BACKGROUND_PATH] or [[Interface\PetBattles\Weather-ArcaneStorm]] )
  1125. avatar_pick_frame.selected_background = avatar [CONST_INDEX_BACKGROUND_PATH] or [[Interface\PetBattles\Weather-ArcaneStorm]]
  1126.  
  1127. if (avatar [CONST_INDEX_BACKGROUND_TEXCOORD]) then
  1128. _G.AvatarPickFrameBackgroundPreview:SetTexCoord ( unpack (avatar [CONST_INDEX_BACKGROUND_TEXCOORD]) )
  1129. avatar_pick_frame.selected_texcoord = avatar [CONST_INDEX_BACKGROUND_TEXCOORD]
  1130. else
  1131. _G.AvatarPickFrameBackgroundPreview:SetTexCoord ( 0.129609375, 1, 1, 0 )
  1132. avatar_pick_frame.selected_texcoord = {0.129609375, 1, 1, 0}
  1133. end
  1134.  
  1135. if (avatar [CONST_INDEX_BACKGROUND_COLOR]) then
  1136. _G.AvatarPickFrameBackgroundPreview:SetVertexColor ( unpack (avatar [CONST_INDEX_BACKGROUND_COLOR]) )
  1137. avatar_pick_frame.selected_color = avatar [CONST_INDEX_BACKGROUND_COLOR]
  1138. else
  1139. _G.AvatarPickFrameBackgroundPreview:SetVertexColor ( 1, 1, 1 )
  1140. avatar_pick_frame.selected_color = {1, 1, 1}
  1141. end
  1142. else
  1143. --> if none
  1144. _G.AvatarPickFrameAvatarPreview:SetTexture ( [[Interface\EncounterJournal\UI-EJ-BOSS-Default]] )
  1145. avatar_pick_frame.selected_avatar = [[Interface\EncounterJournal\UI-EJ-BOSS-Default]]
  1146.  
  1147. local background = NickTag.background_pool [1]
  1148.  
  1149. if (background) then
  1150. _G.AvatarPickFrameBackgroundPreview:SetTexture ( background [1] )
  1151. avatar_pick_frame.selected_background = background [1]
  1152. _G.AvatarPickFrameBackgroundPreview:SetTexCoord (unpack (background [3]))
  1153. avatar_pick_frame.selected_texcoord = background [3]
  1154. _G.AvatarPickFrameBackgroundPreview:SetVertexColor (unpack (avatar_pick_frame.selected_color))
  1155. avatar_pick_frame.selected_color = avatar_pick_frame.selected_color
  1156. end
  1157.  
  1158. end
  1159. end)
  1160.  
  1161. avatar_pick_frame:Hide()
  1162. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement