diff --git a/spec/System/TestDefence_spec.lua b/spec/System/TestDefence_spec.lua index 81f743b3..ad151fbb 100644 --- a/spec/System/TestDefence_spec.lua +++ b/spec/System/TestDefence_spec.lua @@ -844,7 +844,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 diff --git a/src/Classes/ModDB.lua b/src/Classes/ModDB.lua index f3c1ddc8..971bfbed 100644 --- a/src/Classes/ModDB.lua +++ b/src/Classes/ModDB.lua @@ -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 @@ -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 @@ -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 diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index d6ca744a..d258d51a 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -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) diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index fe68915d..6c01c494 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -4254,6 +4254,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),