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
64 changes: 64 additions & 0 deletions spec/System/TestAttacks_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,70 @@ describe("TestAttacks", function()
assert.are.equals(1.1, build.calcsTab.mainOutput.MainHand.AverageHit)
end)

it("matches in-game tooltip DPS for low-level spear skills", function()
build.spec:SelectClass(build.spec.tree.classNameMap.Huntress)
build.characterLevel = 11
build.characterLevelAutoMode = false
build.controls.characterLevel:SetText(11)
build.configTab.input.customMods = [[
10% increased Attack Damage
+10000 to Accuracy Rating
nearby enemies have 100% less armour
nearby enemies have 100% less evasion
]]
build.configTab:BuildModList()
build.itemsTab:CreateDisplayItemFromRaw([[
Apocalypse Edge
Ironhead Spear
Item Level: 7
Quality: 0
LevelReq: 5
Implicits: 1
Grants Skill: Spear Throw
Adds 2 to 4 Physical Damage
]])
build.itemsTab:AddDisplayItem()

local skills = {
{ gemId = "Metadata/Items/Gems/SkillGemPlayerDefaultSpear", level = 4, dps = 32.8 },
{ gemId = "Metadata/Items/Gems/SkillGemWhirlingSlash", level = 1, dps = 11.8 },
{ gemId = "Metadata/Items/Gems/SkillGemPlayerDefaultSpearThrow", level = 4, dps = 28.8 },
{ gemId = "Metadata/Items/Gems/SkillGemTwister", level = 2, dps = 17.5 },
}
for _, skill in ipairs(skills) do
local group = {
enabled = true,
gemList = { {
gemId = skill.gemId,
level = skill.level,
quality = 0,
enabled = true,
count = 1,
enableGlobal1 = true,
enableGlobal2 = true,
} },
}
table.insert(build.skillsTab.socketGroupList, group)
build.skillsTab:ProcessSocketGroup(group)
skill.groupIndex = #build.skillsTab.socketGroupList
end

for _, skill in ipairs(skills) do
local group = build.skillsTab.socketGroupList[skill.groupIndex]
build.mainSocketGroup = skill.groupIndex
build.calcsTab.input.skill_number = skill.groupIndex
group.mainActiveSkill = 1
group.mainActiveSkillCalcs = 1
build.buildFlag = true
build.modFlag = true
runCallback("OnFrame")
build.calcsTab:BuildOutput()
runCallback("OnFrame")

assert.are.equals(skill.dps, round(build.calcsTab.mainOutput.TotalDPS, 1))
end
end)

