Skip to content
Open
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
40 changes: 40 additions & 0 deletions spec/System/TestSpectreBuffs_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
describe("TestSpectreBuffs", function()
before_each(function()
newBuild()
end)

teardown(function()
-- newBuild() takes care of resetting everything in setup()
end)

it("applies buff skills from every spectre in the spectre list", function()
build.spectreList = {
"Metadata/Monsters/LeagueAzmeri/SpecialCorpses/DemonBossHigh", -- Perfect Blood Demon
"Metadata/Monsters/LeagueAzmeri/SpecialCorpses/TigerHigh", -- Perfect Forest Tiger (Haste)
"Metadata/Monsters/LeagueAzmeri/SpecialCorpses/TurtleHigh", -- Perfect Guardian Turtle (Determination)
}
build.skillsTab:PasteSocketGroup("Raise Spectre 20/0 1")
build.calcsTab:BuildOutput()

local env = build.calcsTab.mainEnv
-- The main minion is the Blood Demon, so the Tiger's and Turtle's auras only apply if
-- the other spectres in the list are processed as well
assert.is_true(env.modDB.conditions["AffectedByHaste"] == true)
assert.is_true(env.modDB.conditions["AffectedByDetermination"] == true)
assert.is_true(env.minion.modDB.conditions["AffectedByHaste"] == true)
assert.is_true(env.minion.modDB.conditions["AffectedByDetermination"] == true)
-- The Tiger and Turtle are beasts, so the condition applies even with the Demon selected
assert.is_true(env.modDB.conditions["HaveBeastSpectre"] == true)
end)

it("applies buff skills from the selected spectre only once", function()
build.spectreList = {
"Metadata/Monsters/LeagueAzmeri/SpecialCorpses/TurtleHigh", -- Perfect Guardian Turtle (Determination)
}
build.skillsTab:PasteSocketGroup("Raise Spectre 20/0 1")
build.calcsTab:BuildOutput()

local env = build.calcsTab.mainEnv
assert.is_true(env.modDB.conditions["AffectedByDetermination"] == true)
end)
end)
56 changes: 42 additions & 14 deletions src/Modules/CalcActiveSkill.lua
Original file line number Diff line number Diff line change
Expand Up @@ -681,23 +681,17 @@ function calcs.buildActiveSkillModList(env, activeSkill)
end
activeSkill.minionList = minionList
if minionList[1] and not activeSkill.actor.minionData then
local minionType
if env.mode == "CALCS" and activeSkill == env.player.mainSkill then
local index = isValueInArray(minionList, activeEffect.srcInstance.skillMinionCalcs) or 1
minionType = minionList[index]
activeEffect.srcInstance.skillMinionCalcs = minionType
else
local index = isValueInArray(minionList, activeEffect.srcInstance.skillMinion) or 1
minionType = minionList[index]
activeEffect.srcInstance.skillMinion = minionType
end
if minionType then
local function instantiateMinion(minionType)
if not minionType then
return
end
local minion = { }
activeSkill.minion = minion
skillFlags.haveMinion = true
minion.type = minionType
minion.minionData = env.data.minions[minionType]
minion.hostile = minion.minionData and minion.minionData.hostile or false
if not minion.minionData then
return
end
minion.hostile = minion.minionData.hostile or false
if minion.hostile then
minion.parent = env.enemy
minion.enemy = env.player
Expand Down Expand Up @@ -782,6 +776,40 @@ function calcs.buildActiveSkillModList(env, activeSkill)
minion.weaponData1 = copyTable(minion.weaponData1)
minion.weaponData1.AttackRate = env.player.weaponData1.AttackRate
end
return minion
end
local minionType
if env.mode == "CALCS" and activeSkill == env.player.mainSkill then
local index = isValueInArray(minionList, activeEffect.srcInstance.skillMinionCalcs) or 1
minionType = minionList[index]
activeEffect.srcInstance.skillMinionCalcs = minionType
else
local index = isValueInArray(minionList, activeEffect.srcInstance.skillMinion) or 1
minionType = minionList[index]
activeEffect.srcInstance.skillMinion = minionType
end
activeSkill.spectreListMinions = nil
if minionType then
local minion = instantiateMinion(minionType)
if minion then
activeSkill.minion = minion
skillFlags.haveMinion = true
if isSpectre then
activeSkill.spectreListMinions = { minion }
end
end
end
-- Instantiate the other spectres in the spectre list so their buff skills can be applied
if isSpectre then
activeSkill.spectreListMinions = activeSkill.spectreListMinions or { }
for _, spectreType in ipairs(minionList) do
if not activeSkill.minion or spectreType ~= activeSkill.minion.type then
local extraMinion = instantiateMinion(spectreType)
if extraMinion then
t_insert(activeSkill.spectreListMinions, extraMinion)
end
end
end
end
elseif activeEffect.srcInstance and not (activeEffect.gemData and activeEffect.gemData.secondaryGrantedEffect) then
activeEffect.srcInstance.skillMinionCalcs = nil
Expand Down
79 changes: 67 additions & 12 deletions src/Modules/CalcPerform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1259,13 +1259,52 @@ function calcs.perform(env, skipEHP)
modLib.mergeKeystones(env, env.modDB)

