Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions spec/System/TestDefence_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,102 @@ describe("TestDefence", function()
assert.are.equals(0, floor(poolsRemaining.Life))
assert.are.equals(0, floor(poolsRemaining.OverkillDamage))
end)

it("Unbreakable + Iron Reflexes", function()
build.configTab.input.customMods = [[
you have no dexterity
]]
build.configTab:BuildModList()
runCallback("OnFrame")

-- Get the base to make this test more adaptable to changes
local baseArmour = build.calcsTab.mainOutput.Armour
local baseEvasion = build.calcsTab.mainOutput.Evasion

build.configTab.input.customMods = [[
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
you have no dexterity
]]
build.itemsTab:CreateDisplayItemFromRaw([[
New Item
Shabby Jerkin
Quality: 20
]])
build.itemsTab:AddDisplayItem()
build.configTab:BuildModList()
runCallback("OnFrame")

-- Get the base + Shabby Jerkin to make this test more adaptable to changes
local ironReflexesArmour = build.calcsTab.mainOutput.Armour - baseArmour - baseEvasion

print("build.calcsTab.mainOutput.Armour:" .. build.calcsTab.mainOutput.Armour)

build.configTab.input.customMods = [[
Armour from Equipped Body Armour is doubled
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
you have no dexterity
]]
build.configTab:BuildModList()
runCallback("OnFrame")

-- Evasion from Body Armour is converted to Armour before being doubled
assert.are.equals(2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)

build.configTab.input.customMods = [[
Armour from Equipped Body Armour is doubled
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
Gain no armour from equipped body armour
you have no dexterity
]]
build.configTab:BuildModList()
runCallback("OnFrame")

-- Only the base armour from the chest is affected.
-- Armour converted with Iron Reflexes still applies
assert.are.equals(2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
build.configTab.input.customMods = [[
Armour from Equipped Body Armour is doubled
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
Gain no armour from equipped body armour
defences from equipped body armour are doubled if it has no socketed gems
you have no dexterity
]]
build.configTab:BuildModList()
runCallback("OnFrame")

-- Oath Of Maji double defences stack with Unbreakable
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)

build.configTab.input.customMods = [[
Armour from Equipped Body Armour is doubled
Armour from Equipped Body Armour is doubled
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
Gain no armour from equipped body armour
defences from equipped body armour are doubled if it has no socketed gems
you have no dexterity
]]
build.configTab:BuildModList()
runCallback("OnFrame")

-- Mod form unbreakable should apply only once
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)

build.configTab.input.customMods = [[
Armour from Equipped Body Armour is doubled
Armour from Equipped Body Armour is doubled
Converts all Evasion Rating to Armour. Dexterity provides no bonus to Evasion Rating
Gain no armour from equipped body armour
defences from equipped body armour are doubled if it has no socketed gems
defences from equipped body armour are doubled if it has no socketed gems
you have no dexterity
]]
build.configTab:BuildModList()
runCallback("OnFrame")

-- Oath Of Maji should apply only once
assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour)
end)

it("MoM + EB", function()
build.configTab.input.enemyIsBoss = "None"
-- enough mana and es, 0% and 100% bypass
Expand Down
28 changes: 3 additions & 25 deletions src/Classes/ModDB.lua
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,7 @@ function ModDBClass:SumInternal(context, modType, cfg, flags, keywordFlags, sour
local mod = modList[i]
if mod.type == modType and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or ( mod.source and mod.source:match("[^:]+") == source )) then
if mod[1] then
local value = context:EvalMod(mod, cfg) or 0
if mod[1].globalLimit and mod[1].globalLimitKey then
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] or 0
if globalLimits[mod[1].globalLimitKey] + value > mod[1].globalLimit then
value = mod[1].globalLimit - globalLimits[mod[1].globalLimitKey]
end
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] + value
end
local value = context:EvalMod(mod, cfg, globalLimits) or 0
result = result + value
else
result = result + mod.value
Expand Down Expand Up @@ -133,14 +126,7 @@ function ModDBClass:MoreInternal(context, cfg, flags, keywordFlags, source, ...)
if mod.type == "MORE" and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or mod.source:match("[^:]+") == source) then
local value
if mod[1] then
value = context:EvalMod(mod, cfg) or 0
if mod[1].globalLimit and mod[1].globalLimitKey then
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] or 0
if globalLimits[mod[1].globalLimitKey] + value > mod[1].globalLimit then
value = mod[1].globalLimit - globalLimits[mod[1].globalLimitKey]
end
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] + value
end
value = context:EvalMod(mod, cfg, globalLimits) or 0
else
value = mod.value or 0
end
Expand Down Expand Up @@ -249,15 +235,7 @@ function ModDBClass:TabulateInternal(context, result, modType, cfg, flags, keywo
if (mod.type == modType or not modType) and band(flags, mod.flags) == mod.flags and MatchKeywordFlags(keywordFlags, mod.keywordFlags) and (not source or mod.source:match("[^:]+") == source) then
local value
if mod[1] then
value = context:EvalMod(mod, cfg)
if mod[1].globalLimit and mod[1].globalLimitKey then
value = value or 0
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] or 0
if globalLimits[mod[1].globalLimitKey] + value > mod[1].globalLimit then
value = mod[1].globalLimit - globalLimits[mod[1].globalLimitKey]
end
globalLimits[mod[1].globalLimitKey] = globalLimits[mod[1].globalLimitKey] + value
end
value = context:EvalMod(mod, cfg, globalLimits)
else
value = mod.value
end
Expand Down
12 changes: 11 additions & 1 deletion src/Classes/ModStore.lua
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,22 @@ function ModStoreClass:GetStat(stat, cfg)
end
end

function ModStoreClass:EvalMod(mod, cfg)
function ModStoreClass:EvalMod(mod, cfg, globalLimits)
local value = mod.value
for _, tag in ipairs(mod) do
if tag.type == "Multiplier" then
local target = self
local limitTarget = self

if globalLimits and tag.globalLimit and tag.globalLimitKey then
value = value or 0
globalLimits[tag.globalLimitKey] = globalLimits[tag.globalLimitKey] or 0
if globalLimits[tag.globalLimitKey] + value > tag.globalLimit then
value = tag.globalLimit - globalLimits[tag.globalLimitKey]
end
globalLimits[tag.globalLimitKey] = globalLimits[tag.globalLimitKey] + value
end

-- Allow limiting a self multiplier on a parent multiplier (eg. Agony Crawler on player virulence)
-- This explicit target is necessary because even though the GetMultiplier method does call self.parent.GetMultiplier, it does so with noMod = true,
-- disabling the summation (3rd part): (not noMod and self:Sum("BASE", cfg, multiplierName[var]) or 0)
Expand Down
6 changes: 6 additions & 0 deletions src/Modules/ModParser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4255,6 +4255,12 @@ local specialModList = {
["you have no intelligence"] = {
mod("Int", "MORE", -100),
},
["you have no dexterity"] = {
mod("Dex", "MORE", -100),
},
["you have no strength"] = {
mod("Str", "MORE", -100),
},
["elemental resistances are zero"] = {
mod("FireResist", "OVERRIDE", 0),
mod("ColdResist", "OVERRIDE", 0),
Expand Down