SHARE
TWEET

lualoot.lua

a guest Aug 21st, 2015 309 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Random Stats
  2. local rare_popup = true
  3. local rare_effect = true
  4. local rare_effect_id = CONST_ME_STUN
  5.  
  6. -- Tiers
  7. local tiers = {
  8.         [1] = {
  9.                 prefix = 'rare',
  10.                 chance = {
  11.                         [1] = 10000, -- chance for basic stat
  12.                         [2] = 5000 -- chance for second stat
  13.                 }
  14.         },
  15.  
  16.         [2] = {
  17.                 prefix = 'epic',
  18.                 chance = {
  19.                         [1] = 3333,
  20.                         [2] = 25000
  21.                 }
  22.         },
  23.  
  24.         [3] = {
  25.                 prefix = 'legendary',
  26.                 chance = {
  27.                         [1] = 1000,
  28.                         [2] = 100000 -- Legendary rolls always have two affixes.
  29.                 }
  30.         },
  31. }
  32.  
  33. -- Attributes
  34. local attr = {
  35.         atk = {
  36.                 name = 'Attack',
  37.                 rare = {1, 3}, -- Customize roll numbers here
  38.                 epic = {4, 6},
  39.                 legendary = {7, 10},
  40.         },
  41.         def = {
  42.                 name = 'Defense',
  43.                 rare = {1, 2},
  44.                 epic = {3, 4},
  45.                 legendary = {5, 6},
  46.         },
  47.         extradef = {
  48.                 name = 'Extra Defense',
  49.                 rare = {1, 1},
  50.                 epic = {2, 3},
  51.                 legendary = {4, 5},
  52.         },
  53.         arm = {
  54.                 name = 'Armor',
  55.                 rare = {1, 1},
  56.                 epic = {2, 3},
  57.                 legendary = {4, 5},
  58.         },
  59.         hitchance = {
  60.                 name = 'Accuracy',
  61.                 rare = {1, 5},
  62.                 epic = {6, 10},
  63.                 legendary = {11, 15},
  64.         },
  65.         shootrange = {
  66.                 name = 'Range',
  67.                 rare = {1, 1},
  68.                 epic = {2, 2},
  69.                 legendary = {3, 3},
  70.         },
  71.         charges = {
  72.                 name = 'Charges',
  73.                 rare = {10, 20},
  74.         },
  75.         duration = {
  76.                 name = 'Time',
  77.                 rare = {10, 20},
  78.         },
  79.  
  80.         -- Not available in 1.X
  81.         -- attackSpeed = {},
  82.         -- extraAttack = {},
  83. }
  84.  
  85. local stats = {
  86.         [1] = {ITEM_ATTRIBUTE_ATTACK, attr.atk},
  87.         [2] = {ITEM_ATTRIBUTE_DEFENSE, attr.def},
  88.         [3] = {ITEM_ATTRIBUTE_EXTRADEFENSE, attr.extradef},
  89.         [4] = {ITEM_ATTRIBUTE_ARMOR, attr.arm},
  90.         [5] = {ITEM_ATTRIBUTE_HITCHANCE, attr.hitchance},
  91.         [6] = {ITEM_ATTRIBUTE_SHOOTRANGE, attr.shootrange},
  92.         [7] = {ITEM_ATTRIBUTE_CHARGES, attr.charges},
  93.         [8] = {ITEM_ATTRIBUTE_DURATION, attr.duration},
  94.        
  95.         -- Not available in 1.X
  96.         -- [9] = {ITEM_ATTRIBUTE_ATTACKSPEED, attr.attackSpeed},
  97.         -- [10] = {ITEM_ATTRIBUTE_EXTRAATTACK, attr.extraAttack},
  98. }
  99.  
  100. function stat_getItemDuration(item)
  101.         local it_id = item:getId()
  102.         local tid = ItemType(it_id):getTransformEquipId()
  103.         if tid > 0 then
  104.                 item:transform(tid)
  105.                 local vx = item:getAttribute(ITEM_ATTRIBUTE_DURATION)
  106.                 item:transform(it_id)
  107.                 item:removeAttribute(ITEM_ATTRIBUTE_DURATION)
  108.                 return vx
  109.         end
  110.         return 0
  111. end
  112.  
  113. function loot_attrToVal(item, attr)
  114.         local id = ItemType(item:getId())
  115.         local v = {
  116.                 [ITEM_ATTRIBUTE_ATTACK] = id:getAttack(),
  117.                 [ITEM_ATTRIBUTE_DEFENSE] = id:getDefense(),
  118.                 [ITEM_ATTRIBUTE_EXTRADEFENSE] = id:getExtraDefense(),
  119.                 [ITEM_ATTRIBUTE_ARMOR] = id:getArmor(),
  120.                 [ITEM_ATTRIBUTE_HITCHANCE] = id:getHitChance(),
  121.                 [ITEM_ATTRIBUTE_SHOOTRANGE] = id:getShootRange(),
  122.                 [ITEM_ATTRIBUTE_CHARGES] = id:getCharges(),
  123.                 [ITEM_ATTRIBUTE_DURATION] = stat_getItemDuration(item),
  124.  
  125.                 -- Not available in 1.X
  126.                 -- [ITEM_ATTRIBUTE_ATTACKSPEED] = item:getAttackSpeed(),
  127.                 -- [ITEM_ATTRIBUTE_EXTRAATTACK] = item:getExtraAttack(),
  128.         }
  129.         return v[attr]
  130. end
  131.  
  132. function assign_loot_Stat(c)
  133.         local rares = 0
  134.         local h = c:getItemHoldingCount()
  135.         if h > 0 then
  136.                 for i = 1, h do
  137.                         local available_stats = {}
  138.                         it_u = c:getItem(i - 1)
  139.                         it_id = ItemType(it_u:getId())
  140.                         if it_u:isContainer() then
  141.                                 local crares = assign_loot_Stat(it_u)
  142.                                 rares = rares + crares
  143.                         else
  144.                                 if not it_id:isStackable() then
  145.                                         local wp = it_id:getWeaponType()
  146.                                         if wp > 0 then
  147.                                                 if wp == WEAPON_SHIELD then
  148.                                                         table.insert(available_stats, stats[2])
  149.                                                 elseif wp == WEAPON_DISTANCE then -- type bow
  150.                                                         table.insert(available_stats, stats[1])
  151.                                                         table.insert(available_stats, stats[5])
  152.                                                         table.insert(available_stats, stats[6])
  153.                                                         -- Not available in 1.1
  154.                                                         -- table.insert(available_stats, stats[9])
  155.                                                 -- elseif wp == WEAPON_WAND then -- type wand
  156.                                                         -- SHOOTRANGE doesn't seem to be working for wands
  157.                                                         -- table.insert(available_stats, stats[6])
  158.                                                         -- table.insert(available_stats, stats[9])
  159.                                                 elseif isInArray({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE}, wp) then -- melee weapon
  160.  
  161.                                                         if it_id:getAttack() > 0 then
  162.                                                                 table.insert(available_stats, stats[1])
  163.                                                         end
  164.                                
  165.                                                         if it_id:getDefense() > 0 then
  166.                                                                 table.insert(available_stats, stats[2])
  167.                                                         end
  168.                                
  169.                                                         if it_id:getExtraDefense() ~= 0 then
  170.                                                                 table.insert(available_stats, stats[3])
  171.                                                         end
  172.                                                         -- Not available in 1.1
  173.                                                         -- table.insert(available_stats, stats[10])
  174.                                                 end
  175.                                         else -- Armors, Amulets, Runes and Rings
  176.                                                 if it_id:getArmor() > 0 then -- Ignore clothing
  177.                                                         table.insert(available_stats, stats[4])
  178.                                                 end
  179.  
  180.                                                 -- Rather not roll on consumables
  181.                                                 -- if it_id:getCharges() > 0 then
  182.                                                 --      table.insert(available_stats, stats[7])
  183.                                                 -- end
  184.  
  185.                                                 -- Not working
  186.                                                 -- local eq_id = it_id:getTransformEquipId()
  187.                                                 -- if eq_id > 0 then
  188.                                                 --      table.insert(available_stats, stats[8])
  189.                                                 -- end
  190.                                         end
  191.                                 end
  192.                         end
  193.  
  194.                         if #available_stats > 0 then
  195.                                 -- Skips it all if it's empty
  196.                                 local tier = math.random(1, #tiers)
  197.                                 if #tiers[tier].chance > 0 then
  198.                                         local statsStored = 0
  199.                                         local stats_used = {}
  200.                                         for stat = 1, #tiers[tier].chance do
  201.                                                 if #available_stats > 0 then
  202.                                                         -- Stops if no more stats available
  203.                                                         if stat - 1 == statsStored then
  204.                                                                 -- Checks when it's time to stop adding stats
  205.                                                                 if math.random(1, 100000) <= tiers[tier].chance[stat] then
  206.                                                                         statsStored = statsStored + 1
  207.  
  208.                                                                         local selected_stat = math.random(1, #available_stats)
  209.                                                                         table.insert(stats_used, available_stats[selected_stat])
  210.                                                                         table.remove(available_stats, selected_stat)
  211.                                                                 end
  212.                                                         end
  213.                                                 end
  214.                                         end
  215.  
  216.                                         if #stats_used > 0 then
  217.                                                 rares = rares + 1
  218.                                                 local stat_desc = {}
  219.                                                 for stat = 1, #stats_used do
  220.                        
  221.                                                         if tiers[tier].prefix == tiers[3].prefix then
  222.                                                                 statmin = stats_used[stat][2].legendary[1]
  223.                                                                 statmax = stats_used[stat][2].legendary[2]
  224.                                                         elseif tiers[tier].prefix == tiers[2].prefix then
  225.                                                                 statmin = stats_used[stat][2].epic[1]
  226.                                                                 statmax = stats_used[stat][2].epic[2]
  227.                                                         else
  228.                                                                 statmin = stats_used[stat][2].rare[1]
  229.                                                                 statmax = stats_used[stat][2].rare[2]
  230.                                                         end
  231.                                
  232.                                                         local v = math.random(
  233.                                                                 statmin,
  234.                                                                 statmax
  235.                                                         )
  236.                                
  237.                                                         local basestat = loot_attrToVal(it_u, stats_used[stat][1])
  238.                                                         it_u:setAttribute(stats_used[stat][1], basestat + v) -- Converted to static bonus
  239.                                                         table.insert(stat_desc, '[' .. stats_used[stat][2].name .. ': +' .. v .. ']') -- Put roll results into a table
  240.                                                 end
  241.                        
  242.                                                 -- Replace article if item rolls as epic
  243.                                                 if tiers[tier].prefix == "epic" then
  244.                                                         it_u:setAttribute(ITEM_ATTRIBUTE_ARTICLE, "an")
  245.                                                 end
  246.                                                
  247.                                                 -- Add rarity prefix to item name
  248.                                                 it_u:setAttribute(ITEM_ATTRIBUTE_NAME, tiers[tier].prefix .. " " .. it_id:getName())
  249.                        
  250.                                                 -- It item has a description, retain it instead of over-writing it
  251.                                                 if it_id:getDescription() == "" then
  252.                                                         it_u:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, table.concat(stat_desc, "\n"))
  253.                                                 else
  254.                                                         it_u:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, table.concat(stat_desc, "\n")  .. "\n" .. it_id:getDescription())
  255.                                                 end
  256.  
  257.                                                 -- Capitalize tier.prefix to be used for the animated text above corpses
  258.                                                 rare_text = (tiers[tier].prefix:gsub("^%l", string.upper) .. "!")
  259.                        
  260.                                         end
  261.                                 end
  262.                         end
  263.                 end
  264.         end
  265.         return rares
  266. end
  267.  
  268. function find_loot_Container(pos)
  269.         local rares = 0
  270.         local c = Tile(pos):getTopDownItem()
  271.         if c ~= nil then
  272.                 if c:isContainer() then
  273.                         rares = rares + assign_loot_Stat(c)
  274.                         if rares > 0 then -- If a rare item was rolled, play animation
  275.                                 if rare_popup then
  276.                                         local spectators = Game.getSpectators(pos, false, true, 7, 7, 5, 5)
  277.                                         for i = 1, #spectators do
  278.                                                 spectators[i]:say(rare_text, TALKTYPE_MONSTER_SAY, false, spectators[i], pos)
  279.                                         end
  280.                                 end
  281.                                 if rare_effect then
  282.                                         pos:sendMagicEffect(rare_effect_id)
  283.                                 end
  284.                         end
  285.                         return true
  286.                 end
  287.         end
  288. end
  289.  
  290. function MonsterType.createLoot(self, corpse, modifier)
  291.         if not corpse then
  292.                 return
  293.         end
  294.        
  295.         -- Take lootrate into consideration
  296.         if configManager.getNumber(configKeys.RATE_LOOT) == 0 then
  297.                 return
  298.         end
  299.  
  300.         local owner = Player(corpse:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER))
  301.  
  302.         if not owner or owner:getStamina() > 840 then
  303.        
  304.                 -- The code below caused loot to be added to corpses in the wrong order (gold at the end, items at the start)
  305.                 --
  306.                 --      for _, v in pairs(self:getLoot()) do
  307.                 --      itemList = self:createLootItem(v, modifier)
  308.                 --      if itemList then
  309.                 --               for _, item in ipairs(itemList) do
  310.                 --               print(item:getName())
  311.                 --                      if item:isContainer() then
  312.                 --                              local lootContainer = self:createLootContainer(item, v, modifier)
  313.                 --                              if lootContainer then
  314.                 --                                      corpse:addItemEx(item)
  315.                 --                              end
  316.                 --                      else
  317.                 --                              corpse:addItemEx(item, 1)
  318.                 --                      end
  319.                 --              end
  320.                 --      end
  321.                 --end
  322.                
  323.                 -- Insert Loot into corpse, rewritten as per above.
  324.                 itemIndex = {}
  325.                 for _, v in pairs(self:getLoot()) do
  326.                         itemList = self:createLootItem(v, modifier)
  327.                         if itemList then
  328.                                 for _, item in ipairs(itemList) do
  329.                                         table.insert(itemIndex, item)
  330.                                 end
  331.                         end
  332.                 end
  333.                 for i = #itemIndex, 1, -1 do
  334.                         if itemIndex[i]:isContainer() then
  335.                                 local lootContainer = self:createLootContainer(itemIndex[i], v, modifier)
  336.                                 if lootContainer then
  337.                                         corpse:addItemEx(itemIndex[i])
  338.                                 end
  339.                                 else
  340.                                         corpse:addItemEx(itemIndex[i], 1)
  341.                         end
  342.                 end
  343.        
  344.                
  345.                 -- Apply rarity chance to corpse contents
  346.                 find_loot_Container(corpse:getPosition())
  347.                
  348.                 -- Print loot list to Server Log
  349.                 if owner then
  350.                         local loot_msg = "Loot of " .. self:getNameDescription() .. ": " .. corpse:getContentDescription()
  351.  
  352.                         if owner:getParty() then
  353.                                 owner:getParty():broadcastLoot(loot_msg)
  354.                                 owner:getParty():broadcastChannelLoot(loot_msg)
  355.                         else
  356.                                 owner:sendTextMessage(MESSAGE_INFO_DESCR, loot_msg)
  357.                                 -- Loot channel un-used on my server.
  358.                                 -- owner:channelSay(nil, TALKTYPE_CHANNEL_O, loot_msg, 10)
  359.                         end
  360.                 end
  361.         else
  362.                 local loot_msg = "Loot of " .. self:getNameDescription() .. ": nothing (due to low stamina)"
  363.  
  364.                 if owner:getParty() then
  365.                         owner:getParty():broadcastLoot(loot_msg)
  366.                         owner:getParty():broadcastChannelLoot(loot_msg)
  367.                 else
  368.                         owner:sendTextMessage(MESSAGE_INFO_DESCR, loot_msg)
  369.                 end
  370.         end
  371.  
  372.         corpse:decay()
  373. end
  374.  
  375. function MonsterType.createLootItem(self, lootBlock, modifier)
  376.         local lootTable = {}
  377.         local itemCount = 0
  378.  
  379.         local randvalue = math.random(0, 100000) / (configManager.getNumber(configKeys.RATE_LOOT) * modifier);
  380.         if randvalue < lootBlock.chance then
  381.                 if (ItemType(lootBlock.itemId):isStackable()) then
  382.                         itemCount = randvalue % lootBlock.maxCount + 1;
  383.                 else
  384.                         itemCount = 1;
  385.                 end
  386.         end
  387.  
  388.         while (itemCount > 0) do
  389.                 local n = math.min(itemCount, 100)
  390.                 itemCount = itemCount - n
  391.  
  392.                 local item = Game.createItem(lootBlock.itemId, n)
  393.  
  394.                 if item then
  395.                         if lootBlock.subType ~= -1 then
  396.                                 item:transform(lootBlock.itemId, lootBlock.subType)
  397.                         end
  398.  
  399.                         if lootBlock.actionId ~= -1 then
  400.                                 item:setActionId(lootBlock.actionId)
  401.                         end
  402.  
  403.                         if lootBlock.text and lootBlock.text ~= "" then
  404.                                 item:setAttribute(ITEM_ATTRIBUTE_TEXT, lootBlock.text)
  405.                         end
  406.  
  407.                         table.insert(lootTable, item)
  408.                 end
  409.         end
  410.  
  411.         return #lootTable == 0 and nil or lootTable
  412. end
  413.  
  414. function MonsterType.createLootContainer(self, parent, lootBlock, modifier)
  415.         if #lootBlock.childLoot == 0 then
  416.                 return true
  417.         end
  418.  
  419.         for _, v in pairs(lootBlock.childLoot) do
  420.                 if parent:getSize() < parent:getCapacity() then
  421.                         local itemList = self:createLootItem(v, modifier)
  422.                         if itemList then
  423.                                 for _, item in ipairs(itemList) do
  424.                                         if item:isContainer() then
  425.                                                 local lootContainer = self:createLootContainer(item, v, modifier)
  426.                                                 if lootContainer then
  427.                                                         parent:addItemEx(item)
  428.                                                 end
  429.                                         else
  430.                                                 parent:addItem(item, 1)
  431.                                         end
  432.                                 end
  433.                         end
  434.                 end
  435.         end
  436.  
  437.         return #parent > 0
  438. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top