Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for triggered skills with Snipe Support #6248

Merged
merged 2 commits into from
Aug 14, 2023
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
10 changes: 5 additions & 5 deletions src/Data/SkillStatMap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ return {
skill("triggeredWhileChannelling", true, { type = "SkillType", skillType = SkillType.Triggerable }, { type = "SkillType", skillType = SkillType.Spell }),
},
["skill_triggered_by_snipe"] = {
skill("triggered", true, { type = "SkillType", skillType = SkillType.Triggerable }),
skill("triggeredBySnipe", true, { type = "SkillType", skillType = SkillType.Triggerable }),
},
["triggered_by_spiritual_cry"] = {
skill("triggeredByGeneralsCry", true, { type = "SkillType", skillType = SkillType.Melee }, { type = "SkillType", skillType = SkillType.Attack }),
Expand Down Expand Up @@ -1699,11 +1699,11 @@ return {
["channelled_skill_damage_+%"] = {
mod("Damage", "INC", nil, 0, 0, { type = "SkillType", skillType = SkillType.Channel }),
},
["snipe_triggered_skill_hit_damage_+%_final_per_stage"] = {
mod("Damage", "MORE", nil, ModFlag.Hit, 0, { type = "Multiplier", var = "SnipeStage", limitVar = "SnipeStagesMax" }),
},
["snipe_triggered_skill_ailment_damage_+%_final_per_stage"] = {
mod("Damage", "MORE", nil, ModFlag.Ailment, 0, { type = "Multiplier", var = "SnipeStage", limitVar = "SnipeStagesMax" }),
mod("snipeAilmentMulti", "BASE", nil),
},
["snipe_triggered_skill_hit_damage_+%_final_per_stage"] = {
mod("snipeHitMulti", "BASE", nil),
},
["snipe_triggered_skill_damage_+%_final"] = {
mod("Damage", "MORE", nil),
Expand Down
3 changes: 0 additions & 3 deletions src/Data/Skills/act_dex.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10797,9 +10797,6 @@ skills["ChannelledSnipe"] = {
},
statDescriptionScope = "skill_stat_descriptions",
castTime = 1,
initialFunc = function(activeSkill, output)
activeSkill.skillData.dpsMultiplier = 1 / math.min(math.max(activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:SnipeStage"), 1), activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:SnipeStagesMax"))
end,
statMap = {
["snipe_max_stacks"] = {
mod("Multiplier:SnipeStagesMax", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Buff", unscalable = true }),
Expand Down
3 changes: 0 additions & 3 deletions src/Export/Skills/act_dex.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2032,9 +2032,6 @@ local skills, mod, flag, skill = ...

#skill ChannelledSnipe
#flags attack projectile
initialFunc = function(activeSkill, output)
activeSkill.skillData.dpsMultiplier = 1 / math.min(math.max(activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:SnipeStage"), 1), activeSkill.skillModList:Sum("BASE", cfg, "Multiplier:SnipeStagesMax"))
end,
statMap = {
["snipe_max_stacks"] = {
mod("Multiplier:SnipeStagesMax", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Buff", unscalable = true }),
Expand Down
13 changes: 8 additions & 5 deletions src/Modules/CalcOffence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ local function isTriggered(skillData)
or skillData.triggeredByManaPercentSpent
or skillData.triggeredByParentAttack
or skillData.triggeredWhenHexEnds
or skillData.triggeredBySnipe
end

-- Calculate min/max damage for the given damage type
Expand Down Expand Up @@ -766,10 +767,6 @@ function calcs.offence(env, actor, activeSkill)
end
end
end
--Snipe doesn't grab the max stages multiplier from the gem when granted by Assailum so we add it back here
if skillModList:Flag(nil, "TriggeredByAssailum") and activeSkill.skillTypes[SkillType.Triggerable] then
skillModList:NewMod("Multiplier:SnipeStagesMax", "BASE", 6, "Snipe Max Stages", { type = "GlobalEffect", effectType = "Buff", unscalable = true })
end
if skillModList:Sum("BASE", nil, "CritMultiplierAppliesToDegen") > 0 then
for i, value in ipairs(skillModList:Tabulate("BASE", skillCfg, "CritMultiplier")) do
local mod = value.mod
Expand Down Expand Up @@ -2048,7 +2045,13 @@ function calcs.offence(env, actor, activeSkill)
end
elseif skillData.hitTimeMultiplier and output.Time and not skillData.triggeredOnDeath then
output.HitTime = output.Time * skillData.hitTimeMultiplier
output.HitSpeed = 1 / output.HitTime
if output.Cooldown and skillData.triggered then
output.HitSpeed = 1 / (m_max(output.HitTime, output.Cooldown))
elseif output.Cooldown then
output.HitSpeed = 1 / (output.HitTime + output.Cooldown)
else
output.HitSpeed = 1 / output.HitTime
end
end

-- Other Misc DPS multipliers (like custom source)
Expand Down
84 changes: 84 additions & 0 deletions src/Modules/CalcPerform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3597,6 +3597,90 @@ function calcs.perform(env, avoidCache, fullDPSSkipEHP)
end
end

-- Snipe Support
if env.player.mainSkill.skillData.triggeredBySnipe or env.player.mainSkill.activeEffect.grantedEffect.name == "Snipe" and not env.player.mainSkill.skillFlags.minion then
local triggerName = "Snipe"
local snipeStages = math.min(env.player.modDB:Sum("BASE", nil, "Multiplier:SnipeStage"), env.player.modDB:Sum("BASE", nil, "Multiplier:SnipeStagesMax")) - 0.5 --First stage takes 0.5x time to channel compared to subsequent stages
local maxSnipeStages = env.player.modDB:Sum("BASE", nil, "Multiplier:SnipeStagesMax") - 0.5
if env.player.mainSkill.marked then
if env.player.mainSkill.activeEffect.grantedEffect.name == "Snipe" then
local snipeHitMulti = env.player.mainSkill.skillModList:Sum("BASE", env.player.mainSkill.skillCfg, "snipeHitMulti")
local snipeAilmentMulti = env.player.mainSkill.skillModList:Sum("BASE", env.player.mainSkill.skillCfg, "snipeAilmentMulti")
env.player.mainSkill.skillModList:NewMod("Damage", "MORE", snipeHitMulti * (maxSnipeStages + 0.5), "Snipe", ModFlag.Hit, 0)
env.player.mainSkill.skillModList:NewMod("Damage", "MORE", snipeAilmentMulti * (maxSnipeStages + 0.5), "Snipe", ModFlag.Ailment, 0)
env.player.mainSkill.skillData.hitTimeMultiplier = maxSnipeStages
else
snipeStages = 0 --Triggered skills cannot be channeled by Mirage Archer
end
else
local snipeHitMulti = env.player.mainSkill.skillModList:Sum("BASE", env.player.mainSkill.skillCfg, "snipeHitMulti")
local snipeAilmentMulti = env.player.mainSkill.skillModList:Sum("BASE", env.player.mainSkill.skillCfg, "snipeAilmentMulti")
env.player.mainSkill.skillModList:NewMod("Damage", "MORE", snipeHitMulti * (snipeStages + 0.5), "Snipe", ModFlag.Hit, 0)
env.player.mainSkill.skillModList:NewMod("Damage", "MORE", snipeAilmentMulti * (snipeStages + 0.5), "Snipe", ModFlag.Ailment, 0)
end
if env.player.mainSkill.activeEffect.grantedEffect.name == "Snipe" and env.player.mainSkill.marked then
env.player.mainSkill.skillData.hitTimeMultiplier = env.player.modDB:Sum("BASE", nil, "Multiplier:SnipeStagesMax") - 0.5
end
local triggerSkillCount = 0
local triggerSkillPosition = 1
local posFound = false
local trigRate = 0
local source = nil
for _, skill in ipairs(env.player.activeSkillList) do
if skill.activeEffect.grantedEffect.name == "Snipe" and env.player.mainSkill.activeEffect.grantedEffect.name ~= "Snipe" and skill ~= env.player.mainSkill and skill.socketGroup and skill.socketGroup.slot == env.player.mainSkill.socketGroup.slot then
source, trigRate = findTriggerSkill(env, skill, source, trigRate)
end
if skill.skillData.triggeredBySnipe and env.player.mainSkill.socketGroup.slot == skill.socketGroup.slot then
triggerSkillCount = triggerSkillCount + 1
if skill ~= env.player.mainSkill and not posFound then
triggerSkillPosition = triggerSkillPosition + 1
else
posFound = true
end
end
end
if env.player.mainSkill.activeEffect.grantedEffect.name == "Snipe" then
if triggerSkillCount > 0 then
env.player.mainSkill.skillData.baseMultiplier = 0
env.player.mainSkill.infoMessage = "Triggering Support Skills:"
end
env.player.mainSkill.skillData.hitTimeMultiplier = snipeStages
elseif not source or (snipeStages + 0.5) < triggerSkillPosition then
env.player.mainSkill.skillData.triggeredBySnipe = nil
env.player.mainSkill.infoMessage = s_format("Not enough Snipe stages to Trigger Skill")
env.player.mainSkill.infoMessage2 = "DPS reported assuming Self-Cast"..triggerSkillCount
env.player.mainSkill.infoTrigger = ""
else
env.player.mainSkill.skillData.triggered = true

local uuid = cacheSkillUUID(source)
local sourceTime = GlobalCache.cachedData["CACHE"][uuid].Speed

output.ActionTriggerRate = getTriggerActionTriggerRate(env.player.mainSkill.skillData.cooldown, env, breakdown)
output.SourceTriggerRate = sourceTime
output.ServerTriggerRate = m_min(output.SourceTriggerRate, output.ActionTriggerRate)

if breakdown then
breakdown.SimData = {
s_format("Trigger rate:"),
s_format("1 / %.2f ^8(Snipe channel time)", snipeStages / sourceTime),
s_format("= %.2f ^8per second", output.SourceTriggerRate),
}
breakdown.ServerTriggerRate = {
s_format("%.2f ^8(smaller of 'cap' and 'skill' trigger rates)", output.ServerTriggerRate),
}
end

-- Account for Trigger-related INC/MORE modifiers
addTriggerIncMoreMods(env.player.mainSkill, env.player.mainSkill)
env.player.mainSkill.skillData.triggerRate = sourceTime
env.player.mainSkill.skillData.triggerSource = source
env.player.mainSkill.skillData.hitTimeMultiplier = snipeStages
env.player.mainSkill.infoMessage = "Triggered by Snipe"
env.player.mainSkill.infoTrigger = triggerName
env.player.mainSkill.skillFlags.noDisplay = true
end
end

-- Doom Blast (from Impending Doom)
if env.player.mainSkill.skillData.triggeredWhenHexEnds and not env.player.mainSkill.skillFlags.minion then
Expand Down
8 changes: 3 additions & 5 deletions src/Modules/ModParser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2559,13 +2559,11 @@ local specialModList = {
["socketed gems gain (%d+)%% of physical damage as extra lightning damage"] = function(num) return { mod("ExtraSkillMod", "LIST", { mod = mod("PhysicalDamageGainAsLightning", "BASE", num) }, { type = "SocketedIn", slotName = "{SlotName}" }) } end,
["socketed red gems get (%d+)%% physical damage as extra fire damage"] = function(num) return { mod("ExtraSkillMod", "LIST", { mod = mod("PhysicalDamageGainAsFire", "BASE", num) }, { type = "SocketedIn", slotName = "{SlotName}", keyword = "strength" }) } end,
["socketed non%-channelling bow skills are triggered by snipe"] = {
mod("ExtraSkillMod", "LIST", { mod = flag("TriggeredByAssailum") }, { type = "SocketedIn", slotName = "{SlotName}", keyword = "bow" }, { type = "SkillType", skillType = SkillType.Triggerable }),
mod("ExtraSkillMod", "LIST", { mod = mod("SkillData", "LIST", { key = "showAverage", value = true }) }, { type = "SocketedIn", slotName = "{SlotName}", keyword = "bow" }, { type = "SkillType", skillType = SkillType.Triggerable }),
mod("ExtraSkillMod", "LIST", { mod = mod("SkillData", "LIST", { key = "triggered", value = 1 }) }, { type = "SocketedIn", slotName = "{SlotName}", keyword = "bow" }, { type = "SkillType", skillType = SkillType.Triggerable }),
},
["grants level (%d+) snipe skill"] = function(num) return {
mod("ExtraSupport", "LIST", { skillId = "ChannelledSnipeSupport", level = num }, { type = "SocketedIn", slotName = "{SlotName}" }) }
end,
mod("ExtraSkill", "LIST", { skillId = "ChannelledSnipe", level = num }),
mod("ExtraSupport", "LIST", { skillId = "ChannelledSnipeSupport", level = num }, { type = "SocketedIn", slotName = "{SlotName}" }),
} end,
["socketed triggered bow skills deal (%d+)%% less damage"] = function(num) return { mod("ExtraSkillMod", "LIST", { mod = mod("Damage", "MORE", -num) }, { type = "SocketedIn", slotName = "{SlotName}", keyword = "bow" }, { type = "SkillType", skillType = SkillType.Triggerable }) } end,
["socketed vaal skills require (%d+)%% less souls per use"] = function(num) return { mod("ExtraSkillMod", "LIST", { mod = mod("SoulCost", "MORE", -num) }, { type = "SocketedIn", slotName = "{SlotName}" }, { type = "SkillType", skillType = SkillType.Vaal }) } end,
["hits from socketed vaal skills ignore enemy monster resistances"] = {
Expand Down
Loading