Created
September 2, 2023 17:53
-
-
Save Elmuti/2d85c3d83a47e3ed3a0f52764771654b to your computer and use it in GitHub Desktop.
loot.lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Abyss = require(game.ReplicatedStorage.Abyss.Main) | |
local mathLib = Abyss.LoadModule("MathLib") | |
local pretty = Abyss.LoadModule("PrettyPrinter") | |
local lootLib = {} | |
local RAND_SEED = tick() | |
print("RANDOM SEED: " .. RAND_SEED) | |
math.randomseed(1520448512.2074) | |
for i = 1, 6 do math.random() end | |
local affixes = game.ReplicatedStorage.ItemData.Affixes | |
local baseitems = game.ReplicatedStorage.ItemData.BaseItems | |
local uniques = game.ReplicatedStorage.ItemData.Uniques | |
local rareitemnames = require(game.ReplicatedStorage.ItemData.RareItemNames) | |
local Weapons = { | |
"Bows", | |
"Wands", | |
"OneHandedMaces", | |
"TwoHandedMaces", | |
"OneHandedSwords", | |
"TwoHandedSwords", | |
"Staves", | |
"Daggers" | |
} | |
local RarityChances = { | |
{"Unique", 1}; | |
{"Rare", 65}; | |
{"Magic", 570}; | |
{"Normal", 1200}; | |
} | |
local QualityChances = { | |
{"20", 1}; | |
{"15", 5}; | |
{"10", 12}; | |
{"5", 20}; | |
{"0", 625}; | |
} | |
local ItemChances = { | |
{"Currency", 5}; | |
{"Equipment", 700}; | |
} | |
--chisel weighting: 2754, vaal orb: 689, fusing 3443 | |
local CurrencyDropChances = { | |
--EXTREMELY RARE | |
{"Mirror" , 1};--Mirror | |
{"MeticulousOrb" , 34};--Divine | |
{"SacramentalOrb" , 55};--Exalted | |
--RARE | |
{"OrbOfReformation" , 207};--Regal | |
{"ArchmagesInk" , 275};--GCP | |
{"OrbOfEnhance" , 275};--Blessed | |
{"Blowpipe" , 682};--Bauble | |
--UNCOMMON | |
{"OrbOfFurbishing" , 1377};--Scouring | |
{"SacredOrb" , 1652};--Chaos | |
{"OrbOfMetamorphosis" , 2754};--Alchemy | |
{"OrbOfLuck" , 5508};--Chance | |
{"OrbOfReforging" , 5508};--Alteration | |
--COMMON | |
{"OrbOfAmplification" , 10328};--Augmentation | |
{"Whetstone" , 11095};--Whetstone | |
{"ArmourShard" ,20827};--Scrap | |
{"OrbOfEnchanting" , 20831};--Transmute | |
} | |
local function Deepcopy(orig) | |
local orig_type = type(orig) | |
local copy | |
if orig_type == 'table' then | |
copy = {} | |
for orig_key, orig_value in next, orig, nil do | |
copy[Deepcopy(orig_key)] = Deepcopy(orig_value) | |
end | |
setmetatable(copy, Deepcopy(getmetatable(orig))) | |
else -- number, string, boolean, etc | |
copy = orig | |
end | |
return copy | |
end | |
function lootLib.IsWeapon(basetype) | |
for _,v in pairs(Weapons) do | |
if v == basetype then | |
return true | |
end | |
end | |
return false | |
end | |
function lootLib.GetBaseItemProperty(basetype, baseitem, propertyname) | |
baseitem = string.gsub(baseitem, " ", "") | |
local items = require(baseitems[basetype]) | |
return items[baseitem][propertyname] | |
end | |
function lootLib.GetBaseItemDamage(basetype, baseitem, damagetype) | |
baseitem = string.gsub(baseitem, " ", "") | |
local items = require(baseitems[basetype]) | |
return items[baseitem].Damage[damagetype] | |
end | |
function GenerateRarename(basetype) | |
local prefix = rareitemnames.Prefixes[math.random(1, #rareitemnames.Prefixes)] | |
local bin = rareitemnames.Suffixes[basetype] or rareitemnames.Suffixes[1] | |
return prefix .. " " .. bin[math.random(1, #bin)] | |
end | |
lootLib.GenerateRarename = GenerateRarename | |
function PoolProbabilities(dropList) | |
local pSum = 0 | |
for i=1,#dropList do | |
pSum = pSum + dropList[i][2] | |
end | |
local prevEntry = 0 | |
for i=1,#dropList do | |
dropList[i][2] = prevEntry + dropList[i][2] / pSum | |
--print("Item "..dropList[i][1].." will drop in range "..prevEntry.."-"..dropList[i][2]..", this is a "..(dropList[i][2]-prevEntry)*100 .."% chance.") | |
print("Item "..dropList[i][1].." is a "..(dropList[i][2]-prevEntry)*100 .."% chance.") | |
prevEntry = dropList[i][2] | |
end | |
end | |
function GetItemRarity(IIR) | |
local roll = math.random() | |
if roll < RarityChances[1][2] * (1 + IIR) then | |
return "Unique" | |
elseif roll < RarityChances[2][2] * (1 + IIR) then | |
return "Rare" | |
elseif roll < RarityChances[3][2] * (1 + IIR) then | |
return "Magic" | |
end | |
return "Normal" | |
end | |
function GetBaseItemFromNameAndType(name, basetype) | |
local list = require(game.ReplicatedStorage.ItemData.BaseItems[basetype]) | |
return list[name] | |
end | |
function GetBasenameFromUniquename(uniquedata, itemdata) | |
local bt = itemdata.Basetype | |
local bi = game.ReplicatedStorage.ItemData.BaseItems[bt] | |
local t = require(bi) | |
for itemname, item in pairs(t) do | |
if uniquedata.BaseItem == itemname then | |
return itemname | |
end | |
end | |
end | |
function RollQuality() | |
local qual = "0" | |
local roll = math.random() | |
for _, data in pairs(QualityChances) do | |
if roll < data[2] then | |
qual = data[1] | |
break | |
end | |
end | |
if qual == "20" then | |
return math.random(15, 20) | |
elseif qual == "15" then | |
return math.random(10, 15) | |
elseif qual == "10" then | |
return math.random(5, 10) | |
elseif qual == "5" then | |
return math.random(1, 5) | |
else | |
return 0 | |
end | |
end | |
function lootLib.GenerateUnique(itemlevel, forceSpecific) | |
local baseItem, basetype, baseASD | |
local chosenUniqueName | |
local uniques | |
if forceSpecific == nil then | |
--if base has no uniques, change basetype until it hits unique | |
while true do | |
baseASD, basetype = ChooseBaseItem(itemlevel) | |
baseItem = Deepcopy(baseASD) | |
if game.ReplicatedStorage.ItemData.Uniques[basetype] ~= nil then | |
break | |
end | |
end | |
chosenUniqueName = "" | |
uniques = require(game.ReplicatedStorage.ItemData.Uniques[basetype]) | |
local dropchances = uniques.DropChances | |
if dropchances == nil then | |
warn(basetype .. " doesnt have unique dropchances list") | |
end | |
PoolProbabilities(dropchances) | |
local roll = math.random() | |
for i = 1, #dropchances do | |
if roll < dropchances[i][2] then | |
chosenUniqueName = dropchances[i][1] | |
if (uniques[chosenUniqueName].OverrideReqLvl and uniques[chosenUniqueName].ReqLvl) or (not uniques[chosenUniqueName].OverrideReqLvl and baseItem.ReqLvl) <= itemlevel then | |
chosenUniqueName = "" | |
end | |
end | |
end | |
local new = dropchances[#dropchances][1] | |
if chosenUniqueName == "" and uniques[new].ReqLvl <= itemlevel then | |
chosenUniqueName = new | |
elseif chosenUniqueName == "" and uniques[new].ReqLvl > itemlevel then | |
return nil | |
end | |
else | |
for _, uniqueList in pairs(game.ReplicatedStorage.ItemData.Uniques:GetChildren()) do | |
local file = require(uniqueList) | |
local list = file.DropChances | |
if list ~= nil then | |
for i, droptable in pairs(list) do | |
local name = droptable[1] | |
if name == forceSpecific then | |
print("found unique for " .. forceSpecific) | |
chosenUniqueName = forceSpecific | |
basetype = uniqueList.Name | |
uniques = file | |
end | |
end | |
else | |
warn(uniqueList.Name .. " doesnt have unique drop chances list!") | |
end | |
end | |
end | |
local TheUnique = uniques[chosenUniqueName] | |
baseItem = Deepcopy(GetBaseItemFromNameAndType(TheUnique.BaseItem, basetype)) | |
--print("basetype: "..tostring(basetype)) | |
baseItem.Baseitem = baseItem.Name | |
baseItem.Basetype = basetype | |
baseItem.ItemLevel = itemlevel | |
baseItem.Basename = GetBasenameFromUniquename(TheUnique, baseItem) | |
baseItem.Name = TheUnique.Name | |
baseItem.FlavourText = TheUnique.FlavourText | |
baseItem.RolledModifiers = {Prefixes = {}; Suffixes = {}} | |
if TheUnique.ReplacesImplicitModifier then | |
baseItem.ImplicitModifier = TheUnique.ImplicitModifier | |
end | |
--[[ ROLL IMPLICIT | |
if baseItem.ImplicitModifier ~= nil and baseItem.ImplicitModifier ~= "" and baseItem.ImplicitModifier ~= {} then | |
if typeof(baseItem.ImplicitModifier[2]) == "NumberRange" then | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], math.random(baseItem.ImplicitModifier[2].Min, baseItem.ImplicitModifier[2].Max)} | |
elseif typeof(baseItem.ImplicitModifier[2]) == "table" then | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], NumberRange.new(math.random(baseItem.ImplicitModifier[2][1].Min, baseItem.ImplicitModifier[2][1].Max), math.random(baseItem.ImplicitModifier[2][2].Min, baseItem.ImplicitModifier[2][2].Max))} | |
elseif typeof(baseItem.ImplicitModifier[2]) == "number" then | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], baseItem.ImplicitModifier[2]} | |
end | |
end]] | |
if baseItem.ImplicitModifier ~= nil and baseItem.ImplicitModifier ~= "" and baseItem.ImplicitModifier ~= {} then | |
--print("rolling implicit") | |
if typeof(baseItem.ImplicitModifier[2]) == "NumberRange" then | |
--print("baseItem.ImplicitModifier[1] = " .. baseItem.ImplicitModifier[1]) | |
if baseItem.ImplicitModifier[1] == "FlatPhysicalDamage" or baseItem.ImplicitModifier[1] == "FlatColdDamage" or baseItem.ImplicitModifier[1] == "FlatLightningDamage" or baseItem.ImplicitModifier[1] == "FlatFireDamage" or baseItem.ImplicitModifier[1] == "FlatPoisonDamage" then | |
--print("is damage roll, making implicit numberrange instead of rolling") | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], baseItem.ImplicitModifier[2]} | |
else | |
print("rolling implicit ("..baseItem.ImplicitModifier[1]..")") | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], math.random(baseItem.ImplicitModifier[2].Min, baseItem.ImplicitModifier[2].Max)} | |
end | |
elseif typeof(baseItem.ImplicitModifier[2]) == "table" then | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], NumberRange.new(math.random(baseItem.ImplicitModifier[2][1].Min, baseItem.ImplicitModifier[2][1].Max), math.random(baseItem.ImplicitModifier[2][2].Min, baseItem.ImplicitModifier[2][2].Max))} | |
elseif typeof(baseItem.ImplicitModifier[2]) == "number" then | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], baseItem.ImplicitModifier[2]} | |
end | |
end | |
for i, data in pairs(TheUnique.Modifiers) do | |
if typeof(data[2]) == "NumberRange" then | |
local modname = data[1] | |
if modname == "FlatPhysicalDamage" or modname == "FlatColdDamage" or modname == "FlatLightningDamage" or modname == "FlatFireDamage" or modname == "FlatPoisonDamage" then | |
baseItem.RolledModifiers.Prefixes[modname] = {Name = data[1], Value = data[2]} | |
else | |
baseItem.RolledModifiers.Prefixes[modname] = {Name = data[1], Value = math.random(data[2].Min, data[2].Max)} | |
end | |
elseif typeof(data[2]) == "table" then | |
local modname = data[1] | |
baseItem.RolledModifiers.Prefixes[modname] = {Name = data[1], Value = NumberRange.new(math.random(data[2][1].Min, data[2][1].Max), math.random(data[2][2].Min, data[2][2].Max))} | |
else | |
local modname = data[1] | |
baseItem.RolledModifiers.Suffixes[modname] = {Name = data[1], Value = data[2]} | |
end | |
end | |
if TheUnique.OverrideReqLvl then | |
baseItem.ReqLvl = TheUnique.ReqLvl | |
end | |
baseItem.Modifiers = {Prefixes = {}; Suffixes = {}} | |
if lootLib.IsWeapon(basetype) or baseItem.Evasion ~= nil or baseItem.Armour ~= nil then | |
baseItem.Quality = RollQuality() | |
end | |
if lootLib.IsWeapon(baseItem.Basetype) then | |
baseItem = InitializeWeaponMods(baseItem) | |
else | |
print("initting armour mods") | |
baseItem = InitializeOtherMods(baseItem) | |
end | |
return baseItem | |
end | |
function ChooseBaseItem(itemlevel) | |
local bases = baseitems:GetChildren() | |
local basetype = bases[math.random(1, #bases)] | |
local base = require(basetype) | |
local theName = "" | |
local baselist = {} | |
local names = {} | |
for n, item in pairs(base) do | |
--print("n: "..n.. " item:".. tostring(item).. "ReqLvl: ".. tostring(item.ReqLvl)) | |
if item.ReqLvl == nil then | |
warn("WARNING! Item '"..tostring(basetype.Name).."/"..tostring(item.Name).."' does not have a level requirement stat!") | |
end | |
if item.ReqLvl <= itemlevel then | |
table.insert(baselist, item) | |
table.insert(names, n) | |
end | |
end | |
if #baselist < 1 then | |
warn("#baselist < 1 on basetype "..basetype.Name.. " with " .. itemlevel .. " itemlevel") | |
warn("DUMPING BASELIST TO OUTPUT") | |
for k,v in pairs(baselist) do | |
print(k, v) | |
for i,a in pairs(v) do | |
print("-- "..i, a) | |
end | |
end | |
warn("DONE DUMPING BASELIST TO OUTPUT") | |
error("#baselist < 1 on basetype "..basetype.Name.. " with " .. itemlevel .. " itemlevel") | |
end | |
local roll = math.random(1, #baselist) | |
return baselist[roll], basetype.Name, names[roll] | |
end | |
function ListOfExistingAffixes(rolledmods) | |
local list = {} | |
for i, data in pairs(rolledmods.Prefixes) do | |
table.insert(list, data.Name) | |
end | |
for i, data in pairs(rolledmods.Suffixes) do | |
table.insert(list, data.Name) | |
end | |
return list | |
end | |
function AffixAlreadyUsed(list, affix) | |
for _, v in pairs(list) do | |
if v == affix then | |
return true | |
end | |
end | |
return false | |
end | |
function lootLib.GenerateAffix(basetype, itemlevel, forcePrefix, forceSuffix, usedAffixTypes) | |
local prefixname, suffixname = "", "" | |
local prefix | |
local forcePrefix = forcePrefix or false | |
local forceSuffix = forceSuffix or false | |
local availablePrefixes = {} | |
local availableSuffixes = {} | |
if affixes[basetype] == nil then | |
warn("Base item type "..basetype.." doesnt have a list of affixes!") | |
return nil | |
end | |
local affixList = require(affixes[basetype]) | |
--Compile Affixes that meet level requirements | |
for modtype, data in pairs(affixList.Prefixes) do | |
local lowestTier = #data | |
if data[lowestTier].ReqLvl <= itemlevel then | |
local newdata = {} | |
for tier, affix in pairs(data) do | |
if affix.ReqLvl <= itemlevel then | |
table.insert(newdata, affix) | |
end | |
end | |
availablePrefixes[modtype] = newdata | |
end | |
end | |
for modtype, data in pairs(affixList.Suffixes) do | |
local lowestTier = #data | |
if data[lowestTier].ReqLvl <= itemlevel then | |
local newdata = {} | |
for tier, affix in pairs(data) do | |
if affix.ReqLvl <= itemlevel then | |
table.insert(newdata, affix) | |
end | |
end | |
availableSuffixes[modtype] = newdata | |
end | |
end | |
--Determine prefix or suffix | |
if forcePrefix then | |
prefix = true | |
elseif forceSuffix then | |
prefix = false | |
else | |
local dice = math.random() | |
if dice < 0.5 then | |
prefix = true | |
else | |
prefix = false | |
end | |
end | |
if Abyss.TLength(availablePrefixes) <= 0 or Abyss.TLength(availableSuffixes) <= 0 then | |
error("No available affixes for item '"..basetype.."' with an ilvl of "..itemlevel.." !") | |
end | |
--Return random affix | |
if prefix then | |
local index = math.random(1, Abyss.TLength(availablePrefixes)) | |
local ci = 1 | |
for modtype, data in pairs(availablePrefixes) do | |
if AffixAlreadyUsed(usedAffixTypes, modtype) then | |
print(modtype .. "affix already used") | |
return nil | |
end | |
if ci == index then | |
local roll = data[math.random(1, #data)] | |
prefixname = roll.Name | |
print("prefixname = " .. tostring(roll.Name), "typeof(roll) = " .. typeof(roll)) | |
return modtype, roll, prefixname | |
end | |
ci = ci + 1 | |
end | |
else | |
local index = math.random(1, Abyss.TLength(availableSuffixes)) | |
local ci = 1 | |
for modtype, data in pairs(availableSuffixes) do | |
if AffixAlreadyUsed(usedAffixTypes, modtype) then | |
print(modtype .. "affix already used") | |
return nil | |
end | |
if ci == index then | |
local roll = data[math.random(1, #data)] | |
suffixname = roll.Name | |
print("suffixname = " .. tostring(roll.Name), "typeof(roll) = " .. typeof(roll)) | |
return modtype, roll, suffixname | |
end | |
ci = ci + 1 | |
end | |
end | |
end | |
function lootLib.GenerateItem(itemlevel, numaffixes) | |
--TODO: Don't Roll Flat damage mods if they dont have a range (e.g "Adds 5 to 10 Physical damage" instead of "Adds (5-8) to (10-20) Physical damage" | |
local baseASD, basetype, basename = ChooseBaseItem(itemlevel) --TODO: Should this be a deep copy? | |
local baseItem = Deepcopy(baseASD) | |
baseItem.Basename = basename | |
baseItem.Baseitem = baseItem.Name | |
print(basename) | |
print(baseItem) | |
local MaxPrefixes = 3 | |
local MaxSuffixes = 3 | |
if numaffixes <= 2 then | |
MaxPrefixes = 1 | |
MaxSuffixes = 1 | |
end | |
baseItem.Basetype = basetype | |
if lootLib.IsWeapon(basetype) or baseItem.Evasion ~= nil or baseItem.Armour ~= nil then | |
baseItem.Quality = RollQuality() | |
end | |
--ROLL IMPLICIT | |
if baseItem.ImplicitModifier ~= nil then | |
--print("rolling implicit") | |
if typeof(baseItem.ImplicitModifier[2]) == "NumberRange" then | |
--print("baseItem.ImplicitModifier[1] = " .. baseItem.ImplicitModifier[1]) | |
if baseItem.ImplicitModifier[1] == "FlatPhysicalDamage" or baseItem.ImplicitModifier[1] == "FlatColdDamage" or baseItem.ImplicitModifier[1] == "FlatLightningDamage" or baseItem.ImplicitModifier[1] == "FlatFireDamage" or baseItem.ImplicitModifier[1] == "FlatPoisonDamage" then | |
--print("is damage roll, making implicit numberrange instead of rolling") | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], baseItem.ImplicitModifier[2]} | |
else | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], math.random(baseItem.ImplicitModifier[2].Min, baseItem.ImplicitModifier[2].Max)} | |
end | |
elseif typeof(baseItem.ImplicitModifier[2]) == "table" then | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], NumberRange.new(math.random(baseItem.ImplicitModifier[2][1].Min, baseItem.ImplicitModifier[2][1].Max), math.random(baseItem.ImplicitModifier[2][2].Min, baseItem.ImplicitModifier[2][2].Max))} | |
elseif typeof(baseItem.ImplicitModifier[2]) == "number" then | |
baseItem.RolledImplicitModifier = {baseItem.ImplicitModifier[1], baseItem.ImplicitModifier[2]} | |
end | |
end | |
if numaffixes == 0 then | |
baseItem.ItemLevel = itemlevel | |
baseItem.Basetype = basetype | |
return baseItem | |
end | |
baseItem.Modifiers = {Prefixes = {}; Suffixes = {}} | |
baseItem.RolledModifiers = {Prefixes = {}; Suffixes = {}} | |
local prefixes = 0 | |
local suffixes = 0 | |
while true do | |
local dice = math.random() | |
if dice < 0.5 and prefixes < MaxPrefixes and prefixes + suffixes < numaffixes then | |
--PREFIX | |
local modname, data, prefixname = lootLib.GenerateAffix(basetype, itemlevel, true, false, ListOfExistingAffixes(baseItem.RolledModifiers)) | |
if modname ~= nil then | |
baseItem.PrefixName = prefixname | |
baseItem.Modifiers.Prefixes[modname] = {Name = modname, Value = data.Value, AffixName = data.Name} | |
if typeof(data.Value) == "NumberRange" then | |
local int, float = math.modf(data.Value.Min) | |
local int2, float2 = math.modf(data.Value.Max) | |
if float > 0 or float2 > 0 then | |
baseItem.RolledModifiers.Prefixes[modname] = {Name = modname, Value = mathLib.Round(mathLib.RandomFloat(data.Value.Min, data.Value.Max), 2), AffixName = data.Name} | |
else | |
baseItem.RolledModifiers.Prefixes[modname] = {Name = modname, Value = math.random(data.Value.Min, data.Value.Max), AffixName = data.Name} | |
end | |
elseif typeof(data.Value) == "table" then | |
baseItem.RolledModifiers.Prefixes[modname] = {Name = modname, Value = NumberRange.new(math.random(data.Value[1].Min, data.Value[1].Max), math.random(data.Value[2].Min, data.Value[2].Max)), AffixName = data.Name} | |
end | |
if baseItem.ReqLvl < data.ReqLvl then | |
baseItem.ReqLvl = data.ReqLvl | |
end | |
prefixes = prefixes + 1 | |
end | |
elseif dice >= 0.5 and suffixes < MaxSuffixes and prefixes + suffixes < numaffixes then | |
--SUFFIX | |
local modname, data, suffixname = lootLib.GenerateAffix(basetype, itemlevel, false, true, ListOfExistingAffixes(baseItem.RolledModifiers)) | |
if modname ~= nil then | |
baseItem.SuffixName = suffixname | |
baseItem.Modifiers.Suffixes[modname] = {Name = modname, Value = data.Value, AffixName = data.Name} | |
if typeof(data.Value) == "NumberRange" then | |
local int, float = math.modf(data.Value.Min) | |
local int2, float2 = math.modf(data.Value.Max) | |
if float > 0 or float2 > 0 then | |
baseItem.RolledModifiers.Suffixes[modname] = {Name = modname, Value = mathLib.Round(mathLib.RandomFloat(data.Value.Min, data.Value.Max), 2), AffixName = data.Name} | |
else | |
baseItem.RolledModifiers.Suffixes[modname] = {Name = modname, Value = math.random(data.Value.Min, data.Value.Max), AffixName = data.Name} | |
end | |
elseif typeof(data.Value) == "table" then | |
baseItem.RolledModifiers.Suffixes[modname] = {Name = modname, Value = NumberRange.new(math.random(data.Value[1].Min, data.Value[1].Max), math.random(data.Value[2].Min, data.Value[2].Max)), AffixName = data.Name} | |
end | |
if baseItem.ReqLvl < data.ReqLvl then | |
baseItem.ReqLvl = data.ReqLvl | |
end | |
suffixes = suffixes + 1 | |
end | |
else | |
break | |
end | |
end | |
baseItem.ItemLevel = itemlevel | |
--Make changes to damage tables if flat damage mods are present | |
if lootLib.IsWeapon(baseItem.Basetype) then | |
baseItem = InitializeWeaponMods(baseItem) | |
else | |
baseItem = InitializeOtherMods(baseItem) | |
end | |
return baseItem | |
end | |
local function AffixExists(item, name, includeImplicit) | |
if includeImplicit and (item.RolledImplicitModifier ~= nil and item.RolledImplicitModifier ~= "" and item.RolledImplicitModifier ~= {}) then | |
if item.RolledImplicitModifier[1] == name then | |
return item.RolledImplicitModifier[2] | |
end | |
end | |
for _, prefix in pairs(item.RolledModifiers.Prefixes) do | |
if prefix.Name == name then | |
return prefix.Value | |
end | |
end | |
for _, suffix in pairs(item.RolledModifiers.Suffixes) do | |
if suffix.Name == name then | |
return suffix.Value | |
end | |
end | |
return nil | |
end | |
function InitializeOtherMods(baseItem) | |
local flatarmour = AffixExists(baseItem, "FlatArmour") | |
local flatevasion = AffixExists(baseItem, "FlatEvasion") | |
local incarmour = (AffixExists(baseItem, "LocalIncreasedArmour") or 0) + (math.clamp((baseItem.Quality or 0), 0, 20)) | |
local incevasion = (AffixExists(baseItem, "LocalIncreasedEvasion") or 0) + (math.clamp((baseItem.Quality or 0), 0, 20)) | |
local flathybrid = AffixExists(baseItem, "FlatArmourAndEvasion") | |
local inchybrid = (AffixExists(baseItem, "LocalIncreasedArmourAndEvasion") or 0) + (math.clamp((baseItem.Quality or 0), 0, 20)) | |
local addBlock = AffixExists(baseItem, "AdditionalBlockChance") | |
local incAttributeReqs = AffixExists(baseItem, "IncreasedAttributeRequirements") | |
local redAttributeReqs = AffixExists(baseItem, "ReducedAttributeRequirements") | |
local flatAttReq = AffixExists(baseItem, "FlatAttributeRequirements") | |
local flatStrReq = AffixExists(baseItem, "FlatStrengthRequirements") | |
local flatDexReq = AffixExists(baseItem, "FlatDexterityRequirements") | |
local flatIntReq = AffixExists(baseItem, "FlatIntelligenceRequirements") | |
if incAttributeReqs ~= nil or redAttributeReqs ~= nil or flatAttReq ~= nil or flatStrReq ~= nil or flatDexReq ~= nil or flatIntReq ~= nil then | |
if baseItem.Strength ~= nil then | |
baseItem.Strength = (flatAttReq or 0) + (flatStrReq or 0) + (math.floor(baseItem.Strength * (1 + (((incAttributeReqs or 0) - (redAttributeReqs or 0)) / 100)))) | |
end | |
if baseItem.Dexterity ~= nil then | |
baseItem.Dexterity = (flatAttReq or 0) + (flatDexReq or 0) + (math.floor(baseItem.Dexterity * (1 + (((incAttributeReqs or 0) - (redAttributeReqs or 0)) / 100)))) | |
end | |
if baseItem.Intelligence ~= nil then | |
baseItem.Intelligence = (flatAttReq or 0) + (flatIntReq or 0) + (math.floor(baseItem.Intelligence * (1 + (((incAttributeReqs or 0) - (redAttributeReqs or 0)) / 100)))) | |
end | |
end | |
if baseItem.Armour ~= nil and baseItem.Evasion ~= nil then | |
if baseItem.Armour > 0 and baseItem.Evasion <= 0 then | |
local totalflat = baseItem.Armour + (flatarmour or 0) | |
baseItem.Armour = totalflat * (1 + ((incarmour or 0) / 100)) | |
elseif baseItem.Evasion > 0 and baseItem.Armour <= 0 then | |
local totalflat = baseItem.Evasion + (flatevasion or 0) | |
baseItem.Evasion = totalflat * (1 + ((incevasion or 0) / 100)) | |
elseif baseItem.Evasion > 0 and baseItem.Armour > 0 then | |
local totalflatAR = baseItem.Armour + (flathybrid or 0) | |
local totalflatEV = baseItem.Evasion + (flathybrid or 0) | |
baseItem.Armour = totalflatAR * (1 + ((inchybrid or 0) / 100)) | |
baseItem.Evasion = totalflatEV * (1 + ((inchybrid or 0) / 100)) | |
end | |
end | |
if baseItem.BlockChance ~= nil then | |
if baseItem.BlockChance > 0 then | |
baseItem.BlockChance = baseItem.BlockChance + (addBlock or 0) | |
end | |
end | |
return baseItem | |
end | |
function InitializeWeaponMods(baseItem) | |
local phys = AffixExists(baseItem, "FlatPhysicalDamage") | |
local incphys = (AffixExists(baseItem, "IncreasedPhysicalDamage") or 0) + (math.clamp((baseItem.Quality or 0), 0, 20)) | |
local fire = AffixExists(baseItem, "FlatFireDamage") | |
local cold = AffixExists(baseItem, "FlatColdDamage") | |
local light = AffixExists(baseItem, "FlatLightningDamage") | |
local poison = AffixExists(baseItem, "FlatPoisonDamage") | |
local ias = AffixExists(baseItem, "IncreasedAttackSpeed", true) | |
local rias = AffixExists(baseItem, "ReducedAttackSpeed", true) | |
local crit = AffixExists(baseItem, "LocalCriticalStrikeChance", true) | |
local incAttributeReqs = AffixExists(baseItem, "IncreasedAttributeRequirements") | |
local redAttributeReqs = AffixExists(baseItem, "ReducedAttributeRequirements") | |
local flatAttReq = AffixExists(baseItem, "FlatAttributeRequirements") | |
local flatStrReq = AffixExists(baseItem, "FlatStrengthRequirements") | |
local flatDexReq = AffixExists(baseItem, "FlatDexterityRequirements") | |
local flatIntReq = AffixExists(baseItem, "FlatIntelligenceRequirements") | |
if incAttributeReqs ~= nil or redAttributeReqs ~= nil or flatAttReq ~= nil or flatStrReq ~= nil or flatDexReq ~= nil or flatIntReq ~= nil then | |
if baseItem.Strength ~= nil then | |
baseItem.Strength = (flatAttReq or 0) + (flatStrReq or 0) + (math.floor(baseItem.Strength * (1 + (((incAttributeReqs or 0) - (redAttributeReqs or 0)) / 100)))) | |
end | |
if baseItem.Dexterity ~= nil then | |
baseItem.Dexterity = (flatAttReq or 0) + (flatDexReq or 0) + (math.floor(baseItem.Dexterity * (1 + (((incAttributeReqs or 0) - (redAttributeReqs or 0)) / 100)))) | |
end | |
if baseItem.Intelligence ~= nil then | |
baseItem.Intelligence = (flatAttReq or 0) + (flatIntReq or 0) + (math.floor(baseItem.Intelligence * (1 + (((incAttributeReqs or 0) - (redAttributeReqs or 0)) / 100)))) | |
end | |
end | |
if phys ~= nil then | |
if incphys ~= nil then | |
baseItem.Damage.Physical = NumberRange.new(mathLib.Round((baseItem.Damage.Physical.Min + phys.Min) * (1 + (incphys/100)), 2), mathLib.Round((baseItem.Damage.Physical.Max + phys.Max) * (1 + (incphys/100)), 2)) | |
else | |
baseItem.Damage.Physical = NumberRange.new(baseItem.Damage.Physical.Min + phys.Min, baseItem.Damage.Physical.Max + phys.Max) | |
end | |
elseif phys == nil then | |
if incphys ~= nil then | |
baseItem.Damage.Physical = NumberRange.new(mathLib.Round((baseItem.Damage.Physical.Min) * (1 + (incphys/100)), 2), mathLib.Round((baseItem.Damage.Physical.Max) * (1 + (incphys/100)), 2)) | |
end | |
end | |
if fire ~= nil then | |
baseItem.Damage.Fire = NumberRange.new(baseItem.Damage.Fire.Min + fire.Min, baseItem.Damage.Fire.Max + fire.Max) | |
end | |
if cold ~= nil then | |
baseItem.Damage.Cold = NumberRange.new(baseItem.Damage.Cold.Min + cold.Min, baseItem.Damage.Cold.Max + cold.Max) | |
end | |
if light ~= nil then | |
baseItem.Damage.Lightning = NumberRange.new(baseItem.Damage.Lightning.Min + light.Min, baseItem.Damage.Lightning.Max + light.Max) | |
end | |
if poison ~= nil then | |
baseItem.Damage.Poison = NumberRange.new(baseItem.Damage.Poison.Min + poison.Min, baseItem.Damage.Poison.Max + poison.Max) | |
end | |
if ias ~= nil then | |
baseItem.AttacksPerSecond = mathLib.Round(baseItem.AttacksPerSecond * (1 + (ias/100)), 2) | |
end | |
if rias ~= nil then | |
baseItem.AttacksPerSecond = mathLib.Round(baseItem.AttacksPerSecond * (1 - (rias/100)), 2) | |
end | |
if crit then | |
print("crit is of type " .. typeof(crit)) | |
baseItem.CriticalStrikeChance = mathLib.Round(baseItem.CriticalStrikeChance * (1 + (crit/100)), 2) | |
end | |
return baseItem | |
end | |
function lootLib.DropItem() | |
warn("WARNING! LootLib.DropItem was called from client!") | |
end | |
function lootLib.GetItemDrop(IIR, itemlevel, forceRarity, forceSpecificUnique) | |
print("getting item drop, ilvl ".. itemlevel) | |
local typeRoll = math.random() | |
if forceRarity == nil then | |
--Drop Currency | |
if typeRoll < ItemChances[1][2] then | |
print("currency drop") | |
local roll = math.random() | |
for i = 1, #CurrencyDropChances do | |
local currencyData = CurrencyDropChances[i] | |
if roll <= currencyData[2] then | |
return currencyData[1] | |
end | |
end | |
return CurrencyDropChances[#CurrencyDropChances][1] | |
end | |
end | |
--Drop Equipment | |
local itemRarity = forceRarity or GetItemRarity(IIR) | |
if itemRarity == "Magic" then | |
print("magic drop") | |
local item = lootLib.GenerateItem(itemlevel, math.random(1, 2)) | |
item.Rarity = "Magic" | |
print("generated item") | |
return item | |
elseif itemRarity == "Rare" then | |
print("rare drop") | |
local item = lootLib.GenerateItem(itemlevel, math.random(4, 6)) | |
item.Name = GenerateRarename(item.Basetype) | |
item.Rarity = "Rare" | |
print("generated item") | |
return item | |
elseif itemRarity == "Unique" then | |
print("unique drop") | |
local item = lootLib.GenerateUnique(itemlevel, forceSpecificUnique) | |
if item == nil then | |
return nil | |
end | |
item.Rarity = "Unique" | |
print("generated item") | |
return item | |
else | |
print("normal drop") | |
local item = lootLib.GenerateItem(itemlevel, 0) | |
item.Rarity = "Normal" | |
print("generated item") | |
return item | |
end | |
end | |
function lootLib.DropItem(IIR, itemlevel) | |
print("dropping item :)") | |
return lootLib.GetItemDrop(IIR, itemlevel) | |
end | |
PoolProbabilities(CurrencyDropChances) | |
PoolProbabilities(ItemChances) | |
PoolProbabilities(RarityChances) | |
PoolProbabilities(QualityChances) | |
return lootLib |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment