Guest User

lualoot.lua

a guest
Aug 21st, 2015
331
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