From ef8ba51e26837997387a350da3cecef1618b1184 Mon Sep 17 00:00:00 2001 From: unrealdreamz Date: Fri, 22 May 2026 15:21:29 +0000 Subject: [PATCH] Apply changes from https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2/pull/1929 --- spec/Fixtures/issue1754_block_ehp.xml | 796 +++++++++++++++++++++++++ spec/System/TestDefence_spec.lua | 64 ++ spec/System/TestDefence_spec.lua.rej | 28 + spec/System/TestItemParse_spec.lua.rej | 24 + src/Data/ModCache.lua.rej | 89 +++ src/Modules/CalcDefence.lua | 1 + src/Modules/CalcDefence.lua.rej | 31 + 7 files changed, 1033 insertions(+) create mode 100644 spec/Fixtures/issue1754_block_ehp.xml create mode 100644 spec/System/TestDefence_spec.lua.rej create mode 100644 spec/System/TestItemParse_spec.lua.rej create mode 100644 src/Data/ModCache.lua.rej create mode 100644 src/Modules/CalcDefence.lua.rej diff --git a/spec/Fixtures/issue1754_block_ehp.xml b/spec/Fixtures/issue1754_block_ehp.xml new file mode 100644 index 0000000000..25f4298c63 --- /dev/null +++ b/spec/Fixtures/issue1754_block_ehp.xml @@ -0,0 +1,796 @@ + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + https://www.pathofexile.com/passive-skill-tree/AAAABgIBmLOoS-B_NJGKbCdclipOP9vFgWhlumpKQ4WadaMPYOFndqMZgWxOGXJISbq0Jhb710aZbpD4W2rtFgrJ6lMmjBfMleSg7Nq7hs48U4uSjxwyHiT562uU01NjHsudsTO7jpqu11u3nmdF0J0_KE9-axrZ-s1MlmUEsLAix7koetQKECBG7QsfgxSMu2_FO48BbNNvmSf31deWjCRhMA12mKu2W4f9CzAeKZGcBJEPlG4PJaZorn6ggqzrKw5MD232igVIcwdIxW9-r5hpyqR_wIVyi8p4aqAJuy4KlPLfbNPYZdZGT2nkKhbJabT1ZBOopqic1iLpgSEt-xzWG9ixI8v0sDtO9CIWTti2z8pBVYJZ6YnoxUKFgu7R12fIMILKFHqNgNAu4EKV9f1g5xTUs5EAAA== + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Rarity: RARE +Chimeric Sliver +Ruby +Unique ID: 3f2a054bb6d41d7fe0d14122cc3d55f5b9055285249b5bf81d740ad1d59b6136 +Item Level: 80 +LevelReq: 0 +Implicits: 0 +18% increased Armour +14% increased Attack Damage +19% increased Warcry Speed +{desecrated}2% increased Strength + + + + + + + Rarity: RARE +Loath Wound +Time-Lost Ruby +Unique ID: 79ae21e9e5c5904ecda572dff79ab1d719eac798e1d9cfb35975a9116d915bc5 +Item Level: 78 +LevelReq: 0 +Radius: Medium +Implicits: 0 +Upgrades Radius to Medium +25% increased Effect of Notable Passive Skills in Radius +25% increased Effect of Small Passive Skills in Radius + + + + + + Rarity: UNIQUE +From Nothing +Diamond +Unique ID: 60219c236ed8e1330ab16b8919afb429b870bc28c23e445c4da72a8d0b22b76c +Item Level: 84 +LevelReq: 0 +Radius: Small +Limited to: 1 +Implicits: 0 +Passives in Radius of Resolute Technique can be Allocated +without being connected to your tree +Corrupted + + + + Rarity: RARE +Ghoul Sole +Tasalian Greaves +Armour: 432 +Unique ID: 816f7b3213e27a3f552b294e0066bcb695b3c7a2075c16a000c1cd456ab4311c +Item Level: 82 +Quality: 20 +Sockets: S S +Rune: Soul Core of Tacati +Rune: Soul Core of Tacati +LevelReq: 80 +Implicits: 1 +{enchant}{rune}+22% to Chaos Resistance ++123 to Armour ++110 to maximum Life ++31% to Fire Resistance ++30% to Lightning Resistance ++32% of Armour also applies to Elemental Damage +{desecrated}35% increased Movement Speed +Corrupted + + + + + + + + + + Rarity: RARE +Torment Touch +Vaal Mitts +Armour: 485 +Unique ID: ec3d3e1408f66406a34cc183c6ffb0a87025355c3295bc90ab8be9f8d32c539e +Item Level: 79 +Quality: 20 +Sockets: S +Rune: Idol of Grold +LevelReq: 75 +Implicits: 2 +{enchant}{rune}32% increased total Power counted by Warcries +{enchant}{rune}Bonded: 32% increased Glory generation +36% increased Armour ++156 to maximum Life ++2 to Level of all Melee Skills ++42% of Armour also applies to Elemental Damage +60% increased effect of Socketed Items +{desecrated}+151 to Armour + + + + + + + + + + + Rarity: NORMAL +Evasive Leg +Unique ID: ef550b724c26f2472f48418e92bafea5c8c4a804a960cc7b09066163fba3e44e +Item Level: 99 +LevelReq: 0 +Implicits: 1 +20% increased Evasion Rating + + + + Rarity: NORMAL +Combat Arm +Unique ID: f36295e737b0e7d2e531713f8153dd41e79d029fb6591afd25302dd9f630b099 +Item Level: 99 +LevelReq: 0 +Implicits: 1 +10% increased Attack Speed + + + + Rarity: NORMAL +Guarding Arm +Unique ID: 8a1cb54bc4dfaba7a8cbdc7046e0726011a7a0424d8db8d9e9560e694079f61f +Item Level: 99 +LevelReq: 0 +Implicits: 1 +10% increased Block chance + + + + Rarity: MAGIC +Experimenter's Staunching Charm of the Bountiful +Unique ID: 7b7a2820b483555344ef9156b5dffceebb5dc44774c9109af7f472a6d9a518f8 +Item Level: 81 +Quality: 17 +LevelReq: 18 +Implicits: 1 +Used when you start Bleeding +36% increased Duration +53% increased Charges + + + + + Rarity: UNIQUE +Rite of Passage +Golden Charm +Unique ID: 897c5364a769621daab36f5fcee7e3a3264b236f7cceac264eb9f37546caf810 +Item Level: 81 +Quality: 0 +LevelReq: 50 +Implicits: 1 +Used when you kill a Rare or Unique enemy +Possessed by Spirit Of The Ox for 20 seconds on use + + + Rarity: RARE +Phoenix Bind +Plate Belt +Charm Slots: 2 +Unique ID: 430b1c0f872adfb91474657f630483dbeb06359ccc10a3de78d59f9dc469c3b4 +Item Level: 79 +LevelReq: 24 +Implicits: 2 ++121 to Armour +Has 2 Charm Slots ++142 to Armour ++169 to maximum Life ++123 to maximum Mana ++26 to Strength ++39% to Cold Resistance +{desecrated}+17% to Fire and Chaos Resistances + + + + + + + + + + + Rarity: RARE +Phoenix Pendant +Pearlescent Amulet +Unique ID: f3ab9699d86ffae4a2943e4aab99607bce30d6ae9bdb0ef28b51e1d9eab928ca +Item Level: 78 +LevelReq: 30 +Implicits: 2 +{enchant}Allocates Reinforced Barrier ++10% to all Elemental Resistances ++175 to maximum Life +9% increased maximum Life ++33 to Strength ++32% to Fire Resistance ++29% to Cold Resistance +{desecrated}34% increased Armour + + + + + + + + + + + Rarity: MAGIC +Substantial Ultimate Mana Flask of the Abundant +Unique ID: 2f3e029b0a0e34fc09b8f199f1617aab732678e3f4058ac2b4ab858a14607528 +Item Level: 80 +Quality: 10 +LevelReq: 60 +Implicits: 0 +62% increased Amount Recovered +57% increased Charges + + + + + Rarity: RARE +Onslaught Crest +Imperial Greathelm +Armour: 1269 +Unique ID: 26849265030f23ddccb3e1ddd940f30695811b039ce53ac28c6086af7ca9e2a4 +Item Level: 83 +Quality: 30 +Sockets: S +Rune: Soul Core of Tacati +LevelReq: 80 +Implicits: 1 +{enchant}{rune}+11% to Chaos Resistance ++195 to Armour +91% increased Armour ++174 to maximum Life ++29 to Strength ++29% to Cold Resistance +{desecrated}+29% of Armour also applies to Chaos Damage +Corrupted + + + + + + + + + + Rarity: MAGIC +Seething Ultimate Life Flask of the Brewer +Unique ID: 2375dec92a0147d9ea02dc37bc7f94fb4a993d0886a056c1507e2e836eea3934 +Item Level: 79 +Quality: 22 +LevelReq: 60 +Implicits: 0 +50% reduced Amount Recovered +Instant Recovery +29% reduced Charges per use + + + + + + Rarity: RARE +Armageddon Shatter +Structured Hammer +Unique ID: 0ad6ea8224a123ac010f9c13bee9c7ae415c70fd127db1c79aa110449e0eb4e5 +Item Level: 82 +Quality: 20 +Sockets: S +Rune: Farrul's Rune of the Hunt +LevelReq: 62 +Implicits: 3 +{enchant}{rune}50% increased Attack Damage against Rare or Unique Enemies +{enchant}{rune}Bonded: +1 to Level of all Attack Skills +40% chance to Daze on Hit +Adds 11 to 19 Physical Damage +96% increased Elemental Damage with Attacks ++5 to Level of all Melee Skills ++26 to Strength +Gain 20% of Damage as Extra Physical Damage +{desecrated}Break Armour equal to 4% of Physical Damage dealt + + + + + + + + + + + Rarity: RARE +Carrion Span +Tawhoan Tower Shield +Armour: 1215 +Unique ID: 2957b34aa214fbdc6d0b652646718c039598d898641ffb48e728d0266aa3343f +Item Level: 80 +Quality: 20 +Sockets: S S +Rune: Greater Iron Rune +Rune: Greater Iron Rune +LevelReq: 80 +Implicits: 4 +{enchant}{rune}36% increased Armour, Evasion and Energy Shield +{enchant}{rune}Bonded: +20 to maximum Life +{enchant}{rune}Bonded: +20 to maximum Mana +Grants Skill: Raise Shield ++253 to Armour +89% increased Armour ++185 to maximum Life ++31 to Strength +8% additional Physical Damage Reduction ++28% to Cold Resistance +Corrupted + + + + + + + + + + + + + Rarity: MAGIC +Experimenter's Grounding Charm of the Ample +Unique ID: 4a9b1924da5c16f078735bbea50effa0b1a2ed71596e0ddf13ead3596c58fc35 +Item Level: 81 +Quality: 0 +LevelReq: 32 +Implicits: 1 +Used when you become Shocked +38% increased Duration +69% increased Charges + + + + + Rarity: RARE +Demon Grip +Amethyst Ring +Unique ID: 3a9a4bc4c6c7bf6c851d9e3465e170235570e40f8d701c4bbd68eb17f54bc0e1 +Item Level: 80 +LevelReq: 20 +Implicits: 1 ++11% to Chaos Resistance ++199 to Evasion Rating ++172 to maximum Mana ++29 to Strength ++34% to Lightning Resistance +Leech 6.34% of Physical Attack Damage as Mana +{desecrated}+115 to maximum Life + + + + + + + + + + Rarity: RARE +Pain Shelter +Soldier Cuirass +Armour: 2031 +Unique ID: c1272d9098b999d72429ccdf1fe25c25781e51c8b2d9392ca792f7a41c8ab87e +Item Level: 79 +Quality: 24 +Sockets: S S +Rune: The Greatwolf's Rune of Willpower +Rune: Craiceann's Rune of Warding +LevelReq: 65 +Implicits: 4 +{enchant}{rune}50% reduced effect of Curses on you +{enchant}{rune}15% of Damage is taken from Mana before Life +{enchant}{rune}Bonded: 8% increased Curse Magnitudes +{enchant}{rune}Bonded: 8% of Maximum Life Converted to Energy Shield ++265 to Armour +105% increased Armour +10% increased maximum Life +Hits against you have 47% reduced Critical Damage Bonus ++30% to Lightning Resistance +{desecrated}+43% of Armour also applies to Elemental Damage +Corrupted + + + + + + + + + + + + + Rarity: NORMAL +Evasive Leg +Unique ID: 1170f441dfecf0cfa4c4f7b19833710477ff62ac3fb66c2c1c658daa1f097ccf +Item Level: 99 +LevelReq: 0 +Implicits: 1 +30% increased Evasion Rating + + + + Rarity: RARE +Kraken Hold +Prismatic Ring +Unique ID: 5942bb3b406d8bb45907c9efb803bc7c1e516064294f1739977e1d4f5fcb112c +Item Level: 80 +LevelReq: 35 +Implicits: 1 ++12% to all Elemental Resistances ++164 to Evasion Rating ++116 to maximum Life ++156 to maximum Mana ++35% to Fire Resistance +Leech 7.39% of Physical Attack Damage as Life +{desecrated}+20% to Lightning and Chaos Resistances + + + + + + + + + + Rarity: UNIQUE +Carrion Span +Tawhoan Tower Shield +Armour: 1215 +Unique ID: 2957b34aa214fbdc6d0b652646718c039598d898641ffb48e728d0266aa3343f +Item Level: 80 +Quality: 20 +Sockets: S S +Rune: Greater Iron Rune +Rune: Greater Iron Rune +LevelReq: 80 +Implicits: 4 +{enchant}{rune}36% increased Armour, Evasion and Energy Shield +{enchant}{rune}Bonded: +20 to maximum Life +{enchant}{rune}Bonded: +20 to maximum Mana +Grants Skill: Raise Shield ++253 to Armour +89% increased Armour ++185 to maximum Life ++31 to Strength ++28% to Cold Resistance +Corrupted + + + + + + + + + + + + Rarity: UNIQUE +Undying Hate +Timeless Jewel +Variant: Amanamu +Variant: Kulemak +Variant: Kurgal +Variant: Tecrod +Variant: Ulaman +Selected Variant: 1 +LevelReq: 0 +Radius: Very Large +Limited to: 1 +Implicits: 0 +{variant:1}{range:0.5}Glorifying the defilement of (100-8000) souls in tribute to Amanamu +{variant:2}{range:0.5}Glorifying the defilement of (100-8000) souls in tribute to Kulemak +{variant:3}{range:0.5}Glorifying the defilement of (100-8000) souls in tribute to Kurgal +{variant:4}{range:0.5}Glorifying the defilement of (100-8000) souls in tribute to Tecrod +{variant:5}{range:0.5}Glorifying the defilement of (100-8000) souls in tribute to Ulaman +Passives in radius are Conquered by the Abyssals +Historic + + + + + + + + + + Rarity: UNIQUE +Pain Shelter +Soldier Cuirass +Armour: 2031 +Unique ID: c1272d9098b999d72429ccdf1fe25c25781e51c8b2d9392ca792f7a41c8ab87e +Item Level: 79 +Quality: 24 +Sockets: S S +Rune: The Greatwolf's Rune of Willpower +Rune: Craiceann's Rune of Warding +LevelReq: 65 +Implicits: 4 +{enchant}{rune}50% reduced effect of Curses on you +{enchant}{rune}Bonded: 8% increased Curse Magnitudes +{enchant}{rune}Bonded: 8% of Maximum Life Converted to Energy Shield ++265 to Armour +105% increased Armour +10% increased maximum Life +Hits against you have 47% reduced Critical Damage Bonus ++30% to Lightning Resistance +{desecrated}+43% of Armour also applies to Elemental Damage +Corrupted + + + + + + + + + + + + Rarity: UNIQUE +Torment Touch +Vaal Mitts +Armour: 485 +Unique ID: ec3d3e1408f66406a34cc183c6ffb0a87025355c3295bc90ab8be9f8d32c539e +Item Level: 79 +Quality: 20 +Sockets: S +Rune: Idol of Grold +LevelReq: 75 +Implicits: 2 +{enchant}{rune}32% increased total Power counted by Warcries +{enchant}{rune}Bonded: 32% increased Glory generation +36% increased Armour ++156 to maximum Life ++2 to Level of all Melee Skills ++42% of Armour also applies to Elemental Damage ++170 to mana +{desecrated}+151 to Armour + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/System/TestDefence_spec.lua b/spec/System/TestDefence_spec.lua index f7df77a056..16a16ce4b6 100644 --- a/spec/System/TestDefence_spec.lua +++ b/spec/System/TestDefence_spec.lua @@ -1283,4 +1283,68 @@ describe("TestDefence", function() assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) end) + + it("uses block chance against projectile spells", function() + build.configTab.input.enemyIsBoss = "None" + build.configTab.input.enemyDamageType = "SpellProjectile" + build.configTab.input.customMods = [[ + 20% chance to block + ]] + build.configTab:BuildModList() + runCallback("OnFrame") + + assert.are.equals(20, build.calcsTab.calcsOutput.EffectiveBlockChance) + assert.are.equals(20, build.calcsTab.calcsOutput.EffectiveProjectileBlockChance) + assert.are.equals(20, build.calcsTab.calcsOutput.EffectiveSpellProjectileBlockChance) + assert.are.equals(80, build.calcsTab.calcsOutput.ConfiguredDamageChance) + + build.configTab.input.enemyDamageType = "Average" + build.configTab:BuildModList() + runCallback("OnFrame") + + assert.are.equals(15, build.calcsTab.calcsOutput.EffectiveAverageBlockChance) + assert.are.equals(85, build.calcsTab.calcsOutput.ConfiguredDamageChance) + end) + + it("limits EHP speedup when hit damage is delayed", function() + local function assertClose(actual, expected) + assert.is_true(math.abs(actual - expected) < 0.01) + end + + local function calcEHP(extraMods) + newBuild() + build.configTab.input.enemyPhysicalDamage = "1000" + build.configTab.input.enemyFireDamage = "1000" + build.configTab.input.enemyColdDamage = "1000" + build.configTab.input.enemyLightningDamage = "1000" + build.configTab.input.enemyChaosDamage = "0" + build.configTab.input.customMods = [[ ++4000 to maximum Life ++4000 to maximum Mana +75% of Damage is taken from Mana before Life +25% of Life Loss from Hits is prevented, then that much Life is lost over 4 seconds instead ++75% to all Elemental Resistances ++75% to Chaos Resistance +]] .. (extraMods or "") + build.configTab:BuildModList() + runCallback("OnFrame") + runCallback("OnFrame") + local calcsOutput = build.calcsTab.calcsOutput + return { + TotalEHP = calcsOutput.TotalEHP, + EffectiveBlockChance = calcsOutput.EffectiveBlockChance, + NumberOfMitigatedDamagingHits = calcsOutput.NumberOfMitigatedDamagingHits, + } + end + + local base = calcEHP() + local block = calcEHP("\n+10% to Block chance\n") + + newBuild() + + assertClose(base.TotalEHP, 17582.417582418) + assertClose(block.TotalEHP, 19008.019008019) + assertClose(block.EffectiveBlockChance, 10) + assert.is_true(block.TotalEHP > base.TotalEHP) + end) end) diff --git a/spec/System/TestDefence_spec.lua.rej b/spec/System/TestDefence_spec.lua.rej new file mode 100644 index 0000000000..744786a97c --- /dev/null +++ b/spec/System/TestDefence_spec.lua.rej @@ -0,0 +1,28 @@ +diff a/spec/System/TestDefence_spec.lua b/spec/System/TestDefence_spec.lua (rejected hunks) +@@ -557,20 +557,18 @@ describe("TestDefence", function() + + local function calcEHP(extraMods) + newBuild() +- build.configTab.input.enemyPhysicalDamage = "1000" +- build.configTab.input.enemyFireDamage = "1000" +- build.configTab.input.enemyColdDamage = "1000" +- build.configTab.input.enemyLightningDamage = "1000" ++ build.configTab.input.enemyPhysicalDamage = "500" ++ build.configTab.input.enemyFireDamage = "500" ++ build.configTab.input.enemyColdDamage = "500" ++ build.configTab.input.enemyLightningDamage = "500" + build.configTab.input.enemyChaosDamage = "0" + build.configTab.input.customMods = [[ + +4000 to maximum Life +- +4000 to maximum Mana +- 75% of Damage is taken from Mana before Life +- 25% of Life Loss from Hits is prevented, then that much Life is lost over 4 seconds instead ++ 75% of Life Loss from Hits is prevented, then that much Life is lost over 4 seconds instead + +75% to all Elemental Resistances + +75% to Chaos Resistance + ]] .. (extraMods or "") +- build.configTab:BuildModList() ++ pob1and2Compat() + runCallback("OnFrame") + runCallback("OnFrame") + local calcsOutput = build.calcsTab.calcsOutput diff --git a/spec/System/TestItemParse_spec.lua.rej b/spec/System/TestItemParse_spec.lua.rej new file mode 100644 index 0000000000..de9206ca0a --- /dev/null +++ b/spec/System/TestItemParse_spec.lua.rej @@ -0,0 +1,24 @@ +diff a/spec/System/TestItemParse_spec.lua b/spec/System/TestItemParse_spec.lua (rejected hunks) +@@ -142,22 +142,6 @@ describe("TestItemParse", function() + assert.are.equals("Adds 39 to 62 Fire Damage", item.explicitModLines[1].line) + end) + +- it("Pasted variable-level base granted skills parse at exact exported levels", function() +- local cases = { +- { base = "Bone Wand", line = "Grants Skill: Level 11 Bone Blast", skillId = "BoneBlastPlayer", level = 11 }, +- { base = "Withered Wand", line = "Grants Skill: Level 20 Chaos Bolt", skillId = "WeaponGrantedChaosboltPlayer", level = 20 }, +- { base = "Stoic Sceptre", line = "Grants Skill: Level 20 Discipline", skillId = "DisciplinePlayer", level = 20 }, +- } +- +- for _, case in ipairs(cases) do +- local item = new("Item", "Rarity: Normal\n" .. case.base .. "\nImplicits: 1\n" .. case.line) +- +- assert.are.equals(1, #item.grantedSkills) +- assert.are.equals(case.skillId, item.grantedSkills[1].skillId) +- assert.are.equals(case.level, item.grantedSkills[1].level) +- end +- end) +- + --TODO: POB2 Leagues? + --it("League", function() + --end) diff --git a/src/Data/ModCache.lua.rej b/src/Data/ModCache.lua.rej new file mode 100644 index 0000000000..3514176b95 --- /dev/null +++ b/src/Data/ModCache.lua.rej @@ -0,0 +1,89 @@ +diff a/src/Data/ModCache.lua b/src/Data/ModCache.lua (rejected hunks) +@@ -5146,13 +5146,20 @@ c["Grants Skill: Kelari's Malediction"]={{[1]={flags=0,keywordFlags=0,name="Extr + c["Grants Skill: Kelari, the Tainted Sands"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=1,skillId="SummonSandDjinnPlayer"}}},nil} + c["Grants Skill: Level 11 Black Powder Blitz"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="BlackPowderBlitzReservationPlayer"}}},nil} + c["Grants Skill: Level 11 Blink"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="BlinkReservationPlayer"}}},nil} ++c["Grants Skill: Level 11 Bone Blast"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="BoneBlastPlayer"}}},nil} + c["Grants Skill: Level 11 Bursting Fen Toad"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="ExplodingPoisonToadPlayer"}}},nil} ++c["Grants Skill: Level 11 Chaos Bolt"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="WeaponGrantedChaosboltPlayer"}}},nil} + c["Grants Skill: Level 11 Compose Requiem"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="CrossbowRequiemAmmoPlayer"}}},nil} + c["Grants Skill: Level 11 Crackling Palm"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="CracklingPalmPlayer"}}},nil} + c["Grants Skill: Level 11 Decompose"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="CorpseCloudPlayer"}}},nil} ++c["Grants Skill: Level 11 Discipline"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="DisciplinePlayer"}}},nil} + c["Grants Skill: Level 11 Ember Fusillade"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="EmberFusilladePlayer"}}},nil} ++c["Grants Skill: Level 11 Feast of Flesh"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="FeastOfFleshPlayer"}}},nil} ++c["Grants Skill: Level 11 Firebolt"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="FireboltPlayer"}}},nil} ++c["Grants Skill: Level 11 Freezing Shards"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="FreezingShardsPlayer"}}},nil} + c["Grants Skill: Level 11 Future-Past"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="FuturePastPlayer"}}},nil} + c["Grants Skill: Level 11 Gemini Surge"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="GeminiSurgePlayer"}}},nil} ++c["Grants Skill: Level 11 Heart of Ice"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="HeartOfIcePlayer"}}},nil} + c["Grants Skill: Level 11 Herald of Ash"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="HeraldOfAshPlayer"}}},nil} + c["Grants Skill: Level 11 Herald of Ice"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="HeraldOfIcePlayer"}}},nil} + c["Grants Skill: Level 11 Herald of Thunder"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="HeraldOfThunderPlayer"}}},nil} +@@ -5160,26 +5167,42 @@ c["Grants Skill: Level 11 Icestorm"]={{[1]={flags=0,keywordFlags=0,name="ExtraSk + c["Grants Skill: Level 11 Impurity"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="ImpurityPlayer"}}},nil} + c["Grants Skill: Level 11 Lightning Bolt"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="UniqueBreachLightningBoltPlayer"}}},nil} + c["Grants Skill: Level 11 Living Bomb"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="LivingBombPlayer"}}},nil} ++c["Grants Skill: Level 11 Malice"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="MalicePlayer"}}},nil} ++c["Grants Skill: Level 11 Mana Drain"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="ManaDrainPlayer"}}},nil} ++c["Grants Skill: Level 11 Parry"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="ParryPlayer"}}},nil} + c["Grants Skill: Level 11 Phantasmal Arrow"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="PhantasmalArrowPlayer"}}},nil} ++c["Grants Skill: Level 11 Power Siphon"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="PowerSiphonPlayer"}}},nil} + c["Grants Skill: Level 11 Purity of Fire"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="PurityOfFirePlayer"}}},nil} + c["Grants Skill: Level 11 Purity of Ice"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="PurityOfIcePlayer"}}},nil} + c["Grants Skill: Level 11 Purity of Lightning"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="PurityOfLightningPlayer"}}},nil} ++c["Grants Skill: Level 11 Raise Shield"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="ShieldBlockPlayer"}}},nil} ++c["Grants Skill: Level 11 Sigil of Power"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="SigilOfPowerPlayer"}}},nil} ++c["Grants Skill: Level 11 Skeletal Warrior Minion"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="SummonSkeletalWarriorsPlayer"}}},nil} ++c["Grants Skill: Level 11 Solar Orb"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="SolarOrbPlayer"}}},nil} + c["Grants Skill: Level 11 Spark"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="SparkPlayer"}}},nil} + c["Grants Skill: Level 11 Thundergod's Wrath"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="MetaCastLightningSpellOnHitPlayer"}}},nil} + c["Grants Skill: Level 11 Valako's Charge"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="ValakosChargePlayer"}}},nil} ++c["Grants Skill: Level 11 Volatile Dead"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="VolatileDeadPlayer"}}},nil} + c["Grants Skill: Level 11 Withering Presence"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=11,skillId="WitheringPresencePlayer"}}},nil} + c["Grants Skill: Level 14 Life Remnants"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=14,skillId="LifeRemnantsPlayer"}}},nil} + c["Grants Skill: Level 20 Black Powder Blitz"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="BlackPowderBlitzReservationPlayer"}}},nil} + c["Grants Skill: Level 20 Blink"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="BlinkReservationPlayer"}}},nil} ++c["Grants Skill: Level 20 Bone Blast"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="BoneBlastPlayer"}}},nil} + c["Grants Skill: Level 20 Bursting Fen Toad"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="ExplodingPoisonToadPlayer"}}},nil} ++c["Grants Skill: Level 20 Chaos Bolt"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="WeaponGrantedChaosboltPlayer"}}},nil} + c["Grants Skill: Level 20 Chaotic Infusion"]={nil,nil} + c["Grants Skill: Level 20 Chaotic Infusion 20% increased Attack Speed"]={nil,nil} + c["Grants Skill: Level 20 Compose Requiem"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="CrossbowRequiemAmmoPlayer"}}},nil} + c["Grants Skill: Level 20 Crackling Palm"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="CracklingPalmPlayer"}}},nil} + c["Grants Skill: Level 20 Decompose"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="CorpseCloudPlayer"}}},nil} ++c["Grants Skill: Level 20 Discipline"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="DisciplinePlayer"}}},nil} + c["Grants Skill: Level 20 Ember Fusillade"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="EmberFusilladePlayer"}}},nil} ++c["Grants Skill: Level 20 Feast of Flesh"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="FeastOfFleshPlayer"}}},nil} ++c["Grants Skill: Level 20 Firebolt"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="FireboltPlayer"}}},nil} ++c["Grants Skill: Level 20 Freezing Shards"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="FreezingShardsPlayer"}}},nil} + c["Grants Skill: Level 20 Future-Past"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="FuturePastPlayer"}}},nil} + c["Grants Skill: Level 20 Gemini Surge"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="GeminiSurgePlayer"}}},nil} ++c["Grants Skill: Level 20 Heart of Ice"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="HeartOfIcePlayer"}}},nil} + c["Grants Skill: Level 20 Herald of Ash"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="HeraldOfAshPlayer"}}},nil} + c["Grants Skill: Level 20 Herald of Ice"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="HeraldOfIcePlayer"}}},nil} + c["Grants Skill: Level 20 Herald of Thunder"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="HeraldOfThunderPlayer"}}},nil} +@@ -5195,14 +5218,23 @@ c["Grants Skill: Level 20 Icestorm"]={{[1]={flags=0,keywordFlags=0,name="ExtraSk + c["Grants Skill: Level 20 Impurity"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="ImpurityPlayer"}}},nil} + c["Grants Skill: Level 20 Lightning Bolt"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="UniqueBreachLightningBoltPlayer"}}},nil} + c["Grants Skill: Level 20 Living Bomb"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="LivingBombPlayer"}}},nil} ++c["Grants Skill: Level 20 Malice"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="MalicePlayer"}}},nil} ++c["Grants Skill: Level 20 Mana Drain"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="ManaDrainPlayer"}}},nil} ++c["Grants Skill: Level 20 Parry"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="ParryPlayer"}}},nil} + c["Grants Skill: Level 20 Phantasmal Arrow"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="PhantasmalArrowPlayer"}}},nil} + c["Grants Skill: Level 20 Pinnacle of Power"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="PinnacleOfPowerPlayer"}}},nil} ++c["Grants Skill: Level 20 Power Siphon"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="PowerSiphonPlayer"}}},nil} + c["Grants Skill: Level 20 Purity of Fire"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="PurityOfFirePlayer"}}},nil} + c["Grants Skill: Level 20 Purity of Ice"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="PurityOfIcePlayer"}}},nil} + c["Grants Skill: Level 20 Purity of Lightning"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="PurityOfLightningPlayer"}}},nil} ++c["Grants Skill: Level 20 Raise Shield"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="ShieldBlockPlayer"}}},nil} ++c["Grants Skill: Level 20 Sigil of Power"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SigilOfPowerPlayer"}}},nil} ++c["Grants Skill: Level 20 Skeletal Warrior Minion"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SummonSkeletalWarriorsPlayer"}}},nil} ++c["Grants Skill: Level 20 Solar Orb"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SolarOrbPlayer"}}},nil} + c["Grants Skill: Level 20 Spark"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="SparkPlayer"}}},nil} + c["Grants Skill: Level 20 Thundergod's Wrath"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="MetaCastLightningSpellOnHitPlayer"}}},nil} + c["Grants Skill: Level 20 Valako's Charge"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="ValakosChargePlayer"}}},nil} ++c["Grants Skill: Level 20 Volatile Dead"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="VolatileDeadPlayer"}}},nil} + c["Grants Skill: Level 20 Withering Presence"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=20,skillId="WitheringPresencePlayer"}}},nil} + c["Grants Skill: Life Remnants"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=1,skillId="LifeRemnantsPlayer"}}},nil} + c["Grants Skill: Manifest Weapon"]={{[1]={flags=0,keywordFlags=0,name="ExtraSkill",type="LIST",value={level=1,skillId="ManifestWeaponPlayer"}}},nil} diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index 6f73ef814b..8ae924ed54 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -2740,6 +2740,7 @@ function calcs.buildDefenceEstimations(env, actor) for _, damageType in ipairs(dmgTypeList) do DamageIn[damageType] = output[damageType.."TakenHit"] end + DamageIn["LimitEHPSpeedup"] = output["preventedLifeLossTotal"] > 0 output["NumberOfDamagingHits"] = numberOfHitsToDie(DamageIn) end diff --git a/src/Modules/CalcDefence.lua.rej b/src/Modules/CalcDefence.lua.rej new file mode 100644 index 0000000000..1f80c75266 --- /dev/null +++ b/src/Modules/CalcDefence.lua.rej @@ -0,0 +1,31 @@ +diff a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua (rejected hunks) +@@ -3077,16 +3077,16 @@ function calcs.buildDefenceEstimations(env, actor) + end + iterationMultiplier = 1 + -- to speed it up, run recursively but accelerated +- -- Stateful pool mechanics are not associative: collapsing too many hits into one +- -- can cross MoM/life-loss-prevention boundaries differently from repeated hits. +- local speedUp = DamageIn["StatefulEHP"] and m_min(data.misc.ehpCalcSpeedUp, 4) or data.misc.ehpCalcSpeedUp ++ -- MoM/life-loss-prevention mechanics can collapse too many hits into one ++ -- resulting in eHP jumps so we slow the acceleration. ++ local speedUp = DamageIn["LimitEHPSpeedup"] and 4 or data.misc.ehpCalcSpeedUp + DamageIn["cyclesRan"] = DamageIn["cyclesRan"] or false + if not DamageIn["cyclesRan"] and poolTable.Life > 0 and DamageIn["iterations"] < maxIterations then + Damage = { } + for _, damageType in ipairs(dmgTypeList) do + Damage[damageType] = DamageIn[damageType] * speedUp + end +- Damage["StatefulEHP"] = DamageIn["StatefulEHP"] ++ Damage["LimitEHPSpeedup"] = DamageIn["LimitEHPSpeedup"] + if DamageIn.GainWhenHit then + Damage.GainWhenHit = true + Damage.LifeWhenHit = DamageIn.LifeWhenHit +@@ -3230,7 +3230,7 @@ function calcs.buildDefenceEstimations(env, actor) + output["LifeLossLostOverTime"] = 0 + output["LifeBelowHalfLossLostOverTime"] = 0 + end +- DamageIn["StatefulEHP"] = DamageIn["TrackRecoupable"] or DamageIn["TrackLifeLossOverTime"] or DamageIn.GainWhenHit ++ DamageIn["LimitEHPSpeedup"] = DamageIn["TrackRecoupable"] or DamageIn["TrackLifeLossOverTime"] or DamageIn.GainWhenHit + averageAvoidChance = averageAvoidChance / 5 + output["ConfiguredDamageChance"] = 100 * (blockEffect * suppressionEffect * effectiveDeflectMulti * (1 - averageAvoidChance / 100)) + output["NumberOfMitigatedDamagingHits"] = (output["ConfiguredDamageChance"] ~= 100 or DamageIn["TrackRecoupable"] or DamageIn["TrackLifeLossOverTime"] or DamageIn.GainWhenHit) and numberOfHitsToDie(DamageIn) or output["NumberOfDamagingHits"]