Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix calc mode issues for triggers and mirages #7458

Merged
merged 3 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/Classes/GemSelectControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ function GemSelectClass:CalcOutputWithThisGem(calcFunc, gemData, qualityId)
gemInstance.displayEffect = oldGem.displayEffect
else
gemList[self.index] = nil
calcFunc({ }, { allocNodes = true, requirementsItems = true })
end

return output, gemInstance
Expand Down
2 changes: 0 additions & 2 deletions src/Data/Global.lua
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,6 @@ SkillType = {

GlobalCache = {
cachedData = { MAIN = {}, CALCS = {}, CALCULATOR = {}, CACHE = {}, },
deleteGroup = { },
excludeFullDpsList = { },
noCache = nil,
useFullDPS = false,
numActiveSkillInFullDPS = 0,
Expand Down
2 changes: 1 addition & 1 deletion src/Data/Skills/sup_str.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2139,7 +2139,7 @@ skills["AvengingFlame"] = {
castTime = 1,
preDamageFunc = function(activeSkill, output)
local uuid = activeSkill.skillData.triggerSourceUUID
local cache = uuid and GlobalCache.cachedData["CACHE"][uuid]
local cache = uuid and (GlobalCache.cachedData["MAIN"][uuid] or GlobalCache.cachedData["CALCS"][uuid])
local totemLife = cache and cache.Env.player.output.TotemLife or 0

local add = totemLife * activeSkill.skillData.lifeDealtAsFire / 100
Expand Down
7 changes: 0 additions & 7 deletions src/Modules/Build.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,6 @@ function buildMode:OnFrame(inputEvents)
self.controls.secondaryAscendDrop.list = {{label = "None", ascendClassId = 0}, {label = "Warden", ascendClassId = 1}, {label = "Warlock", ascendClassId = 2}, {label = "Primalist", ascendClassId = 3}}
self.controls.secondaryAscendDrop:SelByValue(self.spec.curSecondaryAscendClassId, "ascendClassId")

local checkFabricatedGroups = self.buildFlag
if self.buildFlag then
-- Wipe Global Cache
wipeGlobalCache()
Expand All @@ -1046,12 +1045,6 @@ function buildMode:OnFrame(inputEvents)
-- Update contents of main skill dropdowns
self:RefreshSkillSelectControls(self.controls, self.mainSocketGroup, "")

-- Delete any possible fabricated groups
if checkFabricatedGroups then
deleteFabricatedGroup(self.skillsTab)
checkFabricatedGroups = false
end

-- Draw contents of current tab
local sideBarWidth = 312
local tabViewPort = {
Expand Down
38 changes: 19 additions & 19 deletions src/Modules/CalcMirages.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ local function calculateMirage(env, config)
end

if mirageSkill then
local newSkill, newEnv = calcs.copyActiveSkill(env, env.mode == "CALCS" and "CALCS" or "MAIN", mirageSkill)
local newSkill, newEnv = calcs.copyActiveSkill(env, env.mode, mirageSkill)
newSkill.skillCfg.skillCond["usedByMirage"] = true
newSkill.skillData.limitedProcessing = true
newSkill.skillData.mirageUses = env.player.mainSkill.skillData.storedUses
Expand Down Expand Up @@ -122,17 +122,17 @@ function calcs.mirages(env)
compareFunc = function(skill, env, config, mirageSkill)
if skill ~= env.player.mainSkill and skill.skillTypes[SkillType.Attack] and not skill.skillTypes[SkillType.Totem] and not skill.skillTypes[SkillType.SummonsTotem] and band(skill.skillCfg.flags, bor(ModFlag.Sword, ModFlag.Weapon1H)) == bor(ModFlag.Sword, ModFlag.Weapon1H) and not skill.skillCfg.skillCond["usedByMirage"] then
local uuid = cacheSkillUUID(skill, env)
if not GlobalCache.cachedData["CACHE"][uuid] or GlobalCache.noCache then
calcs.buildActiveSkill(env, "CACHE", skill)
if not GlobalCache.cachedData[env.mode][uuid] then
calcs.buildActiveSkill(env, env.mode, skill)
end

if GlobalCache.cachedData["CACHE"][uuid] and GlobalCache.cachedData["CACHE"][uuid].CritChance and GlobalCache.cachedData["CACHE"][uuid].CritChance > 0 then
if GlobalCache.cachedData[env.mode][uuid] and GlobalCache.cachedData[env.mode][uuid].CritChance and GlobalCache.cachedData[env.mode][uuid].CritChance > 0 then
if not mirageSkill then
usedSkillBestDps = GlobalCache.cachedData["CACHE"][uuid].TotalDPS
return GlobalCache.cachedData["CACHE"][uuid].ActiveSkill
elseif GlobalCache.cachedData["CACHE"][uuid].TotalDPS > usedSkillBestDps then
usedSkillBestDps = GlobalCache.cachedData["CACHE"][uuid].TotalDPS
return GlobalCache.cachedData["CACHE"][uuid].ActiveSkill
usedSkillBestDps = GlobalCache.cachedData[env.mode][uuid].TotalDPS
return GlobalCache.cachedData[env.mode][uuid].ActiveSkill
elseif GlobalCache.cachedData[env.mode][uuid].TotalDPS > usedSkillBestDps then
usedSkillBestDps = GlobalCache.cachedData[env.mode][uuid].TotalDPS
return GlobalCache.cachedData[env.mode][uuid].ActiveSkill
end
end
end
Expand Down Expand Up @@ -191,21 +191,21 @@ function calcs.mirages(env)
local isDisabled = skill.skillFlags and skill.skillFlags.disable
if skill ~= env.player.mainSkill and (skill.skillTypes[SkillType.Slam] or skill.skillTypes[SkillType.Melee]) and skill.skillTypes[SkillType.Attack] and not skill.skillTypes[SkillType.Vaal] and not isTriggered(skill) and not isDisabled and not skill.skillTypes[SkillType.Totem] and not skill.skillTypes[SkillType.SummonsTotem] and not skill.skillCfg.skillCond["usedByMirage"] then
local uuid = cacheSkillUUID(skill, env)
if not GlobalCache.cachedData["CACHE"][uuid] or GlobalCache.noCache then
calcs.buildActiveSkill(env, "CACHE", skill)
if not GlobalCache.cachedData[env.mode][uuid] or env.mode == "CALCULATOR" then
calcs.buildActiveSkill(env, env.mode, skill)
end

if GlobalCache.cachedData["CACHE"][uuid] then
if GlobalCache.cachedData[env.mode][uuid] then
if not mirageSkill then
usedSkillBestDps = GlobalCache.cachedData["CACHE"][uuid].TotalDPS
EffectiveSourceRate = GlobalCache.cachedData["CACHE"][uuid].Speed
return GlobalCache.cachedData["CACHE"][uuid].ActiveSkill
usedSkillBestDps = GlobalCache.cachedData[env.mode][uuid].TotalDPS
EffectiveSourceRate = GlobalCache.cachedData[env.mode][uuid].Speed
return GlobalCache.cachedData[env.mode][uuid].ActiveSkill

else
if GlobalCache.cachedData["CACHE"][uuid].TotalDPS > usedSkillBestDps then
usedSkillBestDps = GlobalCache.cachedData["CACHE"][uuid].TotalDPS
EffectiveSourceRate = GlobalCache.cachedData["CACHE"][uuid].Speed
return GlobalCache.cachedData["CACHE"][uuid].ActiveSkill
if GlobalCache.cachedData[env.mode][uuid].TotalDPS > usedSkillBestDps then
usedSkillBestDps = GlobalCache.cachedData[env.mode][uuid].TotalDPS
EffectiveSourceRate = GlobalCache.cachedData[env.mode][uuid].Speed
return GlobalCache.cachedData[env.mode][uuid].ActiveSkill
end
end
end
Expand Down
10 changes: 4 additions & 6 deletions src/Modules/CalcPerform.lua
Original file line number Diff line number Diff line change
Expand Up @@ -925,12 +925,10 @@ end
-- 8. Processes buffs and debuffs
-- 9. Processes charges and misc buffs (doActorCharges, doActorMisc)
-- 10. Calculates defence and offence stats (calcs.defence, calcs.offence)
function calcs.perform(env, fullDPSSkipEHP)
function calcs.perform(env, skipEHP)
local modDB = env.modDB
local enemyDB = env.enemyDB

local fullDPSSkipEHP = fullDPSSkipEHP or false

-- Merge keystone modifiers
env.keystonesAdded = { }
mergeKeystones(env)
Expand All @@ -952,7 +950,7 @@ function calcs.perform(env, fullDPSSkipEHP)

env.partyMembers = env.build.partyTab.actor
env.player.partyMembers = env.partyMembers
local partyTabEnableExportBuffs = env.build.partyTab.enableExportBuffs
local partyTabEnableExportBuffs = env.build.partyTab.enableExportBuffs and env.mode ~= "CALCULATOR"

env.minion = env.player.mainSkill.minion
if env.minion then
Expand Down Expand Up @@ -3010,7 +3008,7 @@ function calcs.perform(env, fullDPSSkipEHP)

-- Defence/offence calculations
calcs.defence(env, env.player)
if not fullDPSSkipEHP then
if not skipEHP then
calcs.buildDefenceEstimations(env, env.player)
end

Expand All @@ -3021,7 +3019,7 @@ function calcs.perform(env, fullDPSSkipEHP)

if env.minion then
calcs.defence(env, env.minion)
if not fullDPSSkipEHP then -- main.build.calcsTab.input.showMinion and -- should be disabled unless "calcsTab.input.showMinion" is true
if not skipEHP then -- main.build.calcsTab.input.showMinion and -- should be disabled unless "calcsTab.input.showMinion" is true
calcs.buildDefenceEstimations(env, env.minion)
end
calcs.triggers(env, env.minion)
Expand Down
62 changes: 30 additions & 32 deletions src/Modules/CalcTriggers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ end
-- Identify the trigger action skill for trigger conditions, take highest Attack Per Second
local function findTriggerSkill(env, skill, source, triggerRate, comparer)
local comparer = comparer or function(uuid, source, triggerRate)
local cachedSpeed = GlobalCache.cachedData["CACHE"][uuid].HitSpeed or GlobalCache.cachedData["CACHE"][uuid].Speed
local cachedSpeed = GlobalCache.cachedData[env.mode][uuid].HitSpeed or GlobalCache.cachedData[env.mode][uuid].Speed
return (not source and cachedSpeed) or (cachedSpeed and cachedSpeed > (triggerRate or 0))
end

local uuid = cacheSkillUUID(skill, env)
if not GlobalCache.cachedData["CACHE"][uuid] or GlobalCache.noCache then
calcs.buildActiveSkill(env, "CACHE", skill)
if not GlobalCache.cachedData[env.mode][uuid] or env.mode == "CALCULATOR" then
calcs.buildActiveSkill(env, env.mode, skill)
end

if GlobalCache.cachedData["CACHE"][uuid] and comparer(uuid, source, triggerRate) and (skill.skillFlags and not skill.skillFlags.disable) and (skill.skillCfg and not skill.skillCfg.skillCond["usedByMirage"]) and not skill.skillTypes[SkillType.OtherThingUsesSkill] then
return skill, GlobalCache.cachedData["CACHE"][uuid].HitSpeed or GlobalCache.cachedData["CACHE"][uuid].Speed, uuid
if GlobalCache.cachedData[env.mode][uuid] and comparer(uuid, source, triggerRate) and (skill.skillFlags and not skill.skillFlags.disable) and (skill.skillCfg and not skill.skillCfg.skillCond["usedByMirage"]) and not skill.skillTypes[SkillType.OtherThingUsesSkill] then
return skill, GlobalCache.cachedData[env.mode][uuid].HitSpeed or GlobalCache.cachedData[env.mode][uuid].Speed, uuid
end
return source, triggerRate, source and cacheSkillUUID(source, env)
end
Expand Down Expand Up @@ -460,8 +460,8 @@ local function defaultTriggerHandler(env, config)
actor.mainSkill.skillData.ignoresTickRate = actor.mainSkill.skillData.ignoresTickRate or (actor.mainSkill.skillData.storedUses and actor.mainSkill.skillData.storedUses > 1)

--Account for source unleash
if source and GlobalCache.cachedData["CACHE"][uuid] and source.skillModList:Flag(nil, "HasSeals") and source.skillTypes[SkillType.CanRapidFire] then
local unleashDpsMult = GlobalCache.cachedData["CACHE"][uuid].ActiveSkill.skillData.dpsMultiplier or 1
if source and GlobalCache.cachedData[env.mode][uuid] and source.skillModList:Flag(nil, "HasSeals") and source.skillTypes[SkillType.CanRapidFire] then
local unleashDpsMult = GlobalCache.cachedData[env.mode][uuid].ActiveSkill.skillData.dpsMultiplier or 1
trigRate = trigRate * unleashDpsMult
actor.mainSkill.skillFlags.HasSeals = true
actor.mainSkill.skillData.ignoresTickRate = true
Expand All @@ -471,44 +471,44 @@ local function defaultTriggerHandler(env, config)
end

-- Battlemage's Cry uptime
if actor.mainSkill.skillData.triggeredByBattleMageCry and GlobalCache.cachedData["CACHE"][uuid] and source and source.skillTypes[SkillType.Melee] then
local battleMageUptime = GlobalCache.cachedData["CACHE"][uuid].Env.player.output.BattlemageUpTimeRatio or 100
if actor.mainSkill.skillData.triggeredByBattleMageCry and GlobalCache.cachedData[env.mode][uuid] and source and source.skillTypes[SkillType.Melee] then
local battleMageUptime = GlobalCache.cachedData[env.mode][uuid].Env.player.output.BattlemageUpTimeRatio or 100
trigRate = trigRate * battleMageUptime / 100
if breakdown then
t_insert(breakdown.EffectiveSourceRate, s_format("x %d%% ^8(Battlemage's Cry uptime)", battleMageUptime))
end
end

-- Infernal Cry uptime
if actor.mainSkill.activeEffect.grantedEffect.name == "Combust" and GlobalCache.cachedData["CACHE"][uuid] and source and source.skillTypes[SkillType.Melee] then
local InfernalUpTime = GlobalCache.cachedData["CACHE"][uuid].Env.player.output.InfernalUpTimeRatio or 100
if actor.mainSkill.activeEffect.grantedEffect.name == "Combust" and GlobalCache.cachedData[env.mode][uuid] and source and source.skillTypes[SkillType.Melee] then
local InfernalUpTime = GlobalCache.cachedData[env.mode][uuid].Env.player.output.InfernalUpTimeRatio or 100
trigRate = trigRate * InfernalUpTime / 100
if breakdown then
t_insert(breakdown.EffectiveSourceRate, s_format("x %d%% ^8(Infernal Cry uptime)", InfernalUpTime))
end
end

--Account for skills that can hit multiple times per use
if source and GlobalCache.cachedData["CACHE"][uuid] and source.skillPartName and source.skillPartName:match("(.*)All(.*)Projectiles(.*)") and source.skillFlags.projectile then
local multiHitDpsMult = GlobalCache.cachedData["CACHE"][uuid].Env.player.output.ProjectileCount or 1
if source and GlobalCache.cachedData[env.mode][uuid] and source.skillPartName and source.skillPartName:match("(.*)All(.*)Projectiles(.*)") and source.skillFlags.projectile then
local multiHitDpsMult = GlobalCache.cachedData[env.mode][uuid].Env.player.output.ProjectileCount or 1
trigRate = trigRate * multiHitDpsMult
if breakdown then
t_insert(breakdown.EffectiveSourceRate, s_format("x %.2f ^8(%d projectiles hit)", multiHitDpsMult, multiHitDpsMult))
end
end

--Accuracy and crit chance
if source and (source.skillTypes[SkillType.Melee] or source.skillTypes[SkillType.Attack]) and GlobalCache.cachedData["CACHE"][uuid] and not config.triggerOnUse then
local sourceHitChance = GlobalCache.cachedData["CACHE"][uuid].HitChance
if source and (source.skillTypes[SkillType.Melee] or source.skillTypes[SkillType.Attack]) and GlobalCache.cachedData[env.mode][uuid] and not config.triggerOnUse then
local sourceHitChance = GlobalCache.cachedData[env.mode][uuid].HitChance
trigRate = trigRate * (sourceHitChance or 0) / 100
if breakdown then
t_insert(breakdown.EffectiveSourceRate, s_format("x %.0f%% ^8(%s hit chance)", sourceHitChance, source.activeEffect.grantedEffect.name))
end
if actor.mainSkill.skillData.triggerOnCrit then
local onCritChance = actor.mainSkill.skillData.chanceToTriggerOnCrit or (GlobalCache.cachedData["CACHE"][uuid] and GlobalCache.cachedData["CACHE"][uuid].Env.player.mainSkill.skillData.chanceToTriggerOnCrit)
local onCritChance = actor.mainSkill.skillData.chanceToTriggerOnCrit or (GlobalCache.cachedData[env.mode][uuid] and GlobalCache.cachedData[env.mode][uuid].Env.player.mainSkill.skillData.chanceToTriggerOnCrit)
config.triggerChance = config.triggerChance or actor.mainSkill.skillData.chanceToTriggerOnCrit or onCritChance

local sourceCritChance = GlobalCache.cachedData["CACHE"][uuid].CritChance
local sourceCritChance = GlobalCache.cachedData[env.mode][uuid].CritChance
trigRate = trigRate * (sourceCritChance or 0) / 100
if breakdown then
t_insert(breakdown.EffectiveSourceRate, s_format("x %.2f%% ^8(%s effective crit chance)", sourceCritChance, source.activeEffect.grantedEffect.name))
Expand All @@ -528,15 +528,14 @@ local function defaultTriggerHandler(env, config)

-- Handling for mana spending rate for Manaforged Arrows Support
if actor.mainSkill.skillData.triggeredByManaforged and trigRate > 0 then
local mode = env.mode == "CALCS" and "CALCS" or "MAIN"
local triggeredUUID = cacheSkillUUID(actor.mainSkill, env)
if not GlobalCache.cachedData[mode][triggeredUUID] then
calcs.buildActiveSkill(env, mode, actor.mainSkill, {[triggeredUUID] = true})
if not GlobalCache.cachedData[env.mode][triggeredUUID] then
calcs.buildActiveSkill(env, env.mode, actor.mainSkill, {[triggeredUUID] = true})
end
local triggeredManaCost = GlobalCache.cachedData[mode][triggeredUUID].Env.player.output.ManaCost or 0
local triggeredManaCost = GlobalCache.cachedData[env.mode][triggeredUUID].Env.player.output.ManaCost or 0
if triggeredManaCost > 0 then
local manaSpentThreshold = triggeredManaCost * actor.mainSkill.skillData.ManaForgedArrowsPercentThreshold
local sourceManaCost = GlobalCache.cachedData["CACHE"][uuid].Env.player.output.ManaCost or 0
local sourceManaCost = GlobalCache.cachedData[env.mode][uuid].Env.player.output.ManaCost or 0
if sourceManaCost > 0 then
if breakdown then
t_insert(breakdown.EffectiveSourceRate, s_format("* %.2f ^8(Mana cost of trigger source)", sourceManaCost))
Expand Down Expand Up @@ -599,9 +598,9 @@ local function defaultTriggerHandler(env, config)
output.TriggerRateCap = 1 / actionCooldownTickRounded
end
if config.triggerName == "Doom Blast" and env.build.configTab.input["doomBlastSource"] == "expiration" then
local expirationRate = 1 / GlobalCache.cachedData["CACHE"][uuid].Env.player.output.Duration
local expirationRate = 1 / GlobalCache.cachedData[env.mode][uuid].Env.player.output.Duration
if breakdown and breakdown.EffectiveSourceRate then
breakdown.EffectiveSourceRate[1] = s_format("1 / %.2f ^8(source curse duration)", GlobalCache.cachedData["CACHE"][uuid].Env.player.output.Duration)
breakdown.EffectiveSourceRate[1] = s_format("1 / %.2f ^8(source curse duration)", GlobalCache.cachedData[env.mode][uuid].Env.player.output.Duration)
end
if expirationRate > trigRate then
env.player.modDB:NewMod("UsesCurseOverlaps", "FLAG", true, "Config")
Expand Down Expand Up @@ -1017,8 +1016,8 @@ local configTable = {
return {triggerChance = env.player.modDB:Sum("BASE", nil, "KitavaTriggerChance"),
triggerName = "Kitava's Thirst",
comparer = function(uuid, source, triggerRate)
local cachedSpeed = GlobalCache.cachedData["CACHE"][uuid].HitSpeed or GlobalCache.cachedData["CACHE"][uuid].Speed
local cachedManaCost = GlobalCache.cachedData["CACHE"][uuid].ManaCost
local cachedSpeed = GlobalCache.cachedData[env.mode][uuid].HitSpeed or GlobalCache.cachedData[env.mode][uuid].Speed
local cachedManaCost = GlobalCache.cachedData[env.mode][uuid].ManaCost
return ( (not source and cachedSpeed) or (cachedSpeed and cachedSpeed > (triggerRate or 0)) ) and ( (cachedManaCost or 0) > requiredManaCost )
end,
triggerSkillCond = function(env, skill)
Expand Down Expand Up @@ -1234,20 +1233,19 @@ local configTable = {
if currentSkillSnipeIndex and currentSkillSnipeIndex <= snipeStages then
local source
local trigRate
local mode = env.mode == "CALCS" and "CALCS" or "MAIN"
env.player.mainSkill.skillModList:NewMod("Damage", "MORE", snipeHitMulti * snipeStages , "Snipe", ModFlag.Hit, 0)
env.player.mainSkill.skillModList:NewMod("Damage", "MORE", snipeAilmentMulti * snipeStages , "Snipe", ModFlag.Ailment, 0)
for _, skill in ipairs(env.player.activeSkillList) do
if skill.activeEffect.grantedEffect.name == "Snipe" and skill.socketGroup and skill.socketGroup.slot == env.player.mainSkill.socketGroup.slot then
skill.skillData.hitTimeMultiplier = snipeStages - 0.5
local uuid = cacheSkillUUID(skill, env)
if not GlobalCache.cachedData[mode][uuid] or GlobalCache.noCache then
calcs.buildActiveSkill(env, mode, skill)
if not GlobalCache.cachedData[env.mode][uuid] or env.mode == "CALCULATOR" then
calcs.buildActiveSkill(env, env.mode, skill)
end
local cachedSpeed = GlobalCache.cachedData[mode][uuid].Env.player.output.HitSpeed
local cachedSpeed = GlobalCache.cachedData[env.mode][uuid].Env.player.output.HitSpeed
if (skill.skillFlags and not skill.skillFlags.disable) and (skill.skillCfg and not skill.skillCfg.skillCond["usedByMirage"]) and not skill.skillTypes[SkillType.OtherThingUsesSkill] and ((not source and cachedSpeed) or (cachedSpeed and cachedSpeed > (trigRate or 0))) then
trigRate = cachedSpeed
env.player.output.ChannelTimeToTrigger = GlobalCache.cachedData[mode][uuid].Env.player.output.HitTime
env.player.output.ChannelTimeToTrigger = GlobalCache.cachedData[env.mode][uuid].Env.player.output.HitTime
source = skill
end
end
Expand All @@ -1265,7 +1263,7 @@ local configTable = {
["avenging flame"] = function(env)
return {triggerSkillCond = function(env, skill) return skill.skillFlags.totem and slotMatch(env, skill) end,
comparer = function(uuid, source, currentTotemLife)
local totemLife = GlobalCache.cachedData["CACHE"][uuid].Env.player.output.TotemLife
local totemLife = GlobalCache.cachedData[env.mode][uuid].Env.player.output.TotemLife
return (not source and totemLife) or (totemLife and totemLife > (currentTotemLife or 0))
end,
ignoreSourceRate = true}
Expand Down
Loading
Loading