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