· 7 years ago · Nov 26, 2018, 09:36 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", 10
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
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 return true
611 end
612
613 --> set the "player" nickname and schedule for send updated persona
614 function NickTag:SetNickname (name)
615
616 --> check data before
617 assert (type (name) == "string", "NickTag 'SetNickname' expects a string on #1 argument.")
618
619 --> check if the nickname is okey to allowed to use.
620 local okey, errortype = NickTag:CheckName (name)
621 if (not okey) then
622 NickTag:Msg ("SetNickname() invalid name ", name)
623 return false, errortype
624 end
625
626 --> here we format the text to match titles, e.g converts name like "JASON NICKSHOW" into "Jason Nickshow".
627 name = name:gsub ("(%a)([%w_']*)", titlecase)
628
629 local playerName = UnitName ("player")
630
631 --> get the full nick table.
632 local nickTable = NickTag:GetNicknameTable (playerName)
633 if (not nickTable) then
634 nickTable = NickTag:Create (playerName, true)
635 end
636
637 --> change the nickname for the player nick table.
638 if (nickTable [CONST_INDEX_NICKNAME] ~= name) then
639 nickTable [CONST_INDEX_NICKNAME] = name
640
641 --> send the update for script which need it.
642 NickTag.callbacks:Fire ("NickTag_Update", CONST_INDEX_NICKNAME)
643
644 --> schedule a update for revision and broadcast full persona.
645 --> 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.
646 if (not NickTag.send_scheduled) then
647 NickTag.send_scheduled = true
648 NickTag:ScheduleTimer ("SendPersona", 1)
649 end
650
651 else
652 NickTag:Msg ("SetNickname() name is the same on the pool ", name, nickTable [CONST_INDEX_NICKNAME])
653 end
654
655 return true
656 end
657
658 function NickTag:SetNicknameAvatar (texture, l, r, t, b)
659
660 if (l == nil) then
661 l, r, t, b = 0, 1, 0, 1
662 elseif (type (l) == "table") then
663 l, r, t, b = unpack (l)
664 end
665
666 --> check data before
667 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}])")
668
669 local playerName = UnitName ("player")
670
671 local nickTable = NickTag:GetNicknameTable (playerName)
672 if (not nickTable) then
673 nickTable = NickTag:Create (playerName, true)
674 end
675
676 if (nickTable [CONST_INDEX_AVATAR_PATH] ~= texture) then
677 nickTable [CONST_INDEX_AVATAR_PATH] = texture
678
679 --> by default, CONST_INDEX_AVATAR_TEXCOORD comes as boolean false
680 if (type (nickTable [CONST_INDEX_AVATAR_TEXCOORD]) == "boolean") then
681 nickTable [CONST_INDEX_AVATAR_TEXCOORD] = {}
682 end
683
684 nickTable [CONST_INDEX_AVATAR_TEXCOORD][1] = l
685 nickTable [CONST_INDEX_AVATAR_TEXCOORD][2] = r
686 nickTable [CONST_INDEX_AVATAR_TEXCOORD][3] = t
687 nickTable [CONST_INDEX_AVATAR_TEXCOORD][4] = b
688
689 NickTag.callbacks:Fire ("NickTag_Update", CONST_INDEX_AVATAR_PATH)
690
691 if (not NickTag.send_scheduled) then
692 NickTag.send_scheduled = true
693 NickTag:ScheduleTimer ("SendPersona", 1)
694 end
695 end
696
697 return true
698 end
699
700 --> set the background
701 function NickTag:SetNicknameBackground (path, texcoord, color, silent)
702
703 if (not silent) then
704 assert (type (path) == "string", "NickTag 'SetNicknameBackground' expects a string on #1 argument.")
705 else
706 if (type (path) ~= "string") then
707 return
708 end
709 end
710
711 if (not texcoord) then
712 texcoord = {0, 1, 0, 1}
713 end
714
715 if (not color) then
716 color = {1, 1, 1}
717 end
718
719 local playerName = UnitName ("player")
720
721 local nickTable = NickTag:GetNicknameTable (playerName)
722 if (not nickTable) then
723 nickTable = NickTag:Create (playerName, true)
724 end
725
726 local need_sync = false
727 if (nickTable [CONST_INDEX_BACKGROUND_PATH] ~= path) then
728 nickTable [CONST_INDEX_BACKGROUND_PATH] = path
729 need_sync = true
730 end
731
732 if (nickTable [CONST_INDEX_BACKGROUND_TEXCOORD] ~= texcoord) then
733 nickTable [CONST_INDEX_BACKGROUND_TEXCOORD] = texcoord
734 need_sync = true
735 end
736
737 if (nickTable [CONST_INDEX_BACKGROUND_COLOR] ~= color) then
738 nickTable [CONST_INDEX_BACKGROUND_COLOR] = color
739 need_sync = true
740 end
741
742 if (need_sync) then
743 NickTag.callbacks:Fire ("NickTag_Update", CONST_INDEX_BACKGROUND_PATH)
744
745 if (not NickTag.send_scheduled) then
746 NickTag.send_scheduled = true
747 NickTag:ScheduleTimer ("SendPersona", 1)
748 end
749 end
750
751 return true
752 end
753
754 function NickTag:GetNickname (playerName, default, silent)
755 if (not silent) then
756 assert (type (playerName) == "string", "NickTag 'GetNickname' expects a string or string on #1 argument.")
757 end
758
759 local _table = pool [playerName]
760 if (not _table) then
761 return default or nil
762 end
763 return _table [CONST_INDEX_NICKNAME] or default or nil
764 end
765
766 --> return the avatar and the texcoord.
767 function NickTag:GetNicknameAvatar (playerName, default, silent)
768 if (not silent) then
769 assert (type (playerName) == "string", "NickTag 'GetNicknameAvatar' expects a string or string on #1 argument.")
770 end
771
772 local _table = pool [playerName]
773
774 if (not _table and default) then
775 return default, {0, 1, 0, 1}
776 elseif (not _table) then
777 return "", {0, 1, 0, 1}
778 end
779 return _table [CONST_INDEX_AVATAR_PATH] or default or "", _table [CONST_INDEX_AVATAR_TEXCOORD] or {0, 1, 0, 1}
780 end
781
782 function NickTag:GetNicknameBackground (playerName, default_path, default_texcoord, default_color, silent)
783 if (not silent) then
784 assert (type (playerName) == "string", "NickTag 'GetNicknameBackground' expects a string or string on #1 argument.")
785 end
786
787 local _table = pool [playerName]
788 if (not _table) then
789 return default_path, default_texcoord, default_color
790 end
791 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
792 end
793
794 --> get the full nicktag table
795 function NickTag:GetNicknameTable (playerName, silent)
796 --> check data before
797 if (not silent) then
798 assert (type (playerName) == "string", "NickTag 'GetNicknameTable' expects a string on #1 argument.")
799 else
800 if (not playerName or type (playerName) ~= "string") then
801 return
802 end
803 end
804
805 return pool [playerName]
806 end
807
808------------------------------------------------------------------------------------------------------------------------------------------------------
809--> internal functions
810
811 --> create a empty nick table for the player
812 function NickTag:Create (playerName, isSelf)
813 --> check data before
814 assert (type (playerName) == "string", "NickTag 'Create' expects a string on #1 argument.")
815
816 --> check if alredy exists
817 local alredyHave = pool [playerName]
818 if (alredyHave) then
819 return alredyHave
820 end
821
822 --> create the table:
823 local newTable = {
824 UnitName ("player"), --[1] player nickname
825 false, --[2] avatar texture path
826 false, --[3] avatar texture coord
827 false, --[4] background texture path
828 false, --[5] background texcoord
829 false, --[6] background color
830 1 --[7] revision
831 }
832
833 --> if not my persona, set revision to 0, this make always get update after creation
834 if (not isSelf) then
835 newTable [CONST_INDEX_REVISION] = 0
836 end
837
838 pool [playerName] = newTable
839 return newTable
840 end
841
842 --> inc the revision of the player persona after update nick or avatar
843 function NickTag:IncRevision()
844 local playerName = UnitName ("player")
845 local nickTable = NickTag:GetNicknameTable (playerName)
846 if (not nickTable) then
847 nickTable = NickTag:Create (playerName, true)
848 end
849
850 nickTable [CONST_INDEX_REVISION] = nickTable [CONST_INDEX_REVISION] + 1
851
852 return true
853 end
854
855 --> convert GUID into serial number (deprecated, it uses player name - realm name)
856 function NickTag:GetSerial (serial, silent)
857 return 0
858 end
859
860 --> choose avatar window
861do
862 local avatar_pick_frame = CreateFrame ("frame", "AvatarPickFrame", UIParent)
863 avatar_pick_frame:SetFrameStrata ("DIALOG")
864 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}})
865 avatar_pick_frame:SetBackdropColor (.3, .3, .3, .9)
866 avatar_pick_frame:SetWidth (460)
867 avatar_pick_frame:SetHeight (240)
868
869 avatar_pick_frame.selected_avatar = 1
870 avatar_pick_frame.selected_background = 1
871 avatar_pick_frame.selected_color = {1, 1, 1}
872 avatar_pick_frame.selected_texcoord = {0, 1, 0, 1}
873
874 avatar_pick_frame:SetPoint ("center", UIParent, "center", 200, 0)
875 ---
876 local avatar_texture = avatar_pick_frame:CreateTexture ("AvatarPickFrameAvatarPreview", "overlay")
877 avatar_texture:SetPoint ("topleft", avatar_pick_frame, "topleft", 167, -10)
878 avatar_texture:SetTexture ([[Interface\EncounterJournal\UI-EJ-BOSS-Default]])
879 --
880 local background_texture = avatar_pick_frame:CreateTexture ("AvatarPickFrameBackgroundPreview", "artwork")
881 background_texture:SetPoint ("topleft", avatar_pick_frame, "topleft", 167, 2)
882 background_texture:SetWidth (290)
883 background_texture:SetHeight (75)
884 background_texture:SetTexture (NickTag.background_pool[1][1])
885 background_texture:SetTexCoord (unpack (NickTag.background_pool[1][3]))
886 --
887 local name = avatar_pick_frame:CreateFontString ("AvatarPickFrameName", "overlay", "GameFontHighlightHuge")
888 name:SetPoint ("left", avatar_texture, "right", -11, -17)
889 name:SetText (UnitName ("player"))
890 ---
891
892 local OnClickFunction = function (button)
893 if (button.isAvatar) then
894 local avatar = NickTag.avatar_pool [button.IconID]
895 _G.AvatarPickFrameAvatarPreview:SetTexture ( avatar [1] )
896 avatar_pick_frame.selected_avatar = avatar [1]
897 elseif (button.isBackground) then
898 local background = NickTag.background_pool [button.IconID]
899 _G.AvatarPickFrameBackgroundPreview:SetTexture ( background [1] )
900 _G.AvatarPickFrameBackgroundPreview:SetTexCoord (unpack (background [3]))
901 avatar_pick_frame.selected_background = background [1]
902 avatar_pick_frame.selected_texcoord = background [3]
903 end
904 end
905
906 local selectedColor = function()
907 local r, g, b = ColorPickerFrame:GetColorRGB()
908 background_texture:SetVertexColor (r, g, b)
909 avatar_pick_frame.selected_color[1] = r
910 avatar_pick_frame.selected_color[2] = g
911 avatar_pick_frame.selected_color[3] = b
912 end
913
914 local okey = CreateFrame ("button", "AvatarPickFrameAccept", avatar_pick_frame, "OptionsButtonTemplate")
915 okey:SetPoint ("bottomright", avatar_pick_frame, "bottomright", -37, 12)
916 okey:SetText ("Accept")
917 okey:SetFrameLevel (avatar_pick_frame:GetFrameLevel()+2)
918 okey:SetScript ("OnClick", function (self)
919 avatar_pick_frame:Hide()
920 if (avatar_pick_frame.callback) then
921 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)
922 end
923 end)
924 local change_color = CreateFrame ("button", "AvatarPickFrameColor", avatar_pick_frame, "OptionsButtonTemplate")
925 change_color:SetPoint ("bottomright", avatar_pick_frame, "bottomright", -205, 12)
926 change_color:SetText ("Color")
927 change_color:SetFrameLevel (avatar_pick_frame:GetFrameLevel()+2)
928
929 change_color:SetScript ("OnClick", function (self)
930 ColorPickerFrame.func = selectedColor
931 ColorPickerFrame.hasOpacity = false
932 ColorPickerFrame:SetParent (avatar_pick_frame)
933 ColorPickerFrame:SetColorRGB (_G.AvatarPickFrameBackgroundPreview:GetVertexColor())
934 ColorPickerFrame:ClearAllPoints()
935 ColorPickerFrame:SetPoint ("left", avatar_pick_frame, "right", 0, -10)
936 ColorPickerFrame:Show()
937 end)
938
939 local buttons = {}
940 for i = 0, 2 do
941 local newbutton = CreateFrame ("button", "AvatarPickFrameAvatarScrollButton"..i+1, avatar_pick_frame)
942 newbutton:SetScript ("OnClick", OnClickFunction)
943 newbutton:SetWidth (128)
944 newbutton:SetHeight (64)
945 newbutton:SetPoint ("topleft", avatar_pick_frame, "topleft", 15, (i*70*-1) - 20)
946 newbutton:SetID (i+1)
947 newbutton.isAvatar = true
948 buttons [#buttons+1] = newbutton
949 end
950
951 local buttonsbg = {}
952 for i = 0, 2 do
953 local newbutton = CreateFrame ("button", "AvatarPickFrameBackgroundScrollButton"..i+1, avatar_pick_frame)
954 newbutton:SetScript ("OnClick", OnClickFunction)
955 newbutton:SetWidth (275)
956 newbutton:SetHeight (60)
957 newbutton:SetPoint ("topleft", avatar_pick_frame, "topleft", 157, (i*50*-1) - 80)
958 newbutton:SetID (i+1)
959 newbutton.isBackground = true
960 buttonsbg [#buttonsbg+1] = newbutton
961 end
962
963 local avatar_list = CreateFrame ("ScrollFrame", "AvatarPickFrameAvatarScroll", avatar_pick_frame, "ListScrollFrameTemplate")
964 avatar_list:SetPoint ("topleft", avatar_pick_frame, "topleft", 10, -10)
965 local background_list = CreateFrame ("ScrollFrame", "AvatarPickFrameBackgroundScroll", avatar_pick_frame, "ListScrollFrameTemplate")
966 background_list:SetPoint ("topleft", avatar_pick_frame, "topleft", 147, -85)
967
968 avatar_list:SetWidth (128)
969 avatar_list:SetHeight (220)
970 background_list:SetWidth (275)
971 background_list:SetHeight (140)
972
973 local avatar_scroll_update = function (self)
974 local numMacroIcons = #NickTag.avatar_pool
975 local macroPopupIcon, macroPopupButton, index, texture
976 local macroPopupOffset = FauxScrollFrame_GetOffset (avatar_list)
977
978 for i = 1, 3 do
979 macroPopupIcon = _G ["AvatarPickFrameAvatarScrollButton"..i]
980 macroPopupButton = _G ["AvatarPickFrameAvatarScrollButton"..i]
981 index = (macroPopupOffset * 1) + i
982
983 texture = NickTag.avatar_pool [index][1]
984 if ( index <= numMacroIcons and texture ) then
985 macroPopupButton:SetNormalTexture (texture)
986 macroPopupButton:SetPushedTexture (texture)
987 macroPopupButton:SetDisabledTexture (texture)
988 macroPopupButton:SetHighlightTexture (texture, "ADD")
989 macroPopupButton.IconID = index
990 macroPopupButton:Show()
991 else
992 macroPopupButton:Hide()
993 end
994 end
995 FauxScrollFrame_Update (avatar_list, numMacroIcons , 3, 64)
996 end
997 local background_scroll_update = function (self)
998 local numMacroIcons = #NickTag.background_pool
999 local macroPopupIcon, macroPopupButton, index, texture
1000 local macroPopupOffset = FauxScrollFrame_GetOffset (background_list)
1001
1002 for i = 1, 3 do
1003 macroPopupIcon = _G ["AvatarPickFrameBackgroundScrollButton"..i]
1004 macroPopupButton = _G ["AvatarPickFrameBackgroundScrollButton"..i]
1005 index = (macroPopupOffset * 1) + i
1006
1007 texture = NickTag.background_pool [index][1]
1008 if ( index <= numMacroIcons and texture ) then
1009 macroPopupButton:SetNormalTexture (texture)
1010 macroPopupButton:SetPushedTexture (texture)
1011 macroPopupButton:SetDisabledTexture (texture)
1012 macroPopupButton:SetHighlightTexture (texture, "ADD")
1013 macroPopupButton.IconID = index
1014 macroPopupButton:Show()
1015 else
1016 macroPopupButton:Hide()
1017 end
1018 end
1019 FauxScrollFrame_Update (background_list, numMacroIcons , 3, 40)
1020 end
1021
1022 avatar_list:SetScript ("OnVerticalScroll", function (self, offset)
1023 FauxScrollFrame_OnVerticalScroll (avatar_list, offset, 64, avatar_scroll_update)
1024 end)
1025 background_list:SetScript ("OnVerticalScroll", function (self, offset)
1026 FauxScrollFrame_OnVerticalScroll (background_list, offset, 40, background_scroll_update)
1027 end)
1028
1029 avatar_scroll_update (avatar_list)
1030 background_scroll_update (background_list)
1031
1032 function avatar_pick_frame:SetAvatar (n)
1033 if (type (n) ~= "number") then
1034 n = 1
1035 end
1036 if (n > #NickTag.avatar_pool) then
1037 n = 1
1038 end
1039 local avatar = NickTag.avatar_pool [n]
1040 _G.AvatarPickFrameAvatarPreview:SetTexture ( avatar [1] )
1041 avatar_pick_frame.selected_avatar = avatar [1]
1042 end
1043 function avatar_pick_frame:SetBackground (n)
1044 if (type (n) ~= "number") then
1045 n = 1
1046 end
1047 if (n > #NickTag.background_pool) then
1048 n = 1
1049 end
1050 local background = NickTag.background_pool [n]
1051 _G.AvatarPickFrameBackgroundPreview:SetTexture ( background [1] )
1052 _G.AvatarPickFrameBackgroundPreview:SetTexCoord (unpack (background [3]))
1053 _G.AvatarPickFrameBackgroundPreview:SetVertexColor (unpack (avatar_pick_frame.selected_color))
1054 avatar_pick_frame.selected_background = background [1]
1055 end
1056 function avatar_pick_frame:SetColor (r, g, b)
1057 if (type (r) ~= "number" or r > 1) then
1058 r = 1
1059 end
1060 if (type (g) ~= "number" or g > 1) then
1061 g = 1
1062 end
1063 if (type (b) ~= "number" or b > 1) then
1064 b = 1
1065 end
1066 _G.AvatarPickFrameBackgroundPreview:SetVertexColor (r, g, b)
1067 avatar_pick_frame.selected_color[1] = r
1068 avatar_pick_frame.selected_color[2] = g
1069 avatar_pick_frame.selected_color[3] = b
1070 end
1071
1072 local CONST_INDEX_NICKNAME = 1
1073 local CONST_INDEX_AVATAR_PATH = 2
1074 local CONST_INDEX_AVATAR_TEXCOORD = 3
1075 local CONST_INDEX_BACKGROUND_PATH = 4
1076 local CONST_INDEX_BACKGROUND_TEXCOORD = 5
1077 local CONST_INDEX_BACKGROUND_COLOR = 6
1078
1079 avatar_pick_frame:SetScript ("OnShow", function()
1080 --get player avatar
1081 local avatar = NickTag:GetNicknameTable (UnitGUID ("player"))
1082 if (avatar) then
1083 _G.AvatarPickFrameName:SetText ( avatar [1] or UnitName ("player"))
1084
1085 _G.AvatarPickFrameAvatarPreview:SetTexture ( avatar [CONST_INDEX_AVATAR_PATH] or [[Interface\EncounterJournal\UI-EJ-BOSS-Default]] )
1086 avatar_pick_frame.selected_avatar = avatar [CONST_INDEX_AVATAR_PATH] or [[Interface\EncounterJournal\UI-EJ-BOSS-Default]]
1087
1088 _G.AvatarPickFrameAvatarPreview:SetTexCoord ( 0, 1, 0, 1 ) --> always
1089
1090 _G.AvatarPickFrameBackgroundPreview:SetTexture ( avatar [CONST_INDEX_BACKGROUND_PATH] or [[Interface\PetBattles\Weather-ArcaneStorm]] )
1091 avatar_pick_frame.selected_background = avatar [CONST_INDEX_BACKGROUND_PATH] or [[Interface\PetBattles\Weather-ArcaneStorm]]
1092
1093 if (avatar [CONST_INDEX_BACKGROUND_TEXCOORD]) then
1094 _G.AvatarPickFrameBackgroundPreview:SetTexCoord ( unpack (avatar [CONST_INDEX_BACKGROUND_TEXCOORD]) )
1095 avatar_pick_frame.selected_texcoord = avatar [CONST_INDEX_BACKGROUND_TEXCOORD]
1096 else
1097 _G.AvatarPickFrameBackgroundPreview:SetTexCoord ( 0.129609375, 1, 1, 0 )
1098 avatar_pick_frame.selected_texcoord = {0.129609375, 1, 1, 0}
1099 end
1100
1101 if (avatar [CONST_INDEX_BACKGROUND_COLOR]) then
1102 _G.AvatarPickFrameBackgroundPreview:SetVertexColor ( unpack (avatar [CONST_INDEX_BACKGROUND_COLOR]) )
1103 avatar_pick_frame.selected_color = avatar [CONST_INDEX_BACKGROUND_COLOR]
1104 else
1105 _G.AvatarPickFrameBackgroundPreview:SetVertexColor ( 1, 1, 1 )
1106 avatar_pick_frame.selected_color = {1, 1, 1}
1107 end
1108 else
1109 --> if none
1110 _G.AvatarPickFrameAvatarPreview:SetTexture ( [[Interface\EncounterJournal\UI-EJ-BOSS-Default]] )
1111 avatar_pick_frame.selected_avatar = [[Interface\EncounterJournal\UI-EJ-BOSS-Default]]
1112
1113 local background = NickTag.background_pool [1]
1114
1115 if (background) then
1116 _G.AvatarPickFrameBackgroundPreview:SetTexture ( background [1] )
1117 avatar_pick_frame.selected_background = background [1]
1118 _G.AvatarPickFrameBackgroundPreview:SetTexCoord (unpack (background [3]))
1119 avatar_pick_frame.selected_texcoord = background [3]
1120 _G.AvatarPickFrameBackgroundPreview:SetVertexColor (unpack (avatar_pick_frame.selected_color))
1121 avatar_pick_frame.selected_color = avatar_pick_frame.selected_color
1122 end
1123
1124 end
1125 end)
1126
1127 avatar_pick_frame:Hide()
1128end