From 04aa69a9ee8ee1cdd2d95da97148312258e1199b Mon Sep 17 00:00:00 2001 From: EtherealCarnivore <42915554+EtherealCarnivore@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:29:35 +0200 Subject: [PATCH 1/3] Rename Otherworldly Appendages to Cryogenesis, add new stats 3.28 replaces the old graft damage reduction stats with: - Int single highest attribute: all added damage treated as Lightning - Dex single highest attribute: all added damage treated as Cold Updated tree data (all 4 variants), added ModParser entries, single-highest-attribute conditions in CalcPerform, and flat added damage redirection in CalcOffence. --- src/Modules/CalcOffence.lua | 25 +++++++++++++++++-- src/Modules/CalcPerform.lua | 4 +++ src/Modules/ModParser.lua | 6 +++++ src/TreeData/3_27/tree.lua | 9 +++---- src/TreeData/3_27_alternate/tree.lua | 9 +++---- src/TreeData/3_27_ruthless/tree.lua | 9 +++---- src/TreeData/3_27_ruthless_alternate/tree.lua | 9 +++---- 7 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index c89a4200fd..157399ab62 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -3047,14 +3047,35 @@ function calcs.offence(env, actor, activeSkill) runSkillFunc("postCritFunc") + -- Check for added damage redirection (Cryogenesis) + local addedDamageRedirectType = nil + if skillModList:Flag(cfg, "AllAddedDamageAsLightning") then + addedDamageRedirectType = "Lightning" + elseif skillModList:Flag(cfg, "AllAddedDamageAsCold") then + addedDamageRedirectType = "Cold" + end + -- Calculate base hit damage for _, damageType in ipairs(dmgTypeList) do local damageTypeMin = damageType.."Min" local damageTypeMax = damageType.."Max" local baseMultiplier = activeSkill.activeEffect.grantedEffectLevel.baseMultiplier or skillData.baseMultiplier or 1 local damageEffectiveness = activeSkill.activeEffect.grantedEffectLevel.damageEffectiveness or skillData.damageEffectiveness or 1 - local addedMin = skillModList:Sum("BASE", cfg, damageTypeMin) + enemyDB:Sum("BASE", cfg, "Self"..damageTypeMin) - local addedMax = skillModList:Sum("BASE", cfg, damageTypeMax) + enemyDB:Sum("BASE", cfg, "Self"..damageTypeMax) + local addedMin, addedMax + if addedDamageRedirectType then + if damageType == addedDamageRedirectType then + addedMin, addedMax = 0, 0 + for _, srcType in ipairs(dmgTypeList) do + addedMin = addedMin + skillModList:Sum("BASE", cfg, srcType.."Min") + enemyDB:Sum("BASE", cfg, "Self"..srcType.."Min") + addedMax = addedMax + skillModList:Sum("BASE", cfg, srcType.."Max") + enemyDB:Sum("BASE", cfg, "Self"..srcType.."Max") + end + else + addedMin, addedMax = 0, 0 + end + else + addedMin = skillModList:Sum("BASE", cfg, damageTypeMin) + enemyDB:Sum("BASE", cfg, "Self"..damageTypeMin) + addedMax = skillModList:Sum("BASE", cfg, damageTypeMax) + enemyDB:Sum("BASE", cfg, "Self"..damageTypeMax) + end local addedMult = calcLib.mod(skillModList, cfg, "Added"..damageType.."Damage", "AddedDamage") local baseMin = ((source[damageTypeMin] or 0) + (source[damageType.."BonusMin"] or 0)) * baseMultiplier + addedMin * damageEffectiveness * addedMult local baseMax = ((source[damageTypeMax] or 0) + (source[damageType.."BonusMax"] or 0)) * baseMultiplier + addedMax * damageEffectiveness * addedMult diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 05b2d161b5..a4a7745fd1 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -395,6 +395,8 @@ local function doActorAttribsConditions(env, actor) condList["StrHighestAttribute"] = output.Str >= output.Dex and output.Str >= output.Int condList["IntHighestAttribute"] = output.Int >= output.Str and output.Int >= output.Dex condList["DexHighestAttribute"] = output.Dex >= output.Str and output.Dex >= output.Int + condList["IntSingleHighestAttribute"] = output.Int > output.Str and output.Int > output.Dex + condList["DexSingleHighestAttribute"] = output.Dex > output.Str and output.Dex > output.Int end end @@ -457,6 +459,8 @@ local function doActorAttribsConditions(env, actor) condList["StrHighestAttribute"] = output.Str >= output.Dex and output.Str >= output.Int condList["IntHighestAttribute"] = output.Int >= output.Str and output.Int >= output.Dex condList["DexHighestAttribute"] = output.Dex >= output.Str and output.Dex >= output.Int + condList["IntSingleHighestAttribute"] = output.Int > output.Str and output.Int > output.Dex + condList["DexSingleHighestAttribute"] = output.Dex > output.Str and output.Dex > output.Int end end diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index fd91130b3e..16062c62f1 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -5258,6 +5258,12 @@ local specialModList = { ["consecrated path and purifying flame create profane ground instead of consecrated ground"] = { flag("Condition:CreateProfaneGround"), }, + ["if intelligence is your single highest attribute, all added damage is treated as added lightning damage"] = { + flag("AllAddedDamageAsLightning", { type = "Condition", var = "IntSingleHighestAttribute" }), + }, + ["if dexterity is your single highest attribute, all added damage is treated as added cold damage"] = { + flag("AllAddedDamageAsCold", { type = "Condition", var = "DexSingleHighestAttribute" }), + }, ["you have consecrated ground around you while stationary if strength is your highest attribute"] = { flag("Condition:OnConsecratedGround", { type = "Condition", var = "StrHighestAttribute" }, { type = "Condition", var = "Stationary" }), }, diff --git a/src/TreeData/3_27/tree.lua b/src/TreeData/3_27/tree.lua index 6f3f9332e3..e9216e971e 100644 --- a/src/TreeData/3_27/tree.lua +++ b/src/TreeData/3_27/tree.lua @@ -14450,17 +14450,14 @@ return { }, [52855]= { ["skill"]= 52855, - ["name"]= "Otherworldly Appendages", + ["name"]= "Cryogenesis", ["icon"]= "Art/2DArt/SkillIcons/passives/AtlasTrees/BreachNotable4.png", ["isNotable"]= true, ["ascendancyName"]= "Breachlord", ["isBloodline"]= true, ["stats"]= { - "Take 15% less Lightning Damage with at least one Eshgraft grafted to you", - "Take 15% less Cold Damage with at least one Tulgraft grafted to you", - "Take 15% less Physical Damage with at least one Uulgraft grafted to you", - "Take 15% less Fire Damage with at least one Xophgraft grafted to you", - "Nearby Enemies take 100% increased Damage from Graft Skills" + "If Intelligence is your single highest Attribute, all added Damage is treated as added Lightning Damage", + "If Dexterity is your single highest Attribute, all added Damage is treated as added Cold Damage" }, ["group"]= 26, ["orbit"]= 3, diff --git a/src/TreeData/3_27_alternate/tree.lua b/src/TreeData/3_27_alternate/tree.lua index 3589c96d75..7f8d2335d8 100644 --- a/src/TreeData/3_27_alternate/tree.lua +++ b/src/TreeData/3_27_alternate/tree.lua @@ -15057,17 +15057,14 @@ return { }, [52855]= { ["skill"]= 52855, - ["name"]= "Otherworldly Appendages", + ["name"]= "Cryogenesis", ["icon"]= "Art/2DArt/SkillIcons/passives/AtlasTrees/BreachNotable4.png", ["isNotable"]= true, ["ascendancyName"]= "Breachlord", ["isBloodline"]= true, ["stats"]= { - "Take 15% less Lightning Damage with at least one Eshgraft grafted to you", - "Take 15% less Cold Damage with at least one Tulgraft grafted to you", - "Take 15% less Physical Damage with at least one Uulgraft grafted to you", - "Take 15% less Fire Damage with at least one Xophgraft grafted to you", - "Nearby Enemies take 100% increased Damage from Graft Skills" + "If Intelligence is your single highest Attribute, all added Damage is treated as added Lightning Damage", + "If Dexterity is your single highest Attribute, all added Damage is treated as added Cold Damage" }, ["group"]= 31, ["orbit"]= 3, diff --git a/src/TreeData/3_27_ruthless/tree.lua b/src/TreeData/3_27_ruthless/tree.lua index 6ea05e0d86..b8b41268d6 100644 --- a/src/TreeData/3_27_ruthless/tree.lua +++ b/src/TreeData/3_27_ruthless/tree.lua @@ -14438,17 +14438,14 @@ return { }, [52855]= { ["skill"]= 52855, - ["name"]= "Otherworldly Appendages", + ["name"]= "Cryogenesis", ["icon"]= "Art/2DArt/SkillIcons/passives/AtlasTrees/BreachNotable4.png", ["isNotable"]= true, ["ascendancyName"]= "Breachlord", ["isBloodline"]= true, ["stats"]= { - "Take 15% less Lightning Damage with at least one Eshgraft grafted to you", - "Take 15% less Cold Damage with at least one Tulgraft grafted to you", - "Take 15% less Physical Damage with at least one Uulgraft grafted to you", - "Take 15% less Fire Damage with at least one Xophgraft grafted to you", - "Nearby Enemies take 100% increased Damage from Graft Skills" + "If Intelligence is your single highest Attribute, all added Damage is treated as added Lightning Damage", + "If Dexterity is your single highest Attribute, all added Damage is treated as added Cold Damage" }, ["group"]= 26, ["orbit"]= 3, diff --git a/src/TreeData/3_27_ruthless_alternate/tree.lua b/src/TreeData/3_27_ruthless_alternate/tree.lua index 1d126324c5..42a4b7938f 100644 --- a/src/TreeData/3_27_ruthless_alternate/tree.lua +++ b/src/TreeData/3_27_ruthless_alternate/tree.lua @@ -15058,17 +15058,14 @@ return { }, [52855]= { ["skill"]= 52855, - ["name"]= "Otherworldly Appendages", + ["name"]= "Cryogenesis", ["icon"]= "Art/2DArt/SkillIcons/passives/AtlasTrees/BreachNotable4.png", ["isNotable"]= true, ["ascendancyName"]= "Breachlord", ["isBloodline"]= true, ["stats"]= { - "Take 15% less Lightning Damage with at least one Eshgraft grafted to you", - "Take 15% less Cold Damage with at least one Tulgraft grafted to you", - "Take 15% less Physical Damage with at least one Uulgraft grafted to you", - "Take 15% less Fire Damage with at least one Xophgraft grafted to you", - "Nearby Enemies take 100% increased Damage from Graft Skills" + "If Intelligence is your single highest Attribute, all added Damage is treated as added Lightning Damage", + "If Dexterity is your single highest Attribute, all added Damage is treated as added Cold Damage" }, ["group"]= 31, ["orbit"]= 3, From 377d6579de91eb04ba5bf5b456823900810979dc Mon Sep 17 00:00:00 2001 From: LocalIdentity Date: Fri, 6 Mar 2026 06:18:34 +1100 Subject: [PATCH 2/3] Revert tree changes --- src/TreeData/3_27/tree.lua | 9 ++++++--- src/TreeData/3_27_alternate/tree.lua | 9 ++++++--- src/TreeData/3_27_ruthless/tree.lua | 9 ++++++--- src/TreeData/3_27_ruthless_alternate/tree.lua | 9 ++++++--- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/TreeData/3_27/tree.lua b/src/TreeData/3_27/tree.lua index e9216e971e..6f3f9332e3 100644 --- a/src/TreeData/3_27/tree.lua +++ b/src/TreeData/3_27/tree.lua @@ -14450,14 +14450,17 @@ return { }, [52855]= { ["skill"]= 52855, - ["name"]= "Cryogenesis", + ["name"]= "Otherworldly Appendages", ["icon"]= "Art/2DArt/SkillIcons/passives/AtlasTrees/BreachNotable4.png", ["isNotable"]= true, ["ascendancyName"]= "Breachlord", ["isBloodline"]= true, ["stats"]= { - "If Intelligence is your single highest Attribute, all added Damage is treated as added Lightning Damage", - "If Dexterity is your single highest Attribute, all added Damage is treated as added Cold Damage" + "Take 15% less Lightning Damage with at least one Eshgraft grafted to you", + "Take 15% less Cold Damage with at least one Tulgraft grafted to you", + "Take 15% less Physical Damage with at least one Uulgraft grafted to you", + "Take 15% less Fire Damage with at least one Xophgraft grafted to you", + "Nearby Enemies take 100% increased Damage from Graft Skills" }, ["group"]= 26, ["orbit"]= 3, diff --git a/src/TreeData/3_27_alternate/tree.lua b/src/TreeData/3_27_alternate/tree.lua index 7f8d2335d8..3589c96d75 100644 --- a/src/TreeData/3_27_alternate/tree.lua +++ b/src/TreeData/3_27_alternate/tree.lua @@ -15057,14 +15057,17 @@ return { }, [52855]= { ["skill"]= 52855, - ["name"]= "Cryogenesis", + ["name"]= "Otherworldly Appendages", ["icon"]= "Art/2DArt/SkillIcons/passives/AtlasTrees/BreachNotable4.png", ["isNotable"]= true, ["ascendancyName"]= "Breachlord", ["isBloodline"]= true, ["stats"]= { - "If Intelligence is your single highest Attribute, all added Damage is treated as added Lightning Damage", - "If Dexterity is your single highest Attribute, all added Damage is treated as added Cold Damage" + "Take 15% less Lightning Damage with at least one Eshgraft grafted to you", + "Take 15% less Cold Damage with at least one Tulgraft grafted to you", + "Take 15% less Physical Damage with at least one Uulgraft grafted to you", + "Take 15% less Fire Damage with at least one Xophgraft grafted to you", + "Nearby Enemies take 100% increased Damage from Graft Skills" }, ["group"]= 31, ["orbit"]= 3, diff --git a/src/TreeData/3_27_ruthless/tree.lua b/src/TreeData/3_27_ruthless/tree.lua index b8b41268d6..6ea05e0d86 100644 --- a/src/TreeData/3_27_ruthless/tree.lua +++ b/src/TreeData/3_27_ruthless/tree.lua @@ -14438,14 +14438,17 @@ return { }, [52855]= { ["skill"]= 52855, - ["name"]= "Cryogenesis", + ["name"]= "Otherworldly Appendages", ["icon"]= "Art/2DArt/SkillIcons/passives/AtlasTrees/BreachNotable4.png", ["isNotable"]= true, ["ascendancyName"]= "Breachlord", ["isBloodline"]= true, ["stats"]= { - "If Intelligence is your single highest Attribute, all added Damage is treated as added Lightning Damage", - "If Dexterity is your single highest Attribute, all added Damage is treated as added Cold Damage" + "Take 15% less Lightning Damage with at least one Eshgraft grafted to you", + "Take 15% less Cold Damage with at least one Tulgraft grafted to you", + "Take 15% less Physical Damage with at least one Uulgraft grafted to you", + "Take 15% less Fire Damage with at least one Xophgraft grafted to you", + "Nearby Enemies take 100% increased Damage from Graft Skills" }, ["group"]= 26, ["orbit"]= 3, diff --git a/src/TreeData/3_27_ruthless_alternate/tree.lua b/src/TreeData/3_27_ruthless_alternate/tree.lua index 42a4b7938f..1d126324c5 100644 --- a/src/TreeData/3_27_ruthless_alternate/tree.lua +++ b/src/TreeData/3_27_ruthless_alternate/tree.lua @@ -15058,14 +15058,17 @@ return { }, [52855]= { ["skill"]= 52855, - ["name"]= "Cryogenesis", + ["name"]= "Otherworldly Appendages", ["icon"]= "Art/2DArt/SkillIcons/passives/AtlasTrees/BreachNotable4.png", ["isNotable"]= true, ["ascendancyName"]= "Breachlord", ["isBloodline"]= true, ["stats"]= { - "If Intelligence is your single highest Attribute, all added Damage is treated as added Lightning Damage", - "If Dexterity is your single highest Attribute, all added Damage is treated as added Cold Damage" + "Take 15% less Lightning Damage with at least one Eshgraft grafted to you", + "Take 15% less Cold Damage with at least one Tulgraft grafted to you", + "Take 15% less Physical Damage with at least one Uulgraft grafted to you", + "Take 15% less Fire Damage with at least one Xophgraft grafted to you", + "Nearby Enemies take 100% increased Damage from Graft Skills" }, ["group"]= 31, ["orbit"]= 3, From 2289e9fe3a17dfedf58aa4e2132d6efeff7dd93d Mon Sep 17 00:00:00 2001 From: EtherealCarnivore <42915554+EtherealCarnivore@users.noreply.github.com> Date: Thu, 5 Mar 2026 23:52:50 +0200 Subject: [PATCH 3/3] Add ConvertMod to ModStore/ModList/ModDB Like ReplaceMod but matches by oldName instead of the new mod's name, so it can change a mod's identity (e.g. FireMin -> ColdMin) rather than just updating its value. ModDB moves the mod between name buckets. --- src/Classes/ModDB.lua | 40 ++++++++++++++++++++++++++++++++++++++++ src/Classes/ModList.lua | 21 +++++++++++++++++++++ src/Classes/ModStore.lua | 13 +++++++++++++ 3 files changed, 74 insertions(+) diff --git a/src/Classes/ModDB.lua b/src/Classes/ModDB.lua index f60ac59e49..3b7ae60922 100644 --- a/src/Classes/ModDB.lua +++ b/src/Classes/ModDB.lua @@ -7,6 +7,7 @@ local ipairs = ipairs local pairs = pairs local select = select local t_insert = table.insert +local t_remove = table.remove local m_floor = math.floor local m_min = math.min local m_max = math.max @@ -65,6 +66,45 @@ function ModDBClass:ReplaceModInternal(mod) return false end +---ConvertModInternal +--- Converts an existing mod with oldName to a new mod with a different name. +--- Moves the mod from the old name's bucket to the new name's bucket. +--- If no matching mod exists, then the function returns false +---@param oldName string @The name of the existing mod to find +---@param mod table @The new mod to replace it with +---@return boolean @Whether any mod was converted +function ModDBClass:ConvertModInternal(oldName, mod) + if not self.mods[oldName] then + if self.parent then + return self.parent:ConvertModInternal(oldName, mod) + end + return false + end + + local oldList = self.mods[oldName] + for i = 1, #oldList do + local curMod = oldList[i] + if oldName == curMod.name and mod.type == curMod.type and mod.flags == curMod.flags and mod.keywordFlags == curMod.keywordFlags and mod.source == curMod.source and not curMod.converted then + -- Remove from old name's bucket + t_remove(oldList, i) + -- Add to new name's bucket + local newName = mod.name + if not self.mods[newName] then + self.mods[newName] = { } + end + mod.converted = true + t_insert(self.mods[newName], mod) + return true + end + end + + if self.parent then + return self.parent:ConvertModInternal(oldName, mod) + end + + return false +end + function ModDBClass:AddList(modList) local mods = self.mods for i, mod in ipairs(modList) do diff --git a/src/Classes/ModList.lua b/src/Classes/ModList.lua index b27393279a..7bb6e2aba8 100644 --- a/src/Classes/ModList.lua +++ b/src/Classes/ModList.lua @@ -45,6 +45,27 @@ function ModListClass:ReplaceModInternal(mod) return false end +---ConvertModInternal +--- Converts an existing mod with oldName to a new mod with a different name. +--- If no matching mod exists, then the function returns false +---@param oldName string @The name of the existing mod to find +---@param mod table @The new mod to replace it with +---@return boolean @Whether any mod was converted +function ModListClass:ConvertModInternal(oldName, mod) + for i, curMod in ipairs(self) do + if oldName == curMod.name and mod.type == curMod.type and mod.flags == curMod.flags and mod.keywordFlags == curMod.keywordFlags and mod.source == curMod.source then + self[i] = mod + return true + end + end + + if self.parent then + return self.parent:ConvertModInternal(oldName, mod) + end + + return false +end + function ModListClass:MergeMod(mod, skipNonAdditive) if mod.type == "BASE" or mod.type == "INC" or mod.type == "MORE" then for i = 1, #self do diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index ff0130c481..ec61927e90 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -110,6 +110,19 @@ function ModStoreClass:ReplaceMod(...) end end +---ConvertMod +--- Converts an existing mod to a new name, replacing it in the store. +--- Finds a mod matching oldName with the same type, flags, keywordFlags, and source as the new mod. +--- If no matching mod exists, the new mod is added instead. +---@param oldName string @The name of the existing mod to convert +---@param ... any @Parameters to be passed along to the modLib.createMod function (new name, type, value, source, ...) +function ModStoreClass:ConvertMod(oldName, ...) + local mod = mod_createMod(...) + if not self:ConvertModInternal(oldName, mod) then + self:AddMod(mod) + end +end + function ModStoreClass:Combine(modType, cfg, ...) if modType == "MORE" then return self:More(cfg, ...)