Guest User

Untitled

a guest
Jan 20th, 2017
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.81 KB | None | 0 0
  1. REWARD_CHEST = {
  2.     BOSSES = {"bibby bloodbath", "chizzoron the distorter", "ferumbras",
  3.             "furyosa", "gaz'haragoth", "ghazbaran", "hirintror",
  4.             "jaul", "mad mage", "mawhawk", "morgaroth", "obujos",
  5.             "ocyakao", "omrafir", "orshabaal", "raging mage",
  6.             "tanjis", "the mutated pumpkin", "the pale count",
  7.             "the welter", "tyrn", "white pale", "zulazza the corruptor",
  8.             "zushuka"},
  9.     LOOT = {},         
  10.     DECAY = {},
  11.     DEPOT_ID = 99,
  12.     CONTAINER = 21518,
  13.     ENCODE = true,          --encode stored rewards on db?
  14.     EXPIRE = 7*24*60*60,    --days to erase stored rewards
  15.     STORAGE = 18394,        --player storage for chest exhaustion
  16.     EXHAUST = 5*60,         --time allowed to use again the chest
  17. }
  18.  
  19. -- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss <alexthkloss@web.de>
  20. -- licensed under the terms of the LGPL2
  21.  
  22. -- character table string
  23. local enc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  24.  
  25. function string.encode(str)
  26.     return ((str:gsub('.', function(x)
  27.         local r,enc='',x:byte()
  28.         for i=8,1,-1 do r=r..(enc%2^i-enc%2^(i-1)>0 and '1' or '0') end
  29.         return r;
  30.     end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
  31.         if (#x < 6) then return '' end
  32.         local c=0
  33.         for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
  34.         return enc:sub(c+1,c+1)
  35.     end)..({ '', '==', '=' })[#str%3+1])
  36. end
  37.  
  38. function string.decode(str)
  39.     str = string.gsub(str, '[^'.. enc ..'=]', '')
  40.     return (str:gsub('.', function(x)
  41.         if (x == '=') then return '' end
  42.         local r,f='',(enc:find(x)-1)
  43.         for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
  44.         return r;
  45.     end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
  46.         if (#x ~= 8) then return '' end
  47.         local c=0
  48.         for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
  49.         return string.char(c)
  50.     end))
  51. end
  52.  
  53. function table.find(t, value, sensitive)
  54.     local sensitive = sensitive or true
  55.     if(not sensitive and type(value) == 'string') then
  56.         for i, v in pairs(t) do
  57.             if(type(v) == 'string') then
  58.                 if(v:lower() == value:lower()) then
  59.                     return i
  60.                 end
  61.             end
  62.         end
  63.         return nil
  64.     end
  65.     for i, v in pairs(t) do
  66.         if(v == value) then
  67.             return i
  68.         end
  69.     end
  70.     return nil
  71. end
  72.  
  73. function table.serialize(x, recur)
  74.     local t = type(x)
  75.     recur = recur or {}
  76.     if(t == nil) then
  77.         return "nil"
  78.     elseif(t == "string") then
  79.         return string.format("%q", x)
  80.     elseif(t == "number") then
  81.         return tostring(x)
  82.     elseif(t == "boolean") then
  83.         return x and "true" or "false"
  84.     elseif(getmetatable(x)) then
  85.         error("Can not serialize a table that has a metatable associated with it.")
  86.     elseif(t == "table") then
  87.         if(table.find(recur, x)) then
  88.             error("Can not serialize recursive tables.")
  89.         end
  90.         table.insert(recur, x)
  91.         local s = "{"
  92.         for k, v in pairs(x) do
  93.             s = s .. "[" .. table.serialize(k, recur) .. "]" .. " = " .. table.serialize(v, recur) .. ", "
  94.         end
  95.         return s:sub(0, s:len() - 2) .. "}"
  96.     end
  97.     error("Can not serialize value of type '" .. t .. "'.")
  98. end
  99.  
  100. function table.unserialize(str)
  101.     return loadstring('return ' .. str)()
  102. end
  103.  
  104. function serialize(t)
  105.     return REWARD_CHEST.ENCODE and string.encode(table.serialize(t)) or table.serialize(t)
  106. end
  107.  
  108. function unserialize(str)
  109.     return REWARD_CHEST.ENCODE and table.unserialize(string.decode(str)) or table.unserialize(str)
  110. end
  111.  
  112. function addContainerItems(container, items)
  113.     for k, v in pairs(items) do
  114.         if ItemType(k):isContainer() then
  115.             local newBag = Container(doCreateItemEx(k, 1))
  116.             addContainerItems(newBag, v)
  117.             container:addItemEx(newBag)
  118.         else
  119.             container:addItem(v[1], v[2])
  120.         end
  121.     end
  122. end
  123.  
  124. function MonsterType.createLootItem(self, lootBlock, chance)
  125.     local lootTable, itemCount = {}, 0
  126.     local randvalue = math.random(0, 100000) / (getConfigInfo("rateLoot") * chance)
  127.     if randvalue < lootBlock.chance then
  128.         if (ItemType(lootBlock.itemId):isStackable()) then
  129.             itemCount = randvalue % lootBlock.maxCount + 1
  130.         else
  131.             itemCount = 1
  132.         end
  133.     end
  134.  
  135.     while itemCount > 0 do
  136.         local n = math.min(itemCount, 100)
  137.         itemCount = itemCount - n
  138.         table.insert(lootTable, {lootBlock.itemId, n})
  139.     end
  140.  
  141.     return lootTable
  142. end
  143.  
  144. function MonsterType.getBossReward(self, chance)
  145.     local result = {}
  146.     if getConfigInfo("rateLoot") > 0 then
  147.         for _, loot in pairs(self:getLoot()) do
  148.             local itemList = self:createLootItem(loot, chance)
  149.             if itemList then
  150.                 for _, item in ipairs(itemList) do
  151.                     table.insert(result, item)
  152.                 end
  153.             end
  154.         end
  155.     end
  156.     return result
  157. end
  158.  
  159. function getDecayTime(id, name)
  160.     local decayTime = 0
  161.     do
  162.         local o = io.open('data/items/items.xml','r')
  163.         file = o:read('*a')
  164.         o:close()
  165.     end
  166.     local function sumDecayTime(corpse)
  167.         for attr in file:gmatch('<item.-id="' .. corpse ..'"(.-)</item>') do
  168.             local decayTo = attr:match('<attribute.-key="decayTo".-value="(.-)".-/>')
  169.             local duration = attr:match('<attribute.-key="duration".-value="(.-)".-/>')
  170.             decayTime = decayTime + duration
  171.             if decayTime > 3000 then
  172.                 print("[Warning - RewardChest] Decay time for corpse of " .. name .." is infinite - using 3000 instead")
  173.                 return 3000
  174.             end        
  175.             if tonumber(decayTo) > 0 then
  176.                 sumDecayTime(decayTo)
  177.             end
  178.             break
  179.         end
  180.     end
  181.     sumDecayTime(id)
  182.     return decayTime
  183. end
  184.  
  185. function loadCorpses()
  186.     for _, name in ipairs(REWARD_CHEST.BOSSES) do
  187.         if MonsterType(name) ~= nil then
  188.             REWARD_CHEST.DECAY[name] = getDecayTime(MonsterType(name):getCorpseId(), name)
  189.         end
  190.     end
  191. end
  192. addEvent(loadCorpses, 0)
  193.  
  194. function getPlayerByGUID(guid)
  195.     for _, player in ipairs(Game.getPlayers()) do
  196.         if guid == player:getGuid() then
  197.             return player
  198.         end
  199.     end
  200.     return nil
  201. end
  202.  
  203. function Player.addReward(self, reward, time, id)
  204.     local LootBag = Container(doCreateItemEx(REWARD_CHEST.CONTAINER, 1))
  205.     LootBag:setAttribute('text', time)
  206.     addContainerItems(LootBag, reward)
  207.     if id then
  208.         db.query('DELETE FROM player_rewardchest WHERE id = ' .. id .. ';')
  209.     end
  210.     return self:getDepotChest(REWARD_CHEST.DEPOT_ID, true):addItemEx(LootBag)
  211. end
  212.  
  213. function doSaveReward(uid, name)
  214.     for GUID, items in pairs(REWARD_CHEST.LOOT[uid]) do
  215.         local player = getPlayerByGUID(GUID)
  216.         if player ~= nil then
  217.             player:addReward(items, os.time())
  218.             player:sendTextMessage(MESSAGE_INFO_DESCR, 'Your reward container from ' .. name .. ' was moved to your reward chest.')
  219.         else
  220.             db.query('INSERT INTO player_rewardchest VALUES (NULL, ' .. GUID ..', "' .. serialize(items) ..'", ' .. os.time() ..');')
  221.         end
  222.     end
  223.     REWARD_CHEST.LOOT[uid] = nil
  224. end
  225.  
  226. function Player.updateRewardChest(self)
  227.     db.query('DELETE FROM player_rewardchest WHERE TIME_TO_SEC(TIMEDIFF(NOW(), FROM_UNIXTIME(date))) >= '.. REWARD_CHEST.EXPIRE ..';')
  228.     local Query = db.storeQuery('SELECT id, reward, date FROM player_rewardchest WHERE player_id = '.. self:getGuid() ..';')
  229.     if Query ~= false then
  230.         repeat
  231.             local rewardBag = unserialize(result.getDataString(Query, 'reward'))
  232.             self:addReward(rewardBag, result.getDataInt(Query, 'date'), result.getDataInt(Query, 'id'))
  233.         until not result.next(Query)
  234.         result.free(Query)
  235.     end
  236.     local depotChest = self:getDepotChest(REWARD_CHEST.DEPOT_ID, true)
  237.     for index = (depotChest:getSize() - 1), 0, -1 do
  238.         local container = depotChest:getItem(index)
  239.         if (container:getAttribute('text') ~= nil) and (tonumber(container:getAttribute('text')) + REWARD_CHEST.EXPIRE < os.time()) then
  240.             container:remove()
  241.         end
  242.     end
  243.     return self:setExhaustion(REWARD_CHEST.STORAGE, REWARD_CHEST.EXHAUST)
  244. end
  245.  
  246. function string.diff(self)
  247.     local format = {
  248.         {'day', self / 60 / 60 / 24},
  249.         {'hour', self / 60 / 60 % 24},
  250.         {'minute', self / 60 % 60},
  251.         {'second', self % 60}
  252.     }
  253.  
  254.     local out = {}
  255.     for k, t in ipairs(format) do
  256.         local v = math.floor(t[2])
  257.         if(v > 0) then
  258.             table.insert(out, (k < #format and (#out > 0 and ', ' or '') or ' and ') .. v .. ' ' .. t[1] .. (v ~= 1 and 's' or ''))
  259.         end
  260.     end
  261.     local ret = table.concat(out)
  262.     if ret:len() < 16 and ret:find('second') then
  263.         local a, b = ret:find(' and ')
  264.         ret = ret:sub(b+1)
  265.     end
  266.     return ret
  267. end
  268.  
  269. function doBossReward(monster, corpse)
  270.     REWARD_CHEST.LOOT[corpse:getUniqueId()] = {}
  271.     corpse:setAttribute('aid', 21584)
  272.     corpse:setAttribute('text', corpse:getUniqueId())
  273.     for killer, damage in pairs(monster:getDamageMap()) do
  274.         local player, str = Player(killer), 'Loot of ' .. MonsterType(monster:getName()):getNameDescription() .. ': '
  275.         if player ~= nil then
  276.             local rewardBag = doCreateItemEx(REWARD_CHEST.CONTAINER)
  277.             if player:getStamina() > 840 then
  278.                 local loot = MonsterType(monster:getName()):getBossReward(damage.total/monster:getMaxHealth())
  279.                 if #loot > 0 then
  280.                     addContainerItems(Container(rewardBag), loot)
  281.                     REWARD_CHEST.LOOT[corpse:getUniqueId()][player:getGuid()] = loot
  282.                     str = str .. Container(rewardBag):getContentDescription()
  283.                 else
  284.                     str = str .. 'nothing'
  285.                 end
  286.             else
  287.                 str = str .. 'nothing (due to low stamina)'
  288.             end
  289.             player:sendTextMessage(MESSAGE_INFO_DESCR, str .. '.')
  290.         end
  291.     end
  292.     addEvent(doSaveReward, REWARD_CHEST.DECAY[monster:getName():lower()]*1000, corpse:getUniqueId(), MonsterType(monster:getName()):getNameDescription())
  293. end
  294.  
  295. function onKill(creature, target)
  296.     if (Monster(target) ~= nil) and isInArray(REWARD_CHEST.BOSSES, target:getName():lower()) then
  297.         local corpse = Item(doCreateItem(MonsterType(target:getName()):getCorpseId(), 1, target:getPosition()))
  298.         corpse:decay()
  299.         target:setDropLoot(false)
  300.         doBossReward(target, corpse)
  301.     end
  302. end
Add Comment
Please, Sign In to add comment