-- Build minion skills
local function initMinionSkills(activeSkill, minion, isPrimary)
minion.modDB = new("ModDB"):ModDB()
minion.modDB.actor = minion
if isPrimary then
calcs.createMinionSkills(env, activeSkill)
activeSkill.skillPartName = activeSkill.minion.mainSkill.activeEffect.grantedEffect.name
return
end
-- Build the skills of an extra spectre from the spectre list on a temporary copy of the
-- active skill, so the main minion and the stored skill selection are left untouched
local tempSkill = {
activeEffect = activeSkill.activeEffect,
effectList = activeSkill.effectList,
supportList = activeSkill.supportList,
actor = activeSkill.actor,
socketGroup = activeSkill.socketGroup,
baseSkillModList = activeSkill.baseSkillModList,
skillModList = activeSkill.skillModList,
skillCfg = activeSkill.skillCfg,
skillData = activeSkill.skillData,
skillFlags = activeSkill.skillFlags,
skillTypes = activeSkill.skillTypes,
minionSkillTypes = activeSkill.minionSkillTypes,
buffList = activeSkill.buffList,
minion = minion,
}
local srcInstance = activeSkill.activeEffect and activeSkill.activeEffect.srcInstance
local savedMinionSkill = srcInstance and srcInstance.skillMinionSkill
local savedMinionSkillCalcs = srcInstance and srcInstance.skillMinionSkillCalcs
calcs.createMinionSkills(env, tempSkill)
if srcInstance then
srcInstance.skillMinionSkill = savedMinionSkill
srcInstance.skillMinionSkillCalcs = savedMinionSkillCalcs
end
end
for _, activeSkill in ipairs(env.player.activeSkillList) do
activeSkill.skillModList = new("ModList"):ModList(activeSkill.baseSkillModList)
if activeSkill.minion then
activeSkill.minion.modDB = new("ModDB"):ModDB()
activeSkill.minion.modDB.actor = activeSkill.minion
calcs.createMinionSkills(env, activeSkill)
activeSkill.skillPartName = activeSkill.minion.mainSkill.activeEffect.grantedEffect.name
initMinionSkills(activeSkill, activeSkill.minion, true)
end
if activeSkill.spectreListMinions then
for _, spectreMinion in ipairs(activeSkill.spectreListMinions) do
if spectreMinion ~= activeSkill.minion then
initMinionSkills(activeSkill, spectreMinion, false)
end
end
end
end

Expand Down Expand Up @@ -2161,7 +2200,13 @@ function calcs.perform(env, skipEHP)
local skillId = activeSkill.activeEffect.grantedEffect.id
if skillId and skillId:match("^RaiseSpectre") then
hasActiveSpectreSkill = true
if activeSkill.minion and activeSkill.minion.type then
if activeSkill.spectreListMinions then
for _, spectreMinion in ipairs(activeSkill.spectreListMinions) do
if spectreMinion.type then
t_insert(activeSpectreList, spectreMinion.type)
end
end
elseif activeSkill.minion and activeSkill.minion.type then
t_insert(activeSpectreList, activeSkill.minion.type)
end
end
Expand Down Expand Up @@ -2719,9 +2764,19 @@ function calcs.perform(env, skipEHP)
end
end
end
local minionsToProcess = { }
if activeSkill.minion and activeSkill.minion.activeSkillList then
local castingMinion = activeSkill.minion
for _, activeMinionSkill in ipairs(activeSkill.minion.activeSkillList) do
t_insert(minionsToProcess, activeSkill.minion)
end
if activeSkill.spectreListMinions then
for _, spectreMinion in ipairs(activeSkill.spectreListMinions) do
if spectreMinion ~= activeSkill.minion and spectreMinion.activeSkillList then
t_insert(minionsToProcess, spectreMinion)
end
end
end
for _, castingMinion in ipairs(minionsToProcess) do
for _, activeMinionSkill in ipairs(castingMinion.activeSkillList) do
local function setSpectreSource(modList, sourceSkill)
if activeSkill.skillFlags.spectre then
local source = "Spectre:"
Expand Down Expand Up @@ -2767,7 +2822,7 @@ function calcs.perform(env, skipEHP)
if envMinionCheck then
env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true
else
activeSkill.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true
castingMinion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true
end
local srcList = new("ModList"):ModList()
local inc = modStore:Sum("INC", skillCfg, "BuffEffect", (env.minion == castingMinion) and "BuffEffectOnSelf" or nil)
Expand All @@ -2784,7 +2839,7 @@ function calcs.perform(env, skipEHP)
if env.mode_buffs and activeMinionSkill.skillData.enable then
-- Check for extra modifiers to apply to aura skills
local extraAuraModList = { }
for _, value in ipairs(activeSkill.minion.modDB:List(skillCfg, "ExtraAuraEffect")) do
for _, value in ipairs(castingMinion.modDB:List(skillCfg, "ExtraAuraEffect")) do
local add = true
for _, mod in ipairs(extraAuraModList) do
if modLib.compareModParams(mod, value.mod) then
Expand All @@ -2797,7 +2852,7 @@ function calcs.perform(env, skipEHP)
t_insert(extraAuraModList, copyTable(value.mod, true))
end
end
if not (activeSkill.minion.modDB:Flag(nil, "SelfAurasCannotAffectAllies") or activeSkill.minion.modDB:Flag(nil, "SelfAurasOnlyAffectYou") or activeSkill.minion.modDB:Flag(nil, "SelfAuraSkillsCannotAffectAllies") or skillModList:Flag(skillCfg, "SelfAurasAffectYouAndLinkedTarget")) then
if not (castingMinion.modDB:Flag(nil, "SelfAurasCannotAffectAllies") or castingMinion.modDB:Flag(nil, "SelfAurasOnlyAffectYou") or castingMinion.modDB:Flag(nil, "SelfAuraSkillsCannotAffectAllies") or skillModList:Flag(skillCfg, "SelfAurasAffectYouAndLinkedTarget")) then
if not modDB:Flag(nil, "AlliesAurasCannotAffectSelf") and not modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] then
local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect", "BuffEffectOnPlayer", "AuraBuffEffect") + modDB:Sum("INC", skillCfg, "BuffEffectOnSelf", "AuraEffectOnSelf")
local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") * modDB:More(skillCfg, "BuffEffectOnSelf", "AuraEffectOnSelf")
Expand All @@ -2816,7 +2871,7 @@ function calcs.perform(env, skipEHP)
mergeBuff(srcList, buffs, buff.name)
end
end
if env.minion and not env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] and (env.minion ~= activeSkill.minion or not activeSkill.skillData.auraCannotAffectSelf) then
if env.minion and not env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] and (env.minion ~= castingMinion or not activeSkill.skillData.auraCannotAffectSelf) then
local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect") + env.minion.modDB:Sum("INC", skillCfg, "BuffEffectOnSelf", "AuraEffectOnSelf")
local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect") * env.minion.modDB:More(skillCfg, "BuffEffectOnSelf", "AuraEffectOnSelf")
local mult = (1 + inc / 100) * more
Expand Down Expand Up @@ -2920,7 +2975,7 @@ function calcs.perform(env, skipEHP)
end
end
enemyDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true
if env.minion and env.minion == activeSkill.minion then
if env.minion and env.minion == castingMinion then
env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true
end
if buff.type == "Debuff" then
Expand Down
Loading