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
7 changes: 6 additions & 1 deletion src/Data/SkillStatMap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,9 @@ return {
["totem_skill_attack_speed_+%"] = {
mod("Speed", "INC", nil, ModFlag.Attack, KeywordFlag.Totem)
},
["grenade_skill_cooldown_speed_+%"] = {
mod("CooldownRecovery", "INC", nil),
},
-- AoE
["active_skill_base_area_of_effect_radius"] = {
skill("radius", nil),
Expand Down Expand Up @@ -2655,5 +2658,7 @@ return {
["quality_display_sandstorm_swipe_is_gem"] = {
-- Display Only
},

["quality_display_base_totem_duration_is_gem"] = {
-- Display Only
},
}
1 change: 1 addition & 0 deletions src/Data/Skills/act_int.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4628,6 +4628,7 @@ skills["DarkEffigyProjectilePlayer"] = {
spell = true,
area = true,
projectile = true,
totem = true,
},
constantStats = {
{ "skill_disabled_unless_cloned", 2 },
Expand Down
34 changes: 30 additions & 4 deletions src/Data/Skills/act_str.lua
Original file line number Diff line number Diff line change
Expand Up @@ -563,13 +563,24 @@ skills["SupportAncestralWarriorTotemPlayer"] = {
[39] = { levelRequirement = 0, },
[40] = { levelRequirement = 0, },
},
addFlags = {
totem = true,
},
statSets = {
[1] = {
label = "SupportAncestralWarriorTotemPlayer",
incrementalEffectiveness = 0.054999999701977,
statDescriptionScope = "gem_stat_descriptions",
statMap = {
["support_ancestral_warrior_totem_attack_speed_+%_final"] = {
mod("Speed", "MORE", nil, ModFlag.Attack),
},
},
baseFlags = {
},
baseMods = {
mod("ActiveTotemLimit", "BASE", 1),
},
constantStats = {
{ "skill_disabled_unless_cloned", 2 },
{ "support_ancestral_warrior_totem_attack_speed_+%_final", -25 },
Expand Down Expand Up @@ -1068,7 +1079,7 @@ skills["AttritionPlayer"] = {
{mod("Damage", "MORE", nil, 0, KeywordFlag.Hit, { type = "GlobalEffect", effectType = "Buff"}, { type = "Multiplier", var = "EnemyPresenceSeconds", actor = "enemy", limitVar = "AttritionMaxDamage", div = 2, limitTotal = true }, { type = "ActorCondition", actor = "enemy", var = "RareOrUnique" })},
{mod("CullPercent", "MAX", nil, 0, 0, { type = "GlobalEffect", effectType = "Buff"}, { type = "MultiplierThreshold", var = "EnemyPresenceSeconds", actor = "enemy", thresholdVar = "AttritionCullSeconds"}, { type = "ActorCondition", actor = "enemy", var = "RareOrUnique" }),
value = 10,}
},
},
},
baseFlags = {
},
Expand Down Expand Up @@ -3688,6 +3699,10 @@ skills["ExplosiveGrenadePlayer"] = {
label = "Explosive Grenade",
incrementalEffectiveness = 0.054999999701977,
statDescriptionScope = "explosive_grenade",
statMap = {
["base_skill_show_average_damage_instead_of_dps"] = {
},
},
baseFlags = {
attack = true,
area = true,
Expand Down Expand Up @@ -11222,16 +11237,27 @@ skills["SupportMortarCannonPlayer"] = {
[39] = { levelRequirement = 0, },
[40] = { levelRequirement = 0, },
},
addFlags = {
totem = true,
},
statSets = {
[1] = {
label = "SupportMortarCannonPlayer",
incrementalEffectiveness = 0.054999999701977,
statDescriptionScope = "gem_stat_descriptions",
addFlags = {
totem = true,
statMap = {
["support_grenade_ballista_damage_+%_final"] = {
mod("Damage", "MORE", nil),
},
["support_grenade_ballista_attack_speed_+%_final"] = {
mod("Speed", "MORE", nil, ModFlag.Attack),
},
},
baseFlags = {
},
baseMods = {
mod("ActiveTotemLimit", "BASE", 1),
},
constantStats = {
{ "skill_disabled_unless_cloned", 2 },
{ "support_grenade_ballista_attack_speed_+%_final", -50 },
Expand Down Expand Up @@ -13315,7 +13341,7 @@ skills["SiegeBallistaPlayer"] = {
}
}
skills["SiegeBallistaProjectilePlayer"] = {
name = "",
name = "Artillery",
hidden = true,
skillTypes = { [SkillType.Attack] = true, [SkillType.RangedAttack] = true, [SkillType.Projectile] = true, [SkillType.Barrageable] = true, [SkillType.AttackInPlaceIsDefault] = true, [SkillType.Fire] = true, [SkillType.Area] = true, [SkillType.CannotChain] = true, [SkillType.UsedByTotem] = true, },
weaponTypes = {
Expand Down
2 changes: 1 addition & 1 deletion src/Export/Skills/act_int.txt
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ statMap = {

#skill DarkEffigyProjectilePlayer
#set DarkEffigyProjectilePlayer
#flags spell area projectile
#flags spell area projectile totem
#mods
#skillEnd

Expand Down
32 changes: 27 additions & 5 deletions src/Export/Skills/act_str.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ local skills, mod, flag, skill = ...
#skillEnd

#skill SupportAncestralWarriorTotemPlayer
addFlags = {
totem = true,
},
#set SupportAncestralWarriorTotemPlayer
#flags
statMap = {
["support_ancestral_warrior_totem_attack_speed_+%_final"] = {
mod("Speed", "MORE", nil, ModFlag.Attack),
},
},
#baseMod mod("ActiveTotemLimit", "BASE", 1)
#mods
#skillEnd

Expand Down Expand Up @@ -67,7 +76,7 @@ statMap = {
{mod("Damage", "MORE", nil, 0, KeywordFlag.Hit, { type = "GlobalEffect", effectType = "Buff"}, { type = "Multiplier", var = "EnemyPresenceSeconds", actor = "enemy", limitVar = "AttritionMaxDamage", div = 2, limitTotal = true }, { type = "ActorCondition", actor = "enemy", var = "RareOrUnique" })},
{mod("CullPercent", "MAX", nil, 0, 0, { type = "GlobalEffect", effectType = "Buff"}, { type = "MultiplierThreshold", var = "EnemyPresenceSeconds", actor = "enemy", thresholdVar = "AttritionCullSeconds"}, { type = "ActorCondition", actor = "enemy", var = "RareOrUnique" }),
value = 10,}
},
},
},
#mods
#skillEnd
Expand Down Expand Up @@ -272,6 +281,10 @@ statMap = {
#skill ExplosiveGrenadePlayer
#set ExplosiveGrenadePlayer
#flags attack area projectile
statMap = {
["base_skill_show_average_damage_instead_of_dps"] = {
},
},
#mods
#skillEnd

Expand Down Expand Up @@ -631,11 +644,20 @@ statMap = {
#skillEnd

#skill SupportMortarCannonPlayer
addFlags = {
totem = true,
},
#set SupportMortarCannonPlayer
addFlags = {
totem = true,
},
#flags
statMap = {
["support_grenade_ballista_damage_+%_final"] = {
mod("Damage", "MORE", nil),
},
["support_grenade_ballista_attack_speed_+%_final"] = {
mod("Speed", "MORE", nil, ModFlag.Attack),
},
},
#baseMod mod("ActiveTotemLimit", "BASE", 1)
#mods
#skillEnd

Expand Down Expand Up @@ -743,7 +765,7 @@ statMap = {
#mods
#skillEnd

#skill SiegeBallistaProjectilePlayer
#skill SiegeBallistaProjectilePlayer Artillery
#set SiegeBallistaProjectilePlayer
#flags attack projectile totem
#mods
Expand Down
62 changes: 52 additions & 10 deletions src/Modules/CalcActiveSkill.lua
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ function calcs.createActiveSkill(activeEffect, supportList, env, actor, socketGr
if supportEffect.grantedEffect.addFlags and not summonSkill then
-- Support skill adds flags to supported skills (eg. Remote Mine adds 'mine')
for k in pairs(supportEffect.grantedEffect.addFlags) do
mainSkillFlags[k] = true
calcsSkillFlags[k] = true
skillFlags[k] = true
end
end
end
Expand Down Expand Up @@ -250,6 +249,45 @@ local function getWeaponFlags(env, weaponData, weaponTypes)
return flags, info
end

-- Get stats from totem base skill in case of separate active skills or skills that receive totem status via supports
---@param activeSkill table @activeSkill with totem tag
local function getTotemBaseStats(activeSkill)
local totemBase = {}

if activeSkill.skillTypes[SkillType.SummonsTotem] then -- Skill that summons totems already has stats on activeEffect
totemBase.grantedEffect = activeSkill.activeEffect.grantedEffect
totemBase.gemData = activeSkill.activeEffect.gemData
totemBase.skillLevel = activeSkill.activeEffect.level
elseif activeSkill.skillTypes[SkillType.UsedByTotem] then
if activeSkill.activeEffect.grantedEffect.skillTypes[SkillType.UsedByTotem] then -- is totem skill by default
totemBase.grantedEffect = activeSkill.activeEffect.gemData.grantedEffect
totemBase.gemData = activeSkill.activeEffect.gemData
totemBase.skillLevel = activeSkill.activeEffect.level
elseif activeSkill.supportList then -- skill is receives totem status via support
for _, support in ipairs(activeSkill.supportList) do
if support.grantedEffect.addSkillTypes and (not support.superseded) and support.isSupporting[activeSkill.activeEffect.srcInstance] then
for _, skillType in ipairs(support.grantedEffect.addSkillTypes) do
if skillType == SkillType.UsedByTotem then
totemBase.grantedEffect = support.gemData.grantedEffect
totemBase.gemData = support.gemData
break
end
end
end
if totemBase.gemData or totemBase.grantedEffect then
totemBase.skillLevel = support.level
break
end
end
else
-- A totem skill that neither `SummonsTotem` nor `UsedByTotem` should not be possible, but I am leaving this here to alert us in case of unexpected future edge cases
error("Error: Unexpected SkillType behavior for skill with 'totem' flag")
end
end

return totemBase
end

--- Applies additional modifiers to skills with the "Empowered" flag.
--- Checks for "ExtraEmpoweredMod" mods and applies them
--- if they match the conditions set by the empowering effect.
Expand Down Expand Up @@ -484,10 +522,19 @@ function calcs.buildActiveSkillModList(env, activeSkill)
skillKeywordFlags = bor(skillKeywordFlags, KeywordFlag.Spell)
end

-- Get skill totem ID for totem skills
-- This is used to calculate totem life
-- Find totem base stats
if skillFlags.totem then
activeSkill.skillTotemId = activeGrantedEffect.skillTotemId
local totemBase = getTotemBaseStats(activeSkill)
if totemBase.grantedEffect and totemBase.gemData then
activeSkill.skillData.totemBase = totemBase
end
local totemLevelRequirement = activeSkill.skillData.totemBase and activeSkill.skillData.totemBase.grantedEffect.levels[totemBase.skillLevel].levelRequirement or activeEffect.grantedEffect.levels[activeEffect.level].levelRequirement
-- Note: Some active skills related to totem base skills (e.g. on Shockwave Totem) have level requirement = 0, making the additional ` > 0` check necessary
activeSkill.skillData.totemLevel = (totemLevelRequirement and (totemLevelRequirement > 0)) and totemLevelRequirement or 1

-- Get skill totem ID for totem skills
-- This is used to calculate totem life
activeSkill.skillTotemId = activeGrantedEffect.skillTotemId or (activeSkill.skillData.totemBase and activeSkill.skillData.totemBase.grantedEffect.skillTotemId)
if not activeSkill.skillTotemId then
if activeGrantedEffect.color == 2 then
activeSkill.skillTotemId = 2
Expand Down Expand Up @@ -647,11 +694,6 @@ function calcs.buildActiveSkillModList(env, activeSkill)

applyExtraEmpowerMods(activeSkill)

-- Find totem level
if skillFlags.totem then
activeSkill.skillData.totemLevel = 1 or activeEffect.grantedEffect.levels[activeEffect.level].levelRequirement
end

-- Add active mine multiplier
if skillFlags.mine then
activeSkill.activeMineCount = (env.mode == "CALCS" and activeEffect.srcInstance.skillMineCountCalcs) or (env.mode ~= "CALCS" and activeEffect.srcInstance.skillMineCount)
Expand Down
2 changes: 1 addition & 1 deletion src/Modules/CalcSetup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ function calcs.initModDB(env, modDB)
modDB:NewMod("WarcryCastTime", "BASE", 0.8, "Base")
modDB:NewMod("TotemPlacementTime", "BASE", 0.6, "Base")
modDB:NewMod("BallistaPlacementTime", "BASE", 0.35, "Base")
modDB:NewMod("ActiveTotemLimit", "BASE", 1, "Base")
modDB:NewMod("ShockStacksMax", "BASE", 1, "Base")
modDB:NewMod("ChillStacksMax", "BASE", 1, "Base")
modDB:NewMod("ScorchStacksMax", "BASE", 1, "Base")
Expand Down Expand Up @@ -1786,6 +1785,7 @@ function calcs.initEnv(build, mode, override, specEnv)
end
end


-- Merge Requirements Tables
env.requirementsTable = tableConcat(env.requirementsTableItems, env.requirementsTableGems)

Expand Down