Advertisement
Rochet2

Lua transmogrification

Aug 17th, 2012
1,891
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.23 KB | None | 0 0
  1. local NPCENTRY = 123123 -- Your NPC's entry
  2.  
  3. -- Warning! Executes quite some code. Delay in milliseconds. (applies transmogs)
  4. local DELAY = 500 -- 500 (best visual update, very low population), 1000 (good visual update, very low population), 2000+ (slow visual update, medium  to high population)
  5.  
  6. -- DO NOT TOUCH ANYTHING BELOW!
  7.  
  8. -- Transmog table and functions.
  9. local Transmogs, Hello, Select, AddTransmog, RemoveTransmog, GetValidSources, LoadTransmogs, ApplyTransmogs
  10.  
  11. -- Key0 is the key for inv_slots table, which contains the slotID. Key0 is also used for the inv_slot_names table
  12. local inv_slots =       {0,         2,              4,          5,          6,      7,      8,          9,          14,     15,             16,         17}
  13. local inv_slot_names =  {"Head",    "Shoulders",    "Chest",    "Waist",    "Legs", "Feet", "Wrists",   "Hands",    "Back", "Main hand",    "Off hand", "Ranged"}
  14.  
  15. local INV_BAG, INV_START, INV_END = 255, 1, #inv_slots
  16. local VISIBLE_ITEM_ENTRY_0 = 283
  17. local BAGS =
  18. {
  19.     {BAG = INV_BAG, START = 23, END = 38},
  20.     {BAG = 19, START = 0, END = 35},
  21.     {BAG = 20, START = 0, END = 35},
  22.     {BAG = 21, START = 0, END = 35},
  23.     {BAG = 22, START = 0, END = 35},
  24. }
  25.  
  26. -- bags -1 inventory and backpack, 19-22 other bags
  27. -- slots 0-18 equipment
  28. -- slots 19-22 bags
  29. -- slots 23-38 backpack
  30. -- slots 0-35 other bags
  31.  
  32. local space = 20
  33. local opt_space = 100
  34. local opt_amount = 13 -- Warning! Do not use over 30
  35.  
  36. local Data = {}
  37.  
  38. function Hello(unit, event, player)
  39.     Data[tostring(player:GetGUID())] = nil
  40.     unit:GossipCreateMenu(100, player, 0)
  41.     for Key0 = INV_START, INV_END do
  42.         unit:GossipMenuAddItem(3, inv_slot_names[Key0], Key0+space, 0, "", 0)
  43.     end
  44.     unit:GossipMenuAddItem(4, "Remove all transmogrifications", 0, 0, "Remove transmogrifications from equipped items?", 0)
  45.     unit:GossipSendMenu(player)
  46. end
  47.  
  48. function Select(unit, event, player, id, intid, code)
  49.     local pGUID = tostring(player:GetGUID())
  50.     if(intid == 0) then -- remove all transmogs
  51.         for Key0 = INV_START, INV_END do
  52.             RemoveTransmog(inv_slots[Key0], player)
  53.         end
  54.         player:SendAreaTriggerMessage("Transmogrifications removed")
  55.         Hello(unit, event, player)
  56.     elseif(intid == 1) then
  57.         Hello(unit, event, player)
  58.     elseif(intid > INV_START and intid <= INV_END+1) then -- remove one transmog
  59.         RemoveTransmog(inv_slots[intid-1], player)
  60.         player:SendAreaTriggerMessage("Transmogrification removed from "..inv_slot_names[intid-1])
  61.         Select(unit, event, player, id, intid+space-1, code)
  62.     elseif(intid >= INV_START+space and intid <= INV_END+space) then
  63.         local Key0 = intid-space
  64.         local sources = GetValidSources(inv_slots[Key0], player)
  65.         if(not sources) then
  66.             player:SendAreaTriggerMessage("No item in that slot")
  67.             Hello(unit, event, player)
  68.         elseif(#sources < 2) then
  69.             player:SendAreaTriggerMessage("No suitable items in bags")
  70.             Hello(unit, event, player)
  71.         else
  72.             Data[pGUID] = {Key0, sources}
  73.             unit:GossipCreateMenu(100, player, 0)
  74.             for k = 1, #sources-1 do
  75.                 unit:GossipMenuAddItem(4, sources[k]:GetName(), k+INV_END+space, 0, "", 0)
  76.             end
  77.             unit:GossipMenuAddItem(4, "Remove transmogrification from "..inv_slot_names[Key0], Key0+1, 0, "Remove transmogrif ication from "..inv_slot_names[Key0].."?", 0)
  78.             unit:GossipMenuAddItem(7, "Back..", 1, 0, "", 0)
  79.             unit:GossipSendMenu(player)
  80.         end
  81.     elseif(intid > INV_END+space and intid <= INV_END+space+opt_amount) then
  82.         local slot = inv_slots[Data[pGUID][1]]
  83.         local target = player:GetInventoryItem(INV_BAG, slot)
  84.         local origGUID = Data[pGUID][2][#Data[pGUID][2]] -- no cheating with swapping items on the fly
  85.         if(target and tostring(target:GetGUID()) == origGUID) then
  86.             local source = Data[pGUID][2][intid-INV_END-space]
  87.             if(source and source:GetOwner():IsInWorld() and pGUID == tostring(source:GetOwner():GetGUID())) then
  88.                 AddTransmog(slot, player, source:GetEntryId())
  89.                 player:SendAreaTriggerMessage(inv_slot_names[Data[pGUID][1]].." transmogrified")
  90.             else
  91.                 player:SendAreaTriggerMessage("Source item is not in bags")
  92.             end
  93.         else
  94.             player:SendAreaTriggerMessage("Target item was unequipped")
  95.         end
  96.         Select(unit, event, player, id, Data[pGUID][1]+space, code)
  97.     end
  98. end
  99.  
  100. function AddTransmog(slot, player, fake)
  101.     local item = player:GetInventoryItem(INV_BAG, slot)
  102.     if (item) then
  103.         local pGUID, iGUID = tostring(player:GetGUID()), tostring(item:GetGUID())
  104.         player:SetUInt32Value(VISIBLE_ITEM_ENTRY_0+(slot * 2), fake)
  105.         if (not Transmogs[pGUID]) then
  106.             Transmogs[pGUID] = {}
  107.         end
  108.         if (not Transmogs[pGUID][slot]) then
  109.             Transmogs[pGUID][slot] = {}
  110.         end
  111.         Transmogs[pGUID][slot][iGUID] = fake
  112.         CharDBQuery('REPLACE INTO Transmog_items (player_GUID, item_GUID, slot, fake) VALUES ("'..pGUID..'", "'..iGUID..'", '..slot..', '..fake..')')
  113.         return true
  114.     end
  115.     return false
  116. end
  117.  
  118. function RemoveTransmog(slot, player)
  119.     local pGUID = tostring(player:GetGUID())
  120.     if (Transmogs[pGUID] and Transmogs[pGUID][slot]) then
  121.         local item = player:GetInventoryItem(INV_BAG, slot)
  122.         if (item) then
  123.             local iGUID = tostring(item:GetGUID())
  124.             if (Transmogs[pGUID][slot][iGUID]) then
  125.                 player:SetUInt32Value(VISIBLE_ITEM_ENTRY_0+(slot * 2), item:GetEntryId())
  126.                 Transmogs[pGUID][slot][iGUID] = nil
  127.                 CharDBQuery('DELETE FROM Transmog_items WHERE item_GUID = "'..iGUID..'"')
  128.                 return true
  129.             end
  130.         end
  131.     end
  132.     return false
  133. end
  134.  
  135. function GetValidSources(inv_slot, player) -- returns nil or a table containing the items (can be empty)
  136.     local item = player:GetInventoryItem(INV_BAG, inv_slot)
  137.     if (not item) then return nil end
  138.     local items = {}
  139.     local entries = {}
  140.     local hasitems = false
  141.     for k, DATA in ipairs(BAGS) do
  142.         if (DATA.BAG == INV_BAG or player:GetInventoryItem(INV_BAG, DATA.BAG)) then -- skip nonexistant bags
  143.             for slot = DATA.START, DATA.END do
  144.                 local item = player:GetInventoryItem(DATA.BAG, slot)
  145.                 if(item) then
  146.                     table.insert(entries, item:GetEntryId())
  147.                     items[item:GetEntryId()] = item
  148.                     if (not hasitems) then hasitems = true end
  149.                 end
  150.             end
  151.         end
  152.     end
  153.     if (hasitems) then
  154.         local Q = WorldDBQuery("SELECT inventorytype FROM items WHERE entry = "..item:GetEntryId())
  155.         if (Q) then
  156.             local Q = WorldDBQuery("SELECT entry FROM items WHERE entry IN("..table.concat(entries, ',')..") and inventorytype = "..Q:GetColumn(0):GetULong().." LIMIT "..opt_amount)
  157.             if (Q) then
  158.                 local suitable = {}
  159.                 for i = 1, Q:GetRowCount() do
  160.                     table.insert(suitable, items[Q:GetColumn(0):GetULong()]) -- Could possibly add performance if we let this security off
  161.                     Q:NextRow()
  162.                 end
  163.                 table.insert(suitable, tostring(item:GetGUID()))
  164.                 return suitable
  165.             end
  166.         end
  167.     end
  168.     return {}
  169. end
  170.  
  171. function LoadTransmogs()
  172.     local Time = os.time()
  173.     print("Loading transmogrifications..")
  174.     Transmogs = {}
  175.     -- CharDBQuery("DELETE FROM transmog_items WHERE NOT EXISTS (SELECT 1 FROM playeritems WHERE item_GUID = guid) OR NOT EXISTS (SELECT 1 FROM characters WHERE player_GUID = guid)") -- cleanup before load
  176.     local Q = CharDBQuery("SELECT player_GUID, item_GUID, slot, fake FROM Transmog_items")
  177.     if (Q) then
  178.         for i = 1, Q:GetRowCount() do
  179.             local pGUID, iGUID, slot, fake = Q:GetColumn(0):GetString(), Q:GetColumn(1):GetString(), Q:GetColumn(2):GetULong(), Q:GetColumn(3):GetULong()
  180.             if (not Transmogs[pGUID]) then
  181.                 Transmogs[pGUID] = {}
  182.             end
  183.             if (not Transmogs[pGUID][slot]) then
  184.                 Transmogs[pGUID][slot] = {}
  185.             end
  186.             Transmogs[pGUID][slot][iGUID] = fake
  187.             Q:NextRow()
  188.         end
  189.     end
  190.     print("Transmogrifications loaded in "..(os.time()-Time).." seconds")
  191. end
  192.  
  193. function ApplyTransmogs() -- minimum looping and checking
  194.     local players = GetPlayersInWorld()
  195.     for k, player in ipairs(players) do -- loop players
  196.         if (player and player:IsInWorld()) then -- player exists
  197.             local pGUID = tostring(player:GetGUID())
  198.             if (Transmogs[pGUID]) then -- has transmogs
  199.                 for slot, Data in pairs(Transmogs[pGUID]) do -- looop transmog slots
  200.                     local item = player:GetInventoryItem(INV_BAG, slot)
  201.                     if (item) then -- has item in slot
  202.                         local iGUID = tostring(item:GetGUID())
  203.                         if(Data[iGUID]) then -- check if item has transmog saved
  204.                             player:SetUInt32Value(283+(slot * 2), Data[iGUID]) -- apply transmog
  205.                         end
  206.                     end
  207.                 end
  208.             end
  209.         end
  210.     end
  211. end
  212.  
  213. RegisterUnitGossipEvent(NPCENTRY, 1, Hello)
  214. RegisterUnitGossipEvent(NPCENTRY, 2, Select)
  215. LoadTransmogs()
  216. CreateLuaEvent(ApplyTransmogs, DELAY, 0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement