proudera
New Member
- Joined
- Jun 11, 2017
- Messages
- 33
- Reaction score
- 0
I'm using this script with tfs 1.2 client 10.99.
I can't find a way to increase the loot chance of a rare/epic/legendary item.
Code:
-- Random Stats
local rare_popup = true
local rare_effect = true
local rare_effect_id = CONST_ME_STUN
-- Tiers
local tiers = {
[1] = {
prefix = 'rare',
chance = {
[1] = 10000, -- chance for basic stat
[2] = 5000 -- chance for second stat
}
},
[2] = {
prefix = 'epic',
chance = {
[1] = 3333,
[2] = 25000
}
},
[3] = {
prefix = 'legendary',
chance = {
[1] = 1000,
[2] = 100000 -- Legendary rolls always have two affixes.
}
},
}
-- Attributes
local attr = {
atk = {
name = 'Attack',
rare = {1, 3}, -- Customize roll numbers here
epic = {4, 6},
legendary = {7, 10},
},
def = {
name = 'Defense',
rare = {1, 2},
epic = {3, 4},
legendary = {5, 6},
},
extradef = {
name = 'Extra Defense',
rare = {1, 1},
epic = {2, 3},
legendary = {4, 5},
},
arm = {
name = 'Armor',
rare = {1, 1},
epic = {2, 3},
legendary = {4, 5},
},
hitchance = {
name = 'Accuracy',
rare = {1, 5},
epic = {6, 10},
legendary = {11, 15},
},
shootrange = {
name = 'Range',
rare = {1, 1},
epic = {2, 2},
legendary = {3, 3},
},
charges = {
name = 'Charges',
rare = {10, 20},
},
duration = {
name = 'Time',
rare = {10, 20},
},
-- Not available in 1.X
-- attackSpeed = {},
-- extraAttack = {},
}
local stats = {
[1] = {ITEM_ATTRIBUTE_ATTACK, attr.atk},
[2] = {ITEM_ATTRIBUTE_DEFENSE, attr.def},
[3] = {ITEM_ATTRIBUTE_EXTRADEFENSE, attr.extradef},
[4] = {ITEM_ATTRIBUTE_ARMOR, attr.arm},
[5] = {ITEM_ATTRIBUTE_HITCHANCE, attr.hitchance},
[6] = {ITEM_ATTRIBUTE_SHOOTRANGE, attr.shootrange},
[7] = {ITEM_ATTRIBUTE_CHARGES, attr.charges},
[8] = {ITEM_ATTRIBUTE_DURATION, attr.duration},
-- Not available in 1.X
-- [9] = {ITEM_ATTRIBUTE_ATTACKSPEED, attr.attackSpeed},
-- [10] = {ITEM_ATTRIBUTE_EXTRAATTACK, attr.extraAttack},
}
function stat_getItemDuration(item)
local it_id = item:getId()
local tid = ItemType(it_id):getTransformEquipId()
if tid > 0 then
item:transform(tid)
local vx = item:getAttribute(ITEM_ATTRIBUTE_DURATION)
item:transform(it_id)
item:removeAttribute(ITEM_ATTRIBUTE_DURATION)
return vx
end
return 0
end
function loot_attrToVal(item, attr)
local id = ItemType(item:getId())
local v = {
[ITEM_ATTRIBUTE_ATTACK] = id:getAttack(),
[ITEM_ATTRIBUTE_DEFENSE] = id:getDefense(),
[ITEM_ATTRIBUTE_EXTRADEFENSE] = id:getExtraDefense(),
[ITEM_ATTRIBUTE_ARMOR] = id:getArmor(),
[ITEM_ATTRIBUTE_HITCHANCE] = id:getHitChance(),
[ITEM_ATTRIBUTE_SHOOTRANGE] = id:getShootRange(),
[ITEM_ATTRIBUTE_CHARGES] = id:getCharges(),
[ITEM_ATTRIBUTE_DURATION] = stat_getItemDuration(item),
-- Not available in 1.X
-- [ITEM_ATTRIBUTE_ATTACKSPEED] = item:getAttackSpeed(),
-- [ITEM_ATTRIBUTE_EXTRAATTACK] = item:getExtraAttack(),
}
return v[attr]
end
function assign_loot_Stat(c)
local rares = 0
local h = c:getItemHoldingCount()
if h > 0 then
for i = 1, h do
local available_stats = {}
it_u = c:getItem(i - 1)
it_id = ItemType(it_u:getId())
if it_u:isContainer() then
local crares = assign_loot_Stat(it_u)
rares = rares + crares
else
if not it_id:isStackable() then
local wp = it_id:getWeaponType()
if wp > 0 then
if wp == WEAPON_SHIELD then
table.insert(available_stats, stats[2])
elseif wp == WEAPON_DISTANCE then -- type bow
table.insert(available_stats, stats[1])
table.insert(available_stats, stats[5])
table.insert(available_stats, stats[6])
-- Not available in 1.1
-- table.insert(available_stats, stats[9])
-- elseif wp == WEAPON_WAND then -- type wand
-- SHOOTRANGE doesn't seem to be working for wands
-- table.insert(available_stats, stats[6])
-- table.insert(available_stats, stats[9])
elseif isInArray({WEAPON_SWORD, WEAPON_CLUB, WEAPON_AXE}, wp) then -- melee weapon
if it_id:getAttack() > 0 then
table.insert(available_stats, stats[1])
end
if it_id:getDefense() > 0 then
table.insert(available_stats, stats[2])
end
if it_id:getExtraDefense() ~= 0 then
table.insert(available_stats, stats[3])
end
-- Not available in 1.1
-- table.insert(available_stats, stats[10])
end
else -- Armors, Amulets, Runes and Rings
if it_id:getArmor() > 0 then -- Ignore clothing
table.insert(available_stats, stats[4])
end
-- Rather not roll on consumables
-- if it_id:getCharges() > 0 then
-- table.insert(available_stats, stats[7])
-- end
-- Not working
-- local eq_id = it_id:getTransformEquipId()
-- if eq_id > 0 then
-- table.insert(available_stats, stats[8])
-- end
end
end
end
if #available_stats > 0 then
-- Skips it all if it's empty
local tier = math.random(1, #tiers)
if #tiers[tier].chance > 0 then
local statsStored = 0
local stats_used = {}
for stat = 1, #tiers[tier].chance do
if #available_stats > 0 then
-- Stops if no more stats available
if stat - 1 == statsStored then
-- Checks when it's time to stop adding stats
if math.random(1, 100000) <= tiers[tier].chance[stat] then
statsStored = statsStored + 1
local selected_stat = math.random(1, #available_stats)
table.insert(stats_used, available_stats[selected_stat])
table.remove(available_stats, selected_stat)
end
end
end
end
if #stats_used > 0 then
rares = rares + 1
local stat_desc = {}
for stat = 1, #stats_used do
if tiers[tier].prefix == tiers[3].prefix then
statmin = stats_used[stat][2].legendary[1]
statmax = stats_used[stat][2].legendary[2]
elseif tiers[tier].prefix == tiers[2].prefix then
statmin = stats_used[stat][2].epic[1]
statmax = stats_used[stat][2].epic[2]
else
statmin = stats_used[stat][2].rare[1]
statmax = stats_used[stat][2].rare[2]
end
local v = math.random(
statmin,
statmax
)
local basestat = loot_attrToVal(it_u, stats_used[stat][1])
it_u:setAttribute(stats_used[stat][1], basestat + v) -- Converted to static bonus
table.insert(stat_desc, '[' .. stats_used[stat][2].name .. ': +' .. v .. ']') -- Put roll results into a table
end
-- Replace article if item rolls as epic
if tiers[tier].prefix == "epic" then
it_u:setAttribute(ITEM_ATTRIBUTE_ARTICLE, "an")
end
-- Add rarity prefix to item name
it_u:setAttribute(ITEM_ATTRIBUTE_NAME, tiers[tier].prefix .. " " .. it_id:getName())
-- It item has a description, retain it instead of over-writing it
if it_id:getDescription() == "" then
it_u:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, table.concat(stat_desc, "\n"))
else
it_u:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, table.concat(stat_desc, "\n") .. "\n" .. it_id:getDescription())
end
-- Capitalize tier.prefix to be used for the animated text above corpses
rare_text = (tiers[tier].prefix:gsub("^%l", string.upper) .. "!")
end
end
end
end
end
return rares
end
function find_loot_Container(pos)
local rares = 0
local c = Tile(pos):getTopDownItem()
if c ~= nil then
if c:isContainer() then
rares = rares + assign_loot_Stat(c)
if rares > 0 then -- If a rare item was rolled, play animation
if rare_popup then
local spectators = Game.getSpectators(pos, false, true, 7, 7, 5, 5)
for i = 1, #spectators do
spectators[i]:say(rare_text, TALKTYPE_MONSTER_SAY, false, spectators[i], pos)
end
end
if rare_effect then
pos:sendMagicEffect(rare_effect_id)
end
end
return true
end
end
end
function MonsterType.createLoot(self, corpse, modifier)
if not corpse then
return
end
-- Take lootrate into consideration
if configManager.getNumber(configKeys.RATE_LOOT) == 0 then
return
end
local owner = Player(corpse:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER))
if not owner or owner:getStamina() > 840 then
-- The code below caused loot to be added to corpses in the wrong order (gold at the end, items at the start)
--
-- for _, v in pairs(self:getLoot()) do
-- itemList = self:createLootItem(v, modifier)
-- if itemList then
-- for _, item in ipairs(itemList) do
-- print(item:getName())
-- if item:isContainer() then
-- local lootContainer = self:createLootContainer(item, v, modifier)
-- if lootContainer then
-- corpse:addItemEx(item)
-- end
-- else
-- corpse:addItemEx(item, 1)
-- end
-- end
-- end
--end
-- Insert Loot into corpse, rewritten as per above.
itemIndex = {}
for _, v in pairs(self:getLoot()) do
itemList = self:createLootItem(v, modifier)
if itemList then
for _, item in ipairs(itemList) do
table.insert(itemIndex, item)
end
end
end
for i = #itemIndex, 1, -1 do
if itemIndex[i]:isContainer() then
local lootContainer = self:createLootContainer(itemIndex[i], v, modifier)
if lootContainer then
corpse:addItemEx(itemIndex[i])
end
else
corpse:addItemEx(itemIndex[i], 1)
end
end
-- Apply rarity chance to corpse contents
find_loot_Container(corpse:getPosition())
-- Print loot list to Server Log
if owner then
local loot_msg = "Loot of " .. self:getNameDescription() .. ": " .. corpse:getContentDescription()
if owner:getParty() then
owner:getParty():broadcastLoot(loot_msg)
owner:getParty():broadcastChannelLoot(loot_msg)
else
owner:sendTextMessage(MESSAGE_INFO_DESCR, loot_msg)
-- Loot channel un-used on my server.
-- owner:channelSay(nil, TALKTYPE_CHANNEL_O, loot_msg, 10)
end
end
else
local loot_msg = "Loot of " .. self:getNameDescription() .. ": nothing (due to low stamina)"
if owner:getParty() then
owner:getParty():broadcastLoot(loot_msg)
owner:getParty():broadcastChannelLoot(loot_msg)
else
owner:sendTextMessage(MESSAGE_INFO_DESCR, loot_msg)
end
end
corpse:decay()
end
function MonsterType.createLootItem(self, lootBlock, modifier)
local lootTable = {}
local itemCount = 0
local randvalue = math.random(0, 100000) / (configManager.getNumber(configKeys.RATE_LOOT) * modifier);
if randvalue < lootBlock.chance then
if (ItemType(lootBlock.itemId):isStackable()) then
itemCount = randvalue % lootBlock.maxCount + 1;
else
itemCount = 1;
end
end
while (itemCount > 0) do
local n = math.min(itemCount, 100)
itemCount = itemCount - n
local item = Game.createItem(lootBlock.itemId, n)
if item then
if lootBlock.subType ~= -1 then
item:transform(lootBlock.itemId, lootBlock.subType)
end
if lootBlock.actionId ~= -1 then
item:setActionId(lootBlock.actionId)
end
if lootBlock.text and lootBlock.text ~= "" then
item:setAttribute(ITEM_ATTRIBUTE_TEXT, lootBlock.text)
end
table.insert(lootTable, item)
end
end
return #lootTable == 0 and nil or lootTable
end
function MonsterType.createLootContainer(self, parent, lootBlock, modifier)
if #lootBlock.childLoot == 0 then
return true
end
for _, v in pairs(lootBlock.childLoot) do
if parent:getSize() < parent:getCapacity() then
local itemList = self:createLootItem(v, modifier)
if itemList then
for _, item in ipairs(itemList) do
if item:isContainer() then
local lootContainer = self:createLootContainer(item, v, modifier)
if lootContainer then
parent:addItemEx(item)
end
else
parent:addItem(item, 1)
end
end
end
end
end
return #parent > 0
end
I can't find a way to increase the loot chance of a rare/epic/legendary item.
Last edited: