Files
PathOfBuilding/Modules/Data.lua
Jack Lockwood 8c83776c8e Release 1.4.152.1
Updates uniques with 3.8 Changes
Adds new 3.8 uniques
Fix tempered flesh/mind not working
Fix minion regen nodes on the tree not being parsed correctly
Not all unique mods are parsed correctly
2019-10-05 17:19:24 +10:00

346 lines
12 KiB
Lua

-- Path of Building
--
-- Module: Data
-- Contains static data used by other modules.
--
LoadModule("Data/Global")
local skillTypes = {
"act_str",
"act_dex",
"act_int",
"other",
"glove",
"minion",
"spectre",
"sup_str",
"sup_dex",
"sup_int",
}
local itemTypes = {
"axe",
"bow",
"claw",
"dagger",
"mace",
"staff",
"sword",
"wand",
"helmet",
"body",
"gloves",
"boots",
"shield",
"quiver",
"amulet",
"ring",
"belt",
"jewel",
"flask",
}
local function makeSkillMod(modName, modType, modVal, flags, keywordFlags, ...)
return {
name = modName,
type = modType,
value = modVal,
flags = flags or 0,
keywordFlags = keywordFlags or 0,
...
}
end
local function makeFlagMod(modName, ...)
return makeSkillMod(modName, "FLAG", true, 0, 0, ...)
end
local function makeSkillDataMod(dataKey, dataValue, ...)
return makeSkillMod("SkillData", "LIST", { key = dataKey, value = dataValue }, 0, 0, ...)
end
local function processMod(grantedEffect, mod)
mod.source = grantedEffect.modSource
if type(mod.value) == "table" and mod.value.mod then
mod.value.mod.source = "Skill:"..grantedEffect.id
end
for _, tag in ipairs(mod) do
if tag.type == "GlobalEffect" then
grantedEffect.hasGlobalEffect = true
break
end
end
end
-----------------
-- Common Data --
-----------------
data = { }
data.powerStatList = {
{ stat=nil, label="Offence/Defence", combinedOffDef=true, ignoreForItems=true },
{ stat=nil, label="Name", itemField="Name", ignoreForNodes=true, reverseSort=true, transform=function(value) return value:gsub("^The ","") end},
{ stat="CombinedDPS", label="Combined DPS" },
{ stat="TotalDPS", label="Total DPS" },
{ stat="TotalPoisonDPS", label="Total Poison DPS" },
{ stat="TotalIgniteDPS", label="Total Ignite DPS" },
{ stat="TotalDot", label="Total DoT" },
{ stat="Life", label="Life" },
{ stat="LifeRegen", label="Life regen" },
{ stat="LifeLeechRate", label="Life leech" },
{ stat="EnergyShield", label="Energy Shield" },
{ stat="EnergyShieldRegen", label="Energy Shield regen" },
{ stat="EnergyShieldLeechRate", label="Energy Shield leech" },
{ stat="Mana", label="Mana" },
{ stat="ManaRegen", label="Mana regen" },
{ stat="ManaLeechRate", label="Mana leech" },
{ stat="MeleeAvoidChance", label="Melee avoid chance" },
{ stat="SpellAvoidChance", label="Spell avoid chance" },
{ stat="ProjectileAvoidChance", label="Projectile avoid chance" },
{ stat="PhysicalTakenHitMult", label="Taken Phys dmg", transform=function(value) return 1-value end },
{ stat="FireTakenDotMult", label="Taken Fire dmg", transform=function(value) return 1-value end },
{ stat="ColdTakenDotMult", label="Taken Cold dmg", transform=function(value) return 1-value end },
{ stat="LightningTakenDotMult", label="Taken Lightning dmg", transform=function(value) return 1-value end },
{ stat="ChaosTakenHitMult", label="Taken Chaos dmg", transform=function(value) return 1-value end },
{ stat="CritChance", label="Crit Chance" },
{ stat="BleedChance", label="Bleed Chance" },
{ stat="FreezeChance", label="Freeze Chance" },
{ stat="IgniteChance", label="Ignite Chance" },
{ stat="ShockChance", label="Shock Chance" },
{ stat="EffectiveMovementSpeedMod", label="Move speed" },
}
data.skillColorMap = { colorCodes.STRENGTH, colorCodes.DEXTERITY, colorCodes.INTELLIGENCE, colorCodes.NORMAL }
data.jewelRadius = {
{ rad = 800, col = "^xBB6600", label = "Small" },
{ rad = 1200, col = "^x66FFCC", label = "Medium" },
{ rad = 1500, col = "^x2222CC", label = "Large" }
}
data.labyrinths = {
{ name = "ENDGAME", label = "Eternal" },
{ name = "MERCILESS", label = "Merciless" },
{ name = "CRUEL", label = "Cruel" },
{ name = "NORMAL", label = "Normal" },
}
data.monsterExperienceLevelMap = { [71] = 70.94, [72] = 71.82, [73] = 72.64, [74] = 73.40, [75] = 74.10, [76] = 74.74, [77] = 75.32, [78] = 75.84, [79] = 76.30, [80] = 76.70, [81] = 77.04, [82] = 77.32, [83] = 77.54, [84] = 77.70, }
for i = 1, 70 do
data.monsterExperienceLevelMap[i] = i
end
data.weaponTypeInfo = {
["None"] = { oneHand = true, melee = true, flag = "Unarmed" },
["Bow"] = { oneHand = false, melee = false, flag = "Bow" },
["Claw"] = { oneHand = true, melee = true, flag = "Claw" },
["Dagger"] = { oneHand = true, melee = true, flag = "Dagger" },
["Staff"] = { oneHand = false, melee = true, flag = "Staff" },
["Wand"] = { oneHand = true, melee = false, flag = "Wand" },
["One Handed Axe"] = { oneHand = true, melee = true, flag = "Axe" },
["One Handed Mace"] = { oneHand = true, melee = true, flag = "Mace" },
["One Handed Sword"] = { oneHand = true, melee = true, flag = "Sword" },
["Sceptre"] = { oneHand = true, melee = true, flag = "Mace", label = "One Handed Mace" },
["Thrusting One Handed Sword"] = { oneHand = true, melee = true, flag = "Sword", label = "One Handed Sword" },
["Two Handed Axe"] = { oneHand = false, melee = true, flag = "Axe" },
["Two Handed Mace"] = { oneHand = false, melee = true, flag = "Mace" },
["Two Handed Sword"] = { oneHand = false, melee = true, flag = "Sword" },
}
data.unarmedWeaponData = {
[0] = { type = "None", AttackRate = 1.2, CritChance = 0, PhysicalMin = 2, PhysicalMax = 6 }, -- Scion
[1] = { type = "None", AttackRate = 1.2, CritChance = 0, PhysicalMin = 2, PhysicalMax = 8 }, -- Marauder
[2] = { type = "None", AttackRate = 1.2, CritChance = 0, PhysicalMin = 2, PhysicalMax = 5 }, -- Ranger
[3] = { type = "None", AttackRate = 1.2, CritChance = 0, PhysicalMin = 2, PhysicalMax = 5 }, -- Witch
[4] = { type = "None", AttackRate = 1.2, CritChance = 0, PhysicalMin = 2, PhysicalMax = 6 }, -- Duelist
[5] = { type = "None", AttackRate = 1.2, CritChance = 0, PhysicalMin = 2, PhysicalMax = 6 }, -- Templar
[6] = { type = "None", AttackRate = 1.2, CritChance = 0, PhysicalMin = 2, PhysicalMax = 5 }, -- Shadow
}
data.specialBaseTags = {
["Amulet"] = { shaper = "amulet_shaper", elder = "amulet_elder", },
["Ring"] = { shaper = "ring_shaper", elder = "ring_elder", },
["Claw"] = { shaper = "claw_shaper", elder = "claw_elder", },
["Dagger"] = { shaper = "dagger_shaper", elder = "dagger_elder", },
["Wand"] = { shaper = "wand_shaper", elder = "wand_elder", },
["One Handed Sword"] = { shaper = "sword_shaper", elder = "sword_elder", },
["Thrusting One Handed Sword"] = { shaper = "sword_shaper", elder = "sword_elder", },
["One Handed Axe"] = { shaper = "axe_shaper", elder = "axe_elder", },
["One Handed Mace"] = { shaper = "mace_shaper", elder = "mace_elder", },
["Bow"] = { shaper = "bow_shaper", elder = "bow_elder", },
["Staff"] = { shaper = "staff_shaper", elder = "staff_elder", },
["Two Handed Sword"] = { shaper = "2h_sword_shaper", elder = "2h_sword_elder", },
["Two Handed Axe"] = { shaper = "2h_axe_shaper", elder = "2h_axe_elder", },
["Two Handed Mace"] = { shaper = "2h_mace_shaper", elder = "2h_mace_elder", },
["Quiver"] = { shaper = "quiver_shaper", elder = "quiver_elder", },
["Belt"] = { shaper = "belt_shaper", elder = "belt_elder", },
["Gloves"] = { shaper = "gloves_shaper", elder = "gloves_elder", },
["Boots"] = { shaper = "boots_shaper", elder = "boots_elder", },
["Body Armour"] = { shaper = "body_armour_shaper", elder = "body_armour_elder", },
["Helmet"] = { shaper = "helmet_shaper", elder = "helmet_elder", },
["Shield"] = { shaper = "shield_shaper", elder = "shield_elder", },
["Sceptre"] = { shaper = "sceptre_shaper", elder = "sceptre_elder", },
}
-- Uniques
data.uniques = { }
for _, type in pairs(itemTypes) do
data.uniques[type] = LoadModule("Data/Uniques/"..type)
end
LoadModule("Data/New")
---------------------------
-- Version-specific Data --
---------------------------
for _, targetVersion in ipairs(targetVersionList) do
local verData = setmetatable({ }, { __index = data })
data[targetVersion] = verData
local function dataModule(mod, ...)
return LoadModule("Data/"..targetVersion.."/"..mod, ...)
end
-- Misc data tables
dataModule("Misc", verData)
-- Stat descriptions
if targetVersion ~= "2_6" then
verData.describeStats = LoadModule("Modules/StatDescriber", targetVersion)
end
-- Load item modifiers
verData.itemMods = {
Item = dataModule("ModItem"),
Flask = dataModule("ModFlask"),
Jewel = dataModule("ModJewel"),
JewelAbyss = targetVersion ~= "2_6" and dataModule("ModJewelAbyss") or { },
}
verData.masterMods = dataModule("ModMaster")
verData.enchantments = {
Helmet = dataModule("EnchantmentHelmet"),
Boots = dataModule("EnchantmentBoots"),
Gloves = dataModule("EnchantmentGloves"),
}
verData.essences = dataModule("Essence")
verData.pantheons = targetVersion ~= "2_6" and dataModule("Pantheons") or { }
-- Load skills
verData.skills = { }
verData.skillStatMap = dataModule("SkillStatMap", makeSkillMod, makeFlagMod, makeSkillDataMod)
verData.skillStatMapMeta = {
__index = function(t, key)
local map = verData.skillStatMap[key]
if map then
t[key] = copyTable(map, true)
for _, mod in ipairs(map) do
processMod(t._grantedEffect, mod)
end
return map
end
end
}
for _, type in pairs(skillTypes) do
dataModule("Skills/"..type, verData.skills, makeSkillMod, makeFlagMod, makeSkillDataMod)
end
for skillId, grantedEffect in pairs(verData.skills) do
grantedEffect.id = skillId
grantedEffect.modSource = "Skill:"..skillId
-- Add sources for skill mods, and check for global effects
for _, list in pairs({grantedEffect.baseMods, grantedEffect.qualityMods, grantedEffect.levelMods}) do
for _, mod in pairs(list) do
if mod.name then
processMod(grantedEffect, mod)
else
for _, mod in ipairs(mod) do
processMod(grantedEffect, mod)
end
end
end
end
-- Install stat map metatable
grantedEffect.statMap = grantedEffect.statMap or { }
setmetatable(grantedEffect.statMap, verData.skillStatMapMeta)
grantedEffect.statMap._grantedEffect = grantedEffect
for _, map in pairs(grantedEffect.statMap) do
for _, mod in ipairs(map) do
processMod(grantedEffect, mod)
end
end
end
-- Load gems
verData.gems = dataModule("Gems")
verData.gemForSkill = { }
for gemId, gem in pairs(verData.gems) do
gem.id = gemId
gem.grantedEffect = verData.skills[gem.grantedEffectId]
verData.gemForSkill[gem.grantedEffect] = gemId
gem.secondaryGrantedEffect = gem.secondaryGrantedEffectId and verData.skills[gem.secondaryGrantedEffectId]
gem.grantedEffectList = {
gem.grantedEffect,
gem.secondaryGrantedEffect
}
gem.defaultLevel = (#gem.grantedEffect.levels > 20 and #gem.grantedEffect.levels - 20) or (gem.grantedEffect.levels[3][1] and 3) or 1
end
-- Load minions
verData.minions = { }
dataModule("Minions", verData.minions, makeSkillMod)
verData.spectres = { }
dataModule("Spectres", verData.spectres, makeSkillMod)
for name, spectre in pairs(verData.spectres) do
spectre.limit = "ActiveSpectreLimit"
verData.minions[name] = spectre
end
local missing = { }
for _, minion in pairs(verData.minions) do
for _, skillId in ipairs(minion.skillList) do
if launch.devMode and not verData.skills[skillId] and not missing[skillId] then
ConPrintf("'%s' missing skill '%s'", minion.name, skillId)
missing[skillId] = true
end
end
for _, mod in ipairs(minion.modList) do
mod.source = "Minion:"..minion.name
end
end
-- Item bases
verData.itemBases = { }
for _, type in pairs(itemTypes) do
dataModule("Bases/"..type, verData.itemBases)
end
-- Build lists of item bases, separated by type
verData.itemBaseLists = { }
for name, base in pairs(verData.itemBases) do
if not base.hidden then
local type = base.type
if base.subType then
type = type .. ": " .. base.subType
end
verData.itemBaseLists[type] = verData.itemBaseLists[type] or { }
table.insert(verData.itemBaseLists[type], { label = name:gsub(" %(.+%)",""), name = name, base = base })
end
end
verData.itemBaseTypeList = { }
for type, list in pairs(verData.itemBaseLists) do
table.insert(verData.itemBaseTypeList, type)
table.sort(list, function(a, b)
if a.base.req and b.base.req then
if a.base.req.level == b.base.req.level then
return a.name < b.name
else
return (a.base.req.level or 1) > (b.base.req.level or 1)
end
elseif a.base.req and not b.base.req then
return true
elseif b.base.req and not a.base.req then
return false
else
return a.name < b.name
end
end)
end
table.sort(verData.itemBaseTypeList)
-- Rare templates
verData.rares = dataModule("Rares")
end