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:
Openarl
2017-02-11 00:24:29 +10:00
parent cbae523914
commit b1c9eb5cb6
19 changed files with 969 additions and 301 deletions

View File

@@ -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

View File

@@ -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}%",

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 = { }

View File

@@ -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

View File

@@ -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",