From edd3b4e9d72691826867923584b3d6961661818a Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Fri, 8 May 2026 11:46:08 -0500 Subject: [PATCH 1/4] add support for Expand, add flags for Area vs Damage Seal Supports --- src/Data/Skills/sup_int.lua | 16 ++++++++++++++++ src/Export/Skills/sup_int.txt | 14 ++++++++++++++ src/Modules/CalcOffence.lua | 12 ++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Data/Skills/sup_int.lua b/src/Data/Skills/sup_int.lua index 80cd96b6b..383c2387d 100644 --- a/src/Data/Skills/sup_int.lua +++ b/src/Data/Skills/sup_int.lua @@ -3812,8 +3812,23 @@ skills["SupportExpandPlayer"] = { label = "Expand", incrementalEffectiveness = 0.054999999701977, statDescriptionScope = "gem_stat_descriptions", + statMap = { + ["support_expand_max_seals"] = { + mod("SealCount", "BASE", nil), + }, + ["skill_area_of_effect_+%_per_expand_seal"] = { + mod("SealRepeatPenalty", "MORE", nil), + }, + ["expand_support_seal_gain_frequency_as_%_of_total_cast_time"] = { + mod("SealGainFrequency", "BASE", nil), + }, + }, baseFlags = { }, + baseMods = { + flag("HasSeals"), + flag("AreaSeal"), + }, constantStats = { { "support_expand_max_seals", 3 }, { "support_expand_charge_gain_interval_ms", 0 }, @@ -7592,6 +7607,7 @@ skills["SupportUnleashPlayer"] = { }, baseMods = { flag("HasSeals"), + flag("DamageSeal"), }, constantStats = { { "support_spell_rapid_fire_repeat_use_damage_+%_final", -50 }, diff --git a/src/Export/Skills/sup_int.txt b/src/Export/Skills/sup_int.txt index 36db0880d..0479ecdf0 100644 --- a/src/Export/Skills/sup_int.txt +++ b/src/Export/Skills/sup_int.txt @@ -665,6 +665,19 @@ statMap = { #skill SupportExpandPlayer #set SupportExpandPlayer +statMap = { + ["support_expand_max_seals"] = { + mod("SealCount", "BASE", nil), + }, + ["skill_area_of_effect_+%_per_expand_seal"] = { + mod("SealRepeatPenalty", "MORE", nil), + }, + ["expand_support_seal_gain_frequency_as_%_of_total_cast_time"] = { + mod("SealGainFrequency", "BASE", nil), + }, +}, +#baseMod flag("HasSeals") +#baseMod flag("AreaSeal") #mods #skillEnd @@ -1445,6 +1458,7 @@ statMap = { #skill SupportUnleashPlayer #set SupportUnleashPlayer #baseMod flag("HasSeals") +#baseMod flag("DamageSeal") #mods #skillEnd diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index abf822011..628b4b4c4 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -402,6 +402,14 @@ function calcs.offence(env, actor, activeSkill) output.ArmourBreakPerHit = calcLib.val(skillModList, "ArmourBreakPerHit", skillCfg) local function calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, output, breakdown) + -- Applies increased AoE based on seals count + if skillModList:Flag(nil, "HasSeals") and skillModList:Flag(nil, "AreaSeal") and not skillModList:Flag(nil, "NoRepeatBonuses") then + output.SealCooldown = activeSkill.activeEffect.grantedEffect.castTime * skillModList:Sum("BASE", skillCfg, "SealGainFrequency") / calcLib.mod(skillModList, skillCfg, "SealGainFrequency") / 100 + output.SealMax = skillModList:Sum("BASE", skillCfg, "SealCount") + output.TimeMaxSeals = output.SealCooldown * output.SealMax + env.player.mainSkill.skillModList:NewMod("AreaOfEffect", "INC", (output.SealMax * (calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") - 1) * 100), "Expand") + end + local incArea, moreArea = calcLib.mods(skillModList, skillCfg, "AreaOfEffect", "AreaOfEffectPrimary") output.AreaOfEffectMod = round(round(incArea * moreArea, 10), 2) if skillData.radiusIsWeaponRange then @@ -1096,7 +1104,7 @@ function calcs.offence(env, actor, activeSkill) modDB:NewMod("DPS", "MORE", detonateTwice, "Grenade Activate Twice") end - if skillModList:Flag(nil, "HasSeals") and activeSkill.skillTypes[SkillType.Unleashable] and not skillModList:Flag(nil, "NoRepeatBonuses") then + if skillModList:Flag(nil, "HasSeals") and skillModList:Flag(nil, "DamageSeal") and not skillModList:Flag(nil, "NoRepeatBonuses") then -- Applies DPS multiplier based on seals count local totalCastSpeed = 1 / activeSkill.activeEffect.grantedEffect.castTime * calcLib.mod(skillModList, skillCfg, "Speed") output.SealCooldown = activeSkill.activeEffect.grantedEffect.castTime * skillModList:Sum("BASE", skillCfg, "SealGainFrequency") / calcLib.mod(skillModList, skillCfg, "SealGainFrequency") / 100 @@ -5672,7 +5680,7 @@ function calcs.offence(env, actor, activeSkill) elseif skillFlags.totem then useSpeed = (output.Cooldown and output.Cooldown > 0 and (output.TotemPlacementSpeed > 0 and output.TotemPlacementSpeed or 1 / output.Cooldown) or output.TotemPlacementSpeed) / repeats timeType = "totem placement" - elseif skillModList:Flag(nil, "HasSeals") and skillModList:Flag(nil, "UseMaxUnleash") then + elseif skillModList:Flag(nil, "HasSeals") and skillModList:Flag(nil, "DamageSeal") and skillModList:Flag(nil, "UseMaxUnleash") then useSpeed = env.player.mainSkill.skillData.hitTimeOverride / repeats timeType = "full unleash" elseif output.EffectiveReloadTime then -- Crossbows: Account for mana cost only happening on reload (once all bolts are fired) From d1f5a143f2a29edce5edf418dc9c8217d179b557 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Fri, 8 May 2026 12:17:10 -0500 Subject: [PATCH 2/4] dynamic skill name for damage/aoe source --- src/Modules/CalcOffence.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 628b4b4c4..235f7f2f8 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -401,13 +401,21 @@ function calcs.offence(env, actor, activeSkill) -- Calculate armour break output.ArmourBreakPerHit = calcLib.val(skillModList, "ArmourBreakPerHit", skillCfg) + local function getSkillNameFromFlag(skillModList, flag) + local sourceMod = skillModList:Tabulate("FLAG", nil, flag) + local sourceName = sourceMod[1] and sourceMod[1].mod and sourceMod[1].mod.source -- e.g. Skill:SupportExpandPlayer + local dataSkill = env.data.skills[(sourceName:gsub("Skill:", ""))] + return dataSkill and dataSkill.name + end + local function calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, output, breakdown) -- Applies increased AoE based on seals count if skillModList:Flag(nil, "HasSeals") and skillModList:Flag(nil, "AreaSeal") and not skillModList:Flag(nil, "NoRepeatBonuses") then output.SealCooldown = activeSkill.activeEffect.grantedEffect.castTime * skillModList:Sum("BASE", skillCfg, "SealGainFrequency") / calcLib.mod(skillModList, skillCfg, "SealGainFrequency") / 100 output.SealMax = skillModList:Sum("BASE", skillCfg, "SealCount") output.TimeMaxSeals = output.SealCooldown * output.SealMax - env.player.mainSkill.skillModList:NewMod("AreaOfEffect", "INC", (output.SealMax * (calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") - 1) * 100), "Expand") + local skillName = getSkillNameFromFlag(skillModList, "AreaSeal") or "Support" + env.player.mainSkill.skillModList:NewMod("AreaOfEffect", "INC", (output.SealMax * (calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") - 1) * 100), skillName) end local incArea, moreArea = calcLib.mods(skillModList, skillCfg, "AreaOfEffect", "AreaOfEffectPrimary") @@ -1113,15 +1121,16 @@ function calcs.offence(env, actor, activeSkill) output.TimeMaxSeals = output.SealCooldown * output.SealMax if not skillData.hitTimeOverride then + local skillName = getSkillNameFromFlag(skillModList, "DamageSeal") or "Support" if skillModList:Flag(nil, "UseMaxUnleash") then for i, value in ipairs(skillModList:Tabulate("INC", { }, "MaxSealCrit")) do local mod = value.mod skillModList:NewMod("CritChance", "INC", mod.value, mod.source, mod.flags, mod.keywordFlags, unpack(mod)) end - env.player.mainSkill.skillModList:NewMod("DPS", "MORE", (output.SealMax * calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty")) * 100, "Unleash") + env.player.mainSkill.skillModList:NewMod("DPS", "MORE", (output.SealMax * calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty")) * 100, skillName) env.player.mainSkill.skillData.hitTimeOverride = m_max(output.TimeMaxSeals, totalCastSpeed * 1.1) else - env.player.mainSkill.skillModList:NewMod("DPS", "MORE", round(1 / output.SealCooldown / (totalCastSpeed * 1.1) * calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") * 100, 2), "Unleash") + env.player.mainSkill.skillModList:NewMod("DPS", "MORE", round(1 / output.SealCooldown / (totalCastSpeed * 1.1) * calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") * 100, 2), skillName) end end From 86ae858d14d40a2d108537bd098f514a58825ebb Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Mon, 18 May 2026 09:24:05 -0500 Subject: [PATCH 3/4] updated Zarokh's Revolt with DamageSeal --- src/Data/Skills/sup_int.lua | 1 + src/Export/Skills/sup_int.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Data/Skills/sup_int.lua b/src/Data/Skills/sup_int.lua index 383c2387d..43e7f8c97 100644 --- a/src/Data/Skills/sup_int.lua +++ b/src/Data/Skills/sup_int.lua @@ -8091,6 +8091,7 @@ skills["SupportZarokhsRevoltPlayer"] = { }, baseMods = { flag("HasSeals"), + flag("DamageSeal"), }, constantStats = { { "support_spell_rapid_fire_repeat_use_damage_+%_final", -20 }, diff --git a/src/Export/Skills/sup_int.txt b/src/Export/Skills/sup_int.txt index 0479ecdf0..72b6720fa 100644 --- a/src/Export/Skills/sup_int.txt +++ b/src/Export/Skills/sup_int.txt @@ -1541,6 +1541,7 @@ statMap = { #skill SupportZarokhsRevoltPlayer #set SupportZarokhsRevoltPlayer #baseMod flag("HasSeals") +#baseMod flag("DamageSeal") #mods #skillEnd From df6ee1b948184f0a9d985f308a52e0b62a426b07 Mon Sep 17 00:00:00 2001 From: LocalIdentity Date: Tue, 26 May 2026 20:13:45 +1000 Subject: [PATCH 4/4] Fix to use uptime of seals Fixes the calc to use the uptime for seals and fits it into the existing seal calc --- src/Modules/CalcOffence.lua | 31 +++++++++++++++++-------------- src/Modules/CalcTriggers.lua | 2 +- src/Modules/ConfigOptions.lua | 2 +- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 8f6ebe07d..e81769bbc 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -409,15 +409,6 @@ function calcs.offence(env, actor, activeSkill) end local function calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, output, breakdown) - -- Applies increased AoE based on seals count - if skillModList:Flag(nil, "HasSeals") and skillModList:Flag(nil, "AreaSeal") and not skillModList:Flag(nil, "NoRepeatBonuses") then - output.SealCooldown = activeSkill.activeEffect.grantedEffect.castTime * skillModList:Sum("BASE", skillCfg, "SealGainFrequency") / calcLib.mod(skillModList, skillCfg, "SealGainFrequency") / 100 - output.SealMax = skillModList:Sum("BASE", skillCfg, "SealCount") - output.TimeMaxSeals = output.SealCooldown * output.SealMax - local skillName = getSkillNameFromFlag(skillModList, "AreaSeal") or "Support" - env.player.mainSkill.skillModList:NewMod("AreaOfEffect", "INC", (output.SealMax * (calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") - 1) * 100), skillName) - end - local incArea, moreArea = calcLib.mods(skillModList, skillCfg, "AreaOfEffect", "AreaOfEffectPrimary") output.AreaOfEffectMod = round(round(incArea * moreArea, 10), 2) if skillData.radiusIsWeaponRange then @@ -1130,15 +1121,17 @@ function calcs.offence(env, actor, activeSkill) modDB:NewMod("DPS", "MORE", detonateTwice, "Grenade Activate Twice") end - if skillModList:Flag(nil, "HasSeals") and skillModList:Flag(nil, "DamageSeal") and not skillModList:Flag(nil, "NoRepeatBonuses") then - -- Applies DPS multiplier based on seals count + if skillModList:Flag(nil, "HasSeals") and not skillModList:Flag(nil, "NoRepeatBonuses") then + -- Applies seal bonuses based on seal count local totalCastSpeed = 1 / activeSkill.activeEffect.grantedEffect.castTime * calcLib.mod(skillModList, skillCfg, "Speed") output.SealCooldown = activeSkill.activeEffect.grantedEffect.castTime * skillModList:Sum("BASE", skillCfg, "SealGainFrequency") / calcLib.mod(skillModList, skillCfg, "SealGainFrequency") / 100 output.SealMax = skillModList:Sum("BASE", skillCfg, "SealCount") - output.AverageBurstHits = output.SealMax output.TimeMaxSeals = output.SealCooldown * output.SealMax - if not skillData.hitTimeOverride then + if skillModList:Flag(nil, "DamageSeal") then + output.AverageBurstHits = output.SealMax + end + if skillModList:Flag(nil, "DamageSeal") and not skillData.hitTimeOverride then local skillName = getSkillNameFromFlag(skillModList, "DamageSeal") or "Support" if skillModList:Flag(nil, "UseMaxUnleash") then for i, value in ipairs(skillModList:Tabulate("INC", { }, "MaxSealCrit")) do @@ -1151,6 +1144,16 @@ function calcs.offence(env, actor, activeSkill) env.player.mainSkill.skillModList:NewMod("DPS", "MORE", round(1 / output.SealCooldown / (totalCastSpeed * 1.1) * calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") * 100, 2), skillName) end end + if skillModList:Flag(nil, "AreaSeal") then + local skillName = getSkillNameFromFlag(skillModList, "AreaSeal") or "Support" + local sealArea = (calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") - 1) * 100 + if skillModList:Flag(nil, "UseMaxUnleash") then + env.player.mainSkill.skillModList:NewMod("AreaOfEffect", "INC", output.SealMax * sealArea, skillName) + env.player.mainSkill.skillData.hitTimeOverride = m_max(output.TimeMaxSeals, totalCastSpeed * 1.1) + else + env.player.mainSkill.skillModList:NewMod("AreaOfEffect", "INC", round(1 / output.SealCooldown / totalCastSpeed * sealArea, 2), skillName) + end + end if breakdown then breakdown.SealGainTime = { } @@ -4136,7 +4139,7 @@ function calcs.offence(env, actor, activeSkill) end output.AverageDamage = output.AverageHit * output.HitChance / 100 globalOutput.AverageBurstHits = output.AverageBurstHits or 1 - local repeatPenalty = skillModList:Flag(nil, "HasSeals") and activeSkill.skillTypes[SkillType.Unleashable] and not skillModList:Flag(nil, "NoRepeatBonuses") and calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") or 1 + local repeatPenalty = skillModList:Flag(nil, "HasSeals") and skillModList:Flag(nil, "DamageSeal") and not skillModList:Flag(nil, "NoRepeatBonuses") and calcLib.mod(skillModList, skillCfg, "SealRepeatPenalty") or 1 globalOutput.AverageBurstDamage = output.AverageDamage + output.AverageDamage * (globalOutput.AverageBurstHits - 1) * repeatPenalty or 0 globalOutput.ShowBurst = globalOutput.AverageBurstHits > 1 output.TotalDPS = output.AverageDamage * (globalOutput.HitSpeed or globalOutput.Speed) * skillData.dpsMultiplier * quantityMultiplier diff --git a/src/Modules/CalcTriggers.lua b/src/Modules/CalcTriggers.lua index 35fab416f..d861968b9 100644 --- a/src/Modules/CalcTriggers.lua +++ b/src/Modules/CalcTriggers.lua @@ -439,7 +439,7 @@ local function defaultTriggerHandler(env, config) actor.mainSkill.skillData.ignoresTickRate = actor.mainSkill.skillData.ignoresTickRate or (actor.mainSkill.skillData.storedUses and actor.mainSkill.skillData.storedUses > 1) --Account for source unleash - if source and GlobalCache.cachedData[env.mode][uuid] and source.skillModList:Flag(nil, "HasSeals") and source.skillTypes[SkillType.Unleashable] then + if source and GlobalCache.cachedData[env.mode][uuid] and source.skillModList:Flag(nil, "HasSeals") and source.skillModList:Flag(nil, "DamageSeal") then local unleashDpsMult = GlobalCache.cachedData[env.mode][uuid].ActiveSkill.skillData.dpsMultiplier or 1 trigRate = trigRate * unleashDpsMult actor.mainSkill.skillFlags.HasSeals = true diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index 756282166..6464e516d 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -824,7 +824,7 @@ Huge sets the radius to 11. { var = "overrideGhostShrouds", type = "count", label = "# of Ghost Shrouds (if not maximum):", ifOption = "useGhostShrouds", apply = function(val, modList, enemyModList) modList:NewMod("GhostShrouds", "OVERRIDE", val, "Config", { type = "Condition", var = "Combat" }) end }, - { var = "waitForMaxSeals", type = "check", label = "Do you wait for Max Unleash Seals?", ifFlag = "HasSeals", apply = function(val, modList, enemyModList) + { var = "waitForMaxSeals", type = "check", label = "Do you wait for Max Seals?", ifFlag = "HasSeals", apply = function(val, modList, enemyModList) modList:NewMod("UseMaxUnleash", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) end }, { var = "repeatMode", type = "list", label = "Repeat Mode:", ifCond = "alwaysFinalRepeat", list = {