Release 1.2.40
- Added movement speed calculation - Fixed ignite breakdown - Changed "frozen, shocked, or ignited enemies", and similar, to use varLists (to fix condition detection) - Many changes for flask support
This commit is contained in:
@@ -225,64 +225,65 @@ function buildMode:Init(dbFileName, buildName)
|
||||
-- This defines the stats in the side bar, and also which stats show in node/item comparisons
|
||||
-- This may be user-customisable in the future
|
||||
self.displayStats = {
|
||||
{ mod = "AverageHit", label = "Average Hit", fmt = ".1f", compPercent = true },
|
||||
{ mod = "AverageDamage", label = "Average Damage", fmt = ".1f", compPercent = true, flag = "attack" },
|
||||
{ mod = "Speed", label = "Attack Rate", fmt = ".2f", compPercent = true, flag = "attack" },
|
||||
{ mod = "Speed", label = "Cast Rate", fmt = ".2f", compPercent = true, flag = "spell" },
|
||||
{ mod = "HitSpeed", label = "Hit Rate", fmt = ".2f" },
|
||||
{ mod = "CritChance", label = "Crit Chance", fmt = ".2f%%" },
|
||||
{ mod = "CritMultiplier", label = "Crit Multiplier", fmt = "d%%", pc = true, condFunc = function(v,o) return o.CritChance > 0 end },
|
||||
{ mod = "HitChance", label = "Hit Chance", fmt = ".0f%%", flag = "attack" },
|
||||
{ mod = "TotalDPS", label = "Total DPS", fmt = ".1f", compPercent = true, flag = "notAverage" },
|
||||
{ mod = "TotalDot", label = "DoT DPS", fmt = ".1f", compPercent = true },
|
||||
{ mod = "BleedDPS", label = "Bleed DPS", fmt = ".1f", compPercent = true },
|
||||
{ mod = "IgniteDPS", label = "Ignite DPS", fmt = ".1f", compPercent = true },
|
||||
{ mod = "IgniteDamage", label = "Total Damage per Ignite", fmt = ".1f", compPercent = true },
|
||||
{ mod = "WithIgniteDPS", label = "Total DPS inc. Ignite", fmt = ".1f", compPercent = true },
|
||||
{ mod = "WithIgniteAverageDamage", label = "Average Dmg. inc. Ignite", fmt = ".1f", compPercent = true },
|
||||
{ mod = "PoisonDPS", label = "Poison DPS", fmt = ".1f", compPercent = true },
|
||||
{ mod = "PoisonDamage", label = "Total Damage per Poison", fmt = ".1f", compPercent = true },
|
||||
{ mod = "WithPoisonDPS", label = "Total DPS inc. Poison", fmt = ".1f", compPercent = true },
|
||||
{ mod = "WithPoisonAverageDamage", label = "Average Dmg. inc. Poison", fmt = ".1f", compPercent = true },
|
||||
{ mod = "ManaCost", label = "Mana Cost", fmt = "d", compPercent = true, lowerIsBetter = true, condFunc = function() return true end },
|
||||
{ stat = "AverageHit", label = "Average Hit", fmt = ".1f", compPercent = true },
|
||||
{ stat = "AverageDamage", label = "Average Damage", fmt = ".1f", compPercent = true, flag = "attack" },
|
||||
{ stat = "Speed", label = "Attack Rate", fmt = ".2f", compPercent = true, flag = "attack" },
|
||||
{ stat = "Speed", label = "Cast Rate", fmt = ".2f", compPercent = true, flag = "spell" },
|
||||
{ stat = "HitSpeed", label = "Hit Rate", fmt = ".2f" },
|
||||
{ stat = "CritChance", label = "Crit Chance", fmt = ".2f%%" },
|
||||
{ stat = "CritMultiplier", label = "Crit Multiplier", fmt = "d%%", pc = true, condFunc = function(v,o) return o.CritChance > 0 end },
|
||||
{ stat = "HitChance", label = "Hit Chance", fmt = ".0f%%", flag = "attack" },
|
||||
{ stat = "TotalDPS", label = "Total DPS", fmt = ".1f", compPercent = true, flag = "notAverage" },
|
||||
{ stat = "TotalDot", label = "DoT DPS", fmt = ".1f", compPercent = true },
|
||||
{ stat = "BleedDPS", label = "Bleed DPS", fmt = ".1f", compPercent = true },
|
||||
{ stat = "IgniteDPS", label = "Ignite DPS", fmt = ".1f", compPercent = true },
|
||||
{ stat = "IgniteDamage", label = "Total Damage per Ignite", fmt = ".1f", compPercent = true },
|
||||
{ stat = "WithIgniteDPS", label = "Total DPS inc. Ignite", fmt = ".1f", compPercent = true },
|
||||
{ stat = "WithIgniteAverageDamage", label = "Average Dmg. inc. Ignite", fmt = ".1f", compPercent = true },
|
||||
{ stat = "PoisonDPS", label = "Poison DPS", fmt = ".1f", compPercent = true },
|
||||
{ stat = "PoisonDamage", label = "Total Damage per Poison", fmt = ".1f", compPercent = true },
|
||||
{ stat = "WithPoisonDPS", label = "Total DPS inc. Poison", fmt = ".1f", compPercent = true },
|
||||
{ stat = "WithPoisonAverageDamage", label = "Average Dmg. inc. Poison", fmt = ".1f", compPercent = true },
|
||||
{ stat = "ManaCost", label = "Mana Cost", fmt = "d", compPercent = true, lowerIsBetter = true, condFunc = function() return true end },
|
||||
{ },
|
||||
{ mod = "Str", label = "Strength", fmt = "d" },
|
||||
{ mod = "Dex", label = "Dexterity", fmt = "d" },
|
||||
{ mod = "Int", label = "Intelligence", fmt = "d" },
|
||||
{ stat = "Str", label = "Strength", fmt = "d" },
|
||||
{ stat = "Dex", label = "Dexterity", fmt = "d" },
|
||||
{ stat = "Int", label = "Intelligence", fmt = "d" },
|
||||
{ },
|
||||
{ mod = "Life", label = "Total Life", fmt = "d", compPercent = true },
|
||||
{ mod = "Spec:LifeInc", label = "%Inc Life from Tree", fmt = "d%%", condFunc = function(v,o) return v > 0 and o.Life > 1 end },
|
||||
{ mod = "LifeUnreserved", label = "Unreserved Life", fmt = "d", condFunc = function(v,o) return v < o.Life end, compPercent = true },
|
||||
{ mod = "LifeUnreservedPercent", label = "Unreserved Life", fmt = "d%%", condFunc = function(v,o) return v < 100 end },
|
||||
{ mod = "LifeRegen", label = "Life Regen", fmt = ".1f" },
|
||||
{ stat = "Life", label = "Total Life", fmt = "d", compPercent = true },
|
||||
{ stat = "Spec:LifeInc", label = "%Inc Life from Tree", fmt = "d%%", condFunc = function(v,o) return v > 0 and o.Life > 1 end },
|
||||
{ stat = "LifeUnreserved", label = "Unreserved Life", fmt = "d", condFunc = function(v,o) return v < o.Life end, compPercent = true },
|
||||
{ stat = "LifeUnreservedPercent", label = "Unreserved Life", fmt = "d%%", condFunc = function(v,o) return v < 100 end },
|
||||
{ stat = "LifeRegen", label = "Life Regen", fmt = ".1f" },
|
||||
{ },
|
||||
{ mod = "Mana", label = "Total Mana", fmt = "d", compPercent = true },
|
||||
{ mod = "Spec:ManaInc", label = "%Inc Mana from Tree", fmt = "d%%" },
|
||||
{ mod = "ManaUnreserved", label = "Unreserved Mana", fmt = "d", condFunc = function(v,o) return v < o.Mana end, compPercent = true },
|
||||
{ mod = "ManaUnreservedPercent", label = "Unreserved Mana", fmt = "d%%", condFunc = function(v,o) return v < 100 end },
|
||||
{ mod = "ManaRegen", label = "Mana Regen", fmt = ".1f" },
|
||||
{ stat = "Mana", label = "Total Mana", fmt = "d", compPercent = true },
|
||||
{ stat = "Spec:ManaInc", label = "%Inc Mana from Tree", fmt = "d%%" },
|
||||
{ stat = "ManaUnreserved", label = "Unreserved Mana", fmt = "d", condFunc = function(v,o) return v < o.Mana end, compPercent = true },
|
||||
{ stat = "ManaUnreservedPercent", label = "Unreserved Mana", fmt = "d%%", condFunc = function(v,o) return v < 100 end },
|
||||
{ stat = "ManaRegen", label = "Mana Regen", fmt = ".1f" },
|
||||
{ },
|
||||
{ mod = "EnergyShield", label = "Energy Shield", fmt = "d", compPercent = true },
|
||||
{ mod = "Spec:EnergyShieldInc", label = "%Inc ES from Tree", fmt = "d%%" },
|
||||
{ mod = "EnergyShieldRegen", label = "Energy Shield Regen", fmt = ".1f" },
|
||||
{ mod = "Evasion", label = "Evasion rating", fmt = "d", compPercent = true },
|
||||
{ mod = "Spec:EvasionInc", label = "%Inc Evasion from Tree", fmt = "d%%" },
|
||||
{ mod = "EvadeChance", label = "Evade Chance", fmt = "d%%" },
|
||||
{ mod = "Armour", label = "Armour", fmt = "d", compPercent = true },
|
||||
{ mod = "Spec:ArmourInc", label = "%Inc Armour from Tree", fmt = "d%%" },
|
||||
{ mod = "BlockChance", label = "Block Chance", fmt = "d%%" },
|
||||
{ mod = "SpellBlockChance", label = "Spell Block Chance", fmt = "d%%" },
|
||||
{ mod = "AttackDodgeChance", label = "Attack Dodge Chance", fmt = "d%%" },
|
||||
{ mod = "SpellDodgeChance", label = "Spell Dodge Chance", fmt = "d%%" },
|
||||
{ stat = "EnergyShield", label = "Energy Shield", fmt = "d", compPercent = true },
|
||||
{ stat = "Spec:EnergyShieldInc", label = "%Inc ES from Tree", fmt = "d%%" },
|
||||
{ stat = "EnergyShieldRegen", label = "Energy Shield Regen", fmt = ".1f" },
|
||||
{ stat = "Evasion", label = "Evasion rating", fmt = "d", compPercent = true },
|
||||
{ stat = "Spec:EvasionInc", label = "%Inc Evasion from Tree", fmt = "d%%" },
|
||||
{ stat = "EvadeChance", label = "Evade Chance", fmt = "d%%" },
|
||||
{ stat = "Armour", label = "Armour", fmt = "d", compPercent = true },
|
||||
{ stat = "Spec:ArmourInc", label = "%Inc Armour from Tree", fmt = "d%%" },
|
||||
{ stat = "MovementSpeedMod", label = "Movement Speed Modifier", fmt = "+d%%", mod = true },
|
||||
{ stat = "BlockChance", label = "Block Chance", fmt = "d%%" },
|
||||
{ stat = "SpellBlockChance", label = "Spell Block Chance", fmt = "d%%" },
|
||||
{ stat = "AttackDodgeChance", label = "Attack Dodge Chance", fmt = "d%%" },
|
||||
{ stat = "SpellDodgeChance", label = "Spell Dodge Chance", fmt = "d%%" },
|
||||
{ },
|
||||
{ mod = "FireResist", label = "Fire Resistance", fmt = "d%%", condFunc = function() return true end },
|
||||
{ mod = "ColdResist", label = "Cold Resistance", fmt = "d%%", condFunc = function() return true end },
|
||||
{ mod = "LightningResist", label = "Lightning Resistance", fmt = "d%%", condFunc = function() return true end },
|
||||
{ mod = "ChaosResist", label = "Chaos Resistance", fmt = "d%%", condFunc = function() return true end },
|
||||
{ mod = "FireResistOverCap", label = "Fire Res. Over Max", fmt = "d%%" },
|
||||
{ mod = "ColdResistOverCap", label = "Cold Res. Over Max", fmt = "d%%" },
|
||||
{ mod = "LightningResistOverCap", label = "Lightning Res. Over Max", fmt = "d%%" },
|
||||
{ mod = "ChaosResistOverCap", label = "Chaos Res. Over Max", fmt = "d%%" },
|
||||
{ stat = "FireResist", label = "Fire Resistance", fmt = "d%%", condFunc = function() return true end },
|
||||
{ stat = "ColdResist", label = "Cold Resistance", fmt = "d%%", condFunc = function() return true end },
|
||||
{ stat = "LightningResist", label = "Lightning Resistance", fmt = "d%%", condFunc = function() return true end },
|
||||
{ stat = "ChaosResist", label = "Chaos Resistance", fmt = "d%%", condFunc = function() return true end },
|
||||
{ stat = "FireResistOverCap", label = "Fire Res. Over Max", fmt = "d%%" },
|
||||
{ stat = "ColdResistOverCap", label = "Cold Res. Over Max", fmt = "d%%" },
|
||||
{ stat = "LightningResistOverCap", label = "Lightning Res. Over Max", fmt = "d%%" },
|
||||
{ stat = "ChaosResistOverCap", label = "Chaos Res. Over Max", fmt = "d%%" },
|
||||
}
|
||||
|
||||
self.viewMode = "TREE"
|
||||
@@ -584,11 +585,15 @@ function buildMode:RefreshStatList()
|
||||
-- Build list of side bar stats
|
||||
wipeTable(self.controls.statBox.list)
|
||||
for index, statData in ipairs(self.displayStats) do
|
||||
if statData.mod then
|
||||
if statData.stat then
|
||||
if not statData.flag or self.calcsTab.mainEnv.mainSkill.skillFlags[statData.flag] then
|
||||
local modVal = self.calcsTab.mainOutput[statData.mod]
|
||||
local modVal = self.calcsTab.mainOutput[statData.stat]
|
||||
if modVal and ((statData.condFunc and statData.condFunc(modVal,self.calcsTab.mainOutput)) or (not statData.condFunc and modVal ~= 0)) then
|
||||
t_insert(self.controls.statBox.list, { height = 16, "^7"..statData.label..":", string.format("%s%"..statData.fmt, modVal >= 0 and "^7" or data.colorCodes.NEGATIVE, modVal * (statData.pc and 100 or 1)) })
|
||||
t_insert(self.controls.statBox.list, {
|
||||
height = 16,
|
||||
"^7"..statData.label..":",
|
||||
string.format("%s%"..statData.fmt, modVal >= 0 and "^7" or data.colorCodes.NEGATIVE, modVal * ((statData.pc or statData.mod) and 100 or 1) - (statData.mod and 100 or 0))
|
||||
})
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -603,16 +608,16 @@ end
|
||||
function buildMode:AddStatComparesToTooltip(baseOutput, compareOutput, header)
|
||||
local count = 0
|
||||
for _, statData in ipairs(self.displayStats) do
|
||||
if statData.mod and (not statData.flag or self.calcsTab.mainEnv.mainSkill.skillFlags[statData.flag]) then
|
||||
local diff = (compareOutput[statData.mod] or 0) - (baseOutput[statData.mod] or 0)
|
||||
if statData.stat and (not statData.flag or self.calcsTab.mainEnv.mainSkill.skillFlags[statData.flag]) then
|
||||
local diff = (compareOutput[statData.stat] or 0) - (baseOutput[statData.stat] or 0)
|
||||
if diff > 0.001 or diff < -0.001 then
|
||||
if count == 0 then
|
||||
main:AddTooltipLine(14, header)
|
||||
end
|
||||
local color = ((statData.lowerIsBetter and diff < 0) or (not statData.lowerIsBetter and diff > 0)) and data.colorCodes.POSITIVE or data.colorCodes.NEGATIVE
|
||||
local line = string.format("%s%+"..statData.fmt.." %s", color, diff * (statData.pc and 100 or 1), statData.label)
|
||||
if statData.compPercent and (baseOutput[statData.mod] or 0) ~= 0 and (compareOutput[statData.mod] or 0) ~= 0 then
|
||||
line = line .. string.format(" (%+.1f%%)", (compareOutput[statData.mod] or 0) / (baseOutput[statData.mod] or 0) * 100 - 100)
|
||||
local line = string.format("%s%+"..statData.fmt.." %s", color, diff * ((statData.pc or statData.mod) and 100 or 1), statData.label)
|
||||
if statData.compPercent and (baseOutput[statData.stat] or 0) ~= 0 and (compareOutput[statData.stat] or 0) ~= 0 then
|
||||
line = line .. string.format(" (%+.1f%%)", (compareOutput[statData.stat] or 0) / (baseOutput[statData.stat] or 0) * 100 - 100)
|
||||
end
|
||||
main:AddTooltipLine(14, line)
|
||||
count = count + 1
|
||||
|
||||
@@ -622,6 +622,7 @@ return {
|
||||
}, },
|
||||
} },
|
||||
{ 1, "MiscDefences", 3, "Other Defences", data.colorCodes.DEFENCE, {
|
||||
{ label = "Movement Speed", { format = "x {2:output:MovementSpeedMod}", { modName = "MovementSpeed" }, }, },
|
||||
{ label = "Dodge Chance", { format = "{0:output:AttackDodgeChance}%", { modName = "AttackDodgeChance" }, }, },
|
||||
{ label = "Spell Ddg. Chance", { format = "{0:output:SpellDodgeChance}%", { modName = "SpellDodgeChance" }, }, },
|
||||
{ label = "Block Chance", { format = "{0:output:BlockChance}%",
|
||||
|
||||
@@ -726,12 +726,20 @@ local function mergeMainMods(env, repSlotName, repItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
if item and item.type == "Flask" then
|
||||
if env.configInput["enableFlask"..slot.slotNum] then
|
||||
-- FIXME dunno lol
|
||||
env.modDB.conditions["UsingFlask"] = true
|
||||
else
|
||||
item = nil
|
||||
end
|
||||
end
|
||||
env.itemList[slotName] = item
|
||||
if item then
|
||||
-- Merge mods for this item
|
||||
local srcList = item.modList or item.slotModList[slot.slotNum]
|
||||
env.modDB:AddList(srcList)
|
||||
if item.type ~= "Jewel" then
|
||||
if item.type ~= "Jewel" and item.type ~= "Flask" then
|
||||
-- Update item counts
|
||||
local key
|
||||
if item.rarity == "UNIQUE" then
|
||||
@@ -1169,13 +1177,8 @@ local function performCalcs(env)
|
||||
end
|
||||
|
||||
-- Process conditions that can depend on other conditions
|
||||
if env.mode_effective then
|
||||
if condList["EnemyIgnited"] then
|
||||
condList["EnemyBurning"] = true
|
||||
end
|
||||
condList["EnemyFrozenShockedIgnited"] = condList["EnemyFrozen"] or condList["EnemyShocked"] or condList["EnemyIgnited"]
|
||||
condList["EnemyElementalStatus"] = condList["EnemyChilled"] or condList["EnemyFrozen"] or condList["EnemyShocked"] or condList["EnemyIgnited"]
|
||||
condList["NotEnemyElementalStatus"] = not condList["EnemyElementalStatus"]
|
||||
if condList["EnemyIgnited"] then
|
||||
condList["EnemyBurning"] = true
|
||||
end
|
||||
|
||||
-- Calculate current and maximum charges
|
||||
@@ -1588,6 +1591,10 @@ local function performCalcs(env)
|
||||
|
||||
-- Other defences: block, dodge, stun recovery/avoidance
|
||||
do
|
||||
output.MovementSpeedMod = calcMod(modDB, nil, "MovementSpeed")
|
||||
if modDB:Sum("FLAG", nil, "MovementSpeedCannotBeBelowBase") then
|
||||
output.MovementSpeedMod = m_max(output.MovementSpeedMod, 1)
|
||||
end
|
||||
output.BlockChanceMax = modDB:Sum("BASE", nil, "BlockChanceMax")
|
||||
local shieldData = env.itemList["Weapon 2"] and env.itemList["Weapon 2"].armourData
|
||||
output.BlockChance = m_min(((shieldData and shieldData.BlockChance or 0) + modDB:Sum("BASE", nil, "BlockChance")) * calcMod(modDB, nil, "BlockChance"), output.BlockChanceMax)
|
||||
@@ -2586,6 +2593,11 @@ local function performCalcs(env)
|
||||
if igniteMode == "CRIT" then
|
||||
output.IgniteChanceOnHit = 0
|
||||
end
|
||||
if globalBreakdown then
|
||||
globalBreakdown.IgniteDPS = {
|
||||
s_format("Ignite mode: %s ^8(can be changed in the Configuration tab)", igniteMode == "CRIT" and "Crit Damage" or "Average Damage")
|
||||
}
|
||||
end
|
||||
local baseVal = calcSecondaryEffectBase("Ignite", sourceHitDmg, sourceCritDmg) * 0.2
|
||||
if baseVal > 0 then
|
||||
skillFlags.ignite = true
|
||||
@@ -2597,11 +2609,6 @@ local function performCalcs(env)
|
||||
}
|
||||
end
|
||||
local dotCfg = env.mainSkill.igniteCfg
|
||||
if globalBreakdown then
|
||||
globalBreakdown.IgniteDPS = {
|
||||
s_format("Ignite mode: %s ^8(can be changed in the Configuration tab)", igniteMode == "CRIT" and "Crit Damage" or "Average Damage")
|
||||
}
|
||||
end
|
||||
local effMult = 1
|
||||
if env.mode_effective then
|
||||
local resist = m_min(enemyDB:Sum("BASE", nil, "FireResist", "ElementalResist"), 75)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
-- Module: Data
|
||||
-- Contains static data used by other modules.
|
||||
--
|
||||
local launch = ...
|
||||
|
||||
data = { }
|
||||
|
||||
@@ -257,6 +258,7 @@ local itemTypes = {
|
||||
"ring",
|
||||
"belt",
|
||||
"jewel",
|
||||
launch.enableFlasks and "flask" or nil,
|
||||
}
|
||||
for _, type in pairs(itemTypes) do
|
||||
LoadModule("Data/Bases/"..type, data.itemBases)
|
||||
|
||||
@@ -98,12 +98,22 @@ function itemLib.parseItemRaw(item)
|
||||
item.base = data.itemBases[item.baseName]
|
||||
item.modLines = { }
|
||||
item.implicitLines = 0
|
||||
local flaskBuffLines = { }
|
||||
if item.base and item.base.flask and item.base.flask.buff then
|
||||
for _, line in ipairs(item.base.flask.buff) do
|
||||
flaskBuffLines[line] = true
|
||||
local modList, extra = modLib.parseMod(line)
|
||||
t_insert(item.modLines, { line = line, extra = extra, modList = modList or { }, buff = true })
|
||||
end
|
||||
end
|
||||
local gameModeStage = "FINDIMPLICIT"
|
||||
local gameModeSection = 1
|
||||
local foundExplicit
|
||||
while item.rawLines[l] do
|
||||
local line = item.rawLines[l]
|
||||
if line == "--------" then
|
||||
if flaskBuffLines[line] then
|
||||
flaskBuffLines[line] = nil
|
||||
elseif line == "--------" then
|
||||
gameModeSection = gameModeSection + 1
|
||||
if gameModeStage == "IMPLICIT" then
|
||||
item.implicitLines = #item.modLines
|
||||
@@ -228,7 +238,7 @@ function itemLib.parseItemRaw(item)
|
||||
elseif mode == "GAME" and not foundExplicit then
|
||||
item.implicitLines = 0
|
||||
end
|
||||
if not item.corrupted and not item.uniqueID and item.base and (item.base.armour or item.base.weapon) then
|
||||
if not item.corrupted and not item.uniqueID and item.base and (item.base.armour or item.base.weapon or item.base.flask) then
|
||||
item.quality = 20
|
||||
end
|
||||
if item.variantList then
|
||||
@@ -316,6 +326,8 @@ function itemLib.getPrimarySlotForItem(item)
|
||||
return "Weapon 2"
|
||||
elseif item.type == "Ring" then
|
||||
return "Ring 1"
|
||||
elseif item.type == "Flask" then
|
||||
return "Flask 1"
|
||||
else
|
||||
return item.type
|
||||
end
|
||||
@@ -425,11 +437,52 @@ function itemLib.buildItemModListForSlotNum(item, baseList, slotNum)
|
||||
if item.base.armour.blockChance then
|
||||
armourData.BlockChance = item.base.armour.blockChance + sumLocal(modList, "BlockChance", "BASE", 0)
|
||||
end
|
||||
if item.base.armour.movementPenalty then
|
||||
modList:NewMod("MovementSpeed", "INC", -item.base.armour.movementPenalty, item.modSource, { type = "Condition", var = "IgnoreMovementPenalties", neg = true })
|
||||
end
|
||||
for _, value in ipairs(modList:Sum("LIST", nil, "Misc")) do
|
||||
if value.type == "ArmourData" then
|
||||
armourData[value.key] = value.value
|
||||
end
|
||||
end
|
||||
elseif item.base.flask then
|
||||
local flaskData = item.flaskData
|
||||
local durationInc = sumLocal(modList, "Duration", "INC", 0)
|
||||
if item.base.flask.life or item.base.flask.mana then
|
||||
-- Recovery flask
|
||||
local recoveryMod = 1 + sumLocal(modList, "FlaskRecovery", "INC", 0) / 100
|
||||
local rateMod = 1 + sumLocal(modList, "FlaskRecoveryRate", "INC", 0) / 100
|
||||
local instant = sumLocal(modList, "FlaskInstantRecovery", "BASE", 0)
|
||||
local durBase = item.base.flask.duration * (1 + durationInc / 100)
|
||||
if item.base.flask.life then
|
||||
local base = item.base.flask.life * (1 + item.quality / 100) * recoveryMod
|
||||
local inst = base * instant / 100
|
||||
local grad = base * (1 - instant / 100) * (1 + durationInc / 100)
|
||||
flaskData.lifeTotal = inst + grad
|
||||
flaskData.lifeDuration = durBase / rateMod
|
||||
end
|
||||
if item.base.flask.mana then
|
||||
local base = item.base.flask.mana * (1 + item.quality / 100) * recoveryMod
|
||||
local inst = base * instant / 100
|
||||
local grad = base * (1 - instant / 100) * (1 + durationInc / 100)
|
||||
flaskData.manaTotal = inst + grad
|
||||
flaskData.manaDuration = durBase / rateMod
|
||||
end
|
||||
else
|
||||
-- Utility flask
|
||||
flaskData.duration = round(item.base.flask.duration * (1 + (durationInc + item.quality) / 100), 1)
|
||||
end
|
||||
local extra = sumLocal(modList, "FlaskCharges", "BASE", 0)
|
||||
local usedInc = sumLocal(modList, "FlaskChargesUsed", "INC", 0)
|
||||
local gainedInc = sumLocal(modList, "FlaskChargeRecovery", "INC", 0)
|
||||
flaskData.chargesMax = item.base.flask.chargesMax + extra
|
||||
flaskData.chargesUsed = m_floor(item.base.flask.chargesUsed * (1 + usedInc / 100))
|
||||
flaskData.gainMod = 1 + gainedInc / 100
|
||||
for _, value in ipairs(modList:Sum("LIST", nil, "Misc")) do
|
||||
if value.type == "FlaskData" then
|
||||
flaskData[value.key] = value.value
|
||||
end
|
||||
end
|
||||
elseif item.type == "Jewel" then
|
||||
item.jewelFunc = nil
|
||||
for _, value in ipairs(modList:Sum("LIST", nil, "Misc")) do
|
||||
@@ -450,6 +503,7 @@ function itemLib.buildItemModList(item)
|
||||
local baseList = { }
|
||||
item.baseModList = baseList
|
||||
item.rangeLineList = { }
|
||||
item.modSource = "Item:"..(item.id or -1)..":"..item.name
|
||||
for _, modLine in ipairs(item.modLines) do
|
||||
if not modLine.extra and (not modLine.variantList or modLine.variantList[item.variant]) then
|
||||
if modLine.range then
|
||||
@@ -461,7 +515,7 @@ function itemLib.buildItemModList(item)
|
||||
end
|
||||
end
|
||||
for _, mod in ipairs(modLine.modList) do
|
||||
mod.source = "Item:"..(item.id or -1)..":"..item.name
|
||||
mod.source = item.modSource
|
||||
if type(mod.value) == "table" and mod.value.mod then
|
||||
mod.value.mod.source = mod.source
|
||||
end
|
||||
@@ -477,6 +531,8 @@ function itemLib.buildItemModList(item)
|
||||
item.weaponData = { }
|
||||
elseif item.base.armour then
|
||||
item.armourData = { }
|
||||
elseif item.base.flask then
|
||||
item.flaskData = { }
|
||||
end
|
||||
if item.base.weapon or item.type == "Ring" then
|
||||
item.slotModList = { }
|
||||
|
||||
@@ -13,7 +13,7 @@ local m_max = math.max
|
||||
local m_min = math.min
|
||||
|
||||
LoadModule("Modules/Common")
|
||||
LoadModule("Modules/Data")
|
||||
LoadModule("Modules/Data", launch)
|
||||
LoadModule("Modules/ModTools")
|
||||
LoadModule("Modules/ItemTools")
|
||||
|
||||
@@ -486,7 +486,7 @@ function main:DrawTooltip(x, y, w, h, viewPort, col, center)
|
||||
DrawString(ttX + 6, y, "LEFT", data.size, "VAR", data.text)
|
||||
end
|
||||
y = y + data.size + 2
|
||||
elseif self.tooltipLines[i + 1] and self.tooltipLines[i - 1] and self.tooltipLines[i - 1].text then
|
||||
elseif self.tooltipLines[i + 1] and self.tooltipLines[i - 1] and self.tooltipLines[i + 1].text then
|
||||
if type(col) == "string" then
|
||||
SetDrawColor(col)
|
||||
else
|
||||
|
||||
@@ -91,6 +91,7 @@ local modNameList = {
|
||||
["cold and lightning resistances"] = { "ColdResist", "LightningResist" },
|
||||
["elemental resistances"] = "ElementalResist",
|
||||
["all elemental resistances"] = "ElementalResist",
|
||||
["all maximum elemental resistances"] = { "FireResistMax", "ColdResistMax", "LightningResistMax" },
|
||||
["all maximum resistances"] = { "FireResistMax", "ColdResistMax", "LightningResistMax", "ChaosResistMax" },
|
||||
-- Other defences
|
||||
["to dodge attacks"] = "AttackDodgeChance",
|
||||
@@ -231,6 +232,22 @@ local modNameList = {
|
||||
["light radius"] = "LightRadius",
|
||||
["rarity of items found"] = "LootRarity",
|
||||
["quantity of items found"] = "LootQuantity",
|
||||
-- Flask modifiers
|
||||
["effect"] = "FlaskEffect",
|
||||
["effect of flasks"] = "FlaskEffect",
|
||||
["amount recovered"] = "FlaskRecovery",
|
||||
["life recovery from flasks"] = "FlaskLifeRecovery",
|
||||
["mana recovery from flasks"] = "FlaskManaRecovery",
|
||||
["flask effect duration"] = "FlaskDuration",
|
||||
["recovery speed"] = "FlaskRecoveryRate",
|
||||
["flask recovery speed"] = "FlaskRecoveryRate",
|
||||
["flask life recovery rate"] = "FlaskLifeRecoveryRate",
|
||||
["flask mana recovery rate"] = "FlaskManaRecoveryRate",
|
||||
["extra charges"] = "FlaskCharges",
|
||||
["charges used"] = "FlaskChargesUsed",
|
||||
["flask charges used"] = "FlaskChargesUsed",
|
||||
["flask charges gained"] = "FlaskChargesGained",
|
||||
["charge recovery"] = "FlaskChargeRecovery",
|
||||
}
|
||||
|
||||
-- List of modifier flags
|
||||
@@ -367,6 +384,7 @@ local modTagList = {
|
||||
["while you have onslaught"] = { tag = { type = "Condition", var = "Onslaught" } },
|
||||
["while phasing"] = { tag = { type = "Condition", var = "Phasing" } },
|
||||
["while using a flask"] = { tag = { type = "Condition", var = "UsingFlask" } },
|
||||
["during effect"] = { tag = { type = "Condition", var = "UsingFlask" } },
|
||||
["during flask effect"] = { tag = { type = "Condition", var = "UsingFlask" } },
|
||||
["while on consecrated ground"] = { tag = { type = "Condition", var = "OnConsecratedGround" } },
|
||||
["on burning ground"] = { tag = { type = "Condition", var = "OnBurningGround" } },
|
||||
@@ -416,9 +434,9 @@ local modTagList = {
|
||||
["against frozen enemies"] = { tag = { type = "Condition", var = "EnemyFrozen" }, flags = ModFlag.Hit },
|
||||
["against chilled enemies"] = { tag = { type = "Condition", var = "EnemyChilled" }, flags = ModFlag.Hit },
|
||||
["enemies which are chilled"] = { tag = { type = "Condition", var = "EnemyChilled" }, flags = ModFlag.Hit },
|
||||
["against frozen, shocked or ignited enemies"] = { tag = { type = "Condition", var = "EnemyFrozenShockedIgnited" }, flags = ModFlag.Hit },
|
||||
["against enemies that are affected by elemental status ailments"] = { tag = { type = "Condition", var = "EnemyElementalStatus" }, flags = ModFlag.Hit },
|
||||
["against enemies that are affected by no elemental status ailments"] = { tag = { type = "Condition", var = "NotEnemyElementalStatus" }, flags = ModFlag.Hit },
|
||||
["against frozen, shocked or ignited enemies"] = { tag = { type = "Condition", varList = {"EnemyFrozen","EnemyShocked","EnemyIgnited"} }, flags = ModFlag.Hit },
|
||||
["against enemies that are affected by elemental status ailments"] = { tag = { type = "Condition", varList = {"EnemyFrozen","EnemyChilled","EnemyShocked","EnemyIgnited"} }, flags = ModFlag.Hit },
|
||||
["against enemies that are affected by no elemental status ailments"] = { tagList = { { type = "Condition", varList = {"EnemyFrozen","EnemyChilled","EnemyShocked","EnemyIgnited"}, neg = true }, { type = "Condition", var = "Effective" } }, flags = ModFlag.Hit },
|
||||
}
|
||||
|
||||
local mod = modLib.createMod
|
||||
@@ -485,6 +503,7 @@ local specialModList = {
|
||||
["bleeding you inflict on maimed enemies deals (%d+)%% more damage"] = function(num) return { mod("Damage", "MORE", num, nil, 0, KeywordFlag.Bleed, { type = "Condition", var = "EnemyMaimed"}) } end,
|
||||
["critical strikes ignore enemy monster elemental resistances"] = { flag("IgnoreElementalResistances", { type = "Condition", var = "CriticalStrike" }) },
|
||||
["non%-critical strikes penetrate (%d+)%% of enemy elemental resistances"] = function(num) return { mod("ElementalPenetration", "BASE", num, { type = "Condition", var = "CriticalStrike", neg = true }) } end,
|
||||
["movement speed cannot be modified to below base value"] = { flag("MovementSpeedCannotBeBelowBase") },
|
||||
-- Special node types
|
||||
["(%d+)%% of block chance applied to spells"] = function(num) return { mod("BlockChanceConv", "BASE", num) } end,
|
||||
["(%d+)%% additional block chance with staves"] = function(num) return { mod("BlockChance", "BASE", num, { type = "Condition", var = "UsingStaff" }) } end,
|
||||
@@ -499,6 +518,13 @@ local specialModList = {
|
||||
["cannot be frozen"] = { mod("AvoidFreeze", "BASE", 100) },
|
||||
["cannot be chilled"] = { mod("AvoidChill", "BASE", 100) },
|
||||
["cannot be ignited"] = { mod("AvoidIgnite", "BASE", 100) },
|
||||
["you are immune to bleeding"] = { mod("AvoidBleed", "BASE", 100) },
|
||||
["immunity to shock during flask effect"] = { mod("AvoidShock", "BASE", 100, { type = "Condition", var = "UsingFlask" }) },
|
||||
["immunity to freeze and chill during flask effect"] = { mod("AvoidFreeze", "BASE", 100, { type = "Condition", var = "UsingFlask" }), mod("AvoidChill", "BASE", 100, { type = "Condition", var = "UsingFlask" }) },
|
||||
["immunity to ignite during flask effect"] = { mod("AvoidIgnite", "BASE", 100, { type = "Condition", var = "UsingFlask" }) },
|
||||
["immunity to bleeding during flask effect"] = { mod("AvoidBleed", "BASE", 100, { type = "Condition", var = "UsingFlask" }) },
|
||||
["immune to poison during flask effect"] = { mod("AvoidPoison", "BASE", 100, { type = "Condition", var = "UsingFlask" }) },
|
||||
["immune to curses during flask effect"] = { mod("AvoidCurse", "BASE", 100, { type = "Condition", var = "UsingFlask" }) },
|
||||
["cannot evade enemy attacks"] = { flag("CannotEvade") },
|
||||
["deal no physical damage"] = { flag("DealNoPhysical") },
|
||||
["deal no elemental damage"] = { flag("DealNoLightning"), flag("DealNoCold"), flag("DealNoFire") },
|
||||
@@ -511,6 +537,10 @@ local specialModList = {
|
||||
["skills chain %+(%d) times"] = function(num) return { mod("ChainCount", "BASE", num) } end,
|
||||
["reflects (%d+) physical damage to melee attackers"] = { },
|
||||
["critical strikes with daggers have a (%d+)%% chance to poison the enemy"] = function(num) return { mod("PoisonChance", "BASE", num, nil, ModFlag.Dagger, { type = "Condition", var = "CriticalStrike" }) } end,
|
||||
["ignore all movement penalties from armour"] = { mod("Misc", "LIST", { type = "Condition", var = "IgnoreMovementPenalties" }) },
|
||||
["your critical strike chance is lucky"] = { flag("CritChanceLucky") },
|
||||
["phasing"] = { mod("Misc", "LIST", { type = "Condition", var = "Phasing" }) },
|
||||
["onslaught"] = { mod("Misc", "LIST", { type = "Condition", var = "Onslaught" }) },
|
||||
-- Special item local modifiers
|
||||
["no physical damage"] = { mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalMin" }), mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalMax" }), mod("Misc", "LIST", { type = "WeaponData", key = "PhysicalDPS" }) },
|
||||
["all attacks with this weapon are critical strikes"] = { mod("Misc", "LIST", { type = "WeaponData", key = "critChance", value = 100 }) },
|
||||
@@ -540,6 +570,8 @@ local specialModList = {
|
||||
["socketed gems have blood magic"] = { flag("SkillBloodMagic", { type = "SocketedIn" }) },
|
||||
["socketed gems gain (%d+)%% of physical damage as extra lightning damage"] = function(num) return { mod("PhysicalDamageGainAsLightning", "BASE", num, { type = "SocketedIn" }) } end,
|
||||
["socketed red gems get (%d+)%% physical damage as extra fire damage"] = function(num) return { mod("PhysicalDamageGainAsFire", "BASE", num, { type = "SocketedIn", keyword = "strength" }) } end,
|
||||
["instant recovery"] = { mod("FlaskInstantRecovery", "BASE", 100) },
|
||||
["(%d+)%% of recovery applied instantly"] = function(num) return { mod("FlaskInstantRecovery", "BASE", num) } end,
|
||||
-- Unique item modifiers
|
||||
["your cold damage can ignite"] = { flag("ColdCanIgnite") },
|
||||
["your fire damage can shock but not ignite"] = { flag("FireCanShock"), flag("FireCannotIgnite") },
|
||||
@@ -633,6 +665,7 @@ local convTypes = {
|
||||
["as extra chaos damage"] = "GainAsChaos",
|
||||
["added as chaos damage"] = "GainAsChaos",
|
||||
["gained as extra chaos damage"] = "GainAsChaos",
|
||||
["converted to lightning"] = "ConvertToLightning",
|
||||
["converted to lightning damage"] = "ConvertToLightning",
|
||||
["converted to cold damage"] = "ConvertToCold",
|
||||
["converted to fire damage"] = "ConvertToFire",
|
||||
|
||||
Reference in New Issue
Block a user