Skip to content
Closed
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
20 changes: 20 additions & 0 deletions spec/System/TestItemMods_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ describe("TetsItemMods", function()
-- newBuild() takes care of resetting everything in setup()
end)

it("Queen of the Forest preserves sprinting movement speed only", function()
build.configTab.input.customMods = [[
+60000 to Evasion Rating
30% increased Movement Speed
12% increased Movement Speed while Sprinting
Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75%
Other Modifiers to Movement Speed except for Sprinting do not apply
]]
build.configTab:BuildModList()
runCallback("OnFrame")

assert.are.equals(1.75, build.calcsTab.mainOutput.MovementSpeedMod)

build.configTab.input.conditionSprinting = true
build.configTab:BuildModList()
runCallback("OnFrame")

assert.are.equals(2.37, build.calcsTab.mainOutput.MovementSpeedMod)
end)

it("Both slots mod (evasion and es mastery)", function()

build.configTab.input.customMods = "\z
Expand Down
18 changes: 9 additions & 9 deletions src/Data/ModCache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5340,12 +5340,12 @@ c["Immune to Poison if Equipped Helmet has higher Evasion Rating than Armour"]={
c["Immune to Shock"]={{[1]={flags=0,keywordFlags=0,name="ShockImmune",type="FLAG",value=true}},nil}
c["Immune to Shock if a majority of your Socketed Support Gems are Green"]={{[1]={[1]={type="Condition",var="MajorityGreenSocketedSupports"},flags=0,keywordFlags=0,name="ShockImmune",type="FLAG",value=true}},nil}
c["Immune to Shock while affected by an Archon Buff"]={nil,"Immune to Shock while affected by an Archon Buff "}
c["Increases Movement Speed by 25%, plus 1% per 500 Evasion Rating, up to a maximum of 75%"]={nil,"Increases Movement Speed by 25%, plus 1% per 500 Evasion Rating, up to a maximum of 75% "}
c["Increases Movement Speed by 25%, plus 1% per 500 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply"]={nil,"Increases Movement Speed by 25%, plus 1% per 500 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply "}
c["Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75%"]={nil,"Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75% "}
c["Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply"]={nil,"Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply "}
c["Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75%"]={nil,"Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75% "}
c["Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply"]={nil,"Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply "}
c["Increases Movement Speed by 25%, plus 1% per 500 Evasion Rating, up to a maximum of 75%"]={{[1]={[1]={base=25,div=500,limit=75,limitTotal=true,stat="Evasion",type="PerStat"},flags=0,keywordFlags=0,name="MovementSpeedOnlySprinting",type="INC",value=1}},nil}
c["Increases Movement Speed by 25%, plus 1% per 500 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply"]={{[1]={[1]={base=25,div=500,limit=75,limitTotal=true,stat="Evasion",type="PerStat"},flags=0,keywordFlags=0,name="MovementSpeedOnlySprinting",type="INC",value=1},[2]={flags=0,keywordFlags=0,name="OnlySprintingMovementSpeedApplies",type="FLAG",value=true}},nil}
c["Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75%"]={{[1]={[1]={base=25,div=600,limit=75,limitTotal=true,stat="Evasion",type="PerStat"},flags=0,keywordFlags=0,name="MovementSpeedOnlySprinting",type="INC",value=1}},nil}
c["Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply"]={{[1]={[1]={base=25,div=600,limit=75,limitTotal=true,stat="Evasion",type="PerStat"},flags=0,keywordFlags=0,name="MovementSpeedOnlySprinting",type="INC",value=1},[2]={flags=0,keywordFlags=0,name="OnlySprintingMovementSpeedApplies",type="FLAG",value=true}},nil}
c["Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75%"]={{[1]={[1]={base=25,div=800,limit=75,limitTotal=true,stat="Evasion",type="PerStat"},flags=0,keywordFlags=0,name="MovementSpeedOnlySprinting",type="INC",value=1}},nil}
c["Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75% Other Modifiers to Movement Speed except for Sprinting do not apply"]={{[1]={[1]={base=25,div=800,limit=75,limitTotal=true,stat="Evasion",type="PerStat"},flags=0,keywordFlags=0,name="MovementSpeedOnlySprinting",type="INC",value=1},[2]={flags=0,keywordFlags=0,name="OnlySprintingMovementSpeedApplies",type="FLAG",value=true}},nil}
c["Increases and Reductions to Armour also apply to Energy Shield"]={nil,"Increases and Reductions to Armour also apply to Energy Shield "}
c["Increases and Reductions to Armour also apply to Energy Shield Recharge Rate at 40% of their value"]={{[1]={flags=0,keywordFlags=0,name="ArmourAppliesToEnergyShieldRecharge",type="FLAG",value=true},[2]={flags=0,keywordFlags=0,name="ImprovedArmourAppliesToEnergyShieldRecharge",type="MAX",value=40}},nil}
c["Increases and Reductions to Companion Damage also apply to you"]={{[1]={flags=0,keywordFlags=0,name="CompanionDamageAppliesToPlayer",type="FLAG",value=true}},nil}
Expand Down Expand Up @@ -5678,9 +5678,9 @@ c["Only affects Passives in Very Large Ring"]={{[1]={flags=0,keywordFlags=0,name
c["Only affects Passives in Very Small Ring"]={{[1]={flags=0,keywordFlags=0,name="JewelData",type="LIST",value={key="radiusIndex",value=5}}},nil}
c["Onslaught"]={{[1]={flags=0,keywordFlags=0,name="Condition:Onslaught",type="FLAG",value=true}},nil}
c["Orb Skills have +1 to Limit"]={nil,"Orb Skills have +1 to Limit "}
c["Other Modifiers to Movement Speed except for Sprinting do not apply"]={nil,"Other Modifiers to Movement Speed except for Sprinting do not apply "}
c["Other Modifiers to Movement Speed except for Sprinting do not apply Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75%"]={nil,"Other Modifiers to Movement Speed except for Sprinting do not apply Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75% "}
c["Other Modifiers to Movement Speed except for Sprinting do not apply Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75%"]={nil,"Other Modifiers to Movement Speed except for Sprinting do not apply Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75% "}
c["Other Modifiers to Movement Speed except for Sprinting do not apply"]={{[1]={flags=0,keywordFlags=0,name="OnlySprintingMovementSpeedApplies",type="FLAG",value=true}},nil}
c["Other Modifiers to Movement Speed except for Sprinting do not apply Increases Movement Speed by 25%, plus 1% per 600 Evasion Rating, up to a maximum of 75%"]={{[1]={[1]={base=25,div=600,limit=75,limitTotal=true,stat="Evasion",type="PerStat"},flags=0,keywordFlags=0,name="MovementSpeedOnlySprinting",type="INC",value=1},[2]={flags=0,keywordFlags=0,name="OnlySprintingMovementSpeedApplies",type="FLAG",value=true}},nil}
c["Other Modifiers to Movement Speed except for Sprinting do not apply Increases Movement Speed by 25%, plus 1% per 800 Evasion Rating, up to a maximum of 75%"]={{[1]={[1]={base=25,div=800,limit=75,limitTotal=true,stat="Evasion",type="PerStat"},flags=0,keywordFlags=0,name="MovementSpeedOnlySprinting",type="INC",value=1},[2]={flags=0,keywordFlags=0,name="OnlySprintingMovementSpeedApplies",type="FLAG",value=true}},nil}
c["Overgrown Plant Skills Break 50% increased Armour"]={nil,"Overgrown Plant Skills Break 50% increased Armour "}
c["Pain Attunement"]={{[1]={flags=0,keywordFlags=0,name="Keystone",type="LIST",value="Pain Attunement"}},nil}
c["Parried enemies take more Spell Damage instead of more Attack Damage"]={nil,"Parried enemies take more Spell Damage instead of more Attack Damage "}
Expand Down
42 changes: 41 additions & 1 deletion src/Modules/CalcDefence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,42 @@ local tempTable1 = { }

local isElemental = { Fire = true, Cold = true, Lightning = true }

local function hasSprintingCondition(mod)
for _, tag in ipairs(mod) do
if tag.type == "Condition" and tag.var == "Sprinting" and not tag.neg then
return true
end
end
return false
end

local function sumSprintingMovementSpeedMods(modDB, modType)
local sum = 0
for _, value in ipairs(modDB:Tabulate(modType, nil, "MovementSpeed")) do
if hasSprintingCondition(value.mod) then
sum = sum + value.value
end
end
return sum
end

local function moreSprintingMovementSpeedMods(modDB)
local more = 1
for _, value in ipairs(modDB:Tabulate("MORE", nil, "MovementSpeed")) do
if hasSprintingCondition(value.mod) then
more = more * (1 + value.value / 100)
end
end
return more
end

local function calcOnlySprintingMovementSpeedMod(modDB)
local base = modDB:Sum("BASE", nil, "MovementSpeedOnlySprinting") + sumSprintingMovementSpeedMods(modDB, "BASE")
local inc = modDB:Sum("INC", nil, "MovementSpeedOnlySprinting") + sumSprintingMovementSpeedMods(modDB, "INC")
local more = modDB:More(nil, "MovementSpeedOnlySprinting") * moreSprintingMovementSpeedMods(modDB)
return round((1 + base) * (1 + inc / 100) * more, 3)
end

-- List of all damage types, ordered according to the conversion sequence
local hitSourceList = {"Attack", "Spell"}
local dmgTypeList = {"Physical", "Lightning", "Cold", "Fire", "Chaos"}
Expand Down Expand Up @@ -1871,7 +1907,11 @@ function calcs.defence(env, actor)
end

-- Miscellaneous: move speed, avoidance, weapon swap speed
output.MovementSpeedMod = modDB:Override(nil, "MovementSpeed") or (modDB:Flag(nil, "MovementSpeedEqualHighestLinkedPlayers") and actor.partyMembers.output.MovementSpeedMod or (round((1 + modDB:Sum("BASE", nil, "MovementSpeed")) * calcLib.mod(modDB, nil, "MovementSpeed"), 3)))
if modDB:Flag(nil, "OnlySprintingMovementSpeedApplies") then
output.MovementSpeedMod = calcOnlySprintingMovementSpeedMod(modDB)
else
output.MovementSpeedMod = modDB:Override(nil, "MovementSpeed") or (modDB:Flag(nil, "MovementSpeedEqualHighestLinkedPlayers") and actor.partyMembers.output.MovementSpeedMod or (round((1 + modDB:Sum("BASE", nil, "MovementSpeed", "MovementSpeedOnlySprinting")) * calcLib.mod(modDB, nil, "MovementSpeed", "MovementSpeedOnlySprinting"), 3)))
end
if modDB:Flag(nil, "MovementSpeedCannotBeBelowBase") then
output.MovementSpeedMod = m_max(output.MovementSpeedMod, 1)
end
Expand Down
39 changes: 39 additions & 0 deletions src/Modules/ModParser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2125,6 +2125,39 @@ local function flag(name, ...)
return mod(name, "FLAG", true, ...)
end

local function movementSpeedOnlySprintingPerStat(base, per, stat, div, limit)
return mod("MovementSpeedOnlySprinting", "INC", tonumber(per), {
type = "PerStat",
stat = stat,
div = tonumber(div),
base = tonumber(base),
limit = tonumber(limit),
limitTotal = true,
})
end

local function onlySprintingMovementSpeedFlag()
return flag("OnlySprintingMovementSpeedApplies")
end

local function movementSpeedPerEvasionOnlySprinting(base, _, per, div, limit)
return { movementSpeedOnlySprintingPerStat(base, per, "Evasion", div, limit) }
end

local function movementSpeedPerEvasionWithOnlySprinting(base, _, per, div, limit)
return {
movementSpeedOnlySprintingPerStat(base, per, "Evasion", div, limit),
onlySprintingMovementSpeedFlag(),
}
end

local function movementSpeedPerSpiritWithOnlySprinting(per, _, div, limit)
return {
movementSpeedOnlySprintingPerStat(0, per, "Spirit", div, limit),
onlySprintingMovementSpeedFlag(),
}
end

local gems = {}
for id in pairs(data.gems) do
table.insert(gems, id)
Expand Down Expand Up @@ -2214,6 +2247,12 @@ end

-- List of special modifiers
local specialModList = {
-- Movement speed replacement mods
["increases movement speed by (%d+)%%, plus (%d+)%% per (%d+) evasion rating, up to a maximum of (%d+)%%"] = movementSpeedPerEvasionOnlySprinting,
["increases movement speed by (%d+)%%, plus (%d+)%% per (%d+) evasion rating, up to a maximum of (%d+)%% other modifiers to movement speed except for sprinting do not apply"] = movementSpeedPerEvasionWithOnlySprinting,
["other modifiers to movement speed except for sprinting do not apply increases movement speed by (%d+)%%, plus (%d+)%% per (%d+) evasion rating, up to a maximum of (%d+)%%"] = movementSpeedPerEvasionWithOnlySprinting,
["(%d+)%% increased movement speed per (%d+) spirit, up to a maximum of (%d+)%% other modifiers to movement speed except for sprinting do not apply"] = movementSpeedPerSpiritWithOnlySprinting,
["other modifiers to movement speed except for sprinting do not apply"] = { onlySprintingMovementSpeedFlag() },
-- Explode mods
["enemies you kill have a (%d+)%% chance to explode, dealing a (.+) of their maximum life as (.+) damage"] = function(chance, _, amount, type) -- Obliteration, Unspeakable Gifts (chaos cluster), synth implicit mod, current crusader body mod, Ngamahu Warmonger tattoo
return explodeFunc(chance, amount, type)
Expand Down