From 56e151b66528d258d510d1582c5e6d734af61a6c Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 12 May 2026 02:14:34 -0500 Subject: [PATCH 01/12] add support for Ancestral Call, Crescendo II and III, ancestral boost tree nodes --- src/Data/ModCache.lua | 12 +++--- src/Data/SkillStatMap.lua | 7 ++++ src/Data/Skills/sup_int.lua | 5 +++ src/Data/Skills/sup_str.lua | 18 +++++++++ src/Export/Skills/sup_int.txt | 5 +++ src/Export/Skills/sup_str.txt | 14 +++++++ src/Modules/CalcOffence.lua | 70 ++++++++++++++++++++++++++++++++--- src/Modules/CalcSections.lua | 9 ++++- src/Modules/ModParser.lua | 3 ++ 9 files changed, 129 insertions(+), 14 deletions(-) diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index ad786db07..bcdfe19a5 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -2325,7 +2325,7 @@ c["30% increased Accuracy Rating against Rare or Unique Enemies"]={{[1]={[1]={ac c["30% increased Accuracy Rating at Close Range"]={{[1]={[1]={type="Condition",var="AtCloseRange"},flags=0,keywordFlags=0,name="AccuracyVsEnemy",type="INC",value=30}},nil} c["30% increased Accuracy Rating while moving"]={{[1]={[1]={type="Condition",var="Moving"},flags=0,keywordFlags=0,name="Accuracy",type="INC",value=30}},nil} c["30% increased Archon Buff duration"]={{[1]={flags=0,keywordFlags=0,name="Duration",type="INC",value=30}}," Archon Buff "} -c["30% increased Area of Effect of Ancestrally Boosted Attacks"]={{[1]={flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=30}}," of Ancestrally Boosted Attacks "} +c["30% increased Area of Effect of Ancestrally Boosted Attacks"]={{[1]={flags=1,keywordFlags=0,name="AncestralBoostAreaOfEffect",type="INC",value=30}},nil} c["30% increased Armour"]={{[1]={flags=0,keywordFlags=0,name="Armour",type="INC",value=30}},nil} c["30% increased Armour while Bleeding"]={{[1]={[1]={type="Condition",var="Bleeding"},flags=0,keywordFlags=0,name="Armour",type="INC",value=30}},nil} c["30% increased Armour while Surrounded"]={{[1]={[1]={type="Condition",var="Surrounded"},flags=0,keywordFlags=0,name="Armour",type="INC",value=30}},nil} @@ -2563,8 +2563,7 @@ c["4% chance that if you would gain Rage on Hit, you instead gain up to your max c["4% increased Area of Effect"]={{[1]={flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=4}},nil} c["4% increased Area of Effect for Attacks"]={{[1]={flags=1,keywordFlags=0,name="AreaOfEffect",type="INC",value=4}},nil} c["4% increased Area of Effect for Attacks per Enemy you've Ignited in the last 8 seconds, up to 40%"]={{[1]={flags=1,keywordFlags=0,name="AreaOfEffect",type="INC",value=4}}," per Enemy you've Ignited in the last 8 seconds, up to 40% "} -c["4% increased Area of Effect of Ancestrally Boosted Attacks"]={{[1]={flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=4}}," of Ancestrally Boosted Attacks "} -c["4% increased Area of Effect of Ancestrally Boosted Attacks Ancestrally Boosted Attacks deal 8% increased Damage"]={{[1]={flags=0,keywordFlags=0,name="AreaOfEffect",type="INC",value=4}}," of Ancestrally Boosted Attacks Ancestrally Boosted Attacks deal 8% increased Damage "} +c["4% increased Area of Effect of Ancestrally Boosted Attacks"]={{[1]={flags=1,keywordFlags=0,name="AncestralBoostAreaOfEffect",type="INC",value=4}},nil} c["4% increased Attack Damage per 75 Item Armour and Evasion Rating on Equipped Shield"]={{[1]={[1]={div=75,statList={[1]="ArmourOnWeapon 2",[2]="EvasionOnWeapon 2"},type="PerStat"},[2]={type="Condition",var="UsingShield"},flags=1,keywordFlags=0,name="Damage",type="INC",value=4}},nil} c["4% increased Attack Speed"]={{[1]={flags=1,keywordFlags=0,name="Speed",type="INC",value=4}},nil} c["4% increased Attack Speed while a Rare or Unique Enemy is in your Presence"]={{[1]={[1]={actor="enemy",type="ActorCondition",varList={[1]="NearbyRareOrUniqueEnemy",[2]="RareOrUnique"}},flags=1,keywordFlags=0,name="Speed",type="INC",value=4}},nil} @@ -4338,10 +4337,9 @@ c["Alternating every 5 seconds: Take 40% less Damage from Hits"]={nil,"Alternati c["Always Hits"]={{[1]={[1]={type="Condition",var="{Hand}Attack"},flags=0,keywordFlags=0,name="CannotBeEvaded",type="FLAG",value=true}},nil} c["Always Poison on Hit with this weapon"]={{[1]={[1]={type="Condition",var="{Hand}Attack"},[2]={neg=true,skillType=167,type="SkillType"},flags=8192,keywordFlags=0,name="PoisonChance",type="OVERRIDE",value=100}},nil} c["Always deals Critical Hits against Heavy Stunned Enemies"]={{[1]={[1]={actor="enemy",type="ActorCondition",var="HeavyStunned"},[2]={type="Condition",var="{Hand}Attack"},flags=0,keywordFlags=0,name="CritChance",type="OVERRIDE",value=100}},nil} -c["Ancestrally Boosted Attacks deal 16% increased Damage"]={nil,"Ancestrally Boosted Attacks deal 16% increased Damage "} -c["Ancestrally Boosted Attacks deal 30% increased Damage"]={nil,"Ancestrally Boosted Attacks deal 30% increased Damage "} -c["Ancestrally Boosted Attacks deal 30% increased Damage On Heavy Stunning a Rare or Unique Enemy, your next Attack within 4 seconds will be Ancestrally Boosted"]={nil,"Ancestrally Boosted Attacks deal 30% increased Damage On Heavy Stunning a Rare or Unique Enemy, your next Attack within 4 seconds will be Ancestrally Boosted "} -c["Ancestrally Boosted Attacks deal 8% increased Damage"]={nil,"Ancestrally Boosted Attacks deal 8% increased Damage "} +c["Ancestrally Boosted Attacks deal 16% increased Damage"]={{[1]={flags=1,keywordFlags=0,name="AncestralBoostDamage",type="INC",value=16}},nil} +c["Ancestrally Boosted Attacks deal 30% increased Damage"]={{[1]={flags=1,keywordFlags=0,name="AncestralBoostDamage",type="INC",value=30}},nil} +c["Ancestrally Boosted Attacks deal 8% increased Damage"]={{[1]={flags=1,keywordFlags=0,name="AncestralBoostDamage",type="INC",value=8}},nil} c["Any number of Poisons from this Weapon can affect a target at the same time"]={{[1]={flags=0,keywordFlags=0,name="PoisonCanStack",type="FLAG",value=true},[2]={[1]={type="Condition",var="{Hand}Attack"},[2]={neg=true,skillType=167,type="SkillType"},flags=0,keywordFlags=0,name="PoisonStacks",type="OVERRIDE",value=math.huge}},nil} c["Apply 10 Critical Weakness to Enemies when Consuming a Mark on them"]={{[1]={flags=0,keywordFlags=0,name="ApplyCriticalWeakness",type="FLAG",value=true}},nil} c["Apply Debilitate to Enemies 3 Metres in front of you while your Shield is raised"]={nil,"Apply Debilitate to Enemies 3 Metres in front of you while your Shield is raised "} diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index 78811af1a..67493c620 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -2530,6 +2530,13 @@ return { ["slam_aftershock_chance_%"] = { mod("AftershockChance", "BASE", nil) }, +-- Final Strike +["final_strike_is_ancestrally_boosted"] = { + flag("FinalStrikeAncestrallyBoosted"), +}, +["is_final_strike"] = { + flag("Condition:FinalStrike"), +}, -- Curse ["curse_effect_+%"] = { mod("CurseEffect", "INC", nil), diff --git a/src/Data/Skills/sup_int.lua b/src/Data/Skills/sup_int.lua index 80cd96b6b..7109d0a23 100644 --- a/src/Data/Skills/sup_int.lua +++ b/src/Data/Skills/sup_int.lua @@ -2590,6 +2590,11 @@ skills["SupportCrescendoPlayerTwo"] = { label = "Crescendo II", incrementalEffectiveness = 0.054999999701977, statDescriptionScope = "gem_stat_descriptions", + statMap = { + ["support_crescendo_non_final_strike_attack_speed_+%_final"] = { + mod("Speed", "MORE", nil, ModFlag.Attack, 0, { type = "Condition", var = "FinalStrike", neg = true}) + }, + }, baseFlags = { }, constantStats = { diff --git a/src/Data/Skills/sup_str.lua b/src/Data/Skills/sup_str.lua index 29b4d9390..10f917c18 100644 --- a/src/Data/Skills/sup_str.lua +++ b/src/Data/Skills/sup_str.lua @@ -149,8 +149,17 @@ skills["SupportAncestralCallPlayer"] = { label = "Ancestral Call I", incrementalEffectiveness = 0.054999999701977, statDescriptionScope = "gem_stat_descriptions", + statMap = { + ["ancestral_call_spirit_strike_interval_ms"] = { + mod("AncestralCallCooldown", "BASE", nil), + div = 1000, + }, + }, baseFlags = { }, + baseMods = { + mod("AdditionalStrikeTarget", "BASE", 2), + }, constantStats = { { "ancestral_call_spirit_strike_interval_ms", 5000 }, }, @@ -181,8 +190,17 @@ skills["SupportAncestralCallPlayerTwo"] = { label = "Ancestral Call II", incrementalEffectiveness = 0.054999999701977, statDescriptionScope = "gem_stat_descriptions", + statMap = { + ["ancestral_call_spirit_strike_interval_ms"] = { + mod("AncestralCallCooldown", "BASE", nil), + div = 1000, + }, + }, baseFlags = { }, + baseMods = { + mod("AdditionalStrikeTarget", "BASE", 2), + }, constantStats = { { "ancestral_call_spirit_strike_interval_ms", 3000 }, }, diff --git a/src/Export/Skills/sup_int.txt b/src/Export/Skills/sup_int.txt index 36db0880d..98cc8d354 100644 --- a/src/Export/Skills/sup_int.txt +++ b/src/Export/Skills/sup_int.txt @@ -442,6 +442,11 @@ statMap = { #skill SupportCrescendoPlayerTwo #set SupportCrescendoPlayerTwo +statMap = { + ["support_crescendo_non_final_strike_attack_speed_+%_final"] = { + mod("Speed", "MORE", nil, ModFlag.Attack, 0, { type = "Condition", var = "FinalStrike", neg = true}) + }, +}, #mods #skillEnd diff --git a/src/Export/Skills/sup_str.txt b/src/Export/Skills/sup_str.txt index fd963167b..54664f1bd 100644 --- a/src/Export/Skills/sup_str.txt +++ b/src/Export/Skills/sup_str.txt @@ -26,11 +26,25 @@ local skills, mod, flag, skill = ... #skill SupportAncestralCallPlayer #set SupportAncestralCallPlayer +statMap = { + ["ancestral_call_spirit_strike_interval_ms"] = { + mod("AncestralCallCooldown", "BASE", nil), + div = 1000, + }, +}, +#baseMod mod("AdditionalStrikeTarget", "BASE", 2) #mods #skillEnd #skill SupportAncestralCallPlayerTwo #set SupportAncestralCallPlayerTwo +statMap = { + ["ancestral_call_spirit_strike_interval_ms"] = { + mod("AncestralCallCooldown", "BASE", nil), + div = 1000, + }, +}, +#baseMod mod("AdditionalStrikeTarget", "BASE", 2) #mods #skillEnd diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 03b007201..21f4525c5 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3337,6 +3337,7 @@ function calcs.offence(env, actor, activeSkill) end output.FistOfWarDamageEffect = 1 + output.AncestralCallDamageEffect = 1 if env.mode_combat then local ruthlessEffect = env.configInput.ruthlessSupportMode or "AVERAGE" local ruthlessBlowMaxCount = skillModList:Sum("BASE", cfg, "RuthlessBlowMaxCount") @@ -3355,6 +3356,16 @@ function calcs.offence(env, actor, activeSkill) local ruthlessBlowStunEffect = (ruthlessBlowChance / 100) * ruthlessBlowStunMultiplier skillModList:NewMod("EnemyHeavyStunBuildup", "MORE", ruthlessBlowStunEffect * 100, "Ruthless Blows") + -- passive nodes + local ancestrallyBoostedIncDamageMulti = 1 + modDB:Sum("INC", cfg, "AncestralBoostDamage") / 100 + local ancestrallyBoostedIncArea = modDB:Sum("INC", cfg, "AncestralBoostAreaOfEffect") + -- Final Strike calcs could be done in many other places, but clumping the Ancestral Boost things together made sense + if skillModList:Flag(cfg, "FinalStrikeAncestrallyBoosted") then + local modSource = skillModList:Tabulate("FLAG", cfg, "FinalStrikeAncestrallyBoosted")[1].mod.source -- e.g. Skill:SupportCrescendoPlayerThree + local sourceName = "Ancestral Boost - "..modSource:match("Support(.-)Player") -- crude way to grab Support name, there may be a way in data now or a way to create a map in data with the above structured key + skillModList:NewMod("Damage", "INC", modDB:Sum("INC", cfg, "AncestralBoostDamage"), sourceName, { type = "Condition", var = "FinalStrike" }) + end + globalOutput.FistOfWarCooldown = skillModList:Sum("BASE", cfg, "FistOfWarCooldown") or 0 -- If Fist of War & Active Skill is a Slam Skill & NOT a Vaal Skill & NOT used by mirage or other if globalOutput.FistOfWarCooldown ~= 0 and activeSkill.skillTypes[SkillType.Slam] and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] then @@ -3367,8 +3378,8 @@ function calcs.offence(env, actor, activeSkill) s_format("= %d%%", globalOutput.FistOfWarUptimeRatio), } end - globalOutput.AvgFistOfWarDamage = globalOutput.FistOfWarDamageMultiplier - globalOutput.AvgFistOfWarDamageEffect = 1 + globalOutput.FistOfWarDamageMultiplier * (globalOutput.FistOfWarUptimeRatio / 100) + globalOutput.AvgFistOfWarDamage = globalOutput.FistOfWarDamageMultiplier * ancestrallyBoostedIncDamageMulti + globalOutput.AvgFistOfWarDamageEffect = 1 + globalOutput.FistOfWarDamageMultiplier * ancestrallyBoostedIncDamageMulti * (globalOutput.FistOfWarUptimeRatio / 100) if globalBreakdown then globalBreakdown.AvgFistOfWarDamageEffect = { s_format("1 + (%.2f ^8(fist of war damage multiplier)", globalOutput.FistOfWarDamageMultiplier), @@ -3376,13 +3387,15 @@ function calcs.offence(env, actor, activeSkill) s_format("= %.2f", globalOutput.AvgFistOfWarDamageEffect), } end - globalOutput.MaxFistOfWarDamageEffect = 1 + globalOutput.FistOfWarDamageMultiplier + globalOutput.MaxFistOfWarDamageEffect = 1 + globalOutput.FistOfWarDamageMultiplier * ancestrallyBoostedIncArea if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then output.FistOfWarDamageEffect = globalOutput.MaxFistOfWarDamageEffect skillModList:NewMod("AreaOfEffect", "MORE", skillModList:Sum("BASE", nil, "FistOfWarMOREAoE"), "Max Fist of War Boosted AoE") + skillModList:NewMod("AreaOfEffect", "INC", ancestrallyBoostedIncArea, "Max Fist of War Boosted AoE") else output.FistOfWarDamageEffect = globalOutput.AvgFistOfWarDamageEffect - skillModList:NewMod("AreaOfEffect", "MORE", m_floor(skillModList:Sum("BASE", nil, "FistOfWarMOREAoE") / 100 * globalOutput.FistOfWarUptimeRatio), "Avg Fist Of War Boosted AoE") + skillModList:NewMod("AreaOfEffect", "MORE", m_floor(skillModList:Sum("BASE", nil, "FistOfWarMOREAoE") * globalOutput.FistOfWarUptimeRatio / 100), "Avg Fist Of War Boosted AoE") + skillModList:NewMod("AreaOfEffect", "INC", m_floor(ancestrallyBoostedIncArea * globalOutput.FistOfWarUptimeRatio / 100), "Avg Fist Of War Boosted AoE") end calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput.AvgFistOfWarDamageEffect @@ -3390,6 +3403,48 @@ function calcs.offence(env, actor, activeSkill) else output.FistOfWarDamageEffect = 1 end + + globalOutput.AncestralCallCooldown = skillModList:Sum("BASE", cfg, "AncestralCallCooldown") or 0 + -- If Ancestral Call & Active Skill is NOT a Vaal Skill & NOT used by mirage or other & NOT a Channel Skill + if globalOutput.AncestralCallCooldown ~= 0 and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] and not activeSkill.skillTypes[SkillType.Channel] then + globalOutput.AncestralCallAdditionalStrike = skillModList:Sum("BASE", nil, "AncestralCallAdditionalStrike") + skillModList:NewMod("AdditionalStrikeTarget", "BASE", globalOutput.AncestralCallAdditionalStrike, "Ancestral Call when Ancestrally Boosted") + + globalOutput.AncestralCallDamageMultiplier = ancestrallyBoostedIncDamageMulti + globalOutput.AncestralCallUptimeRatio = m_min( (1 / globalOutput.Speed) / globalOutput.AncestralCallCooldown, 1) * 100 + if globalBreakdown then + globalBreakdown.AncestralCallUptimeRatio = { + s_format("min( (1 / %.2f) ^8(second per attack)", globalOutput.Speed), + s_format("/ %.2f, 1) ^8(ancestral call cooldown)", globalOutput.AncestralCallCooldown), + s_format("= %d%%", globalOutput.AncestralCallUptimeRatio), + } + end + globalOutput.AvgAncestralCallDamage = globalOutput.AncestralCallDamageMultiplier + globalOutput.AvgAncestralCallDamageEffect = 1 + if ancestrallyBoostedIncDamageMulti > 1 then -- if there is no increased damage, then Ancestrally Boosted Strikes do not have any damage portion + globalOutput.AvgAncestralCallDamageEffect = 1 + ancestrallyBoostedIncDamageMulti * (globalOutput.AncestralCallUptimeRatio / 100) + end + if globalBreakdown then + globalBreakdown.AvgAncestralCallDamageEffect = { + s_format("1 + (%.2f ^8(ancestral call damage multiplier)", ancestrallyBoostedIncDamageMulti > 1 and globalOutput.AncestralCallDamageMultiplier or 0), + s_format("x %.2f) ^8(ancestral call uptime ratio)", globalOutput.AncestralCallUptimeRatio / 100 or 0), + s_format("= %.2f", globalOutput.AvgAncestralCallDamageEffect), + } + end + globalOutput.MaxAncestralCallDamageEffect = ancestrallyBoostedIncDamageMulti + if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then + output.AncestralCallDamageEffect = globalOutput.MaxAncestralCallDamageEffect + skillModList:NewMod("AreaOfEffect", "INC", ancestrallyBoostedIncArea, "Max Ancestral Call Boosted AoE") + else + output.AncestralCallDamageEffect = globalOutput.AvgAncestralCallDamageEffect + skillModList:NewMod("AreaOfEffect", "INC", m_floor(ancestrallyBoostedIncArea * globalOutput.AncestralCallUptimeRatio / 100), "Avg Ancestral Call Boosted AoE") + end + calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) + globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput.AvgAncestralCallDamageEffect + globalOutput.TheoreticalMaxOffensiveWarcryEffect = globalOutput.TheoreticalMaxOffensiveWarcryEffect * globalOutput.MaxAncestralCallDamageEffect + else + output.AncestralCallDamageEffect = 1 + end end -- Calculate maximum sustainable fuses and explosion rate for Explosive Arrow @@ -3729,6 +3784,9 @@ function calcs.offence(env, actor, activeSkill) if output.FistOfWarDamageEffect ~= 1 then t_insert(breakdown[damageType], s_format("x %.2f ^8(fist of war effect modifier)", output.FistOfWarDamageEffect)) end + if output.AncestralCallDamageEffect ~= 1 then + t_insert(breakdown[damageType], s_format("x %.2f ^8(ancestral call effect modifier)", output.AncestralCallDamageEffect)) + end if globalOutput.OffensiveWarcryEffect ~= 1 and not activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then t_insert(breakdown[damageType], s_format("x %.2f ^8(aggregated warcry exerted effect modifier)", globalOutput.OffensiveWarcryEffect)) end @@ -3737,9 +3795,9 @@ function calcs.offence(env, actor, activeSkill) end end if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then - output.allMult = output.ScaledDamageEffect * output.FistOfWarDamageEffect * globalOutput.MaxOffensiveWarcryEffect + output.allMult = output.ScaledDamageEffect * output.FistOfWarDamageEffect * output.AncestralCallDamageEffect * globalOutput.MaxOffensiveWarcryEffect else - output.allMult = output.ScaledDamageEffect * output.FistOfWarDamageEffect * globalOutput.OffensiveWarcryEffect + output.allMult = output.ScaledDamageEffect * output.FistOfWarDamageEffect * output.AncestralCallDamageEffect * globalOutput.OffensiveWarcryEffect end local allMult = output.allMult if pass == 1 then diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index 9434a4a2c..5bc20f1ef 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -417,11 +417,18 @@ return { }, { label = "Fist of War", bgCol = colorCodes.MAINHANDBG, haveOutput = "FistOfWarUptimeRatio", { format = "{2:output:AvgFistOfWarDamageEffect}", { breakdown = "AvgFistOfWarDamageEffect"}, }, - { format = "{2:output:AvgFistOfWarDamage}", { modName = "FistOfWarDamageMultiplier", cfg = "skill"}, }, + { format = "{2:output:AvgFistOfWarDamage}", { modName = "FistOfWarDamageMultiplier", cfg = "skill"}, { modName = "AncestralBoostDamage", cfg = "skill" }, }, { format = "{0:output:FistOfWarUptimeRatio}%", { breakdown = "FistOfWarUptimeRatio" }, }, { format = "" }, { format = "{2:output:MaxFistOfWarDamageEffect}" }, }, + { label = "Ancestral Call", bgCol = colorCodes.MAINHANDBG, haveOutput = "AncestralCallUptimeRatio", + { format = "{2:output:AvgAncestralCallDamageEffect}", { breakdown = "AvgAncestralCallDamageEffect"}, }, + { format = "{2:output:AvgAncestralCallDamage}", { modName = "AncestralCallDamageMultiplier", cfg = "skill"}, { modName = "AncestralBoostDamage", cfg = "skill" }, }, + { format = "{0:output:AncestralCallUptimeRatio}%", { breakdown = "AncestralCallUptimeRatio" }, }, + { format = "" }, + { format = "{2:output:MaxAncestralCallDamageEffect}" }, + }, } } } }, { 3, "Dot", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Skill Damage over Time", data = { diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index cc20d66c3..51dabe6cc 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -2622,6 +2622,9 @@ local specialModList = { -- Exerted Attacks ["exerted attacks deal (%d+)%% increased damage"] = function(num) return { mod("ExertIncrease", "INC", num, nil, ModFlag.Attack, 0) } end, ["exerted attacks have (%d+)%% chance to deal double damage"] = function(num) return { mod("ExertDoubleDamageChance", "BASE", num, nil, ModFlag.Attack, 0) } end, + -- Ancestrally Boosted + ["ancestrally boosted attacks deal (%d+)%% increased damage"] = function(num) return { mod("AncestralBoostDamage", "INC", num, nil, ModFlag.Attack, 0) } end, + ["(%d+)%% increased area of effect of ancestrally boosted attacks"] = function(num) return { mod("AncestralBoostAreaOfEffect", "INC", num, nil, ModFlag.Attack, 0) } end, -- Leech Related ["life leech is instant"] = { mod("InstantLifeLeech", "BASE", 100), }, ["mana leech is instant"] = { mod("InstantManaLeech", "BASE", 100), }, From fa20a0297ef2b0125712a4c4ed8f1189c111523d Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 12 May 2026 02:40:03 -0500 Subject: [PATCH 02/12] fix ancestral call inc dmg from tree --- src/Modules/CalcOffence.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 21f4525c5..5e5c23a08 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3357,7 +3357,7 @@ function calcs.offence(env, actor, activeSkill) skillModList:NewMod("EnemyHeavyStunBuildup", "MORE", ruthlessBlowStunEffect * 100, "Ruthless Blows") -- passive nodes - local ancestrallyBoostedIncDamageMulti = 1 + modDB:Sum("INC", cfg, "AncestralBoostDamage") / 100 + local ancestrallyBoostedIncDamageMulti = modDB:Sum("INC", cfg, "AncestralBoostDamage") / 100 local ancestrallyBoostedIncArea = modDB:Sum("INC", cfg, "AncestralBoostAreaOfEffect") -- Final Strike calcs could be done in many other places, but clumping the Ancestral Boost things together made sense if skillModList:Flag(cfg, "FinalStrikeAncestrallyBoosted") then @@ -3421,17 +3421,17 @@ function calcs.offence(env, actor, activeSkill) end globalOutput.AvgAncestralCallDamage = globalOutput.AncestralCallDamageMultiplier globalOutput.AvgAncestralCallDamageEffect = 1 - if ancestrallyBoostedIncDamageMulti > 1 then -- if there is no increased damage, then Ancestrally Boosted Strikes do not have any damage portion + if ancestrallyBoostedIncDamageMulti > 0 then -- if there is no increased damage, then Ancestrally Boosted Strikes do not have any damage portion globalOutput.AvgAncestralCallDamageEffect = 1 + ancestrallyBoostedIncDamageMulti * (globalOutput.AncestralCallUptimeRatio / 100) end if globalBreakdown then globalBreakdown.AvgAncestralCallDamageEffect = { - s_format("1 + (%.2f ^8(ancestral call damage multiplier)", ancestrallyBoostedIncDamageMulti > 1 and globalOutput.AncestralCallDamageMultiplier or 0), + s_format("1 + (%.2f ^8(ancestral call damage multiplier)", ancestrallyBoostedIncDamageMulti > 0 and globalOutput.AncestralCallDamageMultiplier or 0), s_format("x %.2f) ^8(ancestral call uptime ratio)", globalOutput.AncestralCallUptimeRatio / 100 or 0), s_format("= %.2f", globalOutput.AvgAncestralCallDamageEffect), } end - globalOutput.MaxAncestralCallDamageEffect = ancestrallyBoostedIncDamageMulti + globalOutput.MaxAncestralCallDamageEffect = 1 + ancestrallyBoostedIncDamageMulti if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then output.AncestralCallDamageEffect = globalOutput.MaxAncestralCallDamageEffect skillModList:NewMod("AreaOfEffect", "INC", ancestrallyBoostedIncArea, "Max Ancestral Call Boosted AoE") From 8b4a161b3646fa353531fbf1782dbed41cc8cdda Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 12 May 2026 09:17:41 -0500 Subject: [PATCH 03/12] big ole refactor so we stop duplicating code one commit so I can revert if it goes boom --- src/Modules/CalcOffence.lua | 93 +++++++++++++++---------------------- 1 file changed, 37 insertions(+), 56 deletions(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 5e5c23a08..bae75d7b4 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3366,40 +3366,52 @@ function calcs.offence(env, actor, activeSkill) skillModList:NewMod("Damage", "INC", modDB:Sum("INC", cfg, "AncestralBoostDamage"), sourceName, { type = "Condition", var = "FinalStrike" }) end - globalOutput.FistOfWarCooldown = skillModList:Sum("BASE", cfg, "FistOfWarCooldown") or 0 - -- If Fist of War & Active Skill is a Slam Skill & NOT a Vaal Skill & NOT used by mirage or other - if globalOutput.FistOfWarCooldown ~= 0 and activeSkill.skillTypes[SkillType.Slam] and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] then - globalOutput.FistOfWarDamageMultiplier = skillModList:Sum("BASE", nil, "FistOfWarDamageMultiplier") / 100 - globalOutput.FistOfWarUptimeRatio = m_min( (1 / globalOutput.Speed) / globalOutput.FistOfWarCooldown, 1) * 100 + -- dynamic way of calcing the Ancestral Boost for supports without duplicating the code for each unique support + local function calcAncestralBoost(skillName, moreDmg, moreArea) + local skillNameVar = skillName:gsub(" ", "") -- Fist Of War -> FistOfWar + local skillNameLabel = skillName:lower() + + if moreDmg then + globalOutput[skillNameVar.."DamageMultiplier"] = moreDmg * (1 + ancestrallyBoostedIncDamageMulti) + else + globalOutput[skillNameVar.."DamageMultiplier"] = ancestrallyBoostedIncDamageMulti + end + globalOutput[skillNameVar.."UptimeRatio"] = m_min( (1 / globalOutput.Speed) / globalOutput[skillNameVar.."Cooldown"], 1) * 100 if globalBreakdown then - globalBreakdown.FistOfWarUptimeRatio = { + globalBreakdown[skillNameVar.."UptimeRatio"] = { s_format("min( (1 / %.2f) ^8(second per attack)", globalOutput.Speed), - s_format("/ %.2f, 1) ^8(fist of war cooldown)", globalOutput.FistOfWarCooldown), - s_format("= %d%%", globalOutput.FistOfWarUptimeRatio), + s_format("/ %.2f, 1) ^8("..skillNameLabel.." cooldown)", globalOutput[skillNameVar.."Cooldown"]), + s_format("= %d%%", globalOutput[skillNameVar.."UptimeRatio"]), } end - globalOutput.AvgFistOfWarDamage = globalOutput.FistOfWarDamageMultiplier * ancestrallyBoostedIncDamageMulti - globalOutput.AvgFistOfWarDamageEffect = 1 + globalOutput.FistOfWarDamageMultiplier * ancestrallyBoostedIncDamageMulti * (globalOutput.FistOfWarUptimeRatio / 100) + globalOutput["Avg"..skillNameVar.."Damage"] = globalOutput[skillNameVar.."DamageMultiplier"] + globalOutput["Avg"..skillNameVar.."DamageEffect"] = 1 + globalOutput["Avg"..skillNameVar.."Damage"] * (globalOutput[skillNameVar.."UptimeRatio"] / 100) if globalBreakdown then - globalBreakdown.AvgFistOfWarDamageEffect = { - s_format("1 + (%.2f ^8(fist of war damage multiplier)", globalOutput.FistOfWarDamageMultiplier), - s_format("x %.2f) ^8(fist of war uptime ratio)", globalOutput.FistOfWarUptimeRatio / 100), - s_format("= %.2f", globalOutput.AvgFistOfWarDamageEffect), + globalBreakdown["Avg"..skillNameVar.."DamageEffect"] = { + s_format("1 + (%.2f ^8("..skillNameLabel.." damage multiplier)", globalOutput[skillNameVar.."DamageMultiplier"]), + s_format("x %.2f) ^8("..skillNameLabel.." uptime ratio)", globalOutput[skillNameVar.."UptimeRatio"] / 100), + s_format("= %.2f", globalOutput["Avg"..skillNameVar.."DamageEffect"]), } end - globalOutput.MaxFistOfWarDamageEffect = 1 + globalOutput.FistOfWarDamageMultiplier * ancestrallyBoostedIncArea + globalOutput["Max"..skillNameVar.."DamageEffect"] = 1 + globalOutput[skillNameVar.."DamageMultiplier"] if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then - output.FistOfWarDamageEffect = globalOutput.MaxFistOfWarDamageEffect - skillModList:NewMod("AreaOfEffect", "MORE", skillModList:Sum("BASE", nil, "FistOfWarMOREAoE"), "Max Fist of War Boosted AoE") - skillModList:NewMod("AreaOfEffect", "INC", ancestrallyBoostedIncArea, "Max Fist of War Boosted AoE") + output[skillNameVar.."DamageEffect"] = globalOutput["Max"..skillNameVar.."DamageEffect"] + skillModList:NewMod("AreaOfEffect", "MORE", moreArea or 0, "Max "..skillName.." Boosted AoE") + skillModList:NewMod("AreaOfEffect", "INC", ancestrallyBoostedIncArea, "Max "..skillName.." Boosted AoE") else - output.FistOfWarDamageEffect = globalOutput.AvgFistOfWarDamageEffect - skillModList:NewMod("AreaOfEffect", "MORE", m_floor(skillModList:Sum("BASE", nil, "FistOfWarMOREAoE") * globalOutput.FistOfWarUptimeRatio / 100), "Avg Fist Of War Boosted AoE") - skillModList:NewMod("AreaOfEffect", "INC", m_floor(ancestrallyBoostedIncArea * globalOutput.FistOfWarUptimeRatio / 100), "Avg Fist Of War Boosted AoE") + output[skillNameVar.."DamageEffect"] = globalOutput["Avg"..skillNameVar.."DamageEffect"] + skillModList:NewMod("AreaOfEffect", "MORE", m_floor((moreArea or 0) * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") + skillModList:NewMod("AreaOfEffect", "INC", m_floor(ancestrallyBoostedIncArea * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") end calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) - globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput.AvgFistOfWarDamageEffect - globalOutput.TheoreticalMaxOffensiveWarcryEffect = globalOutput.TheoreticalMaxOffensiveWarcryEffect * globalOutput.MaxFistOfWarDamageEffect + globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput["Avg"..skillNameVar.."DamageEffect"] + globalOutput.TheoreticalMaxOffensiveWarcryEffect = globalOutput.TheoreticalMaxOffensiveWarcryEffect * globalOutput["Max"..skillNameVar.."DamageEffect"] + end + + globalOutput.FistOfWarCooldown = skillModList:Sum("BASE", cfg, "FistOfWarCooldown") or 0 + -- If Fist of War & Active Skill is a Slam Skill & NOT a Vaal Skill & NOT used by mirage or other + if globalOutput.FistOfWarCooldown ~= 0 and activeSkill.skillTypes[SkillType.Slam] and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] then + calcAncestralBoost("Fist Of War", (skillModList:Sum("BASE", nil, "FistOfWarDamageMultiplier") / 100), skillModList:Sum("BASE", nil, "FistOfWarMOREAoE")) else output.FistOfWarDamageEffect = 1 end @@ -3409,39 +3421,8 @@ function calcs.offence(env, actor, activeSkill) if globalOutput.AncestralCallCooldown ~= 0 and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] and not activeSkill.skillTypes[SkillType.Channel] then globalOutput.AncestralCallAdditionalStrike = skillModList:Sum("BASE", nil, "AncestralCallAdditionalStrike") skillModList:NewMod("AdditionalStrikeTarget", "BASE", globalOutput.AncestralCallAdditionalStrike, "Ancestral Call when Ancestrally Boosted") - - globalOutput.AncestralCallDamageMultiplier = ancestrallyBoostedIncDamageMulti - globalOutput.AncestralCallUptimeRatio = m_min( (1 / globalOutput.Speed) / globalOutput.AncestralCallCooldown, 1) * 100 - if globalBreakdown then - globalBreakdown.AncestralCallUptimeRatio = { - s_format("min( (1 / %.2f) ^8(second per attack)", globalOutput.Speed), - s_format("/ %.2f, 1) ^8(ancestral call cooldown)", globalOutput.AncestralCallCooldown), - s_format("= %d%%", globalOutput.AncestralCallUptimeRatio), - } - end - globalOutput.AvgAncestralCallDamage = globalOutput.AncestralCallDamageMultiplier - globalOutput.AvgAncestralCallDamageEffect = 1 - if ancestrallyBoostedIncDamageMulti > 0 then -- if there is no increased damage, then Ancestrally Boosted Strikes do not have any damage portion - globalOutput.AvgAncestralCallDamageEffect = 1 + ancestrallyBoostedIncDamageMulti * (globalOutput.AncestralCallUptimeRatio / 100) - end - if globalBreakdown then - globalBreakdown.AvgAncestralCallDamageEffect = { - s_format("1 + (%.2f ^8(ancestral call damage multiplier)", ancestrallyBoostedIncDamageMulti > 0 and globalOutput.AncestralCallDamageMultiplier or 0), - s_format("x %.2f) ^8(ancestral call uptime ratio)", globalOutput.AncestralCallUptimeRatio / 100 or 0), - s_format("= %.2f", globalOutput.AvgAncestralCallDamageEffect), - } - end - globalOutput.MaxAncestralCallDamageEffect = 1 + ancestrallyBoostedIncDamageMulti - if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then - output.AncestralCallDamageEffect = globalOutput.MaxAncestralCallDamageEffect - skillModList:NewMod("AreaOfEffect", "INC", ancestrallyBoostedIncArea, "Max Ancestral Call Boosted AoE") - else - output.AncestralCallDamageEffect = globalOutput.AvgAncestralCallDamageEffect - skillModList:NewMod("AreaOfEffect", "INC", m_floor(ancestrallyBoostedIncArea * globalOutput.AncestralCallUptimeRatio / 100), "Avg Ancestral Call Boosted AoE") - end - calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) - globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput.AvgAncestralCallDamageEffect - globalOutput.TheoreticalMaxOffensiveWarcryEffect = globalOutput.TheoreticalMaxOffensiveWarcryEffect * globalOutput.MaxAncestralCallDamageEffect + -- for special cases, the logic ^ can be done outside the generic calc + calcAncestralBoost("Ancestral Call") else output.AncestralCallDamageEffect = 1 end From 06f5dec603524df0996ac115695dde0b971d197a Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 12 May 2026 09:58:07 -0500 Subject: [PATCH 04/12] added test update CalcSection from "Exerted Warcries" to "Ancestral Boosts" --- spec/System/TestSkills_spec.lua | 17 +++++++++++++++++ src/Modules/CalcOffence.lua | 1 + src/Modules/CalcSections.lua | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/spec/System/TestSkills_spec.lua b/spec/System/TestSkills_spec.lua index 99379fa2d..749d14b14 100644 --- a/spec/System/TestSkills_spec.lua +++ b/spec/System/TestSkills_spec.lua @@ -382,4 +382,21 @@ describe("TestSkills", function() runCallback("OnFrame") assert.True(build.calcsTab.mainOutput.TotalDPS > iceShotDPS) end) + + it("Test Ancestral Call - Ancestral Boost calcs", function() + build.itemsTab:CreateDisplayItemFromRaw([[ + New Item + Fanatic Greathammer + Quality: 0 + ]]) + build.itemsTab:AddDisplayItem() + runCallback("OnFrame") + + build.skillsTab:PasteSocketGroup("Boneshatter 20/0 1\nAncestral Call I 1/0 1") + runCallback("OnFrame") + + assert.True(build.calcsTab.calcsOutput.AvgAncestralCallDamageEffect ~= nil) + assert.True(build.calcsTab.calcsOutput.AncestralCallUptimeRatio ~= nil) + assert.are.equal(3, build.calcsTab.calcsOutput.StrikeTargets) + end) end) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index bae75d7b4..ecfd552b5 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3368,6 +3368,7 @@ function calcs.offence(env, actor, activeSkill) -- dynamic way of calcing the Ancestral Boost for supports without duplicating the code for each unique support local function calcAncestralBoost(skillName, moreDmg, moreArea) + globalOutput.CreateWarcryOffensiveCalcSection = true -- labels for the CalcSection local skillNameVar = skillName:gsub(" ", "") -- Fist Of War -> FistOfWar local skillNameLabel = skillName:lower() diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index 5bc20f1ef..b4687e679 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -355,7 +355,7 @@ return { { label = "Skill DPS", flag = "triggered", { format = "{1:output:TotalDPS}", { breakdown = "TotalDPS" }, { label = "DPS Multiplier", modName = "DPS", cfg = "skill" }, }, }, } } } }, -{ 3, "Warcries", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Exerting Warcries", data = { +{ 3, "Warcries", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Ancestral Boosts", data = { extra = "{2:output:TheoreticalOffensiveWarcryEffect} Avg Combined Impact | {2:output:TheoreticalMaxOffensiveWarcryEffect} Max Combined Impact", colWidth = 114, { From 25f4ba52ae7e48936dfc05d6df6cf4361c8da943 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Tue, 12 May 2026 10:16:40 -0500 Subject: [PATCH 05/12] add data map for gemName given a modSource --- src/Modules/CalcOffence.lua | 2 +- src/Modules/Data.lua | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index ecfd552b5..c50edd6c1 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3362,7 +3362,7 @@ function calcs.offence(env, actor, activeSkill) -- Final Strike calcs could be done in many other places, but clumping the Ancestral Boost things together made sense if skillModList:Flag(cfg, "FinalStrikeAncestrallyBoosted") then local modSource = skillModList:Tabulate("FLAG", cfg, "FinalStrikeAncestrallyBoosted")[1].mod.source -- e.g. Skill:SupportCrescendoPlayerThree - local sourceName = "Ancestral Boost - "..modSource:match("Support(.-)Player") -- crude way to grab Support name, there may be a way in data now or a way to create a map in data with the above structured key + local sourceName = "Ancestral Boost - "..data.gemNameForModSource[modSource] skillModList:NewMod("Damage", "INC", modDB:Sum("INC", cfg, "AncestralBoostDamage"), sourceName, { type = "Condition", var = "FinalStrike" }) end diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index 340d52861..3295b0e68 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -890,6 +890,7 @@ data.gems = LoadModule("Data/Gems") data.gemForSkill = { } data.gemForBaseName = { } data.gemsByGameId = { } +data.gemNameForModSource = { } -- Lookup table - [Gem.grantedEffectId] = VaalGemId data.gemGrantedEffectIdForVaalGemId = { } data.gemVaalGemIdForBaseGemId = { } @@ -899,6 +900,7 @@ local function setupGem(gem, gemId) data.gemForSkill[gem.grantedEffect] = gemId data.gemsByGameId[gem.gameId] = data.gemsByGameId[gem.gameId] or {} data.gemsByGameId[gem.gameId][gem.variantId] = gem + data.gemNameForModSource[gem.grantedEffect.modSource] = gem.name local baseName = gem.name if gem.grantedEffect.support and gem.grantedEffectId ~= "SupportBarrage" then baseName = baseName .. " Support" From d4f5dd646d95ea665bb5a98c9e1e11e0227d38e9 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Fri, 15 May 2026 12:29:15 -0500 Subject: [PATCH 06/12] boosted attacks configOption --- src/Modules/ConfigOptions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index b148d9a4a..47ddf2466 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -193,7 +193,7 @@ local configSettings = { modList:NewMod("Condition:ArmourAvg", "FLAG", true, "Config") end end }, - { var = "warcryMode", type = "list", label = "Exerted/Boosted calc mode:", ifSkill = { "Fist of War", "Infernal Cry", "Ancestral Cry", "Enduring Cry", "General's Cry", "Intimidating Cry", "Rallying Cry", "Seismic Cry", "Battlemage's Cry", "Vengeful Cry" }, tooltip = "Controls how exerted attacks from Warcries are calculated:\nAverage: Averages out Warcry usage with cast time, attack speed and warcry cooldown.\nMax Hit: Shows maximum hit for lining up all warcries.", list = {{val="AVERAGE",label="Average"},{val="MAX",label="Max Hit"}}, apply = function(val, modList, enemyModList) + { var = "warcryMode", type = "list", label = "Boosted calc mode:", tooltip = "Controls how ancestrally boosted attacks are calculated:\nAverage: Averages out Boost usage with cast time, attack speed and cooldown.\nMax Hit: Shows maximum hit for lining up all sources of ancestral boost.", list = {{val="AVERAGE",label="Average"},{val="MAX",label="Max Hit"}}, apply = function(val, modList, enemyModList) if val == "MAX" then modList:NewMod("Condition:WarcryMaxHit", "FLAG", true, "Config") end From b8b1104f13c0aa96d816a7b7709aa785fad25749 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Fri, 15 May 2026 14:12:36 -0500 Subject: [PATCH 07/12] add support for Ancestral Empowerment, including combining Ancestral Empowerment with Fist of War fix Fist of War/ancestrally boosted slams more AOE to inc AOE add test for Combined logic for Ancestral Empowerment and Fist of War --- spec/System/TestSkills_spec.lua | 38 +++++++++++++ src/Data/ModCache.lua | 2 +- src/Data/Skills/sup_str.lua | 6 +- src/Export/Skills/sup_str.txt | 6 +- src/Modules/CalcOffence.lua | 97 +++++++++++++++++++++++++++++---- src/Modules/CalcSections.lua | 14 +++++ src/Modules/ModParser.lua | 5 ++ 7 files changed, 149 insertions(+), 19 deletions(-) diff --git a/spec/System/TestSkills_spec.lua b/spec/System/TestSkills_spec.lua index 749d14b14..4c191c93c 100644 --- a/spec/System/TestSkills_spec.lua +++ b/spec/System/TestSkills_spec.lua @@ -399,4 +399,42 @@ describe("TestSkills", function() assert.True(build.calcsTab.calcsOutput.AncestralCallUptimeRatio ~= nil) assert.are.equal(3, build.calcsTab.calcsOutput.StrikeTargets) end) + + it("Test Combined Ancestral Boosts - Ancestral Empowerment and Fist of War", function() + build.itemsTab:CreateDisplayItemFromRaw([[ + New Item + Fanatic Greathammer + Quality: 0 + ]]) + build.itemsTab:AddDisplayItem() + runCallback("OnFrame") + build.skillsTab:PasteSocketGroup("Leap Slam 20/0 1\nFist of War I 1/0 1") + runCallback("OnFrame") + build.configTab.input.customMods = "every second slam skill you use yourself is ancestrally boosted" + build.configTab:BuildModList() + runCallback("OnFrame") + local fistOfWarOneMaxDmgEffect = build.calcsTab.calcsOutput.MaxAncestralEmpowermentCombinedDamageEffect + + -- test that we are using the calcCombinedAncestralBoost function and the calcSection triggers are correct + assert.True(build.calcsTab.calcsOutput.AncestralEmpowermentCombinedUptimeRatio ~= nil) + assert.True(build.calcsTab.calcsOutput.AncestralEmpowermentUptimeRatio == nil) + assert.True(build.calcsTab.calcsOutput.FistOfWarUptimeRatio == nil) + + newBuild() + build.itemsTab:CreateDisplayItemFromRaw([[ + New Item + Fanatic Greathammer + Quality: 0 + ]]) + build.itemsTab:AddDisplayItem() + runCallback("OnFrame") + build.skillsTab:PasteSocketGroup("Leap Slam 20/0 1\nFist of War III 1/0 1") + runCallback("OnFrame") + build.configTab.input.customMods = "every second slam skill you use yourself is ancestrally boosted" + build.configTab:BuildModList() + runCallback("OnFrame") + + -- test doubled effects of Fist of War III with Ancestral Empowerment + assert.True(fistOfWarOneMaxDmgEffect < build.calcsTab.calcsOutput.MaxAncestralEmpowermentCombinedDamageEffect) + end) end) diff --git a/src/Data/ModCache.lua b/src/Data/ModCache.lua index bcdfe19a5..7af004382 100644 --- a/src/Data/ModCache.lua +++ b/src/Data/ModCache.lua @@ -4866,7 +4866,7 @@ c["Every Rage also grants 2% increased Stun Threshold"]={{[1]={[1]={type="Multip c["Every Rage also grants you 1% increased Minion Attack Speed"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="player",type="Multiplier",var="RageEffect"},flags=1,keywordFlags=0,name="Speed",type="INC",value=1}}}},nil} c["Every Rage also grants you 1% increased Minion Damage"]={{[1]={flags=0,keywordFlags=0,name="MinionModifier",type="LIST",value={mod={[1]={actor="player",type="Multiplier",var="RageEffect"},flags=0,keywordFlags=0,name="Damage",type="INC",value=1}}}},nil} c["Every Third Slam skill that doesn't create Fissures which you use yourself causes 3 additional Aftershocks ahead and to each side of the initial area"]={nil,"Every Third Slam skill that doesn't create Fissures which you use yourself causes 3 additional Aftershocks ahead and to each side of the initial area "} -c["Every second Slam Skill you use yourself is Ancestrally Boosted"]={nil,"Every second Slam Skill you use yourself is Ancestrally Boosted "} +c["Every second Slam Skill you use yourself is Ancestrally Boosted"]={{[1]={[1]={skillType=93,type="SkillType"},flags=0,keywordFlags=0,name="AncestralEmpowerment",type="FLAG",value=true},[2]={[1]={skillType=93,type="SkillType"},flags=0,keywordFlags=0,name="AncestralEmpowermentDamageMultiplier",type="BASE",value=30},[3]={[1]={skillType=93,type="SkillType"},flags=0,keywordFlags=0,name="AncestralEmpowermentIncAoE",type="BASE",value=25}},nil} c["Every second, inflicts Critical Weakness on enemies in your Presence for 1 second"]={{[1]={flags=0,keywordFlags=0,name="ApplyCriticalWeakness",type="FLAG",value=true}},nil} c["Every second, inflicts Critical Weakness on enemies in your Presence for 15 seconds"]={{[1]={flags=0,keywordFlags=0,name="ApplyCriticalWeakness",type="FLAG",value=true}},nil} c["Every second, inflicts Critical Weakness on enemies in your Presence for 18 seconds"]={{[1]={flags=0,keywordFlags=0,name="ApplyCriticalWeakness",type="FLAG",value=true}},nil} diff --git a/src/Data/Skills/sup_str.lua b/src/Data/Skills/sup_str.lua index 10f917c18..2c2ab2be7 100644 --- a/src/Data/Skills/sup_str.lua +++ b/src/Data/Skills/sup_str.lua @@ -3436,7 +3436,7 @@ skills["FistOfWarSupportPlayer"] = { }, baseMods = { mod("FistOfWarDamageMultiplier", "BASE", 30), - mod("FistOfWarMOREAoE", "BASE", 25), + mod("FistOfWarIncAoE", "BASE", 25), }, constantStats = { { "support_ancestral_slam_big_hit_max_count", 1 }, @@ -3477,7 +3477,7 @@ skills["FistOfWarSupportPlayerTwo"] = { }, baseMods = { mod("FistOfWarDamageMultiplier", "BASE", 30), - mod("FistOfWarMOREAoE", "BASE", 25), + mod("FistOfWarIncAoE", "BASE", 25), }, constantStats = { { "support_ancestral_slam_big_hit_max_count", 1 }, @@ -3521,7 +3521,7 @@ skills["FistOfWarSupportPlayerThree"] = { }, baseMods = { mod("FistOfWarDamageMultiplier", "BASE", 60), - mod("FistOfWarMOREAoE", "BASE", 50), + mod("FistOfWarIncAoE", "BASE", 50), }, constantStats = { { "support_ancestral_slam_big_hit_max_count", 1 }, diff --git a/src/Export/Skills/sup_str.txt b/src/Export/Skills/sup_str.txt index 54664f1bd..9b4a6f715 100644 --- a/src/Export/Skills/sup_str.txt +++ b/src/Export/Skills/sup_str.txt @@ -769,7 +769,7 @@ statMap = { }, }, #baseMod mod("FistOfWarDamageMultiplier", "BASE", 30) -#baseMod mod("FistOfWarMOREAoE", "BASE", 25) +#baseMod mod("FistOfWarIncAoE", "BASE", 25) #mods #skillEnd @@ -782,7 +782,7 @@ statMap = { }, }, #baseMod mod("FistOfWarDamageMultiplier", "BASE", 30) -#baseMod mod("FistOfWarMOREAoE", "BASE", 25) +#baseMod mod("FistOfWarIncAoE", "BASE", 25) #mods #skillEnd @@ -798,7 +798,7 @@ statMap = { }, }, #baseMod mod("FistOfWarDamageMultiplier", "BASE", 60) -#baseMod mod("FistOfWarMOREAoE", "BASE", 50) +#baseMod mod("FistOfWarIncAoE", "BASE", 50) #mods #skillEnd diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index c50edd6c1..f52ed03e7 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3338,6 +3338,8 @@ function calcs.offence(env, actor, activeSkill) output.FistOfWarDamageEffect = 1 output.AncestralCallDamageEffect = 1 + output.AncestralEmpowermentDamageEffect = 1 + output.AncestralEmpowermentCombinedDamageEffect = 1 if env.mode_combat then local ruthlessEffect = env.configInput.ruthlessSupportMode or "AVERAGE" local ruthlessBlowMaxCount = skillModList:Sum("BASE", cfg, "RuthlessBlowMaxCount") @@ -3366,8 +3368,9 @@ function calcs.offence(env, actor, activeSkill) skillModList:NewMod("Damage", "INC", modDB:Sum("INC", cfg, "AncestralBoostDamage"), sourceName, { type = "Condition", var = "FinalStrike" }) end - -- dynamic way of calcing the Ancestral Boost for supports without duplicating the code for each unique support - local function calcAncestralBoost(skillName, moreDmg, moreArea) + -- dynamic way of calcing the Ancestral Boost from a single source without duplicating the code + -- uptimeOverride: Ancestral Empowerment + local function calcAncestralBoost(skillName, moreDmg, incArea, uptimeOverride) globalOutput.CreateWarcryOffensiveCalcSection = true -- labels for the CalcSection local skillNameVar = skillName:gsub(" ", "") -- Fist Of War -> FistOfWar local skillNameLabel = skillName:lower() @@ -3377,11 +3380,11 @@ function calcs.offence(env, actor, activeSkill) else globalOutput[skillNameVar.."DamageMultiplier"] = ancestrallyBoostedIncDamageMulti end - globalOutput[skillNameVar.."UptimeRatio"] = m_min( (1 / globalOutput.Speed) / globalOutput[skillNameVar.."Cooldown"], 1) * 100 + globalOutput[skillNameVar.."UptimeRatio"] = uptimeOverride or m_min( (1 / globalOutput.Speed) / globalOutput[skillNameVar.."Cooldown"], 1) * 100 if globalBreakdown then globalBreakdown[skillNameVar.."UptimeRatio"] = { s_format("min( (1 / %.2f) ^8(second per attack)", globalOutput.Speed), - s_format("/ %.2f, 1) ^8("..skillNameLabel.." cooldown)", globalOutput[skillNameVar.."Cooldown"]), + s_format("/ %.2f, 1) ^8("..skillNameLabel.." cooldown)", uptimeOverride and (1 / globalOutput.Speed / (uptimeOverride / 100)) or globalOutput[skillNameVar.."Cooldown"]), s_format("= %d%%", globalOutput[skillNameVar.."UptimeRatio"]), } end @@ -3397,12 +3400,64 @@ function calcs.offence(env, actor, activeSkill) globalOutput["Max"..skillNameVar.."DamageEffect"] = 1 + globalOutput[skillNameVar.."DamageMultiplier"] if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then output[skillNameVar.."DamageEffect"] = globalOutput["Max"..skillNameVar.."DamageEffect"] - skillModList:NewMod("AreaOfEffect", "MORE", moreArea or 0, "Max "..skillName.." Boosted AoE") - skillModList:NewMod("AreaOfEffect", "INC", ancestrallyBoostedIncArea, "Max "..skillName.." Boosted AoE") + skillModList:NewMod("AreaOfEffect", "INC", (incArea or 0) + ancestrallyBoostedIncArea, "Max "..skillName.." Boosted AoE") else output[skillNameVar.."DamageEffect"] = globalOutput["Avg"..skillNameVar.."DamageEffect"] - skillModList:NewMod("AreaOfEffect", "MORE", m_floor((moreArea or 0) * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") - skillModList:NewMod("AreaOfEffect", "INC", m_floor(ancestrallyBoostedIncArea * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") + skillModList:NewMod("AreaOfEffect", "INC", m_floor(((incArea or 0) + ancestrallyBoostedIncArea) * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") + end + calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) + globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput["Avg"..skillNameVar.."DamageEffect"] + globalOutput.TheoreticalMaxOffensiveWarcryEffect = globalOutput.TheoreticalMaxOffensiveWarcryEffect * globalOutput["Max"..skillNameVar.."DamageEffect"] + end + + -- combine Ancentral Empowerment with other sources of Slam Ancestral Boost, namely Fist of War, when both active + local function calcCombinedAncestralBoost(skillName, moreDmg, incArea, uptimeOverride, additionalSkillName) + globalOutput.CreateWarcryOffensiveCalcSection = true -- labels for the CalcSection + local skillNameVar = skillName:gsub(" ", "") -- Fist Of War -> FistOfWar + local skillNameLabel = skillName:lower() + + if moreDmg then + globalOutput[skillNameVar.."DamageMultiplier"] = moreDmg * (1 + ancestrallyBoostedIncDamageMulti) + else + globalOutput[skillNameVar.."DamageMultiplier"] = ancestrallyBoostedIncDamageMulti + end + -- for CalcSections, set the AncestralEmpowerment damage for mod breakdown + globalOutput[skillNameVar.."CombinedDamageMultiplier"] = globalOutput[skillNameVar.."DamageMultiplier"] + skillNameVar = skillNameVar.."Combined" + local additionalSkillNameVar = additionalSkillName:gsub(" ", "") + local additionalSkillNameLabel = additionalSkillName:lower() + + -- a lot of these are doubled up because it would be very long lines otherwise and hopefully this helps legibility + globalOutput[skillNameVar.."UptimeRatio"] = uptimeOverride or m_min( (1 / globalOutput.Speed) / globalOutput[skillNameVar.."Cooldown"], 1) * 100 + globalOutput[skillNameVar.."UptimeRatio"] = globalOutput[skillNameVar.."UptimeRatio"] + (globalOutput[additionalSkillNameVar.."UptimeRatio"] or 0) / 2 + if globalBreakdown then + globalBreakdown[skillNameVar.."UptimeRatio"] = { + s_format("min( (1 / %.2f) ^8(second per attack)", globalOutput.Speed), + s_format("/ %.2f, 1) ^8("..skillNameLabel.." cooldown)", uptimeOverride and (1 / globalOutput.Speed / (uptimeOverride / 100)) or globalOutput[skillNameVar.."Cooldown"]), + "+", + s_format("min( (1 / %.2f) ^8(second per attack)", globalOutput.Speed), + s_format("/ %.2f, 1) ^8("..additionalSkillNameLabel.." cooldown)", globalOutput[additionalSkillNameVar.."Cooldown"]), + s_format("= %d%%", globalOutput[skillNameVar.."UptimeRatio"]), + } + end + globalOutput["Avg"..skillNameVar.."Damage"] = globalOutput[skillNameVar.."DamageMultiplier"] + globalOutput["Avg"..skillNameVar.."DamageEffect"] = 1 + globalOutput["Avg"..skillNameVar.."Damage"] * (uptimeOverride and uptimeOverride / 100 or (globalOutput[skillNameVar.."UptimeRatio"] / 100)) + globalOutput["Avg"..skillNameVar.."DamageEffect"] = (globalOutput["Avg"..skillNameVar.."DamageEffect"] * (1 + globalOutput["Avg"..additionalSkillNameVar.."Damage"] * globalOutput[additionalSkillNameVar.."UptimeRatio"] / 100 / 2)) + if globalBreakdown then + globalBreakdown["Avg"..skillNameVar.."DamageEffect"] = { + s_format("1 + (%.2f x %.2f) ^8("..skillNameLabel.." damage multiplier x ^8"..skillNameLabel.." uptime ratio)", globalOutput[skillNameVar.."DamageMultiplier"], uptimeOverride / 100), + s_format(" + (%.2f x %.2f) ^8("..additionalSkillNameLabel.." damage multiplier x ^8"..additionalSkillNameLabel.." uptime ratio)", globalOutput[additionalSkillNameVar.."DamageMultiplier"], globalOutput[additionalSkillNameVar.."UptimeRatio"] / 100 / 2), + s_format("= %.2f", globalOutput["Avg"..skillNameVar.."DamageEffect"]), + } + end + globalOutput["Avg"..skillNameVar.."Damage"] = globalOutput[skillNameVar.."DamageMultiplier"] + globalOutput[additionalSkillNameVar.."DamageMultiplier"] + globalOutput["Max"..skillNameVar.."DamageEffect"] = 1 + globalOutput[skillNameVar.."DamageMultiplier"] + globalOutput[additionalSkillNameVar.."DamageMultiplier"] + if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then + output[skillNameVar.."DamageEffect"] = globalOutput["Max"..skillNameVar.."DamageEffect"] + skillModList:NewMod("AreaOfEffect", "INC", (incArea or 0) + ancestrallyBoostedIncArea, "Max "..skillName.." Boosted AoE") + else + output[skillNameVar.."DamageEffect"] = globalOutput["Avg"..skillNameVar.."DamageEffect"] + skillModList:NewMod("AreaOfEffect", "INC", m_floor(((incArea or 0) + ancestrallyBoostedIncArea) * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") end calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput["Avg"..skillNameVar.."DamageEffect"] @@ -3410,9 +3465,21 @@ function calcs.offence(env, actor, activeSkill) end globalOutput.FistOfWarCooldown = skillModList:Sum("BASE", cfg, "FistOfWarCooldown") or 0 + if skillModList:Flag(cfg, "AncestralEmpowerment") and activeSkill.skillTypes[SkillType.Slam] and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] then + if globalOutput.FistOfWarCooldown ~= 0 then -- get the fist of war calcs in output to use in Empowerment + calcAncestralBoost("Fist Of War", (skillModList:Sum("BASE", nil, "FistOfWarDamageMultiplier") / 100), skillModList:Sum("BASE", nil, "FistOfWarIncAoE")) + globalOutput.TheoreticalOffensiveWarcryEffect = 1 -- reset effects from FistOfWar calc, we combine later + globalOutput.TheoreticalMaxOffensiveWarcryEffect = 1 + + calcCombinedAncestralBoost("Ancestral Empowerment", (skillModList:Sum("BASE", cfg, "AncestralEmpowermentDamageMultiplier") / 100), skillModList:Sum("BASE", cfg, "AncestralEmpowermentIncAoE"), 50, "Fist Of War") + globalOutput.FistOfWarUptimeRatio = nil -- hide from CalcSections, but we need it for the combined calc first + else + calcAncestralBoost("Ancestral Empowerment", (skillModList:Sum("BASE", cfg, "AncestralEmpowermentDamageMultiplier") / 100), skillModList:Sum("BASE", cfg, "AncestralEmpowermentIncAoE"), 50) + end + end -- If Fist of War & Active Skill is a Slam Skill & NOT a Vaal Skill & NOT used by mirage or other - if globalOutput.FistOfWarCooldown ~= 0 and activeSkill.skillTypes[SkillType.Slam] and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] then - calcAncestralBoost("Fist Of War", (skillModList:Sum("BASE", nil, "FistOfWarDamageMultiplier") / 100), skillModList:Sum("BASE", nil, "FistOfWarMOREAoE")) + if not skillModList:Flag(cfg, "AncestralEmpowerment") and globalOutput.FistOfWarCooldown ~= 0 and activeSkill.skillTypes[SkillType.Slam] and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] then + calcAncestralBoost("Fist Of War", (skillModList:Sum("BASE", nil, "FistOfWarDamageMultiplier") / 100), skillModList:Sum("BASE", nil, "FistOfWarIncAoE")) else output.FistOfWarDamageEffect = 1 end @@ -3769,6 +3836,12 @@ function calcs.offence(env, actor, activeSkill) if output.AncestralCallDamageEffect ~= 1 then t_insert(breakdown[damageType], s_format("x %.2f ^8(ancestral call effect modifier)", output.AncestralCallDamageEffect)) end + if output.AncestralEmpowermentDamageEffect ~= 1 then + t_insert(breakdown[damageType], s_format("x %.2f ^8(ancestral empowerment effect modifier)", output.AncestralEmpowermentDamageEffect)) + end + if output.AncestralEmpowermentCombinedDamageEffect ~= 1 then + t_insert(breakdown[damageType], s_format("x %.2f ^8(ancestral empowerment + effect modifier)", output.AncestralEmpowermentCombinedDamageEffect)) + end if globalOutput.OffensiveWarcryEffect ~= 1 and not activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then t_insert(breakdown[damageType], s_format("x %.2f ^8(aggregated warcry exerted effect modifier)", globalOutput.OffensiveWarcryEffect)) end @@ -3777,9 +3850,9 @@ function calcs.offence(env, actor, activeSkill) end end if activeSkill.skillModList:Flag(nil, "Condition:WarcryMaxHit") then - output.allMult = output.ScaledDamageEffect * output.FistOfWarDamageEffect * output.AncestralCallDamageEffect * globalOutput.MaxOffensiveWarcryEffect + output.allMult = output.ScaledDamageEffect * output.FistOfWarDamageEffect * output.AncestralCallDamageEffect * output.AncestralEmpowermentDamageEffect * output.AncestralEmpowermentCombinedDamageEffect * globalOutput.MaxOffensiveWarcryEffect else - output.allMult = output.ScaledDamageEffect * output.FistOfWarDamageEffect * output.AncestralCallDamageEffect * globalOutput.OffensiveWarcryEffect + output.allMult = output.ScaledDamageEffect * output.FistOfWarDamageEffect * output.AncestralCallDamageEffect * output.AncestralEmpowermentDamageEffect * output.AncestralEmpowermentCombinedDamageEffect * globalOutput.OffensiveWarcryEffect end local allMult = output.allMult if pass == 1 then diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index b4687e679..5862357a5 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -415,6 +415,20 @@ return { { format = "" }, { format = "{2:output:ExertedAttackMaxHitEffect}", { modName = "ExertIncrease", cfg = "skill" }, { modName = "ExertAttackIncrease", cfg = "skill" }, }, }, + { label = "Ancest. Empower +", bgCol = colorCodes.MAINHANDBG, haveOutput = "AncestralEmpowermentCombinedUptimeRatio", + { format = "{2:output:AvgAncestralEmpowermentCombinedDamageEffect}", { breakdown = "AvgAncestralEmpowermentCombinedDamageEffect"}, }, + { format = "{2:output:AvgAncestralEmpowermentCombinedDamage}", { modName = { "AncestralEmpowermentDamageMultiplier", "FistOfWarDamageMultiplier" }, cfg = "skill" }, { modName = "AncestralBoostDamage", cfg = "skill" }, }, + { format = "{0:output:AncestralEmpowermentCombinedUptimeRatio}%", { breakdown = "AncestralEmpowermentCombinedUptimeRatio" }, }, + { format = "" }, + { format = "{2:output:MaxAncestralEmpowermentCombinedDamageEffect}" }, + }, + { label = "Anc. Empowerment", bgCol = colorCodes.MAINHANDBG, haveOutput = "AncestralEmpowermentUptimeRatio", + { format = "{2:output:AvgAncestralEmpowermentDamageEffect}", { breakdown = "AvgAncestralEmpowermentDamageEffect"}, }, + { format = "{2:output:AvgAncestralEmpowermentDamage}", { modName = "AncestralEmpowermentDamageMultiplier", cfg = "skill"}, { modName = "AncestralBoostDamage", cfg = "skill" }, }, + { format = "{0:output:AncestralEmpowermentUptimeRatio}%", { breakdown = "AncestralEmpowermentUptimeRatio" }, }, + { format = "" }, + { format = "{2:output:MaxAncestralEmpowermentDamageEffect}" }, + }, { label = "Fist of War", bgCol = colorCodes.MAINHANDBG, haveOutput = "FistOfWarUptimeRatio", { format = "{2:output:AvgFistOfWarDamageEffect}", { breakdown = "AvgFistOfWarDamageEffect"}, }, { format = "{2:output:AvgFistOfWarDamage}", { modName = "FistOfWarDamageMultiplier", cfg = "skill"}, { modName = "AncestralBoostDamage", cfg = "skill" }, }, diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 51dabe6cc..c64b9c7d6 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -2625,6 +2625,11 @@ local specialModList = { -- Ancestrally Boosted ["ancestrally boosted attacks deal (%d+)%% increased damage"] = function(num) return { mod("AncestralBoostDamage", "INC", num, nil, ModFlag.Attack, 0) } end, ["(%d+)%% increased area of effect of ancestrally boosted attacks"] = function(num) return { mod("AncestralBoostAreaOfEffect", "INC", num, nil, ModFlag.Attack, 0) } end, + ["every second slam skill you use yourself is ancestrally boosted"] = { + flag("AncestralEmpowerment", { type = "SkillType", skillType = SkillType.Slam }), + mod("AncestralEmpowermentDamageMultiplier", "BASE", 30, { type = "SkillType", skillType = SkillType.Slam }), + mod("AncestralEmpowermentIncAoE", "BASE", 25, { type = "SkillType", skillType = SkillType.Slam }), + }, -- Leech Related ["life leech is instant"] = { mod("InstantLifeLeech", "BASE", 100), }, ["mana leech is instant"] = { mod("InstantManaLeech", "BASE", 100), }, From 44d3424942b62da006f431edddab6a1cd7768938 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Fri, 15 May 2026 14:25:26 -0500 Subject: [PATCH 08/12] comment spelling --- src/Modules/CalcOffence.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index f52ed03e7..66c928ca7 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3410,7 +3410,7 @@ function calcs.offence(env, actor, activeSkill) globalOutput.TheoreticalMaxOffensiveWarcryEffect = globalOutput.TheoreticalMaxOffensiveWarcryEffect * globalOutput["Max"..skillNameVar.."DamageEffect"] end - -- combine Ancentral Empowerment with other sources of Slam Ancestral Boost, namely Fist of War, when both active + -- combine Ancestral Empowerment with other sources of Slam Ancestral Boost, namely Fist of War, when both active local function calcCombinedAncestralBoost(skillName, moreDmg, incArea, uptimeOverride, additionalSkillName) globalOutput.CreateWarcryOffensiveCalcSection = true -- labels for the CalcSection local skillNameVar = skillName:gsub(" ", "") -- Fist Of War -> FistOfWar From 1abbaa1f6c4e46fb3a0c99b153687fbbab856071 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Fri, 15 May 2026 20:07:26 -0500 Subject: [PATCH 09/12] better label --- src/Modules/CalcSections.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index 5862357a5..312d4bea9 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -415,7 +415,7 @@ return { { format = "" }, { format = "{2:output:ExertedAttackMaxHitEffect}", { modName = "ExertIncrease", cfg = "skill" }, { modName = "ExertAttackIncrease", cfg = "skill" }, }, }, - { label = "Ancest. Empower +", bgCol = colorCodes.MAINHANDBG, haveOutput = "AncestralEmpowermentCombinedUptimeRatio", + { label = "AncestralEmpower+", bgCol = colorCodes.MAINHANDBG, haveOutput = "AncestralEmpowermentCombinedUptimeRatio", { format = "{2:output:AvgAncestralEmpowermentCombinedDamageEffect}", { breakdown = "AvgAncestralEmpowermentCombinedDamageEffect"}, }, { format = "{2:output:AvgAncestralEmpowermentCombinedDamage}", { modName = { "AncestralEmpowermentDamageMultiplier", "FistOfWarDamageMultiplier" }, cfg = "skill" }, { modName = "AncestralBoostDamage", cfg = "skill" }, }, { format = "{0:output:AncestralEmpowermentCombinedUptimeRatio}%", { breakdown = "AncestralEmpowermentCombinedUptimeRatio" }, }, From 99d7ea74e3aa08449e1de8dbe973931793857914 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Fri, 15 May 2026 20:35:41 -0500 Subject: [PATCH 10/12] fix avg aoe from fist of war --- src/Modules/CalcOffence.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 66c928ca7..7f3ccdae7 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3370,7 +3370,8 @@ function calcs.offence(env, actor, activeSkill) -- dynamic way of calcing the Ancestral Boost from a single source without duplicating the code -- uptimeOverride: Ancestral Empowerment - local function calcAncestralBoost(skillName, moreDmg, incArea, uptimeOverride) + -- combinedCalcs: ignore INC AoE as we will run that in calcCombinedAncestralBoost + local function calcAncestralBoost(skillName, moreDmg, incArea, uptimeOverride, combinedCalcs) globalOutput.CreateWarcryOffensiveCalcSection = true -- labels for the CalcSection local skillNameVar = skillName:gsub(" ", "") -- Fist Of War -> FistOfWar local skillNameLabel = skillName:lower() @@ -3403,7 +3404,9 @@ function calcs.offence(env, actor, activeSkill) skillModList:NewMod("AreaOfEffect", "INC", (incArea or 0) + ancestrallyBoostedIncArea, "Max "..skillName.." Boosted AoE") else output[skillNameVar.."DamageEffect"] = globalOutput["Avg"..skillNameVar.."DamageEffect"] - skillModList:NewMod("AreaOfEffect", "INC", m_floor(((incArea or 0) + ancestrallyBoostedIncArea) * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") + if not combinedCalcs then + skillModList:NewMod("AreaOfEffect", "INC", m_floor(((incArea or 0) + ancestrallyBoostedIncArea) * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") + end end calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput["Avg"..skillNameVar.."DamageEffect"] @@ -3458,6 +3461,7 @@ function calcs.offence(env, actor, activeSkill) else output[skillNameVar.."DamageEffect"] = globalOutput["Avg"..skillNameVar.."DamageEffect"] skillModList:NewMod("AreaOfEffect", "INC", m_floor(((incArea or 0) + ancestrallyBoostedIncArea) * globalOutput[skillNameVar.."UptimeRatio"] / 100), "Avg "..skillName.." Boosted AoE") + skillModList:NewMod("AreaOfEffect", "INC", m_floor(((incArea or 0) + ancestrallyBoostedIncArea) * globalOutput[additionalSkillNameVar.."UptimeRatio"] / 100 / 2), "Avg "..additionalSkillName.." Boosted AoE") end calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) globalOutput.TheoreticalOffensiveWarcryEffect = globalOutput.TheoreticalOffensiveWarcryEffect * globalOutput["Avg"..skillNameVar.."DamageEffect"] @@ -3467,7 +3471,7 @@ function calcs.offence(env, actor, activeSkill) globalOutput.FistOfWarCooldown = skillModList:Sum("BASE", cfg, "FistOfWarCooldown") or 0 if skillModList:Flag(cfg, "AncestralEmpowerment") and activeSkill.skillTypes[SkillType.Slam] and not activeSkill.skillTypes[SkillType.Vaal] and not activeSkill.skillTypes[SkillType.OtherThingUsesSkill] then if globalOutput.FistOfWarCooldown ~= 0 then -- get the fist of war calcs in output to use in Empowerment - calcAncestralBoost("Fist Of War", (skillModList:Sum("BASE", nil, "FistOfWarDamageMultiplier") / 100), skillModList:Sum("BASE", nil, "FistOfWarIncAoE")) + calcAncestralBoost("Fist Of War", (skillModList:Sum("BASE", nil, "FistOfWarDamageMultiplier") / 100), skillModList:Sum("BASE", nil, "FistOfWarIncAoE"), nil, true) globalOutput.TheoreticalOffensiveWarcryEffect = 1 -- reset effects from FistOfWar calc, we combine later globalOutput.TheoreticalMaxOffensiveWarcryEffect = 1 From dcf59422729d867ba6c1764d4704adc7a3c6bba9 Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Fri, 15 May 2026 21:45:16 -0500 Subject: [PATCH 11/12] forgot AOE portion for Crescendo III --- src/Modules/CalcOffence.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 7f3ccdae7..3358d8de6 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3366,6 +3366,8 @@ function calcs.offence(env, actor, activeSkill) local modSource = skillModList:Tabulate("FLAG", cfg, "FinalStrikeAncestrallyBoosted")[1].mod.source -- e.g. Skill:SupportCrescendoPlayerThree local sourceName = "Ancestral Boost - "..data.gemNameForModSource[modSource] skillModList:NewMod("Damage", "INC", modDB:Sum("INC", cfg, "AncestralBoostDamage"), sourceName, { type = "Condition", var = "FinalStrike" }) + skillModList:NewMod("AreaOfEffect", "INC", ancestrallyBoostedIncArea, sourceName, { type = "Condition", var = "FinalStrike" }) + calcAreaOfEffect(skillModList, skillCfg, skillData, skillFlags, globalOutput, globalBreakdown) end -- dynamic way of calcing the Ancestral Boost from a single source without duplicating the code From 04f89c8c5eed2bb68adde39097f07fce6b43f02e Mon Sep 17 00:00:00 2001 From: Peechey <92683202+Peechey@users.noreply.github.com> Date: Thu, 21 May 2026 02:15:17 -0500 Subject: [PATCH 12/12] add support for Infernal Cry's empowered buff --- src/Data/SkillStatMap.lua | 6 ++++++ src/Data/Skills/act_str.lua | 5 +++++ src/Export/Skills/act_str.txt | 5 +++++ src/Modules/CalcOffence.lua | 25 +++++++++++++------------ src/Modules/CalcPerform.lua | 4 +++- src/Modules/CalcSections.lua | 24 ++++++++++++------------ src/Modules/CalcTriggers.lua | 2 +- 7 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index 67493c620..984eef123 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -586,6 +586,12 @@ return { ["warcry_speed_+%"] = { mod("WarcrySpeed", "INC", nil, 0, KeywordFlag.Warcry), }, +["warcry_empowers_per_X_monster_power_mp_cap"] = { + mod("WarcryPowerCap", "BASE", nil), +}, +["warcry_empowers_per_X_monster_power"] = { + mod("WarcryPowerPer", "BASE", nil), +}, ["display_this_skill_cooldown_does_not_recover_during_buff"] = { flag("NoCooldownRecoveryInDuration"), }, diff --git a/src/Data/Skills/act_str.lua b/src/Data/Skills/act_str.lua index 23d10619e..65d76e141 100644 --- a/src/Data/Skills/act_str.lua +++ b/src/Data/Skills/act_str.lua @@ -7500,6 +7500,11 @@ skills["InfernalCryPlayer"] = { label = "Infernal Cry", incrementalEffectiveness = 0.054999999701977, statDescriptionScope = "infernal_cry", + statMap = { + ["infernal_cry_exerted_attack_all_damage_%_to_gain_as_fire_%"] = { + mod("DamageGainAsFire", "BASE", nil, ModFlag.Melee, 0, { type = "GlobalEffect", effectType = "Warcry" }, { type = "Condition", var = "Empowered" }), + }, + }, baseFlags = { warcry = true, area = true, diff --git a/src/Export/Skills/act_str.txt b/src/Export/Skills/act_str.txt index c2c2b7c9a..74ea3e062 100644 --- a/src/Export/Skills/act_str.txt +++ b/src/Export/Skills/act_str.txt @@ -481,6 +481,11 @@ statMap = { #skill InfernalCryPlayer #set InfernalCryPlayer #flags warcry area duration +statMap = { + ["infernal_cry_exerted_attack_all_damage_%_to_gain_as_fire_%"] = { + mod("DamageGainAsFire", "BASE", nil, ModFlag.Melee, 0, { type = "GlobalEffect", effectType = "Warcry" }, { type = "Condition", var = "Empowered" }), + }, +}, #mods #skillEnd diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 3358d8de6..d34fba141 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3104,26 +3104,27 @@ function calcs.offence(env, actor, activeSkill) end globalOutput.AncestralCryCalculated = true elseif value.activeEffect.grantedEffect.name == "Infernal Cry" and not globalOutput.InfernalCryCalculated then + globalOutput.CreateWarcryOffensiveCalcSection = true globalOutput.InfernalCryDuration = calcSkillDuration(value.skillModList, value.skillCfg, value.skillData, env, enemyDB) globalOutput.InfernalCryCooldown = calcSkillCooldown(value.skillModList, value.skillCfg, value.skillData) globalOutput.InfernalCryCastTime = calcWarcryCastTime(value.skillModList, value.skillCfg, value.skillData, actor) if activeSkill.skillTypes[SkillType.Melee] then - globalOutput.InfernalExertsCount = env.modDB:Sum("BASE", nil, "NumInfernalExerts") or 0 - local baseUptimeRatio = m_min((globalOutput.InfernalExertsCount / globalOutput.Speed) / (globalOutput.InfernalCryCooldown + globalOutput.InfernalCryCastTime), 1) * 100 + globalOutput.InfernalEmpoweredCount = (modDB:Override(nil, "WarcryPower") or value.skillModList:Sum("BASE", nil, "WarcryPowerCap")) / value.skillModList:Sum("BASE", nil, "WarcryPowerPer") + local baseUptimeRatio = m_min((globalOutput.InfernalEmpoweredCount / globalOutput.Speed) / (globalOutput.InfernalCryCooldown + globalOutput.InfernalCryCastTime), 1) * 100 local storedUses = value.skillData.storedUses or 0 + value.skillModList:Sum("BASE", value.skillCfg, "AdditionalCooldownUses") - globalOutput.InfernalUpTimeRatio = m_min(100, baseUptimeRatio * storedUses) - globalOutput.GlobalWarcryUptimeRatio = globalOutput.GlobalWarcryUptimeRatio + globalOutput.InfernalUpTimeRatio + globalOutput.InfernalCryUptimeRatio = m_min(100, baseUptimeRatio * storedUses) + globalOutput.GlobalWarcryUptimeRatio = globalOutput.GlobalWarcryUptimeRatio + globalOutput.InfernalCryUptimeRatio if globalBreakdown then - globalBreakdown.InfernalUpTimeRatio = { } - t_insert(globalBreakdown.InfernalUpTimeRatio, s_format("(%d ^8(number of exerts)", globalOutput.InfernalExertsCount)) - t_insert(globalBreakdown.InfernalUpTimeRatio, s_format("/ %.2f) ^8(attacks per second)", globalOutput.Speed)) + globalBreakdown.InfernalCryUptimeRatio = { } + t_insert(globalBreakdown.InfernalCryUptimeRatio, s_format("(%.2f ^8(number of empowered)", globalOutput.InfernalEmpoweredCount)) + t_insert(globalBreakdown.InfernalCryUptimeRatio, s_format("/ %.2f) ^8(attacks per second)", globalOutput.Speed)) if globalOutput.InfernalCryCastTime > 0 then - t_insert(globalBreakdown.InfernalUpTimeRatio, s_format("/ (%.2f ^8(warcry cooldown)", globalOutput.InfernalCryCooldown)) - t_insert(globalBreakdown.InfernalUpTimeRatio, s_format("+ %.2f) ^8(warcry casttime)", globalOutput.InfernalCryCastTime)) + t_insert(globalBreakdown.InfernalCryUptimeRatio, s_format("/ (%.2f ^8(warcry cooldown)", globalOutput.InfernalCryCooldown)) + t_insert(globalBreakdown.InfernalCryUptimeRatio, s_format("+ %.2f) ^8(warcry cast time)", globalOutput.InfernalCryCastTime)) else - t_insert(globalBreakdown.InfernalUpTimeRatio, s_format("/ %.2f ^8(average warcry cooldown)", globalOutput.InfernalCryCooldown)) + t_insert(globalBreakdown.InfernalCryUptimeRatio, s_format("/ %.2f ^8(average warcry cooldown)", globalOutput.InfernalCryCooldown)) end - t_insert(globalBreakdown.InfernalUpTimeRatio, s_format("= %d%%", globalOutput.InfernalUpTimeRatio)) + t_insert(globalBreakdown.InfernalCryUptimeRatio, s_format("= %d%%", globalOutput.InfernalCryUptimeRatio)) end end globalOutput.InfernalCryCalculated = true @@ -3287,7 +3288,7 @@ function calcs.offence(env, actor, activeSkill) -- Calculate Exerted Attack Uptime -- There are various strategies a player could use to maximize either warcry effect stacking or staggering -- 1) they don't pay attention and therefore we calculated exerted attack uptime as just the maximum uptime of any enabled warcries that exert attacks - local warcryList = {"AncestralUpTimeRatio", "InfernalUpTimeRatio", "IntimidatingUpTimeRatio", "RallyingUpTimeRatio", "SeismicUpTimeRatio", "BattlemageUpTimeRatio"} + local warcryList = {"AncestralUpTimeRatio", "InfernalCryUptimeRatio", "IntimidatingUpTimeRatio", "RallyingUpTimeRatio", "SeismicUpTimeRatio", "BattlemageUpTimeRatio"} for _, cryTimeRatio in ipairs(warcryList) do globalOutput.ExertedAttackUptimeRatio = m_max(globalOutput.ExertedAttackUptimeRatio or 0, globalOutput[cryTimeRatio] or 0) end diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index ee090a7c6..d32db5b79 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -1919,7 +1919,9 @@ function calcs.perform(env, skipEHP) end local full_duration = calcSkillDuration(modStore, skillCfg, activeSkill.skillData, env, enemyDB) local actual_cooldown = calcSkillCooldown(modStore, skillCfg, activeSkill.skillData) - local uptime = modDB:Flag(nil, "Condition:WarcryMaxHit") and 1 or m_min(full_duration / actual_cooldown, 1) + -- need to scale warcry buffs by their actual uptime + local warcryOutputUptime = env.build.calcsTab.mainOutput and (env.build.calcsTab.mainOutput[warcryName.."CryUptimeRatio"] / 100) or nil + local uptime = modDB:Flag(nil, "Condition:WarcryMaxHit") and 1 or warcryOutputUptime or m_min(full_duration / actual_cooldown, 1) local extraWarcryModList = activeSkill.activeEffect.grantedEffect.name == "Rallying Cry" and new("ModList") or {} if not modDB:Flag(nil, "CannotGainWarcryBuffs") then if not buff.applyNotPlayer then diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index 312d4bea9..967ac4ba6 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -355,7 +355,7 @@ return { { label = "Skill DPS", flag = "triggered", { format = "{1:output:TotalDPS}", { breakdown = "TotalDPS" }, { label = "DPS Multiplier", modName = "DPS", cfg = "skill" }, }, }, } } } }, -{ 3, "Warcries", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Ancestral Boosts", data = { +{ 3, "Warcries", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Empowered Stats", data = { extra = "{2:output:TheoreticalOffensiveWarcryEffect} Avg Combined Impact | {2:output:TheoreticalMaxOffensiveWarcryEffect} Max Combined Impact", colWidth = 114, { @@ -363,7 +363,7 @@ return { { format = "Effective Impact" }, { format = "Avg Dmg Effect" }, { format = "Uptime" }, - { format = "Number of Exerts" }, + { format = "# of Empowered" }, { format = "Max 1-Hit Impact"}, }, { label = "Seismic Cry", haveOutput = "SeismicUpTimeRatio", @@ -387,11 +387,11 @@ return { { format = "{0:output:RallyingExertsCount}" }, { format = "{2:output:RallyingMaxHitEffect}" }, }, - { label = "Infernal Cry", haveOutput = "InfernalUpTimeRatio", + { label = "Infernal Cry", haveOutput = "InfernalCryUptimeRatio", { format = "" }, { format = "" }, - { format = "{0:output:InfernalUpTimeRatio}%", { breakdown = "InfernalUpTimeRatio" }, }, - { format = "{0:output:InfernalExertsCount}" }, + { format = "{0:output:InfernalCryUptimeRatio}%", { breakdown = "InfernalCryUptimeRatio" }, }, + { format = "{0:output:InfernalEmpoweredCount}" }, { format = "" }, }, { label = "Battlemage's Cry", haveOutput = "BattlemageUpTimeRatio", @@ -408,13 +408,13 @@ return { { format = "{0:output:AncestralExertsCount}" }, { format = "" }, }, - { label = "Exerted Attacks", bgCol = colorCodes.MAINHANDBG, haveOutput = "ExertedAttackUptimeRatio", - { format = "{2:output:ExertedAttackHitEffect}", { breakdown = "ExertedAttackHitEffect"}, }, - { format = "{2:output:ExertedAttackAvgDmg}", { modName = "ExertIncrease", cfg = "skill" }, { modName = "ExertAttackIncrease", cfg = "skill" }, }, - { format = "{0:output:ExertedAttackUptimeRatio}%", { breakdown = "ExertedAttackUptimeRatio" }, }, - { format = "" }, - { format = "{2:output:ExertedAttackMaxHitEffect}", { modName = "ExertIncrease", cfg = "skill" }, { modName = "ExertAttackIncrease", cfg = "skill" }, }, - }, + --{ label = "Exerted Attacks", bgCol = colorCodes.MAINHANDBG, haveOutput = "ExertedAttackUptimeRatio", + -- { format = "{2:output:ExertedAttackHitEffect}", { breakdown = "ExertedAttackHitEffect"}, }, + -- { format = "{2:output:ExertedAttackAvgDmg}", { modName = "ExertIncrease", cfg = "skill" }, { modName = "ExertAttackIncrease", cfg = "skill" }, }, + -- { format = "{0:output:ExertedAttackUptimeRatio}%", { breakdown = "ExertedAttackUptimeRatio" }, }, + -- { format = "" }, + -- { format = "{2:output:ExertedAttackMaxHitEffect}", { modName = "ExertIncrease", cfg = "skill" }, { modName = "ExertAttackIncrease", cfg = "skill" }, }, + --}, { label = "AncestralEmpower+", bgCol = colorCodes.MAINHANDBG, haveOutput = "AncestralEmpowermentCombinedUptimeRatio", { format = "{2:output:AvgAncestralEmpowermentCombinedDamageEffect}", { breakdown = "AvgAncestralEmpowermentCombinedDamageEffect"}, }, { format = "{2:output:AvgAncestralEmpowermentCombinedDamage}", { modName = { "AncestralEmpowermentDamageMultiplier", "FistOfWarDamageMultiplier" }, cfg = "skill" }, { modName = "AncestralBoostDamage", cfg = "skill" }, }, diff --git a/src/Modules/CalcTriggers.lua b/src/Modules/CalcTriggers.lua index 35fab416f..639ed6941 100644 --- a/src/Modules/CalcTriggers.lua +++ b/src/Modules/CalcTriggers.lua @@ -489,7 +489,7 @@ local function defaultTriggerHandler(env, config) -- Infernal Cry uptime if actor.mainSkill.activeEffect.grantedEffect.name == "Combust" and GlobalCache.cachedData[env.mode][uuid] and source and source.skillTypes[SkillType.Melee] then - local infernalCryExertsCount = GlobalCache.cachedData[env.mode][uuid].Env.player.output.InfernalExertsCount + local infernalCryExertsCount = GlobalCache.cachedData[env.mode][uuid].Env.player.output.InfernalEmpoweredCount local infernalCryDuration = ceil_b(GlobalCache.cachedData[env.mode][uuid].Env.player.output.InfernalCryDuration, data.misc.ServerTickTime) local infernalCryCastTime = GlobalCache.cachedData[env.mode][uuid].Env.player.output.InfernalCryCastTime local infernalCryCooldown = ceil_b(GlobalCache.cachedData[env.mode][uuid].Env.player.output.InfernalCryCooldown, data.misc.ServerTickTime)