it("correctly adds damage with oracle forced outcome", function()
-- Setup: Add weapon with no crit chance, and strip enemy defenses
build.itemsTab:CreateDisplayItemFromRaw([[
Expand Down
18 changes: 15 additions & 3 deletions spec/System/TestSkills_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -354,15 +354,27 @@ describe("TestSkills", function()
assert.True(baseLeapSlamHit < build.calcsTab.mainOutput.AverageDamage)
end)

it("applies minion offensive multiplier to all attack damage", function()
it("applies generated minion offensive multiplier to attack damage", function()
build.skillsTab:PasteSocketGroup("Wolf Pack 20/0 1")
runCallback("OnFrame")

local minion = build.calcsTab.mainEnv.minion
local expectedPhysicalMax = round(build.calcsTab.mainEnv.data.monsterAllyDamageTable[minion.level] * (1 + minion.minionData.damageSpread))
local expectedPhysicalMax = floor(floor(build.calcsTab.mainEnv.data.monsterAllyDamageTable[minion.level]) * minion.minionData.damage * (1 + minion.minionData.damageSpread))

assert.are.equals(expectedPhysicalMax, minion.weaponData1.PhysicalMax)
assert.are.near(-30, minion.mainSkill.skillModList:Sum("MORE", minion.mainSkill.skillCfg, "Damage"), 0.0001)
assert.are.near(-30, minion.mainSkill.skillModList:Sum("MORE", minion.mainSkill.skillCfg, "AddedDamage"), 0.0001)
assert.are.equals(0, minion.mainSkill.skillModList:Sum("MORE", minion.mainSkill.skillCfg, "Damage"))
end)

it("does not apply minion offensive multiplier to spectre or companion added damage", function()
for _, skill in ipairs({ "Spectre: Lightless Abomination 20/0 1", "Companion: Lightless Abomination 20/0 1" }) do
newBuild()
build.skillsTab:PasteSocketGroup(skill)
runCallback("OnFrame")

local minion = build.calcsTab.mainEnv.minion
assert.are.equals(0, minion.mainSkill.skillModList:Sum("MORE", minion.mainSkill.skillCfg, "AddedDamage"))
end
end)

it("Inspiring Ally only mirrors companion damage, not generic minion damage", function()
Expand Down
8 changes: 4 additions & 4 deletions src/Modules/CalcActiveSkill.lua
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ function calcs.buildActiveSkillModList(env, activeSkill)
skillModList:NewMod("Damage", "MORE", -100 * activeSkill.actor.minionData.damageFixup, "Damage Fixup", ModFlag.Attack)
skillModList:NewMod("Speed", "MORE", 100 * activeSkill.actor.minionData.damageFixup, "Damage Fixup", ModFlag.Attack)
elseif activeSkill.actor.minionData.damage ~= 1 then
skillModList:NewMod("Damage", "MORE", (activeSkill.actor.minionData.damage - 1) * 100, activeSkill.actor.minionData.name .." Damage Multiplier", ModFlag.Attack)
skillModList:NewMod("AddedDamage", "MORE", (activeSkill.actor.minionData.damage - 1) * 100, activeSkill.actor.minionData.name .." Damage Multiplier", ModFlag.Attack, { type = "SkillName", skillNameList = { "Spectre", "Companion" }, partialMatch = true, summonSkill = true, neg = true })
end
end
if skillModList:Flag(activeSkill.skillCfg, "DisableSkill") and not skillModList:Flag(activeSkill.skillCfg, "EnableSkill") then
Expand Down Expand Up @@ -905,7 +905,7 @@ function calcs.buildActiveSkillModList(env, activeSkill)
local attackTime = minion.minionData.attackTime
local damageTable = (monsterDamage or minion.minionData.hostile) and env.data.monsterDamageTable or env.data.monsterAllyDamageTable
minion.hiddenDamageFixup = monsterDamage and (round(env.data.monsterAllyDamageTable[minion.level] / damageTable[minion.level] * data.misc.SpectreBeastDamageFixup, 2) - 1) or 0
local damage = damageTable[minion.level]
local damage = floor(damageTable[minion.level]) * minion.minionData.damage
if not minion.minionData.baseDamageIgnoresAttackSpeed then -- minions with this flag do not factor attack time into their base damage
damage = damage * attackTime
end
Expand Down Expand Up @@ -934,8 +934,8 @@ function calcs.buildActiveSkillModList(env, activeSkill)
type = minion.minionData.weaponType1 or "None",
AttackRate = 1 / attackTime,
CritChance = minion.minionData.critChance,
PhysicalMin = round(damage * (1 - minion.minionData.damageSpread)),
PhysicalMax = round(damage * (1 + minion.minionData.damageSpread)),
PhysicalMin = floor(damage * (1 - minion.minionData.damageSpread)),
PhysicalMax = floor(damage * (1 + minion.minionData.damageSpread)),
range = minion.minionData.attackRange,
}
end
Expand Down
8 changes: 4 additions & 4 deletions src/Modules/CalcOffence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ local function calcGainedDamage(activeSkill, output, cfg, damageType)

local gainedMin, gainedMax = 0, 0
for _, otherType in ipairs(dmgTypeList) do
local baseMin = m_floor(output[otherType.."MinBase"] * activeSkill.conversionTable[otherType].mult)
local baseMax = m_floor(output[otherType.."MaxBase"] * activeSkill.conversionTable[otherType].mult)
local baseMin = output[otherType.."MinBase"] * activeSkill.conversionTable[otherType].mult
local baseMax = output[otherType.."MaxBase"] * activeSkill.conversionTable[otherType].mult
local gainMult = gainTable[otherType][damageType]
if gainMult and gainMult > 0 then
-- Damage is being converted/gained from the other damage type
Expand Down Expand Up @@ -3953,8 +3953,8 @@ function calcs.offence(env, actor, activeSkill)
local baseMax = output[damageTypeMax.."Base"]
local summedMin = baseMin * convMult + convertedMin + gainedMin
local summedMax = baseMax * convMult + convertedMax + gainedMax
output[damageType.."SummedMinBase"] = round(summedMin)
output[damageType.."SummedMaxBase"] = round(summedMax)
output[damageType.."SummedMinBase"] = summedMin
output[damageType.."SummedMaxBase"] = summedMax
if breakdown then
if (baseMin ~= 0 or baseMax ~= 0) then
if convMult ~= 1 then
Expand Down
Loading