From af58b9303a7fb76c4722544f3a278186ed1d34ce Mon Sep 17 00:00:00 2001 From: Paliak <91493239+Paliak@users.noreply.github.com> Date: Tue, 22 Jul 2025 22:46:32 +0200 Subject: [PATCH 1/7] FIX(mirage): fix cap GC cooldown by mirage+attack delay The Howlcrack unique item sets the cooldown of warcies to 0 causing the GC dps to explode into infinity due to division by zero. This was caused by the assumption that the mirages instantly spawn and attack. This commit makes it so that the cooldown is at least the amount of time it takes to spawm them all and attack or channel for 1s. --- src/Modules/CalcMirages.lua | 50 +++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/src/Modules/CalcMirages.lua b/src/Modules/CalcMirages.lua index 8d84278c42..1ec8678bca 100644 --- a/src/Modules/CalcMirages.lua +++ b/src/Modules/CalcMirages.lua @@ -361,10 +361,24 @@ function calcs.mirages(env) end } elseif env.player.mainSkill.skillData.triggeredByGeneralsCry then - env.player.mainSkill.skillTypes[SkillType.Triggered] = true local maxMirageWarriors = 0 local cooldown = 1 local generalsCryActiveSkill + local uuid = cacheSkillUUID(env.player.mainSkill, env) + + -- Prevent infinite recusion + if env.limitedSkills and env.limitedSkills[uuid] then + return + end + + env.player.mainSkill.skillTypes[SkillType.Triggered] = true + env.player.mainSkill.skillCfg.skillCond["usedByMirage"] = true + env.player.mainSkill.skillTypes[SkillType.OtherThingUsesSkill] = true + + if not GlobalCache.cachedData[env.mode][uuid] or env.mode == "CALCULATOR" then + calcs.buildActiveSkill(env, env.mode, env.player.mainSkill, uuid, {[uuid] = true}) + end + local mainSkillOutputCache = GlobalCache.cachedData[env.mode][uuid].Env.player.output -- Find the active General's Cry gem to get active properties for _, skill in ipairs(env.player.activeSkillList) do @@ -375,17 +389,32 @@ function calcs.mirages(env) end end + -- Scale dps with mirage quantity + for _, value in ipairs(generalsCryActiveSkill.skillModList:Tabulate("BASE", generalsCryActiveSkill.skillCfg, "GeneralsCryDoubleMaxCount")) do + local mod = value.mod + env.player.mainSkill.skillModList:NewMod("QuantityMultiplier", mod.type, mod.value, mod.source, mod.flags, mod.keywordFlags) + maxMirageWarriors = maxMirageWarriors + mod.value + end + + -- Scale cooldown to have maximum number of Mirages at once. 0.3s for first mirage then 0.2s for each extra + local mirageSpawnTime = 0.3 + 0.2 * maxMirageWarriors + if env.player.mainSkill.skillTypes[SkillType.Channel] then + mirageSpawnTime = mirageSpawnTime + 1 + else + mirageSpawnTime = mirageSpawnTime + (mainSkillOutputCache.HitTime or mainSkillOutputCache.Time) + env.player.mainSkill.skillData.timeOverride = 1 + end + + -- This is so that it's consistant with the info messege but removing this could make it more accurate numbers wise + mirageSpawnTime = round(mirageSpawnTime, 2) + cooldown = m_max(cooldown, mirageSpawnTime) + -- Scale dps with GC's cooldown env.player.mainSkill.skillData.dpsMultiplier = (env.player.mainSkill.skillData.dpsMultiplier or 1) * (1 / cooldown) -- Does not use player resources env.player.mainSkill.skillModList:NewMod("HasNoCost", "FLAG", true, "Used by mirage") - -- Non-channelled skills only attack once, disregard attack rate - if not env.player.mainSkill.skillTypes[SkillType.Channel] then - env.player.mainSkill.skillData.timeOverride = 1 - end - -- Supported Attacks Count as Exerted for _, value in ipairs(env.player.mainSkill.skillModList:Tabulate("INC", env.player.mainSkill.skillCfg, "ExertIncrease")) do local mod = value.mod @@ -408,13 +437,8 @@ function calcs.mirages(env) env.player.mainSkill.skillModList:NewMod("DoubleDamageChance", mod.type, mod.value, mod.source, mod.flags, mod.keywordFlags) end - -- Scale dps with mirage quantity - for _, value in ipairs(generalsCryActiveSkill.skillModList:Tabulate("BASE", generalsCryActiveSkill.skillCfg, "GeneralsCryDoubleMaxCount")) do - local mod = value.mod - env.player.mainSkill.skillModList:NewMod("QuantityMultiplier", mod.type, mod.value, mod.source, mod.flags, mod.keywordFlags) - maxMirageWarriors = maxMirageWarriors + mod.value - end - env.player.mainSkill.infoMessage = tostring(maxMirageWarriors) .. " GC Mirage Warriors using " .. env.player.mainSkill.activeEffect.grantedEffect.name + env.player.mainSkill.infoMessage = tostring(maxMirageWarriors) .. " GC Mirages using " .. env.player.mainSkill.activeEffect.grantedEffect.name + env.player.mainSkill.infoMessage2 = tostring(mirageSpawnTime) .. "s for " .. tostring(maxMirageWarriors) .. " Mirages to finish Attacking" end return calculateMirage(env, config) From 86007f21786ee100e2b5b0f1e33c2d226d7d3d11 Mon Sep 17 00:00:00 2001 From: Paliak <91493239+Paliak@users.noreply.github.com> Date: Tue, 22 Jul 2025 22:53:10 +0200 Subject: [PATCH 2/7] FIX: cleanup handling of limitedSkills table --- src/Modules/CalcMirages.lua | 2 +- src/Modules/CalcPerform.lua | 2 +- src/Modules/CalcTriggers.lua | 10 +++++----- src/Modules/Calcs.lua | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Modules/CalcMirages.lua b/src/Modules/CalcMirages.lua index 1ec8678bca..9452e9b2a3 100644 --- a/src/Modules/CalcMirages.lua +++ b/src/Modules/CalcMirages.lua @@ -376,7 +376,7 @@ function calcs.mirages(env) env.player.mainSkill.skillTypes[SkillType.OtherThingUsesSkill] = true if not GlobalCache.cachedData[env.mode][uuid] or env.mode == "CALCULATOR" then - calcs.buildActiveSkill(env, env.mode, env.player.mainSkill, uuid, {[uuid] = true}) + calcs.buildActiveSkill(env, env.mode, env.player.mainSkill, uuid, {uuid}) end local mainSkillOutputCache = GlobalCache.cachedData[env.mode][uuid].Env.player.output diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 54ba87f67f..e182eca09c 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -30,7 +30,7 @@ local bnot = bit.bnot local function getCachedOutputValue(env, activeSkill, ...) local uuid = cacheSkillUUID(activeSkill, env) if not GlobalCache.cachedData[env.mode][uuid] or env.mode == "CALCULATOR" then - calcs.buildActiveSkill(env, env.mode, activeSkill, uuid, {[uuid] = true}) + calcs.buildActiveSkill(env, env.mode, activeSkill, uuid, {uuid}) end local tempValues = {} diff --git a/src/Modules/CalcTriggers.lua b/src/Modules/CalcTriggers.lua index 9de2e9b3a5..7eb2d84db9 100644 --- a/src/Modules/CalcTriggers.lua +++ b/src/Modules/CalcTriggers.lua @@ -517,7 +517,7 @@ local function defaultTriggerHandler(env, config) if actor.mainSkill.skillData.triggeredByManaforged and trigRate > 0 then local triggeredUUID = cacheSkillUUID(actor.mainSkill, env) if not GlobalCache.cachedData[env.mode][triggeredUUID] then - calcs.buildActiveSkill(env, env.mode, actor.mainSkill, triggeredUUID, {[triggeredUUID] = true}) + calcs.buildActiveSkill(env, env.mode, actor.mainSkill, triggeredUUID, {triggeredUUID}) end local triggeredManaCost = GlobalCache.cachedData[env.mode][triggeredUUID].Env.player.output.ManaCostRaw or 0 if triggeredManaCost > 0 then @@ -1176,7 +1176,7 @@ local configTable = { else -- Needed to get the cooldown form the active part for _, skill in ipairs(env.player.activeSkillList) do if skill.activeEffect.grantedEffect.name == "Call to Arms" then - env.player.mainSkill.triggeredBy = skill.activeEffect + env.player.mainSkill.triggeredBy.grantedEffect = skill.activeEffect.grantedEffect break end end @@ -1194,7 +1194,7 @@ local configTable = { else -- Needed to get the cooldown form the active part for _, skill in ipairs(env.player.activeSkillList) do if skill.activeEffect.grantedEffect.name == "Automation" then - env.player.mainSkill.triggeredBy = skill.activeEffect + env.player.mainSkill.triggeredBy.grantedEffect = skill.activeEffect.grantedEffect break end end @@ -1214,7 +1214,7 @@ local configTable = { -- with skills like Automation and Spellslinger for _, skill in ipairs(env.player.activeSkillList) do if skill.activeEffect.grantedEffect.name == "Autoexertion" then - env.player.mainSkill.triggeredBy = skill.activeEffect + env.player.mainSkill.triggeredBy.grantedEffect = skill.activeEffect.grantedEffect break end end @@ -1248,7 +1248,7 @@ local configTable = { env.player.mainSkill.skillFlags.globalTrigger = true local uuid = cacheSkillUUID(env.player.mainSkill, env) if not GlobalCache.cachedData[env.mode][uuid] or env.mode == "CALCULATOR" then - calcs.buildActiveSkill(env, env.mode, env.player.mainSkill, uuid, {[uuid] = true}) + calcs.buildActiveSkill(env, env.mode, env.player.mainSkill, uuid, {uuid}) end env.player.mainSkill.skillData.triggerRateCapOverride = 1 / GlobalCache.cachedData[env.mode][uuid].Env.player.output.Duration if env.player.breakdown then diff --git a/src/Modules/Calcs.lua b/src/Modules/Calcs.lua index 1dee86156f..3038fef566 100644 --- a/src/Modules/Calcs.lua +++ b/src/Modules/Calcs.lua @@ -393,10 +393,10 @@ function calcs.buildActiveSkill(env, mode, skill, targetUUID, limitedProcessingF -- env.limitedSkills contains a map of uuids that should be limited in calculation -- this is in order to prevent infinite recursion loops fullEnv.limitedSkills = fullEnv.limitedSkills or {} - for uuid, _ in pairs(env.limitedSkills or {}) do + for _, uuid in ipairs(env.limitedSkills or {}) do fullEnv.limitedSkills[uuid] = true end - for uuid, _ in pairs(limitedProcessingFlags or {}) do + for _, uuid in ipairs(limitedProcessingFlags or {}) do fullEnv.limitedSkills[uuid] = true end From 30b5032b062c3b0c7c80a86d7cbe6e205ab0a8fb Mon Sep 17 00:00:00 2001 From: Paliak <91493239+Paliak@users.noreply.github.com> Date: Tue, 22 Jul 2025 22:54:30 +0200 Subject: [PATCH 3/7] FIX: cleanup target skill selection for SacredWisps and MirageArcher --- src/Modules/CalcMirages.lua | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/Modules/CalcMirages.lua b/src/Modules/CalcMirages.lua index 9452e9b2a3..747e064943 100644 --- a/src/Modules/CalcMirages.lua +++ b/src/Modules/CalcMirages.lua @@ -24,7 +24,7 @@ local function calculateMirage(env, config) return end - local mirageSkill = nil + local mirageSkill = config.mirageSkill if config.compareFunc then for _, skill in ipairs(env.player.activeSkillList) do @@ -63,11 +63,7 @@ function calcs.mirages(env) if env.player.mainSkill.skillData.triggeredByMirageArcher then config = { calcMainSkillOffence = true, - compareFunc = function(skill, env, config, mirageSkill) - if not env.player.mainSkill.skillCfg.skillCond["usedByMirage"] and env.player.weaponData1.type == "Bow" then - return env.player.mainSkill - end - end, + mirageSkill = env.player.mainSkill, preCalcFunc = function(env, newSkill, newEnv) local moreDamage = newSkill.skillModList:Sum("BASE", newSkill.skillCfg, "MirageArcherLessDamage") local moreAttackSpeed = newSkill.skillModList:Sum("BASE", newSkill.skillCfg, "MirageArcherLessAttackSpeed") @@ -297,11 +293,7 @@ function calcs.mirages(env) elseif env.player.mainSkill.skillData.triggeredBySacredWisps then config = { calcMainSkillOffence = true, - compareFunc = function(skill, env, config, mirageSkill) - if not env.player.mainSkill.skillCfg.skillCond["usedByMirage"] and env.player.weaponData1.type == "Wand" then - return env.player.mainSkill - end - end, + mirageSkill = env.player.mainSkill, preCalcFunc = function(env, newSkill, newEnv) local lessDamage = newSkill.skillModList:Sum("BASE", env.player.mainSkill.skillCfg, "SacredWispsLessDamage") local wispsMaxCount From 5f5b0e24ac8f8e746ab4be00175d7dcd3761f08b Mon Sep 17 00:00:00 2001 From: Paliak <91493239+Paliak@users.noreply.github.com> Date: Tue, 22 Jul 2025 22:55:42 +0200 Subject: [PATCH 4/7] FIX: mark the cache generated by mirage calcs as CALCULATOR The env used by mirage skills is often modified causing the resulting env to differ. This has not caused issues to there not beign any caching use after calcMirages but this could come up in the future. Marking the env as CALCULATOR still allows for the env to be cached in case it's really needed but it will prevent it being used in most cases. --- src/Modules/CalcMirages.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/CalcMirages.lua b/src/Modules/CalcMirages.lua index 747e064943..ded5e34ec7 100644 --- a/src/Modules/CalcMirages.lua +++ b/src/Modules/CalcMirages.lua @@ -35,7 +35,7 @@ local function calculateMirage(env, config) end if mirageSkill then - local newSkill, newEnv = calcs.copyActiveSkill(env, env.mode, mirageSkill) + local newSkill, newEnv = calcs.copyActiveSkill(env, "CALCULATOR", mirageSkill) newSkill.skillCfg.skillCond["usedByMirage"] = true newEnv.limitedSkills = newEnv.limitedSkills or {} newEnv.limitedSkills[cacheSkillUUID(newSkill, newEnv)] = true From a1779a930cf7eb9a91bec617592b5e6e9642177a Mon Sep 17 00:00:00 2001 From: Paliak <91493239+Paliak@users.noreply.github.com> Date: Tue, 22 Jul 2025 23:00:38 +0200 Subject: [PATCH 5/7] FIX: remove vestigial CACHE table This was once used as the main table holding the cached output of skills. It has been entirely replaced by the remaining tables. --- src/Data/Global.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Global.lua b/src/Data/Global.lua index 7b1f9572c5..c11eb8de67 100644 --- a/src/Data/Global.lua +++ b/src/Data/Global.lua @@ -321,6 +321,6 @@ SkillType = { } GlobalCache = { - cachedData = { MAIN = {}, CALCS = {}, CALCULATOR = {}, CACHE = {}, }, + cachedData = { MAIN = {}, CALCS = {}, CALCULATOR = {} }, } From e7b4cec9c549104385ee34b3acda44a4e24ab41e Mon Sep 17 00:00:00 2001 From: Paliak <91493239+Paliak@users.noreply.github.com> Date: Tue, 22 Jul 2025 23:03:24 +0200 Subject: [PATCH 6/7] MISC: typo --- src/Modules/CalcMirages.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/CalcMirages.lua b/src/Modules/CalcMirages.lua index ded5e34ec7..eb65b93431 100644 --- a/src/Modules/CalcMirages.lua +++ b/src/Modules/CalcMirages.lua @@ -397,7 +397,7 @@ function calcs.mirages(env) env.player.mainSkill.skillData.timeOverride = 1 end - -- This is so that it's consistant with the info messege but removing this could make it more accurate numbers wise + -- This is so that it's consistant with the info message but removing this could make it more accurate numbers wise mirageSpawnTime = round(mirageSpawnTime, 2) cooldown = m_max(cooldown, mirageSpawnTime) From fc4d1b70f2cdab2858a39a0e92ca66e38592ea0a Mon Sep 17 00:00:00 2001 From: Paliak <91493239+Paliak@users.noreply.github.com> Date: Tue, 22 Jul 2025 23:12:11 +0200 Subject: [PATCH 7/7] FIX: typo --- src/Modules/CalcMirages.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/CalcMirages.lua b/src/Modules/CalcMirages.lua index eb65b93431..2a560c6afb 100644 --- a/src/Modules/CalcMirages.lua +++ b/src/Modules/CalcMirages.lua @@ -358,7 +358,7 @@ function calcs.mirages(env) local generalsCryActiveSkill local uuid = cacheSkillUUID(env.player.mainSkill, env) - -- Prevent infinite recusion + -- Prevent infinite recursion if env.limitedSkills and env.limitedSkills[uuid] then return end