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