· 6 years ago · Jul 26, 2019, 07:40 PM
1local NPC_Entry = 190009
2
3local RequireGold = 1
4local GoldModifier = 1.0
5local GoldCost = 100000
6
7local RequireToken = false
8local TokenEntry = 49426
9local TokenAmount = 1
10
11local AllowMixedArmorTypes = false
12local AllowMixedWeaponTypes = false
13
14local Qualities =
15{
16 [0] = false, -- AllowPoor
17 [1] = false, -- AllowCommon
18 [2] = true , -- AllowUncommon
19 [3] = true , -- AllowRare
20 [4] = true , -- AllowEpic
21 [5] = false, -- AllowLegendary
22 [6] = false, -- AllowArtifact
23 [7] = true , -- AllowHeirloom
24}
25
26local EQUIPMENT_SLOT_START = 0
27local EQUIPMENT_SLOT_HEAD = 0
28local EQUIPMENT_SLOT_NECK = 1
29local EQUIPMENT_SLOT_SHOULDERS = 2
30local EQUIPMENT_SLOT_BODY = 3
31local EQUIPMENT_SLOT_CHEST = 4
32local EQUIPMENT_SLOT_WAIST = 5
33local EQUIPMENT_SLOT_LEGS = 6
34local EQUIPMENT_SLOT_FEET = 7
35local EQUIPMENT_SLOT_WRISTS = 8
36local EQUIPMENT_SLOT_HANDS = 9
37local EQUIPMENT_SLOT_FINGER1 = 10
38local EQUIPMENT_SLOT_FINGER2 = 11
39local EQUIPMENT_SLOT_TRINKET1 = 12
40local EQUIPMENT_SLOT_TRINKET2 = 13
41local EQUIPMENT_SLOT_BACK = 14
42local EQUIPMENT_SLOT_MAINHAND = 15
43local EQUIPMENT_SLOT_OFFHAND = 16
44local EQUIPMENT_SLOT_RANGED = 17
45local EQUIPMENT_SLOT_TABARD = 18
46local EQUIPMENT_SLOT_END = 19
47
48local INVENTORY_SLOT_BAG_START = 19
49local INVENTORY_SLOT_BAG_END = 23
50
51local INVENTORY_SLOT_ITEM_START = 23
52local INVENTORY_SLOT_ITEM_END = 39
53
54local INVTYPE_CHEST = 5
55local INVTYPE_WEAPON = 13
56local INVTYPE_ROBE = 20
57local INVTYPE_WEAPONMAINHAND = 21
58local INVTYPE_WEAPONOFFHAND = 22
59
60local ITEM_CLASS_WEAPON = 2
61local ITEM_CLASS_ARMOR = 4
62
63local ITEM_SUBCLASS_WEAPON_BOW = 2
64local ITEM_SUBCLASS_WEAPON_GUN = 3
65local ITEM_SUBCLASS_WEAPON_CROSSBOW = 18
66local ITEM_SUBCLASS_WEAPON_FISHING_POLE = 20
67
68local EXPANSION_WOTLK = 2
69local EXPANSION_TBC = 1
70local PLAYER_VISIBLE_ITEM_1_ENTRYID
71local ITEM_SLOT_MULTIPLIER
72if GetCoreExpansion() < EXPANSION_TBC then
73 PLAYER_VISIBLE_ITEM_1_ENTRYID = 260
74 ITEM_SLOT_MULTIPLIER = 12
75elseif GetCoreExpansion() < EXPANSION_WOTLK then
76 PLAYER_VISIBLE_ITEM_1_ENTRYID = 346
77 ITEM_SLOT_MULTIPLIER = 16
78else
79 PLAYER_VISIBLE_ITEM_1_ENTRYID = 283
80 ITEM_SLOT_MULTIPLIER = 2
81end
82
83local INVENTORY_SLOT_BAG_0 = 255
84
85local SlotNames = {
86 [EQUIPMENT_SLOT_HEAD ] = {"Head", nil, nil, nil, nil, nil, nil, nil, nil},
87 [EQUIPMENT_SLOT_SHOULDERS ] = {"Shoulders", nil, nil, nil, nil, nil, nil, nil, nil},
88 [EQUIPMENT_SLOT_BODY ] = {"Shirt", nil, nil, nil, nil, nil, nil, nil, nil},
89 [EQUIPMENT_SLOT_CHEST ] = {"Chest", nil, nil, nil, nil, nil, nil, nil, nil},
90 [EQUIPMENT_SLOT_WAIST ] = {"Waist", nil, nil, nil, nil, nil, nil, nil, nil},
91 [EQUIPMENT_SLOT_LEGS ] = {"Legs", nil, nil, nil, nil, nil, nil, nil, nil},
92 [EQUIPMENT_SLOT_FEET ] = {"Feet", nil, nil, nil, nil, nil, nil, nil, nil},
93 [EQUIPMENT_SLOT_WRISTS ] = {"Wrists", nil, nil, nil, nil, nil, nil, nil, nil},
94 [EQUIPMENT_SLOT_HANDS ] = {"Hands", nil, nil, nil, nil, nil, nil, nil, nil},
95 [EQUIPMENT_SLOT_BACK ] = {"Back", nil, nil, nil, nil, nil, nil, nil, nil},
96 [EQUIPMENT_SLOT_MAINHAND ] = {"Main hand", nil, nil, nil, nil, nil, nil, nil, nil},
97 [EQUIPMENT_SLOT_OFFHAND ] = {"Off hand", nil, nil, nil, nil, nil, nil, nil, nil},
98 [EQUIPMENT_SLOT_RANGED ] = {"Ranged", nil, nil, nil, nil, nil, nil, nil, nil},
99 [EQUIPMENT_SLOT_TABARD ] = {"Tabard", nil, nil, nil, nil, nil, nil, nil, nil},
100}
101local Locales = {
102 {"Update menu", nil, nil, nil, nil, nil, nil, nil, nil},
103 {"Remove all transmogrifications", nil, nil, nil, nil, nil, nil, nil, nil},
104 {"Remove transmogrifications from all equipped items?", nil, nil, nil, nil, nil, nil, nil, nil},
105 {"Using this item for transmogrify will bind it to you and make it non-refundable and non-tradeable.\nDo you wish to continue?", nil, nil, nil, nil, nil, nil, nil, nil},
106 {"Remove transmogrification from %s?", nil, nil, nil, nil, nil, nil, nil, nil},
107 {"Back..", nil, nil, nil, nil, nil, nil, nil, nil},
108 {"Remove transmogrification", nil, nil, nil, nil, nil, nil, nil, nil},
109 {"Transmogrifications removed from equipped items", nil, nil, nil, nil, nil, nil, nil, nil},
110 {"You have no transmogrified items equipped", nil, nil, nil, nil, nil, nil, nil, nil},
111 {"%s transmogrification removed", nil, nil, nil, nil, nil, nil, nil, nil},
112 {"No transmogrification on %s slot", nil, nil, nil, nil, nil, nil, nil, nil},
113 {"%s transmogrified", nil, nil, nil, nil, nil, nil, nil, nil},
114 {"Selected items are not suitable", nil, nil, nil, nil, nil, nil, nil, nil},
115 {"Selected item does not exist", nil, nil, nil, nil, nil, nil, nil, nil},
116 {"Equipment slot is empty", nil, nil, nil, nil, nil, nil, nil, nil},
117 {"You don't have enough %ss", nil, nil, nil, nil, nil, nil, nil, nil},
118 {"Not enough money", nil, nil, nil, nil, nil, nil, nil, nil},
119}
120local function LocText(id, p) -- "%s":format("test")
121 if Locales[id] then
122 local s = Locales[id][p:GetDbcLocale()+1] or Locales[id][1]
123 if s then
124 return s
125 end
126 end
127 return "Text not found: "..(id or 0)
128end
129--[[
130typedef UNORDERED_MAP<uint32, uint32> transmogData
131typedef UNORDERED_MAP<uint32, transmogData> transmogMap
132static transmogMap entryMap -- entryMap[pGUID][iGUID] = entry
133static transmogData dataMap -- dataMap[iGUID] = pGUID
134]]
135local entryMap = {}
136local dataMap = {}
137
138local function GetSlotName(slot, locale)
139 if not SlotNames[slot] then return end
140 return locale and SlotNames[slot][locale+1] or SlotNames[slot][1]
141end
142
143local function GetFakePrice(item)
144 local sellPrice = item:GetSellPrice()
145 local minPrice = 10000
146 if sellPrice < minPrice then
147 sellPrice = minPrice
148 end
149 return sellPrice
150end
151
152local function GetFakeEntry(item)
153 local guid = item and item:GetGUIDLow()
154 if guid and dataMap[guid] then
155 if entryMap[dataMap[guid]] then
156 return entryMap[dataMap[guid]][guid]
157 end
158 end
159end
160
161local function DeleteFakeFromDB(itemGUID)
162 if dataMap[itemGUID] then
163 if entryMap[dataMap[itemGUID]] then
164 entryMap[dataMap[itemGUID]][itemGUID] = nil
165 end
166 dataMap[itemGUID] = nil
167 end
168 CharDBExecute("DELETE FROM custom_transmogrification WHERE GUID = "..itemGUID)
169end
170
171local function DeleteFakeEntry(item)
172 if not GetFakeEntry(item) then
173 return false
174 end
175 item:GetOwner():UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (item:GetSlot() * ITEM_SLOT_MULTIPLIER), item:GetEntry())
176 DeleteFakeFromDB(item:GetGUIDLow())
177 return true
178end
179
180local function SetFakeEntry(item, entry)
181 local player = item:GetOwner()
182 if player then
183 local pGUID = player:GetGUIDLow()
184 local iGUID = item:GetGUIDLow()
185 player:UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (item:GetSlot() * ITEM_SLOT_MULTIPLIER), entry)
186 if not entryMap[pGUID] then
187 entryMap[pGUID] = {}
188 end
189 entryMap[pGUID][iGUID] = entry
190 dataMap[iGUID] = pGUID
191 CharDBExecute("REPLACE INTO custom_transmogrification (GUID, FakeEntry, Owner) VALUES ("..iGUID..", "..entry..", "..pGUID..")")
192 end
193end
194
195local function IsRangedWeapon(Class, SubClass)
196 return Class == ITEM_CLASS_WEAPON and (
197 SubClass == ITEM_SUBCLASS_WEAPON_BOW or
198 SubClass == ITEM_SUBCLASS_WEAPON_GUN or
199 SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW)
200end
201
202local function SuitableForTransmogrification(player, transmogrified, transmogrifier)
203 if not transmogrified or not transmogrifier then
204 return false
205 end
206
207 if not Qualities[transmogrifier:GetQuality()] then
208 return false
209 end
210
211 if not Qualities[transmogrified:GetQuality()] then
212 return false
213 end
214
215 if transmogrified:GetDisplayId() == transmogrifier:GetDisplayId() then
216 return false
217 end
218
219 local fentry = GetFakeEntry(transmogrified)
220 if fentry and fentry == transmogrifier:GetEntry() then
221 return false
222 end
223
224 if not player:CanUseItem(transmogrifier) then
225 return false
226 end
227
228 local fierClass = transmogrifier:GetClass()
229 local fiedClass = transmogrified:GetClass()
230 local fierSubClass = transmogrifier:GetSubClass()
231 local fiedSubClass = transmogrified:GetSubClass()
232 local fierInventorytype = transmogrifier:GetInventoryType()
233 local fiedInventorytype = transmogrified:GetInventoryType()
234
235 if fiedInventorytype == INVTYPE_BAG or
236 fiedInventorytype == INVTYPE_RELIC or
237 -- fiedInventorytype == INVTYPE_BODY or
238 fiedInventorytype == INVTYPE_FINGER or
239 fiedInventorytype == INVTYPE_TRINKET or
240 fiedInventorytype == INVTYPE_AMMO or
241 fiedInventorytype == INVTYPE_QUIVER then
242 return false
243 end
244
245 if fierInventorytype == INVTYPE_BAG or
246 fierInventorytype == INVTYPE_RELIC or
247 -- fierInventorytype == INVTYPE_BODY or
248 fierInventorytype == INVTYPE_FINGER or
249 fierInventorytype == INVTYPE_TRINKET or
250 fierInventorytype == INVTYPE_AMMO or
251 fierInventorytype == INVTYPE_QUIVER then
252 return false
253 end
254
255 if fierClass ~= fiedClass then
256 return false
257 end
258
259 if IsRangedWeapon(fiedClass, fiedSubClass) ~= IsRangedWeapon(fierClass, fierSubClass) then
260 return false
261 end
262
263 if fierSubClass ~= fiedSubClass and not IsRangedWeapon(fiedClass, fiedSubClass) then
264 if fierClass == ITEM_CLASS_ARMOR and not AllowMixedArmorTypes then
265 return false
266 end
267 if fierClass == ITEM_CLASS_WEAPON and not AllowMixedWeaponTypes then
268 return false
269 end
270 end
271
272 if (fierInventorytype ~= fiedInventorytype) then
273 if (fierClass == ITEM_CLASS_WEAPON and not ((IsRangedWeapon(fiedClass, fiedSubClass) or
274 ((fiedInventorytype == INVTYPE_WEAPON or fiedInventorytype == INVTYPE_2HWEAPON) and
275 (fierInventorytype == INVTYPE_WEAPON or fierInventorytype == INVTYPE_2HWEAPON)) or
276 ((fiedInventorytype == INVTYPE_WEAPONMAINHAND or fiedInventorytype == INVTYPE_WEAPONOFFHAND) and
277 (fierInventorytype == INVTYPE_WEAPON or fierInventorytype == INVTYPE_2HWEAPON))))) then
278 return false
279 end
280 if (fierClass == ITEM_CLASS_ARMOR and
281 not ((fierInventorytype == INVTYPE_CHEST or fierInventorytype == INVTYPE_ROBE) and
282 (fiedInventorytype == INVTYPE_CHEST or fiedInventorytype == INVTYPE_ROBE))) then
283 return false
284 end
285 end
286
287 return true
288end
289
290local menu_id = math.random(1000)
291
292local function OnGossipHello(event, player, creature)
293 player:GossipClearMenu()
294 for slot = EQUIPMENT_SLOT_START, EQUIPMENT_SLOT_END-1 do
295 local transmogrified = player:GetItemByPos(INVENTORY_SLOT_BAG_0, slot)
296 if transmogrified then
297 if Qualities[transmogrified:GetQuality()] then
298 local slotName = GetSlotName(slot, player:GetDbcLocale())
299 if slotName then
300 player:GossipMenuAddItem(3, slotName, EQUIPMENT_SLOT_END, slot)
301 end
302 end
303 end
304 end
305 player:GossipMenuAddItem(4, LocText(2, player), EQUIPMENT_SLOT_END+2, 0, false, LocText(3, player), 0)
306 player:GossipMenuAddItem(7, LocText(1, player), EQUIPMENT_SLOT_END+1, 0)
307 player:GossipSendMenu(100, creature, menu_id)
308end
309
310local _items = {}
311local function OnGossipSelect(event, player, creature, slotid, uiAction)
312 if slotid == EQUIPMENT_SLOT_END then -- Show items you can use
313 local transmogrified = player:GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction)
314 if transmogrified then
315 local lowGUID = player:GetGUIDLow()
316 _items[lowGUID] = {} -- Remove this with logix
317 local limit = 0
318 local price = 0
319 if RequireGold == 1 then
320 price = GetFakePrice(transmogrified)*GoldModifier
321 elseif RequireGold == 2 then
322 price = GoldCost
323 end
324
325 for i = INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END-1 do
326 if limit > 30 then
327 break
328 end
329 local transmogrifier = player:GetItemByPos(INVENTORY_SLOT_BAG_0, i)
330 if transmogrifier then
331 local display = transmogrifier:GetDisplayId()
332 if SuitableForTransmogrification(player, transmogrified, transmogrifier) then
333 if not _items[lowGUID][display] then
334 limit = limit + 1
335 _items[lowGUID][display] = {transmogrifier:GetBagSlot(), transmogrifier:GetSlot()}
336 local popup = LocText(4, player).."\n\n"..transmogrifier:GetItemLink(player:GetDbcLocale()).."\n"
337 if RequireToken then
338 popup = popup.."\n"..TokenAmount.." x "..GetItemLink(TokenEntry, player:GetDbcLocale())
339 end
340 player:GossipMenuAddItem(4, transmogrifier:GetItemLink(player:GetDbcLocale()), uiAction, display, false, popup, price)
341 end
342 end
343 end
344 end
345
346 for i = INVENTORY_SLOT_BAG_START, INVENTORY_SLOT_BAG_END-1 do
347 local bag = player:GetItemByPos(INVENTORY_SLOT_BAG_0, i)
348 if bag then
349 for j = 0, bag:GetBagSize()-1 do
350 if limit > 30 then
351 break
352 end
353 local transmogrifier = player:GetItemByPos(i, j)
354 if transmogrifier then
355 local display = transmogrifier:GetDisplayId()
356 if SuitableForTransmogrification(player, transmogrified, transmogrifier) then
357 if not _items[lowGUID][display] then
358 limit = limit + 1
359 _items[lowGUID][display] = {transmogrifier:GetBagSlot(), transmogrifier:GetSlot()}
360 player:GossipMenuAddItem(4, transmogrifier:GetItemLink(player:GetDbcLocale()), uiAction, display, false, popup, price)
361 end
362 end
363 end
364 end
365 end
366 end
367
368 player:GossipMenuAddItem(4, LocText(7, player), EQUIPMENT_SLOT_END+3, uiAction, false, LocText(5, player):format(GetSlotName(uiAction, player:GetDbcLocale())))
369 player:GossipMenuAddItem(7, LocText(6, player), EQUIPMENT_SLOT_END+1, 0)
370 player:GossipSendMenu(100, creature, menu_id)
371 else
372 OnGossipHello(event, player, creature)
373 end
374 elseif slotid == EQUIPMENT_SLOT_END+1 then -- Back
375 OnGossipHello(event, player, creature)
376 elseif slotid == EQUIPMENT_SLOT_END+2 then -- Remove Transmogrifications
377 local removed = false
378 for slot = EQUIPMENT_SLOT_START, EQUIPMENT_SLOT_END-1 do
379 local transmogrifier = player:GetItemByPos(INVENTORY_SLOT_BAG_0, slot)
380 if transmogrifier then
381 if DeleteFakeEntry(transmogrifier) and not removed then
382 removed = true
383 end
384 end
385 end
386 if removed then
387 player:SendAreaTriggerMessage(LocText(8, player))
388 -- player:PlayDirectSound(3337)
389 else
390 player:SendNotification(LocText(9, player))
391 end
392 OnGossipHello(event, player, creature)
393 elseif slotid == EQUIPMENT_SLOT_END+3 then -- Remove Transmogrification from single item
394 local transmogrifier = player:GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction)
395 if transmogrifier then
396 if DeleteFakeEntry(transmogrifier) then
397 player:SendAreaTriggerMessage(LocText(10, player):format(GetSlotName(uiAction, player:GetDbcLocale())))
398 -- player:PlayDirectSound(3337)
399 else
400 player:SendNotification(LocText(11, player):format(GetSlotName(uiAction, player:GetDbcLocale())))
401 end
402 end
403 OnGossipSelect(event, player, creature, EQUIPMENT_SLOT_END, uiAction)
404 else -- Transmogrify
405 local lowGUID = player:GetGUIDLow()
406 if not RequireToken or player:GetItemCount(TokenEntry) >= TokenAmount then
407 local transmogrified = player:GetItemByPos(INVENTORY_SLOT_BAG_0, slotid)
408 if transmogrified then
409 if _items[lowGUID] and _items[lowGUID][uiAction] and _items[lowGUID][uiAction] then
410 local transmogrifier = player:GetItemByPos(_items[lowGUID][uiAction][1], _items[lowGUID][uiAction][2])
411 if transmogrifier:GetOwnerGUID() == player:GetGUID() and (transmogrifier:IsInBag() or transmogrifier:GetBagSlot() == INVENTORY_SLOT_BAG_0) and SuitableForTransmogrification(player, transmogrified, transmogrifier) then
412 local price
413 if RequireGold == 1 then
414 price = GetFakePrice(transmogrified)*GoldModifier
415 elseif RequireGold == 2 then
416 price = GoldCost
417 end
418 if not price or player:GetCoinage() >= price then
419 if price then
420 player:ModifyMoney(-price)
421 end
422 if RequireToken then
423 player:RemoveItem(TokenEntry, TokenAmount)
424 end
425 SetFakeEntry(transmogrified, transmogrifier:GetEntry())
426 -- transmogrifier:SetNotRefundable(player)
427 transmogrifier:SetBinding(true)
428 -- player:PlayDirectSound(3337)
429 player:SendAreaTriggerMessage(LocText(12, player):format(GetSlotName(slotid, player:GetDbcLocale())))
430 else
431 player:SendNotification(LocText(17, player))
432 end
433 else
434 player:SendNotification(LocText(13, player))
435 end
436 else
437 player:SendNotification(LocText(14, player))
438 end
439 else
440 player:SendNotification(LocText(15, player))
441 end
442 else
443 player:SendNotification(LocText(16, player):format(GetItemLink(TokenEntry, player:GetDbcLocale())))
444 end
445 _items[lowGUID] = {}
446 OnGossipSelect(event, player, creature, EQUIPMENT_SLOT_END, slotid)
447 end
448end
449
450local function OnLogin(event, player)
451 local playerGUID = player:GetGUIDLow()
452 entryMap[playerGUID] = {}
453 local result = CharDBQuery("SELECT GUID, FakeEntry FROM custom_transmogrification WHERE Owner = "..playerGUID)
454 if result then
455 repeat
456 local itemGUID = result:GetUInt32(0)
457 local fakeEntry = result:GetUInt32(1)
458 -- if sObjectMgr:GetItemTemplate(fakeEntry) then
459 -- {
460 dataMap[itemGUID] = playerGUID
461 entryMap[playerGUID][itemGUID] = fakeEntry
462 -- }
463 -- else
464 -- sLog:outError(LOG_FILTER_SQL, "Item entry (Entry: %u, itemGUID: %u, playerGUID: %u) does not exist, deleting.", fakeEntry, itemGUID, playerGUID)
465 -- Transmogrification::DeleteFakeFromDB(itemGUID)
466 -- end
467 until not result:NextRow()
468
469 for slot = EQUIPMENT_SLOT_START, EQUIPMENT_SLOT_END-1 do
470 local item = player:GetItemByPos(INVENTORY_SLOT_BAG_0, slot)
471 if item then
472 if entryMap[playerGUID] then
473 if entryMap[playerGUID][item:GetGUIDLow()] then
474 player:UpdateUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (item:GetSlot() * ITEM_SLOT_MULTIPLIER), entryMap[playerGUID][item:GetGUIDLow()])
475 end
476 end
477 end
478 end
479 end
480end
481
482local function OnLogout(event, player)
483 local pGUID = player:GetGUIDLow()
484 entryMap[pGUID] = nil
485end
486
487local function OnEquip(event, player, item, bag, slot)
488 local fentry = GetFakeEntry(item)
489 if fentry then
490 if item:GetOwnerGUID() ~= player:GetGUID() then
491 DeleteFakeFromDB(item:GetGUIDLow())
492 return
493 end
494 player:SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * ITEM_SLOT_MULTIPLIER), fentry)
495 end
496end
497
498-- Note, Query is instant when Execute is delayed
499CharDBQuery([[
500CREATE TABLE IF NOT EXISTS `custom_transmogrification` (
501`GUID` INT(10) UNSIGNED NOT NULL COMMENT 'Item guidLow',
502`FakeEntry` INT(10) UNSIGNED NOT NULL COMMENT 'Item entry',
503`Owner` INT(10) UNSIGNED NOT NULL COMMENT 'Player guidLow',
504PRIMARY KEY (`GUID`)
505)
506COMMENT='version 4.0'
507COLLATE='latin1_swedish_ci'
508ENGINE=InnoDB;
509]])
510
511print("Deleting non-existing transmogrification entries...")
512CharDBQuery("DELETE FROM custom_transmogrification WHERE NOT EXISTS (SELECT 1 FROM item_instance WHERE item_instance.guid = custom_transmogrification.GUID)")
513
514RegisterPlayerEvent(3, OnLogin)
515RegisterPlayerEvent(4, OnLogout)
516RegisterPlayerEvent(29, OnEquip)
517
518-- Test code
519--RegisterPlayerEvent(18, function(e,p,m,t,l) if m == "test" then OnGossipHello(e,p,p) end end)
520--RegisterPlayerGossipEvent(menu_id, 2, OnGossipSelect)
521
522RegisterCreatureGossipEvent(NPC_Entry, 1, OnGossipHello)
523RegisterCreatureGossipEvent(NPC_Entry, 2, OnGossipSelect)
524
525local plrs = GetPlayersInWorld()
526if plrs then
527 for k, player in ipairs(plrs) do
528 OnLogin(k, player)
529 end
530end