diff --git a/spec/System/TestDefence_spec.lua b/spec/System/TestDefence_spec.lua index 8a0d4daa3f..705b189fbe 100644 --- a/spec/System/TestDefence_spec.lua +++ b/spec/System/TestDefence_spec.lua @@ -22,7 +22,7 @@ describe("TestDefence", function() build.configTab.input.enemyIsBoss = "None" build.configTab:BuildModList() runCallback("OnFrame") - + assert.are.equals(60, build.calcsTab.calcsOutput.PhysicalMaximumHitTaken) assert.are.equals(38, build.calcsTab.calcsOutput.FireMaximumHitTaken) assert.are.equals(38, build.calcsTab.calcsOutput.ColdMaximumHitTaken) @@ -122,12 +122,12 @@ describe("TestDefence", function() assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) end) - + -- a small helper function to calculate damage taken from limited test parameters local function takenHitFromTypeMaxHit(type, enemyDamageMulti) return build.calcsTab.calcs.takenHitFromDamage(build.calcsTab.calcsOutput[type.."MaximumHitTaken"] * (enemyDamageMulti or 1), type, build.calcsTab.calcsEnv.player) end - + it("progenesis and petrified blood", function() build.configTab.input.enemyIsBoss = "None" -- Petrified blood @@ -153,7 +153,7 @@ describe("TestDefence", function() assert.are.equals(3000, build.calcsTab.calcsOutput.LightningMaximumHitTaken) assert.are.equals(3000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken) build.skillsTab.socketGroupList = {} - + build.skillsTab:PasteSocketGroup("\z Petrified Blood 20/0 Default 1\n\z Arrogance 21/0 Default 1\n\z @@ -178,7 +178,7 @@ describe("TestDefence", function() assert.are.equals(6000, build.calcsTab.calcsOutput.LightningMaximumHitTaken) assert.are.equals(3000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken) build.skillsTab.socketGroupList = {} - + build.skillsTab:PasteSocketGroup("\z Petrified Blood 20/0 Default 1\n\z ") -- 80% petrified effect, starting from full life, should make the life pool be equivalent to 0.5 * life (unprotected upper half) and then 5 * 0.5 * life (protected lower half), making it 3* bigger in total @@ -199,7 +199,7 @@ describe("TestDefence", function() assert.are.equals(9000, build.calcsTab.calcsOutput.LightningMaximumHitTaken) assert.are.equals(9000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken) build.skillsTab.socketGroupList = {} - + -- Progenesis build.configTab.input.customMods = "\z +200 to all resistances\n\z @@ -217,7 +217,7 @@ describe("TestDefence", function() assert.are.equals(6000, build.calcsTab.calcsOutput.ColdMaximumHitTaken) assert.are.equals(6000, build.calcsTab.calcsOutput.LightningMaximumHitTaken) assert.are.equals(6000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken) - + build.configTab.input.customMods = "\z +200 to all resistances\n\z +200 to all maximum resistances\n\z @@ -235,7 +235,7 @@ describe("TestDefence", function() assert.are.equals(9000, build.calcsTab.calcsOutput.ColdMaximumHitTaken) assert.are.equals(9000, build.calcsTab.calcsOutput.LightningMaximumHitTaken) assert.are.equals(6000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken) - + -- Progenesis + petrified blood build.skillsTab:PasteSocketGroup("\z Petrified Blood 20/0 Default 1\n\z @@ -261,7 +261,7 @@ describe("TestDefence", function() assert.are.equals(6000, build.calcsTab.calcsOutput.LightningMaximumHitTaken) assert.are.equals(6000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken) build.skillsTab.socketGroupList = {} - + build.skillsTab:PasteSocketGroup("\z Petrified Blood 20/0 Default 1\n\z ") @@ -284,7 +284,7 @@ describe("TestDefence", function() assert.are.equals(9000, build.calcsTab.calcsOutput.LightningMaximumHitTaken) assert.are.equals(9000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken) build.skillsTab.socketGroupList = {} - + build.skillsTab:PasteSocketGroup("\z Petrified Blood 20/0 Default 1\n\z ") @@ -306,14 +306,14 @@ describe("TestDefence", function() assert.are.equals(13000, build.calcsTab.calcsOutput.ColdMaximumHitTaken) assert.are.equals(13000, build.calcsTab.calcsOutput.LightningMaximumHitTaken) assert.are.equals(10000, build.calcsTab.calcsOutput.ChaosMaximumHitTaken) - + local _, takenDamages = takenHitFromTypeMaxHit("Fire", 0.8) local poolsRemaining = build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player) assert.are.equals(0, poolsRemaining.EnergyShield) assert.are.equals(0, poolsRemaining.Life) assert.are.equals(120, poolsRemaining.LifeLossLostOverTime) assert.are.equals(20, poolsRemaining.LifeBelowHalfLossLostOverTime) - + build.skillsTab:PasteSocketGroup("\z Petrified Blood 20/0 Default 1\n\z ") @@ -336,25 +336,25 @@ describe("TestDefence", function() build.configTab.input.conditionUsingFlask = true build.configTab:BuildModList() runCallback("OnFrame") - + _, takenDamages = takenHitFromTypeMaxHit("Fire") poolsRemaining = build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player) assert.are.equals(0, poolsRemaining.Life) assert.are.equals(0, poolsRemaining.EnergyShield) assert.is.not_false(poolsRemaining.Mana > 0) - + _, takenDamages = takenHitFromTypeMaxHit("Lightning") poolsRemaining = build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player) assert.are.equals(0, poolsRemaining.Life) assert.are.equals(0, poolsRemaining.EnergyShield) assert.are.equals(0, poolsRemaining.Mana) - + _, takenDamages = takenHitFromTypeMaxHit("Chaos") poolsRemaining = build.calcsTab.calcs.reducePoolsByDamage(nil, takenDamages, build.calcsTab.calcsEnv.player) assert.are.equals(0, poolsRemaining.Life) assert.are.equals(0, poolsRemaining.EnergyShield) assert.are.equals(0, poolsRemaining.Mana) - + build.skillsTab.socketGroupList = {} end) @@ -555,7 +555,7 @@ describe("TestDefence", function() end it("damage conversion max hits", function() build.configTab.input.enemyIsBoss = "None" - + build.configTab.input.customMods = "\z +940 to maximum life\n\z +200 to all resistances\n\z @@ -608,7 +608,7 @@ describe("TestDefence", function() runCallback("OnFrame") assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Physical"))) assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Cold"))) - + build.configTab.input.customMods = "\z +940 to maximum life\n\z +10000 to armour\n\z @@ -622,7 +622,7 @@ describe("TestDefence", function() runCallback("OnFrame") assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Physical"))) assert.is.not_false(withinTenPercent(1000, takenHitFromTypeMaxHit("Cold"))) - + build.configTab.input.customMods = "\z +99 to energy shield\n\z 100% less attributes\n\z @@ -636,7 +636,7 @@ describe("TestDefence", function() assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) end) - + it("damage conversion to different size pools", function() -- conversion into a smaller pool build.configTab.input.customMods = "\z @@ -654,7 +654,7 @@ describe("TestDefence", function() assert.are.equals(0, floor(poolsRemaining.Mana)) assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) - + build.configTab.input.customMods = "\z +40 to maximum life\n\z +950 to mana\n\z @@ -670,7 +670,7 @@ describe("TestDefence", function() assert.are.equals(0, floor(poolsRemaining.Mana)) assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) - + build.configTab.input.customMods = "\z +40 to maximum life\n\z +1950 to mana\n\z @@ -686,7 +686,7 @@ describe("TestDefence", function() assert.are.equals(1000, round(poolsRemaining.Mana)) assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) - + -- conversion into a bigger pool build.configTab.input.customMods = "\z +40 to maximum life\n\z @@ -703,7 +703,7 @@ describe("TestDefence", function() assert.are.equals(0, floor(poolsRemaining.Mana)) assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) - + build.configTab.input.customMods = "\z +40 to maximum life\n\z +950 to mana\n\z @@ -719,7 +719,7 @@ describe("TestDefence", function() assert.are.equals(0, floor(poolsRemaining.Mana)) assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) - + build.configTab.input.customMods = "\z +40 to maximum life\n\z +1950 to mana\n\z @@ -898,7 +898,7 @@ describe("TestDefence", function() assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) end) - + it("Unbreakable + Iron Reflexes", function() build.configTab.input.customMods = [[ you have no dexterity @@ -993,7 +993,7 @@ describe("TestDefence", function() -- Oath Of Maji should apply only once assert.are.equals(2*2*ironReflexesArmour + baseArmour + baseEvasion, build.calcsTab.mainOutput.Armour) end) - + it("MoM + EB", function() build.configTab.input.enemyIsBoss = "None" -- enough mana and es, 0% and 100% bypass @@ -1020,7 +1020,7 @@ describe("TestDefence", function() assert.are.equals(2000, round(poolsRemaining.Mana)) assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) - + -- enough mana and es, 50% bypass build.configTab.input.customMods = [[ 50% of damage is taken from mana before life @@ -1085,7 +1085,7 @@ describe("TestDefence", function() assert.are.equals(1940, round(poolsRemaining.Mana)) assert.are.equals(0, floor(poolsRemaining.Life)) assert.are.equals(0, floor(poolsRemaining.OverkillDamage)) - + -- mana bottleneck, 0% and 100% bypass build.configTab.input.customMods = [[ 50% of damage is taken from mana before life diff --git a/spec/System/TestItemMods_spec.lua b/spec/System/TestItemMods_spec.lua index 766c6f45fe..72d3b02098 100644 --- a/spec/System/TestItemMods_spec.lua +++ b/spec/System/TestItemMods_spec.lua @@ -197,7 +197,7 @@ describe("TetsItemMods", function() assert.are.equals(genericRingInt - initialInt, build.calcsTab.mainOutput.Int - genericRingInt) end) - + it("Kalandra's Touch influence copy", function() build.skillsTab:PasteSocketGroup("Slot: Weapon 1\nSmite 20/0 Default 1\n") @@ -308,7 +308,7 @@ describe("TetsItemMods", function() end) it("Both slots explicit mod with mixed mod rings (evasion and es mastery)", function() - + build.configTab.input.customMods = "\z 20% increased Maximum Energy Shield if both Equipped Rings have an Explicit Evasion Modifier\n\z " diff --git a/spec/System/TestItemParse_spec.lua b/spec/System/TestItemParse_spec.lua index 4890207cea..2ec187e07e 100644 --- a/spec/System/TestItemParse_spec.lua +++ b/spec/System/TestItemParse_spec.lua @@ -307,7 +307,7 @@ describe("TestItemParse", function() item = new("Item", raw("Has a Two Handed Sword Crucible Passive Skill Tree")) assert.truthy(item.canHaveTwoHandedSwordCrucibleTree) end) - + it("tags", function() local item = new("Item", raw("{tags:life,physical_damage}+8 to Strength")) assert.are.same({ "life", "physical_damage" }, item.explicitModLines[1].modTags) diff --git a/spec/System/TestSkills_spec.lua b/spec/System/TestSkills_spec.lua index 0e67ddc80d..36ba738052 100644 --- a/spec/System/TestSkills_spec.lua +++ b/spec/System/TestSkills_spec.lua @@ -53,7 +53,7 @@ describe("TestAttacks", function() assert.True(build.calcsTab.mainOutput.SkillTriggerRate == build.calcsTab.mainOutput.Speed) end) - + it("Test Sacred wisps using current skill", function() build.itemsTab:CreateDisplayItemFromRaw([[Elemental Wand Imbued Wand @@ -76,11 +76,11 @@ describe("TestAttacks", function() assert.True(build.calcsTab.mainOutput.MirageDPS ~= nil) end) - + it("Test Scorching ray applying exposure at max stages", function() build.skillsTab:PasteSocketGroup("Scorching Ray 20/0 Default 1\n") runCallback("OnFrame") - + local mainSocketGroup = build.skillsTab.socketGroupList[build.mainSocketGroup] local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance srcInstance.skillStageCount = 8 @@ -103,14 +103,14 @@ describe("TestAttacks", function() it("Test Adrenaline affecting blight max stage count", function() build.skillsTab:PasteSocketGroup("Blight 20/0 Default 1\n") runCallback("OnFrame") - + local mainSocketGroup = build.skillsTab.socketGroupList[build.mainSocketGroup] local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance srcInstance.skillPart = 2 build.modFlag = true build.buildFlag = true runCallback("OnFrame") - + local preAdrenalineMaxStages = build.calcsTab.mainEnv.player.activeSkillList[1].skillModList:Sum("BASE", nil, "Multiplier:BlightMaxStages") build.configTab.input.buffAdrenaline = true build.configTab:BuildModList() diff --git a/spec/System/TestTriggers_spec.lua b/spec/System/TestTriggers_spec.lua index 3006513dad..230fadd7ba 100644 --- a/spec/System/TestTriggers_spec.lua +++ b/spec/System/TestTriggers_spec.lua @@ -27,10 +27,10 @@ describe("TestTriggers", function() {range:0.5}+(15-25)% to Global Critical Strike Multiplier]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Reave 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -52,13 +52,13 @@ describe("TestTriggers", function() 10% increased Area of Effect]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.mainSocketGroup = 2 build.modFlag = true build.buildFlag = true build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -80,13 +80,13 @@ describe("TestTriggers", function() 10% increased Area of Effect]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.mainSocketGroup = 2 build.modFlag = true build.buildFlag = true build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -107,7 +107,7 @@ describe("TestTriggers", function() build.configTab.input["buffPhasing"] = true build.configTab:BuildModList() runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -133,7 +133,7 @@ describe("TestTriggers", function() Hits ignore Enemy Monster Chaos Resistance if all Equipped Items are Elder Items]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -174,7 +174,7 @@ describe("TestTriggers", function() {variant:5,6,7}Penetrate 4% Elemental Resistances per Abyss Jewel affecting you]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -196,10 +196,10 @@ describe("TestTriggers", function() Culling Strike]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -228,7 +228,7 @@ describe("TestTriggers", function() {variant:1}Cannot be Stunned when on Low Life]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.itemsTab:CreateDisplayItemFromRaw([[+3 Bow Thicket Bow Crafted: true @@ -250,7 +250,7 @@ describe("TestTriggers", function() build.skillsTab:PasteSocketGroup("Frenzy 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -274,7 +274,7 @@ describe("TestTriggers", function() 40% reduced Movement Speed when on Low Life]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.itemsTab:CreateDisplayItemFromRaw([[+3 Bow Thicket Bow Crafted: true @@ -296,7 +296,7 @@ describe("TestTriggers", function() build.skillsTab:PasteSocketGroup("Frenzy 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -321,10 +321,10 @@ describe("TestTriggers", function() {variant:2}{range:0.5}Hits with this Weapon gain (75-100)% of Physical Damage as Extra Cold or Lightning Damage]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -347,10 +347,10 @@ describe("TestTriggers", function() Damage Penetrates 20% Fire Resistance]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -370,10 +370,10 @@ describe("TestTriggers", function() Trigger Level 20 Icicle Burst when you Hit a Frozen Enemy]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -397,10 +397,10 @@ describe("TestTriggers", function() {variant:3}Attacks have 25% chance to inflict Bleeding]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -420,10 +420,10 @@ describe("TestTriggers", function() {tags:mana}{range:0.5}(20-30)% increased Mana Regeneration Rate]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -448,10 +448,10 @@ describe("TestTriggers", function() Weapons you Animate create an additional copy]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -484,10 +484,10 @@ describe("TestTriggers", function() {variant:3,4}10% chance to Cover Enemies in Ash on Hit]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Kinetic Blast 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -506,10 +506,10 @@ describe("TestTriggers", function() 15% chance to Poison on Hit]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Reave 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -534,10 +534,10 @@ describe("TestTriggers", function() This item can be anointed by Cassia]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -556,10 +556,10 @@ describe("TestTriggers", function() 20% chance to Trigger Level 20 Tentacle Whip on Kill]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -578,10 +578,10 @@ describe("TestTriggers", function() 20% chance to Trigger Level 20 Summon Volatile Anomaly on Kill]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -599,13 +599,13 @@ describe("TestTriggers", function() Trigger a Socketed Spell when you Attack with this Weapon, with a 0.25 second Cooldown]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Slot: Weapon 1\nArc 20/0 Default 1\n") runCallback("OnFrame") build.skillsTab:PasteSocketGroup("Kinetic Blast 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -642,13 +642,13 @@ describe("TestTriggers", function() 5% chance to Blind Enemies on Hit with Attacks]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Slot: Weapon 2\nRain of Arrows 20/0 Default 1\n") runCallback("OnFrame") build.skillsTab:PasteSocketGroup("Frenzy 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -686,13 +686,13 @@ describe("TestTriggers", function() 5% chance to Blind Enemies on Hit with Attacks]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Slot: Weapon 2\nRain of Arrows 20/0 Default 1\n") runCallback("OnFrame") build.skillsTab:PasteSocketGroup("Arc 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -739,13 +739,13 @@ describe("TestTriggers", function() {variant:1,2}{range:0.5}(10-15)% increased Stun and Block Recovery]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Slot: Helmet\nArc 20/0 Default 1\n") runCallback("OnFrame") build.skillsTab:PasteSocketGroup("Frenzy 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -765,13 +765,13 @@ describe("TestTriggers", function() {range:0.5}(10-20)% increased Cast Speed with Curse Skills]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Slot: Gloves\nEnfeeble 20/0 Default 1\n") runCallback("OnFrame") build.skillsTab:PasteSocketGroup("Despair 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -790,12 +790,12 @@ describe("TestTriggers", function() Damage cannot be Reflected]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.mainSocketGroup = 2 build.modFlag = true build.buildFlag = true runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -819,13 +819,13 @@ describe("TestTriggers", function() {crafted}Spells Triggered this way have 150% more Cost]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Slot: Weapon 1\nArc 20/0 Default 1\n") runCallback("OnFrame") build.skillsTab:PasteSocketGroup("Reave 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -850,7 +850,7 @@ describe("TestTriggers", function() {variant:2}50% chance to Trigger Socketed Spells when you Spend at least 100 Mana on an Upfront Cost to Use or Trigger a Skill, with a 0.1 second Cooldown]]) build.itemsTab:AddDisplayItem() runCallback("OnFrame") - + build.itemsTab:CreateDisplayItemFromRaw([[The Blood Reaper Headsman Axe Variant: Pre 3.0.0 @@ -877,7 +877,7 @@ describe("TestTriggers", function() build.skillsTab:PasteSocketGroup("Ice Nova 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -914,7 +914,7 @@ describe("TestTriggers", function() build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -945,7 +945,7 @@ describe("TestTriggers", function() build.skillsTab:PasteSocketGroup("Reave 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -973,7 +973,7 @@ describe("TestTriggers", function() build.skillsTab:PasteSocketGroup("Cast On Critical Strike 20/0 Default 1\nArc 20/0 Default 1\nCyclone 20/0 Default 1\n") runCallback("OnFrame") - + assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) @@ -1001,7 +1001,7 @@ describe("TestTriggers", function() build.skillsTab:PasteSocketGroup("Cast on Melee Kill 20/0 Default 1\nArc 20/0 Default 1\nCyclone 20/0 Default 1\n") runCallback("OnFrame") - + build.configTab.input["conditionKilledRecently"] = true build.configTab:BuildModList() runCallback("OnFrame") @@ -1012,7 +1012,7 @@ describe("TestTriggers", function() it("Trigger Holy Relic", function() build.skillsTab:PasteSocketGroup("Summon Holy Relic 20/0 Default 1\n") runCallback("OnFrame") - + build.skillsTab:PasteSocketGroup("Smite 20/0 Default 1\n") runCallback("OnFrame") @@ -1303,14 +1303,14 @@ describe("TestTriggers", function() assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) - + it("Trigger Automation", function() build.skillsTab:PasteSocketGroup("Steelskin 20/0 Default 1\nAutomation 20/0 Default 1\n") runCallback("OnFrame") assert.True(build.calcsTab.mainOutput.SkillTriggerRate ~= nil) end) - + it("Trigger Svalinn", function() build.itemsTab:CreateDisplayItemFromRaw([[Rarity: UNIQUE Svalinn Girded diff --git a/src/Classes/BuildListControl.lua b/src/Classes/BuildListControl.lua index 3f42430ce9..4a11c625dd 100644 --- a/src/Classes/BuildListControl.lua +++ b/src/Classes/BuildListControl.lua @@ -9,8 +9,8 @@ local s_format = string.format local BuildListClass = newClass("BuildListControl", "ListControl", function(self, anchor, rect, listMode) self.ListControl(anchor, rect, 20, "VERTICAL", false, listMode.list) self.listMode = listMode - self.colList = { - { width = function() return self:GetProperty("width") - 172 end }, + self.colList = { + { width = function() return self:GetProperty("width") - 172 end }, { }, } self.showRowSeparators = true @@ -136,7 +136,7 @@ function BuildListClass:RenameBuild(build, copyOnName) main:ClosePopup() self.listMode:SelectControl(self) end) - main:OpenPopup(370, 100, (copyOnName and "Copy " or "Rename ")..(build.folderName and "Folder" or "Build"), controls, "save", "edit") + main:OpenPopup(370, 100, (copyOnName and "Copy " or "Rename ")..(build.folderName and "Folder" or "Build"), controls, "save", "edit") end function BuildListClass:DeleteBuild(build) @@ -183,9 +183,9 @@ function BuildListClass:GetRowValue(column, index, build) end elseif column == 2 then if build.buildName then - return s_format("%sLevel %d %s", - build.className and colorCodes[build.className:upper()] or "^7", - build.level or 1, + return s_format("%sLevel %d %s", + build.className and colorCodes[build.className:upper()] or "^7", + build.level or 1, (build.ascendClassName ~= "None" and build.ascendClassName) or build.className or "?" ) else @@ -246,5 +246,5 @@ function BuildListClass:OnSelKeyDown(index, build, key) self:LoadBuild(build) elseif key == "F2" then self:RenameBuild(build) - end + end end diff --git a/src/Classes/CalcBreakdownControl.lua b/src/Classes/CalcBreakdownControl.lua index 351e301e3b..1e9dafb1d5 100644 --- a/src/Classes/CalcBreakdownControl.lua +++ b/src/Classes/CalcBreakdownControl.lua @@ -31,7 +31,7 @@ function CalcBreakdownClass:IsMouseOver() if not self:IsShown() then return end - return self:IsMouseInBounds() or self:GetMouseOverControl() + return self:IsMouseInBounds() or self:GetMouseOverControl() end function CalcBreakdownClass:SetBreakdownData(displayData, pinned) @@ -87,7 +87,7 @@ function CalcBreakdownClass:SetBreakdownData(displayData, pinned) local _, num = string.gsub(row[col.key], "%d%d%d%d", "") -- count how many commas will be added if main.showThousandsSeparators and num > 0 then col.width = m_max(col.width or 0, DrawStringWidth(16, "VAR", col.label) + 6, DrawStringWidth(12, "VAR", row[col.key]) + 6 + (4 * num)) - else + else col.width = m_max(col.width or 0, DrawStringWidth(16, "VAR", col.label) + 6, DrawStringWidth(12, "VAR", row[col.key]) + 6) end end @@ -176,7 +176,7 @@ function CalcBreakdownClass:AddBreakdownSection(sectionData) local section = { type = "TABLE", rowList = breakdown.reservations, - colList = { + colList = { { label = "Skill", key = "skillName" }, { label = "Base", key = "base" }, { label = "MCM", key = "mult" }, @@ -193,7 +193,7 @@ function CalcBreakdownClass:AddBreakdownSection(sectionData) local section = { type = "TABLE", rowList = breakdown.damageTypes, - colList = { + colList = { { label = "From", key = "source", right = true }, { label = "Base", key = "base" }, { label = "Inc/red", key = "inc" }, @@ -240,8 +240,8 @@ function CalcBreakdownClass:AddBreakdownSection(sectionData) table.sort(rowList, function(a, b) return a['base'] > b['base'] end) - - local section = { + + local section = { type = "TABLE", rowList = rowList, colList = colList, @@ -294,7 +294,7 @@ function CalcBreakdownClass:AddModSection(sectionData, modList) type = "TABLE", label = sectionData.label, rowList = rowList, - colList = { + colList = { { label = "Value", key = "displayValue" }, { label = "Stat", key = "name" }, { label = "Skill types", key = "flags" }, @@ -337,7 +337,7 @@ function CalcBreakdownClass:AddModSection(sectionData, modList) local sourceType = row.mod.source:match("[^:]+") if not sourceTotals[sourceType] then sourceTotals[sourceType] = { } - end + end end for sourceType, lines in pairs(sourceTotals) do cfg.source = sourceType @@ -526,7 +526,7 @@ function CalcBreakdownClass:FormatModValue(value, modType) return "?" end else - return value + return value end end diff --git a/src/Classes/CalcSectionControl.lua b/src/Classes/CalcSectionControl.lua index bee372e91f..bc0a903a35 100644 --- a/src/Classes/CalcSectionControl.lua +++ b/src/Classes/CalcSectionControl.lua @@ -162,7 +162,7 @@ function CalcSectionClass:FormatVal(val, p) end function CalcSectionClass:FormatStr(str, actor, colData) - str = str:gsub("{output:([%a%.:]+)}", function(c) + str = str:gsub("{output:([%a%.:]+)}", function(c) local ns, var = c:match("^(%a+)%.(%a+)$") if ns then return actor.output[ns] and actor.output[ns][var] or "" @@ -170,7 +170,7 @@ function CalcSectionClass:FormatStr(str, actor, colData) return actor.output[c] or "" end end) - str = str:gsub("{(%d+):output:([%a%.:]+)}", function(p, c) + str = str:gsub("{(%d+):output:([%a%.:]+)}", function(p, c) local ns, var = c:match("^(%a+)%.(%a+)$") if ns then return self:FormatVal(actor.output[ns] and actor.output[ns][var] or 0, tonumber(p)) @@ -210,7 +210,7 @@ function CalcSectionClass:FormatStr(str, actor, colData) if modType == "MORE" then modTotal = (modTotal - 1) * 100 end - return self:FormatVal(modTotal, tonumber(p)) + return self:FormatVal(modTotal, tonumber(p)) end) return str end @@ -226,7 +226,7 @@ function CalcSectionClass:Draw(viewPort, noTooltip) DrawImage(nil, x, y, width, height) SetDrawColor(0.10, 0.10, 0.10) DrawImage(nil, x + 2, y + 2, width - 4, height - 4) - + local primary = true local lineY = y for _, subSec in ipairs(self.subSection) do diff --git a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua index 281c8178cd..0204867efc 100644 --- a/src/Classes/CalcsTab.lua +++ b/src/Classes/CalcsTab.lua @@ -13,7 +13,7 @@ local buffModeDropList = { { label = "Unbuffed", buffMode = "UNBUFFED" }, { label = "Buffed", buffMode = "BUFFED" }, { label = "In Combat", buffMode = "COMBAT" }, - { label = "Effective DPS", buffMode = "EFFECTIVE" } + { label = "Effective DPS", buffMode = "EFFECTIVE" } } local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Control", function(self, build) @@ -37,8 +37,8 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro -- Special section for skill/mode selection self:NewSection(3, "SkillSelect", 1, colorCodes.NORMAL, {{ defaultCollapsed = false, label = "View Skill Details", data = { - { label = "Socket Group", { controlName = "mainSocketGroup", - control = new("DropDownControl", nil, {0, 0, 300, 16}, nil, function(index, value) + { label = "Socket Group", { controlName = "mainSocketGroup", + control = new("DropDownControl", nil, {0, 0, 300, 16}, nil, function(index, value) self.input.skill_number = index self:AddUndoState() self.build.buildFlag = true @@ -51,14 +51,14 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro end } }, }, - { label = "Active Skill", { controlName = "mainSkill", + { label = "Active Skill", { controlName = "mainSkill", control = new("DropDownControl", nil, {0, 0, 300, 16}, nil, function(index, value) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] mainSocketGroup.mainActiveSkillCalcs = index self.build.buildFlag = true end) }, }, - { label = "Skill Part", playerFlag = "multiPart", { controlName = "mainSkillPart", + { label = "Skill Part", playerFlag = "multiPart", { controlName = "mainSkillPart", control = new("DropDownControl", nil, {0, 0, 250, 16}, nil, function(index, value) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance @@ -84,7 +84,7 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro self.build.buildFlag = true end) }, }, - { label = "Show Minion Stats", flag = "haveMinion", { controlName = "showMinion", + { label = "Show Minion Stats", flag = "haveMinion", { controlName = "showMinion", control = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) self.input.showMinion = state self:AddUndoState() @@ -117,10 +117,10 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro self.build.buildFlag = true end) } }, - { label = "Calculation Mode", { - controlName = "mode", - control = new("DropDownControl", nil, {0, 0, 100, 16}, buffModeDropList, function(index, value) - self.input.misc_buffMode = value.buffMode + { label = "Calculation Mode", { + controlName = "mode", + control = new("DropDownControl", nil, {0, 0, 100, 16}, buffModeDropList, function(index, value) + self.input.misc_buffMode = value.buffMode self:AddUndoState() self.build.buildFlag = true end, [[ @@ -130,7 +130,7 @@ The stats in the sidebar are always shown in Effective DPS mode, regardless of t Unbuffed: No auras, buffs, or other support skills or effects will apply. This is equivalent to standing in town. Buffed: Aura and buff skills apply. This is equivalent to standing in your hideout with auras and buffs turned on. In Combat: Charges and combat buffs such as Onslaught will also apply. This will show your character sheet stats in combat. -Effective DPS: Curses and enemy properties (such as resistances and status conditions) will also apply. This estimates your true DPS.]]) +Effective DPS: Curses and enemy properties (such as resistances and status conditions) will also apply. This estimates your true DPS.]]) }, }, { label = "Aura and Buff Skills", flag = "buffs", textSize = 12, { format = "{output:BuffList}", { breakdown = "SkillBuffs" } }, }, { label = "Combat Buffs", flag = "combat", textSize = 12, { format = "{output:CombatList}" }, }, @@ -306,7 +306,7 @@ function CalcsTabClass:Draw(viewPort, inputEvents) section.y = section.y - self.controls.scrollBar.offset section:UpdatePos() end - + self.controls.search.y = 4 - self.controls.scrollBar.offset for _, event in ipairs(inputEvents) do @@ -444,7 +444,7 @@ function CalcsTabClass:BuildOutput() self.controls.breakdown:SetBreakdownData() self.controls.breakdown:SetBreakdownData(self.displayData, self.displayPinned) end - + -- Retrieve calculator functions self.nodeCalculator = { self.calcs.getNodeCalculator(self.build) } self.miscCalculator = { self.calcs.getMiscCalculator(self.build) } @@ -492,7 +492,7 @@ function CalcsTabClass:PowerBuilder() if coroutine.running() then coroutine.yield() end - + local start = GetTime() for nodeId, node in pairs(self.build.spec.nodes) do wipeTable(node.power) diff --git a/src/Classes/ConfigTab.lua b/src/Classes/ConfigTab.lua index 28de4d9598..b53971f499 100644 --- a/src/Classes/ConfigTab.lua +++ b/src/Classes/ConfigTab.lua @@ -27,12 +27,12 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.configSetOrderList = { 1 } self:NewConfigSet(1) self:SetActiveConfigSet(1, true) - + self.enemyLevel = 1 self.sectionList = { } self.varControls = { } - + self.toggleConfigs = false self.controls.sectionAnchor = new("LabelControl", { "TOPLEFT", self, "TOPLEFT" }, { 0, 20, 0, 0 }, "") @@ -756,7 +756,7 @@ function ConfigTabClass:Draw(viewPort, inputEvents) self.height = viewPort.height for _, event in ipairs(inputEvents) do - if event.type == "KeyDown" then + if event.type == "KeyDown" then if event.key == "z" and IsKeyDown("CTRL") then self:Undo() self.build.buildFlag = true @@ -818,7 +818,7 @@ function ConfigTabClass:Draw(viewPort, inputEvents) maxColY = m_max(maxColY, colY[col]) end end - + local newSetList = { } for index, configSetId in ipairs(self.configSetOrderList) do local configSet = self.configSets[configSetId] diff --git a/src/Classes/Control.lua b/src/Classes/Control.lua index 110eb6884e..6b5bb927f7 100644 --- a/src/Classes/Control.lua +++ b/src/Classes/Control.lua @@ -7,15 +7,15 @@ local t_insert = table.insert local m_floor = math.floor local anchorPos = { - ["TOPLEFT"] = { 0 , 0 }, - ["TOP"] = { 0.5, 0 }, - ["TOPRIGHT"] = { 1 , 0 }, - ["RIGHT"] = { 1 , 0.5 }, - ["BOTTOMRIGHT"] = { 1 , 1 }, - ["BOTTOM"] = { 0.5, 1 }, - ["BOTTOMLEFT"] = { 0 , 1 }, - ["LEFT"] = { 0 , 0.5 }, - ["CENTER"] = { 0.5, 0.5 }, + ["TOPLEFT"] = { 0 , 0 }, + ["TOP"] = { 0.5, 0 }, + ["TOPRIGHT"] = { 1 , 0 }, + ["RIGHT"] = { 1 , 0.5 }, + ["BOTTOMRIGHT"] = { 1 , 1 }, + ["BOTTOM"] = { 0.5, 1 }, + ["BOTTOMLEFT"] = { 0 , 1 }, + ["LEFT"] = { 0 , 0.5 }, + ["CENTER"] = { 0.5, 0.5 }, } --[[ @@ -25,7 +25,7 @@ local rect = { width, height, } - + could possibly have minWidth, minHeight, diff --git a/src/Classes/ControlHost.lua b/src/Classes/ControlHost.lua index 30f1573cbf..c0e4b16e7c 100644 --- a/src/Classes/ControlHost.lua +++ b/src/Classes/ControlHost.lua @@ -56,7 +56,7 @@ function ControlHostClass:ProcessControlsInput(inputEvents, viewPort) if selControl.OnKeyUp then self:SelectControl(selControl:OnKeyUp(event.key)) end - + inputEvents[id] = nil end @@ -68,7 +68,7 @@ function ControlHostClass:ProcessControlsInput(inputEvents, viewPort) if not selControl and mOverControl.OnKeyUp and mOverControl:OnKeyUp(event.key) then inputEvents[id] = nil end - + if mOverControl.OnHoverKeyUp then mOverControl:OnHoverKeyUp(event.key) end @@ -82,7 +82,7 @@ function ControlHostClass:ProcessControlsInput(inputEvents, viewPort) inputEvents[id] = nil end end - end + end end function ControlHostClass:DrawControls(viewPort, selControl) diff --git a/src/Classes/DraggerControl.lua b/src/Classes/DraggerControl.lua index de331cbb04..3212a191a1 100644 --- a/src/Classes/DraggerControl.lua +++ b/src/Classes/DraggerControl.lua @@ -116,7 +116,7 @@ function DraggerClass:OnKeyDown(key) if self.onKeyDown then self.onKeyDown({ X = cursorX, Y = cursorY }) end - + self.cursorX = cursorX self.cursorY = cursorY end diff --git a/src/Classes/DropDownControl.lua b/src/Classes/DropDownControl.lua index bd75e93f1d..44ceff83d3 100644 --- a/src/Classes/DropDownControl.lua +++ b/src/Classes/DropDownControl.lua @@ -238,7 +238,7 @@ function DropDownClass:Draw(viewPort, noTooltip) -- fit dropHeight to filtered content but keep initial orientation self.dropHeight = m_max(m_min(self.dropHeight, self:GetDropCount() * lineHeight), lineHeight) - + local mOver, mOverComp = self:IsMouseOver() local dropExtra = self.dropHeight + 4 scrollBar:SetContentDimension(lineHeight * self:GetDropCount(), self.dropHeight) @@ -291,8 +291,8 @@ function DropDownClass:Draw(viewPort, noTooltip) if (mOver or self.dropped) and mOverComp ~= "DROP" and not noTooltip then SetDrawLayer(nil, 100) self:DrawTooltip( - x, y - (self.dropped and self.dropUp and dropExtra or 0), - width, height + (self.dropped and dropExtra or 0), + x, y - (self.dropped and self.dropUp and dropExtra or 0), + width, height + (self.dropped and dropExtra or 0), viewPort, mOver and "BODY" or "OUT", self.selIndex, self.list[self.selIndex]) SetDrawLayer(nil, 0) @@ -385,7 +385,7 @@ function DropDownClass:Draw(viewPort, noTooltip) if type(listVal) == "table" then label = listVal.label detail = listVal.detail - else + else label = listVal end DrawString(0, y, "LEFT", lineHeight, "VAR", label) @@ -517,7 +517,7 @@ function DropDownClass:SetList(textList) if textList then wipeTable(self.list) self.list = textList - --check width on new list + --check width on new list self:CheckDroppedWidth(self.enableDroppedWidth) end end @@ -531,16 +531,16 @@ function DropDownClass:CheckDroppedWidth(enable) end local lineHeight = self.height - 4 - -- do not be smaller than the created width + -- do not be smaller than the created width local dWidth = self.width for _, line in ipairs(self.list) do if type(line) == "table" then line = line.label or "" end - -- +10 to stop clipping + -- +10 to stop clipping dWidth = m_max(dWidth, DrawStringWidth(lineHeight, "VAR", line) + 10) end - -- no greater than self.maxDroppedWidth + -- no greater than self.maxDroppedWidth self.droppedWidth = m_min(dWidth + scrollWidth, self.maxDroppedWidth) if self.enableChangeBoxWidth then local line = self.list[self.selIndex] @@ -552,7 +552,7 @@ function DropDownClass:CheckDroppedWidth(enable) boxWidth = DrawStringWidth(lineHeight, "VAR", line or "") + 20 self.width = m_max(m_min(boxWidth, 390), 190) end - + self.controls.scrollBar.x = self.droppedWidth - self.width - 1 else self.droppedWidth = self.width diff --git a/src/Classes/EditControl.lua b/src/Classes/EditControl.lua index 2964057adf..a9fa168590 100644 --- a/src/Classes/EditControl.lua +++ b/src/Classes/EditControl.lua @@ -187,7 +187,7 @@ function EditClass:ZoomText(zoom) end local textHeight = self.lineHeight - if zoom == "+" then + if zoom == "+" then textHeight = textHeight + 1 elseif zoom == "-" then textHeight = textHeight - 1 @@ -586,7 +586,7 @@ function EditClass:OnKeyDown(key, doubleClick) if self.lineHeight and not ctrl then self.caret = self.caret + #self.buf:sub(self.caret, -1):match("[^\n]*") else - self.caret = #self.buf + 1 + self.caret = #self.buf + 1 end self.lastUndoState.caret = self.caret self:ScrollCaretIntoView() diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index e47744bacc..06d1c727b2 100644 --- a/src/Classes/GemSelectControl.lua +++ b/src/Classes/GemSelectControl.lua @@ -99,9 +99,9 @@ function GemSelectClass:CalcOutputWithThisGem(calcFunc, gemData, qualityId, useF else gemList[self.index] = nil end - + self.skillsTab.displayGroup.displayGemList = displayGemList - + return output, gemInstance end diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index 2a6264140a..8843047b73 100644 --- a/src/Classes/ImportTab.lua +++ b/src/Classes/ImportTab.lua @@ -191,7 +191,7 @@ You can get this from your web browser's cookies while logged into the Path of E end) self.controls.enablePartyExportBuffs = new("CheckBoxControl", {"LEFT",self.controls.generateCode,"RIGHT"}, {100, 0, 18}, "Export Support", function(state) self.build.partyTab.enableExportBuffs = state - self.build.buildFlag = true + self.build.buildFlag = true end, "This is for party play, to export support character, it enables the exporting of auras, curses and modifiers to the enemy", false) self.controls.generateCodeOut = new("EditControl", {"TOPLEFT",self.controls.generateCodeLabel,"BOTTOMLEFT"}, {0, 8, 250, 20}, "", "Code", "%Z") self.controls.generateCodeOut.enabled = function() @@ -397,7 +397,7 @@ function ImportTabClass:Save(xml) xml.attrib.importLink = self.build.importLink end -- Gets rid of erroneous, potentially infinitely nested full base64 XML stored as an import link - xml.attrib.importLink = (xml.attrib.importLink and xml.attrib.importLink:len() < 100) and xml.attrib.importLink or nil + xml.attrib.importLink = (xml.attrib.importLink and xml.attrib.importLink:len() < 100) and xml.attrib.importLink or nil end function ImportTabClass:Draw(viewPort, inputEvents) @@ -700,12 +700,12 @@ function ImportTabClass:ImportPassiveTreeAndJewels(json, charData) end end - self.build.spec:ImportFromNodeList(charPassiveData.character, - charPassiveData.ascendancy, - charPassiveData.alternate_ascendancy or 0, - charPassiveData.hashes, - charPassiveData.skill_overrides, - charPassiveData.mastery_effects or {}, + self.build.spec:ImportFromNodeList(charPassiveData.character, + charPassiveData.ascendancy, + charPassiveData.alternate_ascendancy or 0, + charPassiveData.hashes, + charPassiveData.skill_overrides, + charPassiveData.mastery_effects or {}, latestTreeVersion .. (charData.league:match("Ruthless") and "_ruthless" or "") .. (isAscendancyInTree(charData.class, latestTreeVersion) and "" or "_alternate") ) self.build.treeTab:SetActiveSpec(self.build.treeTab.activeSpec) @@ -719,7 +719,7 @@ function ImportTabClass:ImportPassiveTreeAndJewels(json, charData) local resistancePenaltyIndex = 3 if self.build.Act then -- Estimate resistance penalty setting based on act progression estimate if type(self.build.Act) == "string" and self.build.Act == "Endgame" then resistancePenaltyIndex = 3 - elseif type(self.build.Act) == "number" then + elseif type(self.build.Act) == "number" then if self.build.Act < 5 then resistancePenaltyIndex = 1 elseif self.build.Act > 5 and self.build.Act < 11 then resistancePenaltyIndex = 2 elseif self.build.Act > 10 then resistancePenaltyIndex = 3 end @@ -1087,7 +1087,7 @@ function ImportTabClass:ImportSocketedItems(item, socketedItems, slotName) local normalizedBasename, qualityType = self.build.skillsTab:GetBaseNameAndQuality(socketedItem.typeLine, nil) local gemId = self.build.data.gemForBaseName[normalizedBasename:lower()] if socketedItem.hybrid then - -- Used by transfigured gems and dual-skill gems (currently just Stormbind) + -- Used by transfigured gems and dual-skill gems (currently just Stormbind) normalizedBasename, qualityType = self.build.skillsTab:GetBaseNameAndQuality(socketedItem.hybrid.baseTypeName, nil) gemId = self.build.data.gemForBaseName[normalizedBasename:lower()] if gemId and socketedItem.hybrid.isVaalGem then diff --git a/src/Classes/Item.lua b/src/Classes/Item.lua index 7d7b5e7029..b4e44991c1 100644 --- a/src/Classes/Item.lua +++ b/src/Classes/Item.lua @@ -53,7 +53,7 @@ local influenceInfo = itemLib.influenceInfo.all local ItemClass = newClass("Item", function(self, raw, rarity, highQuality) if raw then self:ParseRaw(sanitiseText(raw), rarity, highQuality) - end + end end) -- Reset all influence keys to false @@ -367,7 +367,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality) local gameModeStage = "FINDIMPLICIT" local foundExplicit, foundImplicit - while self.rawLines[l] do + while self.rawLines[l] do local line = self.rawLines[l] if flaskBuffLines and flaskBuffLines[line] then flaskBuffLines[line] = nil @@ -437,14 +437,14 @@ function ItemClass:ParseRaw(raw, rarity, highQuality) elseif specName == "Radius" and self.type == "Jewel" then self.jewelRadiusLabel = specVal:match("^%a+") if specVal:match("^%a+") == "Variable" then - -- Jewel radius is variable and must be read from it's mods instead after they are parsed - deferJewelRadiusIndexAssignment = true - else - for index, data in pairs(data.jewelRadius) do - if specVal:match("^%a+") == data.label then - self.jewelRadiusIndex = index - break - end + -- Jewel radius is variable and must be read from it's mods instead after they are parsed + deferJewelRadiusIndexAssignment = true + else + for index, data in pairs(data.jewelRadius) do + if specVal:match("^%a+") == data.label then + self.jewelRadiusIndex = index + break + end end end elseif specName == "Limited to" and self.type == "Jewel" then @@ -570,11 +570,11 @@ function ItemClass:ParseRaw(raw, rarity, highQuality) elseif specName == "Note" then self.note = specVal elseif specName == "Str" or specName == "Strength" or specName == "Dex" or specName == "Dexterity" or - specName == "Int" or specName == "Intelligence" then + specName == "Int" or specName == "Intelligence" then self.requirements[specName:sub(1,3):lower()] = specToNumber(specVal) elseif specName == "Critical Strike Range" or specName == "Attacks per Second" or specName == "Weapon Range" or - specName == "Critical Strike Chance" or specName == "Physical Damage" or specName == "Elemental Damage" or - specName == "Chaos Damage" or specName == "Chance to Block" or specName == "Block chance" or + specName == "Critical Strike Chance" or specName == "Physical Damage" or specName == "Elemental Damage" or + specName == "Chaos Damage" or specName == "Chance to Block" or specName == "Block chance" or specName == "Armour" or specName == "Energy Shield" or specName == "Evasion" then self.hidden_specs = true -- Anything else is an explicit with a colon in it (Fortress Covenant, Pure Talent, etc) unless it's part of the custom name @@ -836,7 +836,7 @@ function ItemClass:ParseRaw(raw, rarity, highQuality) end self.affixLimit = 0 if self.crafted then - if not self.affixes then + if not self.affixes then self.crafted = false elseif self.rarity == "MAGIC" then if self.prefixes.limit or self.suffixes.limit then @@ -926,7 +926,7 @@ function ItemClass:NormaliseQuality() elseif not self.uniqueID and not self.corrupted and not self.split and not self.mirrored and self.quality < 20 then self.quality = 20 end - end + end end function ItemClass:GetModSpawnWeight(mod, includeTags, excludeTags) @@ -1095,7 +1095,7 @@ function ItemClass:BuildRaw() if baseLine.variantList then writeModLine(baseLine) end - end + end if self.hasAltVariant then t_insert(rawLines, "Has Alt Variant: true") t_insert(rawLines, "Selected Alt Variant: " .. self.variantAlt) @@ -1228,7 +1228,7 @@ function ItemClass:Craft() end end statOrder[order] = modLine - end + end end end end @@ -1243,7 +1243,7 @@ function ItemClass:Craft() end function ItemClass:CheckModLineVariant(modLine) - return not modLine.variantList + return not modLine.variantList or modLine.variantList[self.variant] or (self.hasAltVariant and modLine.variantList[self.variantAlt]) or (self.hasAltVariant2 and modLine.variantList[self.variantAlt2]) @@ -1341,7 +1341,7 @@ function ItemClass:BuildModListForSlotNum(baseList, slotNum) local groupCounts = {} for _, socket in ipairs(self.sockets) do local group = socket.group - groupCounts[group] = (groupCounts[group] or 0) + 1 + groupCounts[group] = (groupCounts[group] or 0) + 1 if multiName[socket.color] then modList:NewMod(multiName[socket.color], "BASE", 1, "Item Sockets") end @@ -1579,11 +1579,11 @@ function ItemClass:BuildModListForSlotNum(baseList, slotNum) if jewelData.clusterJewelSkill and not self.clusterJewel.skills[jewelData.clusterJewelSkill] then jewelData.clusterJewelSkill = nil end - jewelData.clusterJewelValid = jewelData.clusterJewelKeystone - or ((jewelData.clusterJewelSkill or jewelData.clusterJewelSmallsAreNothingness) and jewelData.clusterJewelNodeCount) + jewelData.clusterJewelValid = jewelData.clusterJewelKeystone + or ((jewelData.clusterJewelSkill or jewelData.clusterJewelSmallsAreNothingness) and jewelData.clusterJewelNodeCount) or (jewelData.clusterJewelSocketCountOverride and jewelData.clusterJewelNothingnessCount) end - end + end return { unpack(modList) } end @@ -1628,7 +1628,7 @@ function ItemClass:BuildModList() if modLine.range then -- Check if line actually has a range if modLine.line:find("%((%-?%d+%.?%d*)%-(%-?%d+%.?%d*)%)") then - local strippedModeLine = modLine.line:gsub("\n"," ") + local strippedModeLine = modLine.line:gsub("\n"," ") local catalystScalar = getCatalystScalar(self.catalyst, modLine.modTags, self.catalystQuality) -- Put the modified value into the string local line = itemLib.applyRange(strippedModeLine, modLine.range, catalystScalar) @@ -1706,7 +1706,7 @@ function ItemClass:BuildModList() -- Force the socket count to be equal to the stated number self.selectableSocketCount = socketCount local group = 0 - for i = 1, m_max(socketCount, #self.sockets) do + for i = 1, m_max(socketCount, #self.sockets) do if i > socketCount then self.sockets[i] = nil elseif not self.sockets[i] then diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 1f7ec7e3c8..87906da12e 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -15,7 +15,7 @@ local m_ceil = math.ceil local m_floor = math.floor local m_modf = math.modf -local rarityDropList = { +local rarityDropList = { { label = colorCodes.NORMAL.."Normal", rarity = "NORMAL" }, { label = colorCodes.MAGIC.."Magic", rarity = "MAGIC" }, { label = colorCodes.RARE.."Rare", rarity = "RARE" }, @@ -53,7 +53,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self.Control() self.build = build - + self.socketViewer = new("PassiveTreeView") self.items = { } @@ -123,7 +123,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro return self.activeItemSet.useSecondWeaponSet end for i = 1, 6 do - local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap Abyssal Socket "..i, "Abyssal #"..i) + local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap Abyssal Socket "..i, "Abyssal #"..i) addSlot(abyssal) abyssal.parentSlot = swapSlot abyssal.weaponSet = 2 @@ -136,7 +136,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro if slotName == "Weapon 1" or slotName == "Weapon 2" or slotName == "Helmet" or slotName == "Gloves" or slotName == "Body Armour" or slotName == "Boots" or slotName == "Belt" then -- Add Abyssal Socket slots for i = 1, 6 do - local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Abyssal Socket "..i, "Abyssal #"..i) + local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Abyssal Socket "..i, "Abyssal #"..i) addSlot(abyssal) abyssal.parentSlot = slot if slotName:match("Weapon") then @@ -260,23 +260,23 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self:CraftItem() end) self.controls.craftDisplayItem.shown = function() - return self.displayItem == nil + return self.displayItem == nil end self.controls.newDisplayItem = new("ButtonControl", {"TOPLEFT",self.controls.craftDisplayItem,"TOPRIGHT"}, {8, 0, 120, 20}, "Create custom...", function() self:EditDisplayItemText() end) - self.controls.displayItemTip = new("LabelControl", {"TOPLEFT",self.controls.craftDisplayItem,"BOTTOMLEFT"}, {0, 8, 100, 16}, + self.controls.displayItemTip = new("LabelControl", {"TOPLEFT",self.controls.craftDisplayItem,"BOTTOMLEFT"}, {0, 8, 100, 16}, [[^7Double-click an item from one of the lists, or copy and paste an item from in game (hover over the item and Ctrl+C) to view or edit -the item and add it to your build. You can -also clone an item within Path of Building by +the item and add it to your build. You can +also clone an item within Path of Building by copying and pasting it with Ctrl+C and Ctrl+V. -You can Control + Click an item to equip it, or -drag it onto the slot. This will also add it to +You can Control + Click an item to equip it, or +drag it onto the slot. This will also add it to your build if it's from the unique/template list. -If there's 2 slots an item can go in, +If there's 2 slots an item can go in, holding Shift will put it in the second.]]) self.controls.sharedItemList = new("SharedItemListControl", {"TOPLEFT",self.controls.craftDisplayItem, "BOTTOMLEFT"}, {0, 232, 340, 308}, self, true) @@ -306,11 +306,11 @@ holding Shift will put it in the second.]]) if not self.controls.displayItemVariant:IsShown() then return 0 end - return (28 + - (self.displayItem.hasAltVariant and 24 or 0) + - (self.displayItem.hasAltVariant2 and 24 or 0) + + return (28 + + (self.displayItem.hasAltVariant and 24 or 0) + + (self.displayItem.hasAltVariant2 and 24 or 0) + (self.displayItem.hasAltVariant3 and 24 or 0) + - (self.displayItem.hasAltVariant4 and 24 or 0) + + (self.displayItem.hasAltVariant4 and 24 or 0) + (self.displayItem.hasAltVariant5 and 24 or 0)) end}) self.controls.displayItemVariant = new("DropDownControl", {"TOPLEFT", self.controls.displayItemSectionVariant,"TOPLEFT"}, {0, 0, 300, 20}, nil, function(index, value) @@ -424,7 +424,7 @@ holding Shift will put it in the second.]]) self.controls.displayItemAddSocket.shown = function() return #self.displayItem.sockets < self.displayItem.selectableSocketCount + self.displayItem.abyssalSocketCount end - + -- Section: Enchant / Anoint / Corrupt self.controls.displayItemSectionEnchant = new("Control", {"TOPLEFT",self.controls.displayItemSectionSockets,"BOTTOMLEFT"}, {0, 0, 0, function() return (self.controls.displayItemEnchant:IsShown() or self.controls.displayItemEnchant2:IsShown() or self.controls.displayItemAnoint:IsShown() or self.controls.displayItemAnoint2:IsShown() or self.controls.displayItemCorrupt:IsShown() ) and 28 or 0 @@ -494,7 +494,7 @@ holding Shift will put it in the second.]]) self.controls.displayItemAddImplicit.shown = function() return self.displayItem and self.displayItem.type ~= "Tincture" and (self.displayItem.corruptible or ((self.displayItem.type ~= "Flask" and self.displayItem.type ~= "Jewel") and - (self.displayItem.rarity == "NORMAL" or self.displayItem.rarity == "MAGIC" or self.displayItem.rarity == "RARE"))) and + (self.displayItem.rarity == "NORMAL" or self.displayItem.rarity == "MAGIC" or self.displayItem.rarity == "RARE"))) and not self.displayItem.implicitsCannotBeChanged end @@ -617,7 +617,7 @@ holding Shift will put it in the second.]]) return self.displayItem and self.displayItem.crafted and self.displayItem.clusterJewel end } - + self.controls.displayItemClusterJewelNodeCountLabel = new("LabelControl", {"TOPLEFT",self.controls.displayItemClusterJewelSkill,"BOTTOMLEFT"}, {0, 7, 0, 14}, "^7Added Passives:") self.controls.displayItemClusterJewelNodeCount = new("SliderControl", {"LEFT",self.controls.displayItemClusterJewelNodeCountLabel,"RIGHT"}, {2, 0, 150, 20}, function(val) local divVal = self.controls.displayItemClusterJewelNodeCount:GetDivVal() @@ -673,7 +673,7 @@ holding Shift will put it in the second.]]) end return false end - + if priorMod then if flipRange(priorMod, self.displayItem.affixes[drop.list[drop.selIndex].modList[index]]) then range = 1 - range @@ -811,7 +811,7 @@ holding Shift will put it in the second.]]) else mod = self.displayItem.affixes[modList[1 + round((#modList - 1) * main.defaultItemAffixQuality)]] end - + -- Adding Mod self:AddModComparisonTooltip(tooltip, mod) end @@ -1056,17 +1056,17 @@ function ItemsTabClass:Save(xml) } for _, id in ipairs(self.itemOrderList) do local item = self.items[id] - local child = { - elem = "Item", - attrib = { - id = tostring(id), - variant = item.variant and tostring(item.variant), - variantAlt = item.variantAlt and tostring(item.variantAlt), + local child = { + elem = "Item", + attrib = { + id = tostring(id), + variant = item.variant and tostring(item.variant), + variantAlt = item.variantAlt and tostring(item.variantAlt), variantAlt2 = item.variantAlt2 and tostring(item.variantAlt2), - variantAlt3 = item.variantAlt3 and tostring(item.variantAlt3), - variantAlt4 = item.variantAlt4 and tostring(item.variantAlt4), + variantAlt3 = item.variantAlt3 and tostring(item.variantAlt3), + variantAlt4 = item.variantAlt4 and tostring(item.variantAlt4), variantAlt5 = item.variantAlt5 and tostring(item.variantAlt5) - } + } } item:BuildAndParseRaw() t_insert(child, item.raw) @@ -1177,9 +1177,9 @@ function ItemsTabClass:Draw(viewPort, inputEvents) end self.x = self.x - self.controls.scrollBarH.offset self.y = self.y - self.controls.scrollBarV.offset - + for _, event in ipairs(inputEvents) do - if event.type == "KeyDown" then + if event.type == "KeyDown" then if event.key == "v" and IsKeyDown("CTRL") then local newItem = Paste() if newItem:find("{ ", 0, true) then @@ -1410,12 +1410,12 @@ function ItemsTabClass:AddItem(item, noAutoEquip, index) end end end - + -- Add it to the list local replacing = self.items[item.id] self.items[item.id] = item item:BuildModList() - + if replacing and (replacing.clusterJewel or item.clusterJewel or replacing.baseName == "Timeless Jewel") then -- We're replacing an existing item, and either the new or old one is a cluster jewel if isValueInTable(self.build.spec.jewels, item.id) then @@ -1688,7 +1688,7 @@ function ItemsTabClass:UpdateAffixControls() else self:UpdateAffixControl(self.controls["displayItemAffix"..i], item, "Suffix", "suffixes", i - prefixLimit) end - end + end -- The custom affixes may have had their indexes changed, so the custom control UI is also rebuilt so that it will -- reference the correct affix index. self:UpdateCustomControls() @@ -1714,7 +1714,7 @@ function ItemsTabClass:UpdateAffixControl(control, item, type, outputTable, outp end end end - if item.clusterJewel and item.clusterJewelSkill then + if item.clusterJewel and item.clusterJewelSkill then local skill = item.clusterJewel.skills[item.clusterJewelSkill] if skill then extraTags[skill.tag] = true @@ -1836,7 +1836,7 @@ function ItemsTabClass:UpdateCustomControls() local id = item.id self:CreateDisplayItemFromRaw(item:BuildRaw()) self.displayItem.id = id - end + end i = i + 1 end end @@ -1874,7 +1874,7 @@ end function ItemsTabClass:AddModComparisonTooltip(tooltip, mod) local slotName = self.displayItem:GetPrimarySlot() local newItem = new("Item", self.displayItem:BuildRaw()) - + for _, subMod in ipairs(mod) do t_insert(newItem.explicitModLines, { line = checkLineForAllocates(subMod, self.build.spec.nodes), modTags = mod.modTags, [mod.type] = true }) end @@ -1884,7 +1884,7 @@ function ItemsTabClass:AddModComparisonTooltip(tooltip, mod) local calcFunc = self.build.calcsTab:GetMiscCalculator() local outputBase = calcFunc({ repSlotName = slotName, repItem = self.displayItem }) local outputNew = calcFunc({ repSlotName = slotName, repItem = newItem }) - self.build:AddStatComparesToTooltip(tooltip, outputBase, outputNew, "\nAdding this mod will give: ") + self.build:AddStatComparesToTooltip(tooltip, outputBase, outputNew, "\nAdding this mod will give: ") end -- Returns the first slot in which the given item is equipped @@ -1990,7 +1990,7 @@ function ItemsTabClass:CraftItem() local raritySel = controls.rarity.selIndex if base.base.flask or (base.base.type == "Jewel" and base.base.subType == "Charm") - or base.base.type == "Tincture" + or base.base.type == "Tincture" then if raritySel == 3 then raritySel = 2 @@ -2102,7 +2102,7 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) tooltip:AddLine(14, "For Normal and Magic items, the base name must be somewhere in the first line. E.g.:") tooltip:AddLine(14, "Scholar's Platinum Kris of Joy") end - end + end controls.cancel = new("ButtonControl", nil, {45, 470, 80, 20}, "Cancel", function() main:ClosePopup() end) @@ -2113,7 +2113,7 @@ end function ItemsTabClass:EnchantDisplayItem(enchantSlot) self.enchantSlot = enchantSlot or 1 - local controls = { } + local controls = { } local enchantments = self.displayItem.enchantments local haveSkills = true for _, source in ipairs(self.build.data.enchantmentSource) do @@ -2127,7 +2127,7 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) if haveSkills then for _, socketGroup in ipairs(self.build.skillsTab.socketGroupList) do for _, gemInstance in ipairs(socketGroup.gemList) do - if gemInstance.gemData then + if gemInstance.gemData then for _, grantedEffect in ipairs(gemInstance.gemData.grantedEffectList) do if not grantedEffect.support and enchantments[grantedEffect.name] then skillsUsed[grantedEffect.name] = true @@ -2332,7 +2332,7 @@ end function ItemsTabClass:AnointDisplayItem(enchantSlot) self.anointEnchantSlot = enchantSlot or 1 - local controls = { } + local controls = { } controls.notableDB = new("NotableDBControl", {"TOPLEFT",nil,"TOPLEFT"}, {10, 60, 360, 360}, self, self.build.spec.tree.nodes, "ANOINT") local function saveLabel() @@ -2361,7 +2361,7 @@ function ItemsTabClass:AnointDisplayItem(enchantSlot) controls.save.tooltipFunc = function(tooltip) tooltip:Clear() self:AppendAnointTooltip(tooltip, controls.notableDB.selValue) - end + end controls.close = new("ButtonControl", {"TOPLEFT", controls.save, "TOPRIGHT" }, {10, 0, 80, 20}, "Cancel", function() main:ClosePopup() end) @@ -2371,7 +2371,7 @@ end -- Opens the item corrupting popup function ItemsTabClass:CorruptDisplayItem(modType) local currentModType = modType or "Corrupted" - local controls = { } + local controls = { } local implicitList = { } local sourceList = { "Corrupted", "Scourge" } local function buildImplicitList(modType) @@ -2555,7 +2555,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) controls.save.tooltipFunc = function(tooltip) tooltip:Clear() self:AddItemTooltip(tooltip, corruptItem(), nil, true) - end + end controls.close = new("ButtonControl", nil, {45, 99, 80, 20}, "Cancel", function() main:ClosePopup() end) @@ -2786,11 +2786,11 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() controls.save.tooltipFunc = function(tooltip) tooltip:Clear() self:AddItemTooltip(tooltip, addModifier()) - end + end controls.close = new("ButtonControl", nil, {45, 75, 80, 20}, "Cancel", function() main:ClosePopup() end) - main:OpenPopup(710, 105, "Add Modifier to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") + main:OpenPopup(710, 105, "Add Modifier to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") end -- Opens the crucible modifier popup @@ -2818,7 +2818,7 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() includeTags["minion_unique_weapon"] = true end if self.displayItem.canHaveOnlySupportSkillsCrucibleTree then - return keyMap["crucible_unique_staff"] and mod.weightVal[keyMap["crucible_unique_staff"]] ~= 0 + return keyMap["crucible_unique_staff"] and mod.weightVal[keyMap["crucible_unique_staff"]] ~= 0 elseif self.displayItem.canHaveShieldCrucibleTree then return self.displayItem:GetModSpawnWeight(mod, { ["crucible_unique_helmet"] = true, ["shield"] = true }) > 0 elseif self.displayItem.canHaveTwoHandedSwordCrucibleTree then @@ -3173,11 +3173,11 @@ function ItemsTabClass:AddImplicitToDisplayItem() controls.save.tooltipFunc = function(tooltip) tooltip:Clear() self:AddItemTooltip(tooltip, addModifier()) - end + end controls.close = new("ButtonControl", nil, {45, 100, 80, 20}, "Cancel", function() main:ClosePopup() end) - main:OpenPopup(710, 130, "Add Implicit to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") + main:OpenPopup(710, 130, "Add Implicit to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") end function ItemsTabClass:AddItemSetTooltip(tooltip, itemSet) @@ -3273,7 +3273,7 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode) end tooltip:AddLine(16, elemLine) tooltip:AddLine(16, s_format("^x7F7F7FElemental DPS: "..colorCodes.MAGIC.."%.1f", weaponData.ElementalDPS)) - totalDamageTypes = totalDamageTypes + 1 + totalDamageTypes = totalDamageTypes + 1 end if weaponData.ChaosDPS then tooltip:AddLine(16, s_format("^x7F7F7FChaos Damage: "..colorCodes.CHAOS.."%d-%d "..colorCodes.MAGIC.."(%.1f DPS)", weaponData.ChaosMin, weaponData.ChaosMax, weaponData.ChaosDPS)) @@ -3355,7 +3355,7 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode) elseif base.tincture then -- Tincture-specific info local tinctureData = item.tinctureData - + if item.quality and item.quality > 0 then tooltip:AddLine(16, s_format("^x7F7F7FQuality: "..colorCodes.MAGIC.."+%d%%", item.quality)) end @@ -3396,7 +3396,7 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode) end end end - + if item.catalyst and item.catalyst > 0 and item.catalyst <= #catalystQualityFormat and item.catalystQuality and item.catalystQuality > 0 then tooltip:AddLine(16, s_format(catalystQualityFormat[item.catalyst], item.catalystQuality)) tooltip:AddSeparator(10) @@ -3439,8 +3439,8 @@ function ItemsTabClass:AddItemTooltip(tooltip, item, slot, dbMode) end -- Requirements - self.build:AddRequirementsToTooltip(tooltip, item.requirements.level, - item.requirements.strMod, item.requirements.dexMod, item.requirements.intMod, + self.build:AddRequirementsToTooltip(tooltip, item.requirements.level, + item.requirements.strMod, item.requirements.dexMod, item.requirements.intMod, item.requirements.str or 0, item.requirements.dex or 0, item.requirements.int or 0) -- Modifiers diff --git a/src/Classes/ListControl.lua b/src/Classes/ListControl.lua index 34dd0e7f41..cea91433b4 100644 --- a/src/Classes/ListControl.lua +++ b/src/Classes/ListControl.lua @@ -163,10 +163,10 @@ function ListClass:Draw(viewPort, noTooltip) end end end - if self.selDragActive and self.dragTargetList then - self.dragTarget = nil + if self.selDragActive and self.dragTargetList then + self.dragTarget = nil for _, target in ipairs(self.dragTargetList) do - if not self.dragTarget and target.otherDragSource == self and target:IsMouseOver() then + if not self.dragTarget and target.otherDragSource == self and target:IsMouseOver() then self.dragTarget = target target.otherDragTargeting = true else @@ -175,7 +175,7 @@ function ListClass:Draw(viewPort, noTooltip) end end - local label = self:GetProperty("label") + local label = self:GetProperty("label") if label then DrawString(x + self.labelPositionOffset[1], y - 20 + self.labelPositionOffset[2], "LEFT", 16, self.font, label) end @@ -213,7 +213,7 @@ function ListClass:Draw(viewPort, noTooltip) local value = list[index] local text = self:GetRowValue(colIndex, index, value) local icon = nil - if self.GetRowIcon then + if self.GetRowIcon then icon = self:GetRowIcon(colIndex, index, value) end local textWidth = DrawStringWidth(textHeight, colFont, text) @@ -440,7 +440,7 @@ function ListClass:OnKeyUp(key) end self.selValue = nil end - if self.dragTargetList then + if self.dragTargetList then for _, target in ipairs(self.dragTargetList) do target.otherDragSource = nil target.otherDragTargeting = false diff --git a/src/Classes/MinionListControl.lua b/src/Classes/MinionListControl.lua index 1bd119853c..bdec3a250b 100644 --- a/src/Classes/MinionListControl.lua +++ b/src/Classes/MinionListControl.lua @@ -59,10 +59,10 @@ function MinionListClass:AddValueTooltip(tooltip, index, minionId) if minion.evasion then tooltip:AddLine(14, s_format("^7Evasion Multiplier: x%.2f", 1 + minion.evasion)) end - tooltip:AddLine(14, s_format("^7Resistances: %s%d^7/%s%d^7/%s%d^7/%s%d", - colorCodes.FIRE, minion.fireResist, - colorCodes.COLD, minion.coldResist, - colorCodes.LIGHTNING, minion.lightningResist, + tooltip:AddLine(14, s_format("^7Resistances: %s%d^7/%s%d^7/%s%d^7/%s%d", + colorCodes.FIRE, minion.fireResist, + colorCodes.COLD, minion.coldResist, + colorCodes.LIGHTNING, minion.lightningResist, colorCodes.CHAOS, minion.chaosResist )) tooltip:AddLine(14, s_format("^7Base Damage: x%.2f", minion.damage)) diff --git a/src/Classes/MinionSearchListControl.lua b/src/Classes/MinionSearchListControl.lua index f0f4d28e13..97b5ed84a4 100644 --- a/src/Classes/MinionSearchListControl.lua +++ b/src/Classes/MinionSearchListControl.lua @@ -9,14 +9,14 @@ local t_remove = table.remove local s_format = string.format local MinionSearchListClass = newClass("MinionSearchListControl", "MinionListControl", function(self, anchor, rect, data, list, dest) - self.MinionListControl(anchor, rect, data, list, dest) + self.MinionListControl(anchor, rect, data, list, dest) self.unfilteredList = copyTable(list) self.isMutable = false self.controls.searchText = new("EditControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 128, 18}, "", "Search", "%c", 100, function(buf) self:ListFilterChanged(buf, self.controls.searchModeDropDown.selIndex) - end, nil, nil, true) - + end, nil, nil, true) + self.controls.searchModeDropDown = new("DropDownControl", {"LEFT",self.controls.searchText,"RIGHT"}, {2, 0, 60, 18}, { "Names", "Skills", "Both"}, function(index, value) self:ListFilterChanged(self.controls.searchText.buf, index) end) diff --git a/src/Classes/ModDB.lua b/src/Classes/ModDB.lua index f60ac59e49..277253c46c 100644 --- a/src/Classes/ModDB.lua +++ b/src/Classes/ModDB.lua @@ -61,7 +61,7 @@ function ModDBClass:ReplaceModInternal(mod) if self.parent then return self.parent:ReplaceModInternal(mod) end - + return false end diff --git a/src/Classes/ModList.lua b/src/Classes/ModList.lua index 92851c1805..6e41bdc73a 100644 --- a/src/Classes/ModList.lua +++ b/src/Classes/ModList.lua @@ -41,7 +41,7 @@ function ModListClass:ReplaceModInternal(mod) if self.parent then return self.parent:ReplaceModInternal(mod) end - + return false end diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index 3969a77e46..2bc2bd6f40 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -202,9 +202,9 @@ function ModStoreClass:Max(cfg, ...) local val = self:EvalMod(value.mod, cfg) if val > (max or 0) then max = val - end + end end - return max + return max end ---HasMod @@ -390,7 +390,7 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) limitTotal = limit else mult = m_min(mult, limit) - end + end end if type(value) == "table" then value = copyTable(value) @@ -439,7 +439,7 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) limitTotal = limit else mult = m_min(mult, limit) - end + end end if type(value) == "table" then value = copyTable(value) @@ -653,7 +653,7 @@ function ModStoreClass:EvalMod(mod, cfg, globalLimits) end return false end - + local match = {} if tag.slotName then match["slotName"] = (tag.slotName == cfg.slotName) or false diff --git a/src/Classes/NotableDBControl.lua b/src/Classes/NotableDBControl.lua index d08ec4080c..e4fc7815ba 100644 --- a/src/Classes/NotableDBControl.lua +++ b/src/Classes/NotableDBControl.lua @@ -158,7 +158,7 @@ function NotableDBClass:ListBuilder() start = now end end - + if #infinites > 0 then self.sortMaxPower = self.sortMaxPower * 2 for _, node in ipairs(infinites) do diff --git a/src/Classes/PartyTab.lua b/src/Classes/PartyTab.lua index 61b0140368..20e254b1a0 100644 --- a/src/Classes/PartyTab.lua +++ b/src/Classes/PartyTab.lua @@ -31,9 +31,9 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se EnableExportBuffs = false, showAdvancedTools = false, } - + local partyDestinations = { "All", "Party Member Stats", "Aura", "Curse", "Warcry Skills", "Link Skills", "EnemyConditions", "EnemyMods" } - + local theme = { stringHeight = 16, buttonHeight = 20, @@ -58,9 +58,9 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se local notesDesc = [[^7To import a build it must be exported with "Export support" enabled in the import/export tab Auras with the highest effect will take priority, your curses will take priority over a support's - + All of these effects can be found in the Calcs tab]] - + self.controls.notesDesc = new("LabelControl", {"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, theme.stringHeight}, notesDesc) self.controls.notesDesc.width = function() local width = self.width / 2 - 16 @@ -74,7 +74,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.importCodeHeader.y = function() return theme.lineCounter(self.controls.notesDesc.label) + 4 end - + local clearInputText = function() if partyDestinations[self.controls.importCodeDestination.selIndex] == "All" or partyDestinations[self.controls.importCodeDestination.selIndex] == "Party Member Stats" then self.controls.editPartyMemberStats:SetText("") @@ -112,7 +112,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.enemyMods:SetText("") end end - + local importCodeHandle = function (buf) self.importCodeSite = nil self.importCodeDetail = "" @@ -154,12 +154,12 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.importCodeDetail = colorCodes.POSITIVE.."Code is valid" self.importCodeXML = xmlText end - + local finishImport = function() if not self.importCodeValid or self.importCodeFetching then return end - + local currentCurseBuffer = nil local currentLinkBuffer = nil if self.controls.appendNotReplace.state ~= true then @@ -180,14 +180,14 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.actor["Warcry"] = { } end if partyDestinations[self.controls.importCodeDestination.selIndex] == "All" or partyDestinations[self.controls.importCodeDestination.selIndex] == "Link Skills" then - -- only one link can be applied at a time anyway + -- only one link can be applied at a time anyway currentLinkBuffer = self.controls.editLinks.buf self.controls.editLinks:SetText("") wipeTable(self.actor["Link"]) self.actor["Link"] = { } end end - + -- Parse the XML local dbXML, errMsg = common.xml.ParseXML(self.importCodeXML) if not dbXML then @@ -274,12 +274,12 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self:ParseBuffs(self.enemyModList, self.controls.enemyCond.buf, "EnemyConditions") self:ParseBuffs(self.enemyModList, self.controls.enemyMods.buf, "EnemyMods", self.controls.simpleEnemyMods) end - self.build.buildFlag = true + self.build.buildFlag = true break end end end - + self.controls.importCodeIn = new("EditControl", {"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, theme.buttonHeight}, "", nil, nil, nil, importCodeHandle) self.controls.importCodeIn.width = function() return (self.width > 880) and 328 or (self.width / 2 - 100) @@ -331,22 +331,22 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.appendNotReplace.y = function() return (self.width > theme.widthThreshold1) and 0 or 24 end - - self.controls.clear = new("ButtonControl", {"LEFT",self.controls.appendNotReplace,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Clear", function() + + self.controls.clear = new("ButtonControl", {"LEFT",self.controls.appendNotReplace,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Clear", function() clearInputText() wipeTable(self.enemyModList) self.enemyModList = new("ModList") self.build.buildFlag = true end) self.controls.clear.tooltipText = "^7Clears all the party tab imported data" - + self.controls.ShowAdvanceTools = new("CheckBoxControl", {"TOPLEFT",self.controls.importCodeDestination,"BOTTOMLEFT"}, {140, 4, theme.buttonHeight}, "^7Show Advanced Info", function(state) end, "This shows the advanced info like what stats each aura/curse etc are adding, as well as enables the ability to edit them without a re-export\nDo not edit any boxes unless you know what you are doing, use copy/paste or import instead", false) self.controls.ShowAdvanceTools.y = function() return (self.width > theme.widthThreshold1) and 4 or 28 end - - self.controls.removeEffects = new("ButtonControl", {"LEFT",self.controls.ShowAdvanceTools,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Disable Party Effects", function() + + self.controls.removeEffects = new("ButtonControl", {"LEFT",self.controls.ShowAdvanceTools,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Disable Party Effects", function() wipeTable(self.actor) wipeTable(self.enemyModList) self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"), output = { } } @@ -355,8 +355,8 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.build.buildFlag = true end) self.controls.removeEffects.tooltipText = "^7Removes the effects of the supports, without removing the data\nUse \"rebuild all\" to apply the effects again" - - self.controls.rebuild = new("ButtonControl", {"LEFT",self.controls.removeEffects,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "^7Rebuild All", function() + + self.controls.rebuild = new("ButtonControl", {"LEFT",self.controls.removeEffects,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "^7Rebuild All", function() wipeTable(self.actor) wipeTable(self.enemyModList) self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"), output = { } } @@ -369,7 +369,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self:ParseBuffs(self.actor["Link"], self.controls.editLinks.buf, "Link", self.controls.simpleLinks) self:ParseBuffs(self.enemyModList, self.controls.enemyCond.buf, "EnemyConditions") self:ParseBuffs(self.enemyModList, self.controls.enemyMods.buf, "EnemyMods", self.controls.simpleEnemyMods) - self.build.buildFlag = true + self.build.buildFlag = true end) self.controls.rebuild.tooltipText = "^7Reparse all the inputs incase they have been disabled or they have changed since loading the build or importing" self.controls.rebuild.x = function() @@ -390,7 +390,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editAuras.height = function() return (self.controls.editWarcries.hasFocus or self.controls.editLinks.hasFocus) and theme.bufferHeightSmall or theme.bufferHeightLeft() end - + self.controls.editAuras.shown = function() return self.controls.ShowAdvanceTools.state end @@ -559,11 +559,11 @@ function PartyTabClass:Load(xml, fileName) self.lastContent.EnemyCond = self.controls.enemyCond.buf self.lastContent.EnemyMods = self.controls.enemyMods.buf self.lastContent.EnableExportBuffs = self.enableExportBuffs - + self.controls.importCodeDestination:SelByValue(xml.attrib.destination or "All") self.controls.appendNotReplace.state = xml.attrib.append == "true" self.controls.ShowAdvanceTools.state = xml.attrib.ShowAdvanceTools == "true" - + self.lastContent.showAdvancedTools = self.controls.ShowAdvanceTools.state end @@ -699,7 +699,7 @@ function PartyTabClass:Draw(viewPort, inputEvents) self:DrawControls(viewPort) - self.modFlag = (self.lastContent.Aura ~= self.controls.editAuras.buf + self.modFlag = (self.lastContent.Aura ~= self.controls.editAuras.buf or self.lastContent.Curse ~= self.controls.editCurses.buf or self.lastContent.Warcry ~= self.controls.editWarcries.buf or self.lastContent.Link ~= self.controls.editLinks.buf diff --git a/src/Classes/PassiveSpec.lua b/src/Classes/PassiveSpec.lua index 65c5a158a4..7b6a34a372 100644 --- a/src/Classes/PassiveSpec.lua +++ b/src/Classes/PassiveSpec.lua @@ -145,7 +145,7 @@ function PassiveSpecClass:Load(xml, dbFileName) launch:ShowErrMsg("^1Error parsing '%s': 'Override' element missing 'nodeId' attribute", dbFileName) return true end - + -- In case a tattoo has been replaced by a different one attempt to find the new name for it if not self.tree.tattoo.nodes[child.attrib.dn] then for name ,data in pairs(self.tree.tattoo.nodes) do @@ -211,7 +211,7 @@ function PassiveSpecClass:Save(xml) end end t_insert(xml, sockets) - + local overrides = { elem = "Overrides" } @@ -234,7 +234,7 @@ end -- Import passive spec from the provided class IDs and node hash list function PassiveSpecClass:ImportFromNodeList(classId, ascendClassId, secondaryAscendClassId, hashList, hashOverrides, masteryEffects, treeVersion) - if hashOverrides == nil then hashOverrides = {} end + if hashOverrides == nil then hashOverrides = {} end if treeVersion and treeVersion ~= self.treeVersion then self:Init(treeVersion) self.build.treeTab.showConvert = self.treeVersion ~= latestTreeVersion @@ -350,7 +350,7 @@ end function PassiveSpecClass:DecodePoePlannerURL(url, return_tree_version_only) -- poeplanner uses little endian numbers (GGG using BIG). -- If return_tree_version_only is True, then the return value will either be an error message or the tree version. - -- both error messages begin with 'Invalid' + -- both error messages begin with 'Invalid' local function byteToInt(bytes, start) -- get a little endian number from two bytes return bytes:byte(start) + bytes:byte(start + 1) * 256 @@ -379,7 +379,7 @@ function PassiveSpecClass:DecodePoePlannerURL(url, return_tree_version_only) compressedNotesLength: u16 compressedNotesBytes: []u8 (gzip) - TreeBuild: + TreeBuild: treeSerializationVersion: u16 treeVersion: u16 character: u8 @@ -616,7 +616,7 @@ function PassiveSpecClass:SelectSecondaryAscendClass(ascendClassId) end end end - + self.curSecondaryAscendClassId = ascendClassId if ascendClassId == 0 then self.curSecondaryAscendClass = nil @@ -1303,7 +1303,7 @@ function PassiveSpecClass:BuildAllDependsAndPaths() for nodeId, itemId in pairs(self.jewels) do if self.allocNodes[nodeId] then if itemId ~= 0 and ( - self.build.itemsTab.items[itemId] and ( + self.build.itemsTab.items[itemId] and ( self.build.itemsTab.items[itemId].jewelData and self.build.itemsTab.items[itemId].jewelData.intuitiveLeapLike and self.build.itemsTab.items[itemId].jewelRadiusIndex @@ -1372,7 +1372,7 @@ function PassiveSpecClass:BuildAllDependsAndPaths() end end end - + -- Reset and rebuild all node paths for id, node in pairs(self.nodes) do node.pathDist = (node.alloc and #node.intuitiveLeapLikesAffecting == 0) and 0 or 1000 diff --git a/src/Classes/PassiveSpecListControl.lua b/src/Classes/PassiveSpecListControl.lua index f227764d8f..2d4840ed27 100644 --- a/src/Classes/PassiveSpecListControl.lua +++ b/src/Classes/PassiveSpecListControl.lua @@ -73,8 +73,8 @@ function PassiveSpecListClass:GetRowValue(column, index, spec) if column == 1 then local used = spec:CountAllocNodes() return (spec.treeVersion ~= latestTreeVersion and ("["..treeVersions[spec.treeVersion].display.."] ") or "") - .. (spec.title or "Default") - .. " (" .. (spec.curAscendClassName ~= "None" and spec.curAscendClassName or spec.curClassName) .. ", " .. used .. " points)" + .. (spec.title or "Default") + .. " (" .. (spec.curAscendClassName ~= "None" and spec.curAscendClassName or spec.curClassName) .. ", " .. used .. " points)" .. (index == self.treeTab.activeSpec and " ^9(Current)" or "") end end @@ -98,7 +98,7 @@ function PassiveSpecListClass:OnSelDelete(index, spec) t_remove(self.list, index) self.selIndex = nil self.selValue = nil - if index == self.treeTab.activeSpec then + if index == self.treeTab.activeSpec then self.treeTab:SetActiveSpec(m_max(1, index - 1)) else self.treeTab.activeSpec = isValueInArray(self.list, self.treeTab.build.spec) diff --git a/src/Classes/PassiveTree.lua b/src/Classes/PassiveTree.lua index 33163c4ca7..ef84191f81 100644 --- a/src/Classes/PassiveTree.lua +++ b/src/Classes/PassiveTree.lua @@ -121,7 +121,7 @@ local PassiveTreeClass = newClass("PassiveTree", function(self, treeVersion) } end end - + -- hide alternate_ascendancies as they are unobtainable in the newest versions and will cause a crash if an older version is loaded with it at the moment if self.alternate_ascendancies then if launch.devMode then @@ -141,13 +141,13 @@ local PassiveTreeClass = newClass("PassiveTree", function(self, treeVersion) for i, group in pairs(temp_groups) do self.groups[i] = nil end - + self.alternate_ascendancies = nil end - + if self.alternate_ascendancies then self.secondaryAscendNameMap = { } - local alternate_ascendancies_class = { + local alternate_ascendancies_class = { ["name"]= "alternate_ascendancies", ["classes"]= self.alternate_ascendancies } @@ -395,7 +395,7 @@ local PassiveTreeClass = newClass("PassiveTree", function(self, treeVersion) end node.__index = node node.linkedId = { } - nodeMap[node.id] = node + nodeMap[node.id] = node -- Determine node type if node.classStartIndex then @@ -470,7 +470,7 @@ local PassiveTreeClass = newClass("PassiveTree", function(self, treeVersion) elseif node.type == "Notable" or node.type == "Keystone" then self.clusterNodeMap[node.dn] = node end - + self:ProcessNode(node) end @@ -771,7 +771,7 @@ function PassiveTreeClass:BuildConnector(node1, node2) nodeId2 = node2.id, c = { } -- This array will contain the quad's data: 1-8 are the vertex coordinates, 9-16 are the texture coordinates -- Only the texture coords are filled in at this time; the vertex coords need to be converted from tree-space to screen-space first - -- This will occur when the tree is being drawn; .vert will map line state (Normal/Intermediate/Active) to the correct tree-space coordinates + -- This will occur when the tree is being drawn; .vert will map line state (Normal/Intermediate/Active) to the correct tree-space coordinates } if node1.g == node2.g and node1.o == node2.o then -- Nodes are in the same orbit of the same group diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index 6cb5125f4c..e3567709cc 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -27,7 +27,7 @@ local PassiveTreeViewClass = newClass("PassiveTreeView", function(self) self.jewelShadedInnerRing:Load("Assets/ShadedInnerRing.png", "CLAMP") self.jewelShadedInnerRingFlipped = NewImageHandle() self.jewelShadedInnerRingFlipped:Load("Assets/ShadedInnerRingFlipped.png", "CLAMP") - + self.eternal1 = NewImageHandle() self.eternal1:Load("TreeData/PassiveSkillScreenEternalEmpireJewelCircle1.png", "CLAMP") self.eternal2 = NewImageHandle() @@ -99,7 +99,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) local cursorX, cursorY = GetCursorPos() local mOver = cursorX >= viewPort.x and cursorX < viewPort.x + viewPort.width and cursorY >= viewPort.y and cursorY < viewPort.y + viewPort.height - + -- Process input events local treeClick for id, event in ipairs(inputEvents) do @@ -140,7 +140,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) self:Zoom(IsKeyDown("SHIFT") and 3 or 1, viewPort) elseif event.key == "WHEELDOWN" then self:Zoom(IsKeyDown("SHIFT") and -3 or -1, viewPort) - end + end end end end @@ -250,7 +250,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) end end end - -- Use the trace path as the path + -- Use the trace path as the path hoverPath = { } for _, pathNode in pairs(self.tracePath) do hoverPath[pathNode] = true @@ -570,7 +570,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) -- Convert node position to screen-space local scrX, scrY = treeToScreen(node.x, node.y) - + -- Determine color for the base artwork if self.showHeatMap then if not isAlloc and node.type ~= "ClassStart" and node.type ~= "AscendClassStart" then @@ -744,7 +744,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) self.tooltip:Draw(m_floor(scrX - size), m_floor(scrY - size), size * 2, size * 2, viewPort) end end - + -- Draw ring overlays for jewel sockets SetDrawLayer(nil, 25) for nodeId in pairs(tree.sockets) do @@ -866,7 +866,7 @@ function PassiveTreeViewClass:Focus(x, y, viewPort, build) local tree = build.spec.tree local scale = m_min(viewPort.width, viewPort.height) / tree.size * self.zoom - + self.zoomX = -x * scale self.zoomY = -y * scale end @@ -935,7 +935,7 @@ function PassiveTreeViewClass:DoesNodeMatchSearchParams(node) if #needMatches == 0 then return true end - + -- Check node id for devs if launch.devMode then err, needMatches = PCall(search, tostring(node.id), needMatches) @@ -1028,7 +1028,7 @@ function PassiveTreeViewClass:AddNodeTooltip(tooltip, node, build) line = line .. " " .. modStr end end - if line ~= " " and (node.mods[i].extra or not node.mods[i].list) then + if line ~= " " and (node.mods[i].extra or not node.mods[i].list) then local line = colorCodes.UNSUPPORTED..line line = main.notSupportedModTooltips and (line .. main.notSupportedTooltipText) or line tooltip:AddLine(16, line) diff --git a/src/Classes/PowerReportListControl.lua b/src/Classes/PowerReportListControl.lua index 0b08bdd60f..1ed09dbaeb 100644 --- a/src/Classes/PowerReportListControl.lua +++ b/src/Classes/PowerReportListControl.lua @@ -25,7 +25,7 @@ local PowerReportListClass = newClass("PowerReportListControl", "ListControl", f self.showClusters = false self.allocated = false self.label = "Building Tree..." - + self.controls.filterSelect = new("DropDownControl", {"BOTTOMRIGHT", self, "TOPRIGHT"}, {0, -2, 200, 20}, { "Show Unallocated", "Show Unallocated & Clusters", "Show Allocated" }, function(index, value) @@ -51,7 +51,7 @@ end function PowerReportListClass:ReSort(colIndex) -- Reverse power sort for allocated because it uses negative numbers - local compare = self.allocated and + local compare = self.allocated and function(a, b) return a < b end or function(a, b) return a > b end diff --git a/src/Classes/RectangleOutlineControl.lua b/src/Classes/RectangleOutlineControl.lua index 8b8b0b9d47..44fb98a1b0 100644 --- a/src/Classes/RectangleOutlineControl.lua +++ b/src/Classes/RectangleOutlineControl.lua @@ -4,16 +4,16 @@ -- Simple Outline Only Rectangle control -- local RectangleOutlineClass = newClass("RectangleOutlineControl", "Control", function(self, anchor, rect, colors, stroke) - self.Control(anchor, rect) - self.stroke = stroke or 1 - self.colors = colors or { 1, 1, 1 } + self.Control(anchor, rect) + self.stroke = stroke or 1 + self.colors = colors or { 1, 1, 1 } end) function RectangleOutlineClass:Draw() - local x, y = self:GetPos() - SetDrawColor(unpack(self.colors)) - DrawImage(nil, x, y, self.width + self.stroke, self.stroke) - DrawImage(nil, x, y + self.height, self.width + self.stroke, self.stroke) - DrawImage(nil, x, y, self.stroke, self.height + self.stroke) - DrawImage(nil, x + self.width, y, self.stroke, self.height + self.stroke) + local x, y = self:GetPos() + SetDrawColor(unpack(self.colors)) + DrawImage(nil, x, y, self.width + self.stroke, self.stroke) + DrawImage(nil, x, y + self.height, self.width + self.stroke, self.stroke) + DrawImage(nil, x, y, self.stroke, self.height + self.stroke) + DrawImage(nil, x + self.width, y, self.stroke, self.height + self.stroke) end diff --git a/src/Classes/ResizableEditControl.lua b/src/Classes/ResizableEditControl.lua index 66a0402e3f..032b171bd4 100644 --- a/src/Classes/ResizableEditControl.lua +++ b/src/Classes/ResizableEditControl.lua @@ -7,40 +7,40 @@ local m_max = math.max local m_min = math.min local ResizableEditClass = newClass("ResizableEditControl", "EditControl", function(self, anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) - self.EditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) + self.EditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) local x, y, width, height, minWidth, minHeight, maxWidth, maxHeight = unpack(rect) - self.minHeight = minHeight or height - self.maxHeight = maxHeight or height - self.minWidth = minWidth or width - self.maxWidth = maxWidth or width - self.controls.draggerHeight = new("DraggerControl", {"BOTTOMRIGHT", self, "BOTTOMRIGHT"}, {7, 7, 14, 14}, "//", nil, nil, function (position) - -- onRightClick - if (self.height ~= self.minHeight) or (self.width ~= self.minWidth) then - self:SetWidth(self.minWidth) - self:SetHeight(self.minHeight) - else - self:SetWidth(self.maxWidth) - self:SetHeight(self.maxHeight) - end - end) + self.minHeight = minHeight or height + self.maxHeight = maxHeight or height + self.minWidth = minWidth or width + self.maxWidth = maxWidth or width + self.controls.draggerHeight = new("DraggerControl", {"BOTTOMRIGHT", self, "BOTTOMRIGHT"}, {7, 7, 14, 14}, "//", nil, nil, function (position) + -- onRightClick + if (self.height ~= self.minHeight) or (self.width ~= self.minWidth) then + self:SetWidth(self.minWidth) + self:SetHeight(self.minHeight) + else + self:SetWidth(self.maxWidth) + self:SetHeight(self.maxHeight) + end + end) self.protected = false end) function ResizableEditClass:Draw(viewPort, noTooltip) - self:SetBoundedDrag(self) - self.EditControl:Draw(viewPort, noTooltip) + self:SetBoundedDrag(self) + self.EditControl:Draw(viewPort, noTooltip) end function ResizableEditClass:SetBoundedDrag() - if self.controls.draggerHeight.dragging then - local cursorX, cursorY = GetCursorPos() - local x, y = self:GetPos() - self:SetHeight(cursorY - y) - self:SetWidth(cursorX - x) - end + if self.controls.draggerHeight.dragging then + local cursorX, cursorY = GetCursorPos() + local x, y = self:GetPos() + self:SetHeight(cursorY - y) + self:SetWidth(cursorX - x) + end end function ResizableEditClass:SetWidth(width) - self.width = m_max(m_min(width or 0, self.maxWidth), self.minWidth) + self.width = m_max(m_min(width or 0, self.maxWidth), self.minWidth) end function ResizableEditClass:SetHeight(height) - self.height = m_max(m_min(height or 0, self.maxHeight), self.minHeight) + self.height = m_max(m_min(height or 0, self.maxHeight), self.minHeight) end \ No newline at end of file diff --git a/src/Classes/SkillListControl.lua b/src/Classes/SkillListControl.lua index 02a95c3ffe..64b7912abd 100644 --- a/src/Classes/SkillListControl.lua +++ b/src/Classes/SkillListControl.lua @@ -46,13 +46,13 @@ local SkillListClass = newClass("SkillListControl", "ListControl", function(self end) end) self.controls.deleteAll.enabled = function() - return #self.list > 0 + return #self.list > 0 end self.controls.new = new("ButtonControl", {"RIGHT",self.controls.deleteAll,"LEFT"}, {-4, 0, 60, 18}, "New", function() - local newGroup = { - label = "", - enabled = true, - gemList = { } + local newGroup = { + label = "", + enabled = true, + gemList = { } } t_insert(self.list, newGroup) self.selIndex = #self.list @@ -76,11 +76,11 @@ function SkillListClass:GetRowValue(column, index, socketGroup) local colour = currentMainSkill and "" or "^x7F7F7F" label = colour .. label .. " (Disabled)" end - if currentMainSkill then + if currentMainSkill then local activeLabel = disabled and " (Forced Active)" or " (Active)" label = label .. colorCodes.RELIC .. activeLabel end - if socketGroup.includeInFullDPS then + if socketGroup.includeInFullDPS then label = label .. colorCodes.CUSTOM .. " (FullDPS)" end return label @@ -123,7 +123,7 @@ function SkillListClass:OnSelect(index, socketGroup) end function SkillListClass:OnSelCopy(index, socketGroup) - if not socketGroup.source then + if not socketGroup.source then self.skillsTab:CopySocketGroup(socketGroup) end end diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 13f4f83194..2f60815763 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -19,7 +19,7 @@ local groupSlotDropList = { { label = "Helmet", slotName = "Helmet" }, { label = "Body Armour", slotName = "Body Armour" }, { label = "Gloves", slotName = "Gloves" }, - { label = "Boots", slotName = "Boots" }, + { label = "Boots", slotName = "Boots" }, { label = "Amulet", slotName = "Amulet" }, { label = "Ring 1", slotName = "Ring 1" }, { label = "Ring 2", slotName = "Ring 2" }, @@ -108,7 +108,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont -- Socket group list self.controls.groupList = new("SkillListControl", { "TOPLEFT", self, "TOPLEFT" }, { 20, 54, 360, 300 }, self) - self.controls.groupTip = new("LabelControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, 8, 0, 14 }, + self.controls.groupTip = new("LabelControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, 8, 0, 14 }, [[ ^7Usage Tips: - You can copy/paste socket groups using Ctrl+C and Ctrl+V. @@ -397,7 +397,7 @@ function SkillsTabClass:Load(xml, fileName) end self.controls.showAltQualityGems.state = self.showAltQualityGems self.controls.showSupportGemTypes:SelByValue(xml.attrib.showSupportGemTypes or "ALL", "show") - self.controls.sortGemsByDPSFieldControl:SelByValue(xml.attrib.sortGemsByDPSField or "CombinedDPS", "type") + self.controls.sortGemsByDPSFieldControl:SelByValue(xml.attrib.sortGemsByDPSField or "CombinedDPS", "type") self.showSupportGemTypes = self.controls.showSupportGemTypes:GetSelValueByKey("show") self.sortGemsByDPSField = self.controls.sortGemsByDPSFieldControl:GetSelValueByKey("type") for _, node in ipairs(xml) do diff --git a/src/Classes/SliderControl.lua b/src/Classes/SliderControl.lua index 2c3048de48..fcb106041c 100644 --- a/src/Classes/SliderControl.lua +++ b/src/Classes/SliderControl.lua @@ -144,7 +144,7 @@ function SliderClass:OnKeyDown(key) if mOverComp == "SLIDE" then local x, y = self:GetPos() self:SetValFromKnobX(cursorX - x - 1 - self.knobSize / 2) - end + end self.dragKnobX = self:GetKnobXForVal() end end diff --git a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua index 969ab8e6ed..e5993e87e3 100644 --- a/src/Classes/Tooltip.lua +++ b/src/Classes/Tooltip.lua @@ -77,7 +77,7 @@ end function TooltipClass:AddLine(size, text) if text then - for line in s_gmatch(text .. "\n", "([^\n]*)\n") do + for line in s_gmatch(text .. "\n", "([^\n]*)\n") do if line:match("^.*(Equipping)") == "Equipping" or line:match("^.*(Removing)") == "Removing" then t_insert(self.blocks, { height = size + 2}) else @@ -212,7 +212,7 @@ function TooltipClass:Draw(x, y, w, h, viewPort) elseif self.center then ttX = m_floor(x - ttW/2) end - + SetDrawColor(1, 1, 1) local columns, maxColumnHeight, drawStack = self:CalculateColumns(ttY, ttX, ttH, ttW, viewPort) @@ -223,7 +223,7 @@ function TooltipClass:Draw(x, y, w, h, viewPort) DrawImage(nil, ttX, ttY + BORDER_WIDTH, ttW * columns - BORDER_WIDTH, maxColumnHeight - 2 * BORDER_WIDTH) --SetDrawLayer(nil, GetDrawLayer()) SetDrawColor(1, 1, 1) - for i, lines in ipairs(drawStack) do + for i, lines in ipairs(drawStack) do if #lines < 6 then if(type(self.color) == "string") then SetDrawColor(self.color) @@ -238,7 +238,7 @@ function TooltipClass:Draw(x, y, w, h, viewPort) end end if type(self.color) == "string" then - SetDrawColor(self.color) + SetDrawColor(self.color) else SetDrawColor(unpack(self.color)) end diff --git a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua index 7c28064107..7bb54acd4b 100644 --- a/src/Classes/TradeQuery.lua +++ b/src/Classes/TradeQuery.lua @@ -601,7 +601,7 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) for row_idx in pairs(self.resultTbl) do self:UpdateControlsWithItems(row_idx) end - end) + end) controls.cancel = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, { 0, -10, 80, 20 }, "Cancel", function() if previousSelectionList and #previousSelectionList > 0 then self.statSortSelectionList = copyTable(previousSelectionList, true) diff --git a/src/Classes/TradeQueryGenerator.lua b/src/Classes/TradeQueryGenerator.lua index 7793d13daf..fad2869864 100644 --- a/src/Classes/TradeQueryGenerator.lua +++ b/src/Classes/TradeQueryGenerator.lua @@ -329,7 +329,7 @@ function TradeQueryGeneratorClass:ProcessMod(modId, mod, tradeQueryStatsParsed, max = #max > 0 and tonumber(max) or tonumber(min) tokenizeOffset = tokenizeOffset + (endPos - startPos) - + if inverse then sign = nil min = -min @@ -617,13 +617,13 @@ function TradeQueryGeneratorClass:GeneratePassiveNodeWeights(nodesToTest) if self.alreadyWeightedMods[entry.tradeMod.id] ~= nil then goto continue end - + local nodeName = entry.tradeMod.text:match("1 Added Passive Skill is (.*)") or entry.tradeMod.text:match("Allocates (.*)") if not nodeName then goto continue end local node = self.itemsTab.build.spec.tree.clusterNodeMap[nodeName] or self.itemsTab.build.spec.tree.notableMap[nodeName] - + local baseOutput = self.calcContext.baseOutput local output = self.calcContext.calcFunc({ addNodes = { [node] = true } }) local meanStatDiff = TradeQueryGeneratorClass.WeightedRatioOutputs(baseOutput, output, self.calcContext.options.statWeights) * 1000 - (self.calcContext.baseStatValue or 0) @@ -631,7 +631,7 @@ function TradeQueryGeneratorClass:GeneratePassiveNodeWeights(nodesToTest) t_insert(self.modWeights, { tradeModId = entry.tradeMod.id, weight = meanStatDiff, meanStatDiff = meanStatDiff, invert = false }) end self.alreadyWeightedMods[entry.tradeMod.id] = true - + local now = GetTime() if now - start > 50 then -- Would be nice to update x/y progress on the popup here, but getting y ahead of time has a cost, and the visual seems to update on a significant delay anyways so it's not very useful @@ -891,18 +891,18 @@ function TradeQueryGeneratorClass:FinishQuery() local originalOutput = originalItem and self.calcContext.calcFunc({ repSlotName = self.calcContext.slot.slotName, repItem = self.calcContext.testItem }) or self.calcContext.baseOutput local currentStatDiff = TradeQueryGeneratorClass.WeightedRatioOutputs(self.calcContext.baseOutput, originalOutput, self.calcContext.options.statWeights) * 1000 - (self.calcContext.baseStatValue or 0) - + -- Sort by mean Stat diff rather than weight to more accurately prioritize stats that can contribute more table.sort(self.modWeights, function(a, b) return a.meanStatDiff > b.meanStatDiff end) - + -- A megalomaniac is not being compared to anything and the currentStatDiff will be 0, so just go for an arbitrary min weight - in this case triple the weight of the worst evaluated node. local megalomaniacSpecialMinWeight = self.calcContext.special.itemName == "Megalomaniac" and self.modWeights[#self.modWeights] * 3 -- This Stat diff value will generally be higher than the weighted sum of the same item, because the stats are all applied at once and can thus multiply off each other. -- So apply a modifier to get a reasonable min and hopefully approximate that the query will start out with small upgrades. local minWeight = megalomaniacSpecialMinWeight or currentStatDiff * 0.5 - + -- Generate trade query str and open in browser local filters = 0 local queryTable = { @@ -927,7 +927,7 @@ function TradeQueryGeneratorClass:FinishQuery() sort = { ["statgroup.0"] = "desc" }, engine = "new" } - + for k, v in pairs(self.calcContext.special.queryExtra or {}) do queryTable.query[k] = v end diff --git a/src/Classes/TradeQueryRateLimiter.lua b/src/Classes/TradeQueryRateLimiter.lua index 0570612534..b2e843af03 100644 --- a/src/Classes/TradeQueryRateLimiter.lua +++ b/src/Classes/TradeQueryRateLimiter.lua @@ -7,259 +7,259 @@ ---@class TradeQueryRateLimiter local TradeQueryRateLimiterClass = newClass("TradeQueryRateLimiter", function(self) - -- policies_sample = { - -- -- label: policy - -- ["trade-search-request-limit"] = { - -- -- label: rule - -- ["Ip"] = { - -- ["state"] = { - -- ["60"] = {["timeout"] = 0, ["request"] = 1}, - -- ["300"] = {["timeout"] = 0, ["request"] = 1}, - -- ["10"] = {["timeout"] = 0, ["request"] = 1} - -- }, - -- ["limits"] = { - -- ["60"] = {["timeout"] = 120, ["request"] = 15}, - -- ["300"] = {["timeout"] = 1800, ["request"] = 60}, - -- ["10"] = {["timeout"] = 60, ["request"] = 8} - -- } - -- }, - -- ["Account"] = { - -- ["state"] = { - -- ["5"] = {["timeout"] = 0, ["request"] = 1} - -- }, - -- ["limits"] = { - -- ["5"] = {["timeout"] = 60, ["request"] = 3} - -- } - -- } - -- } - -- } - self.policies = {} - self.retryAfter = {} - self.lastUpdate = {} - self.requestHistory = {} - -- leave this much safety margin on limits for external use (browser, trade app) - self.limitMargin = 1 - -- convenient name lookup, can be extended - self.policyNames = { - ["search"] = "trade-search-request-limit", - ["fetch"] = "trade-fetch-request-limit" - } - self.delayCache = {} - self.requestId = 0 - -- we are tracking ongoing requests to update the rate limits state when - -- the last request is finished since this is a reliable sync point. (no pending modifications on state) - -- Otherwise we are managing our local state and updating only if the response - -- state shows more requests than expected (external requests) - self.pendingRequests = { - ["trade-search-request-limit"] = {}, - ["trade-fetch-request-limit"] = {} - } + -- policies_sample = { + -- -- label: policy + -- ["trade-search-request-limit"] = { + -- -- label: rule + -- ["Ip"] = { + -- ["state"] = { + -- ["60"] = {["timeout"] = 0, ["request"] = 1}, + -- ["300"] = {["timeout"] = 0, ["request"] = 1}, + -- ["10"] = {["timeout"] = 0, ["request"] = 1} + -- }, + -- ["limits"] = { + -- ["60"] = {["timeout"] = 120, ["request"] = 15}, + -- ["300"] = {["timeout"] = 1800, ["request"] = 60}, + -- ["10"] = {["timeout"] = 60, ["request"] = 8} + -- } + -- }, + -- ["Account"] = { + -- ["state"] = { + -- ["5"] = {["timeout"] = 0, ["request"] = 1} + -- }, + -- ["limits"] = { + -- ["5"] = {["timeout"] = 60, ["request"] = 3} + -- } + -- } + -- } + -- } + self.policies = {} + self.retryAfter = {} + self.lastUpdate = {} + self.requestHistory = {} + -- leave this much safety margin on limits for external use (browser, trade app) + self.limitMargin = 1 + -- convenient name lookup, can be extended + self.policyNames = { + ["search"] = "trade-search-request-limit", + ["fetch"] = "trade-fetch-request-limit" + } + self.delayCache = {} + self.requestId = 0 + -- we are tracking ongoing requests to update the rate limits state when + -- the last request is finished since this is a reliable sync point. (no pending modifications on state) + -- Otherwise we are managing our local state and updating only if the response + -- state shows more requests than expected (external requests) + self.pendingRequests = { + ["trade-search-request-limit"] = {}, + ["trade-fetch-request-limit"] = {} + } end) function TradeQueryRateLimiterClass:GetPolicyName(key) - return self.policyNames[key] + return self.policyNames[key] end function TradeQueryRateLimiterClass:ParseHeader(headerString) - local headers = {} - for k, v in headerString:gmatch("([%a%d%-]+): ([%g ]+)") do - if k == nil then error("Unparsable Header") end - headers[k:lower()] = v - end - return headers + local headers = {} + for k, v in headerString:gmatch("([%a%d%-]+): ([%g ]+)") do + if k == nil then error("Unparsable Header") end + headers[k:lower()] = v + end + return headers end -function TradeQueryRateLimiterClass:ParsePolicy(headerString) - local policies = {} - local headers = self:ParseHeader(headerString) - local policyName = headers["x-rate-limit-policy"] - policies[policyName] = {} - local retryAfter = headers["retry-after"] - if retryAfter then - policies[policyName].retryAfter = os.time() + retryAfter - end - local ruleNames = {} - for match in headers["x-rate-limit-rules"]:gmatch("[^,]+") do - ruleNames[#ruleNames+1] = match:lower() - end - for _, ruleName in pairs(ruleNames) do - policies[policyName][ruleName] = {} - local properties = { - ["limits"] = "x-rate-limit-"..ruleName, - ["state"] = "x-rate-limit-"..ruleName.."-state", - } - for key, headerKey in pairs(properties) do - policies[policyName][ruleName][key] = {} - local headerValue = headers[headerKey] - for bucket in headerValue:gmatch("[^,]+") do -- example 8:10:60,15:60:120,60:300:1800 - local next = bucket:gmatch("[^:]+") -- example 8:10:60 - local request, window, timeout = tonumber(next()), tonumber(next()), tonumber(next()) - policies[policyName][ruleName][key][window] = { - ["request"] = request, - ["timeout"] = timeout - } - end - end - end - return policies +function TradeQueryRateLimiterClass:ParsePolicy(headerString) + local policies = {} + local headers = self:ParseHeader(headerString) + local policyName = headers["x-rate-limit-policy"] + policies[policyName] = {} + local retryAfter = headers["retry-after"] + if retryAfter then + policies[policyName].retryAfter = os.time() + retryAfter + end + local ruleNames = {} + for match in headers["x-rate-limit-rules"]:gmatch("[^,]+") do + ruleNames[#ruleNames+1] = match:lower() + end + for _, ruleName in pairs(ruleNames) do + policies[policyName][ruleName] = {} + local properties = { + ["limits"] = "x-rate-limit-"..ruleName, + ["state"] = "x-rate-limit-"..ruleName.."-state", + } + for key, headerKey in pairs(properties) do + policies[policyName][ruleName][key] = {} + local headerValue = headers[headerKey] + for bucket in headerValue:gmatch("[^,]+") do -- example 8:10:60,15:60:120,60:300:1800 + local next = bucket:gmatch("[^:]+") -- example 8:10:60 + local request, window, timeout = tonumber(next()), tonumber(next()), tonumber(next()) + policies[policyName][ruleName][key][window] = { + ["request"] = request, + ["timeout"] = timeout + } + end + end + end + return policies end function TradeQueryRateLimiterClass:UpdateFromHeader(headerString) - local newPolicies = self:ParsePolicy(headerString) - for policyKey, policyValue in pairs(newPolicies) do - if self.requestHistory[policyKey] == nil then - self.requestHistory[policyKey] = { timestamps = {} } - end - if policyValue.retryAfter then - self.retryAfter[policyKey] = policyValue.retryAfter - policyValue.retryAfter = nil - end - if self.limitMargin > 0 then - newPolicies = self:ReduceLimits(self.limitMargin, newPolicies) - end - if self.policies[policyKey] == nil or #self.pendingRequests[policyKey] == 0 then - self.policies[policyKey] = policyValue - else - for rule, ruleValue in pairs(policyValue) do - for window, state in pairs(ruleValue.state) do - local oldState = self.policies[policyKey][rule]["state"][window] - if state.request > oldState.request then - oldState.request = state.request - end - end - end - end - self.lastUpdate[policyKey] = os.time() - -- calculate maxWindow sizes for requestHistory tables - local maxWindow = 0 - for _, rule in pairs(policyValue) do - for window, _ in pairs(rule.limits) do - maxWindow = math.max(maxWindow, window) - end - end - self.requestHistory[policyKey].maxWindow = maxWindow - end + local newPolicies = self:ParsePolicy(headerString) + for policyKey, policyValue in pairs(newPolicies) do + if self.requestHistory[policyKey] == nil then + self.requestHistory[policyKey] = { timestamps = {} } + end + if policyValue.retryAfter then + self.retryAfter[policyKey] = policyValue.retryAfter + policyValue.retryAfter = nil + end + if self.limitMargin > 0 then + newPolicies = self:ReduceLimits(self.limitMargin, newPolicies) + end + if self.policies[policyKey] == nil or #self.pendingRequests[policyKey] == 0 then + self.policies[policyKey] = policyValue + else + for rule, ruleValue in pairs(policyValue) do + for window, state in pairs(ruleValue.state) do + local oldState = self.policies[policyKey][rule]["state"][window] + if state.request > oldState.request then + oldState.request = state.request + end + end + end + end + self.lastUpdate[policyKey] = os.time() + -- calculate maxWindow sizes for requestHistory tables + local maxWindow = 0 + for _, rule in pairs(policyValue) do + for window, _ in pairs(rule.limits) do + maxWindow = math.max(maxWindow, window) + end + end + self.requestHistory[policyKey].maxWindow = maxWindow + end end function TradeQueryRateLimiterClass:NextRequestTime(policy, time) - local now = time or os.time() - local nextTime = now - if self.policies[policy] == nil then - if self.requestHistory[policy] and #self.requestHistory[policy].timestamps > 0 then - -- a request has been made and we are waiting for the response to parse limits, block requests using a long cooldown (PoE2 release date) - -- practically blocking indefinitely until rate limits are initialized - return 1956528000 - else - -- first request, don't block to acquire rate limits from first response - return now - end - end - if self.retryAfter[policy] and self.retryAfter[policy] >= now then - nextTime = math.max(nextTime, self.retryAfter[policy]) - return nextTime - end - self:AgeOutRequests(policy) - for _, rule in pairs(self.policies[policy]) do - for window, _ in pairs(rule.limits) do - if rule.state[window].timeout > 0 then - --an extra second is added to the time calculations here and below in order to avoid problems caused by the low resolution of os.time() - nextTime = math.max(nextTime, self.lastUpdate[policy] + rule.state[window].timeout + 1) - end - if rule.state[window].request >= rule.limits[window].request then - -- reached limit, calculate next request time - -- find oldest timestamp in window - local oldestRequestIdx = 0 - for _, timestamp in pairs(self.requestHistory[policy].timestamps) do - if timestamp >= now - window then - oldestRequestIdx = oldestRequestIdx + 1 - else - break - end - end - if oldestRequestIdx == 0 then - -- state reached limit but we don't have any recent timestamps (external factors) - nextTime = math.max(nextTime, self.lastUpdate[policy] + rule.limits[window].timeout + 1) - else - -- the expiration time of oldest timestamp in the window - local nextAvailableTime = self.requestHistory[policy].timestamps[oldestRequestIdx] + window + 1 - nextTime = math.max(nextTime, nextAvailableTime) - end - end - end - end - return nextTime + local now = time or os.time() + local nextTime = now + if self.policies[policy] == nil then + if self.requestHistory[policy] and #self.requestHistory[policy].timestamps > 0 then + -- a request has been made and we are waiting for the response to parse limits, block requests using a long cooldown (PoE2 release date) + -- practically blocking indefinitely until rate limits are initialized + return 1956528000 + else + -- first request, don't block to acquire rate limits from first response + return now + end + end + if self.retryAfter[policy] and self.retryAfter[policy] >= now then + nextTime = math.max(nextTime, self.retryAfter[policy]) + return nextTime + end + self:AgeOutRequests(policy) + for _, rule in pairs(self.policies[policy]) do + for window, _ in pairs(rule.limits) do + if rule.state[window].timeout > 0 then + --an extra second is added to the time calculations here and below in order to avoid problems caused by the low resolution of os.time() + nextTime = math.max(nextTime, self.lastUpdate[policy] + rule.state[window].timeout + 1) + end + if rule.state[window].request >= rule.limits[window].request then + -- reached limit, calculate next request time + -- find oldest timestamp in window + local oldestRequestIdx = 0 + for _, timestamp in pairs(self.requestHistory[policy].timestamps) do + if timestamp >= now - window then + oldestRequestIdx = oldestRequestIdx + 1 + else + break + end + end + if oldestRequestIdx == 0 then + -- state reached limit but we don't have any recent timestamps (external factors) + nextTime = math.max(nextTime, self.lastUpdate[policy] + rule.limits[window].timeout + 1) + else + -- the expiration time of oldest timestamp in the window + local nextAvailableTime = self.requestHistory[policy].timestamps[oldestRequestIdx] + window + 1 + nextTime = math.max(nextTime, nextAvailableTime) + end + end + end + end + return nextTime end function TradeQueryRateLimiterClass:InsertRequest(policy, timestamp, time) - local now = time or os.time() - timestamp = timestamp or now - if self.requestHistory[policy] == nil then - self.requestHistory[policy] = { timestamps = {} } - end - local insertIndex = 1 - for i, v in ipairs(self.requestHistory[policy].timestamps) do - if timestamp >= v then - insertIndex = i - break - end - end - table.insert(self.requestHistory[policy].timestamps, insertIndex, timestamp) - if self.policies[policy] then - for _, rule in pairs(self.policies[policy]) do - for _, window in pairs(rule.state) do - window.request = window.request + 1 - end - end - self.lastUpdate[policy] = now - end - local requestId = self.requestId - self.requestId = self.requestId + 1 - table.insert(self.pendingRequests[policy], requestId) - return requestId + local now = time or os.time() + timestamp = timestamp or now + if self.requestHistory[policy] == nil then + self.requestHistory[policy] = { timestamps = {} } + end + local insertIndex = 1 + for i, v in ipairs(self.requestHistory[policy].timestamps) do + if timestamp >= v then + insertIndex = i + break + end + end + table.insert(self.requestHistory[policy].timestamps, insertIndex, timestamp) + if self.policies[policy] then + for _, rule in pairs(self.policies[policy]) do + for _, window in pairs(rule.state) do + window.request = window.request + 1 + end + end + self.lastUpdate[policy] = now + end + local requestId = self.requestId + self.requestId = self.requestId + 1 + table.insert(self.pendingRequests[policy], requestId) + return requestId end function TradeQueryRateLimiterClass:FinishRequest(policy, requestId) - if self.pendingRequests[policy] then - for index, value in ipairs(self.pendingRequests[policy]) do - if value == requestId then - table.remove(self.pendingRequests[policy], index) - end - end - end + if self.pendingRequests[policy] then + for index, value in ipairs(self.pendingRequests[policy]) do + if value == requestId then + table.remove(self.pendingRequests[policy], index) + end + end + end end function TradeQueryRateLimiterClass:AgeOutRequests(policy, time) - local now = time or os.time() - local requestHistory = self.requestHistory[policy] - requestHistory.lastCheck = requestHistory.lastCheck or now - if (requestHistory.lastCheck == now) then - return - end - for i = #requestHistory.timestamps, 1 , -1 do - local timestamp = requestHistory.timestamps[i] - for _, rule in pairs(self.policies[policy]) do - for window, windowValue in pairs(rule.state) do - if timestamp >= (requestHistory.lastCheck - window) and timestamp < (now - window) then - -- timestamp that used to be in the window on last check - windowValue.request = math.max(windowValue.request - 1, 0) - end - end - end - if timestamp < now - requestHistory.maxWindow then - table.remove(requestHistory.timestamps, i) - end - end - requestHistory.lastCheck = now + local now = time or os.time() + local requestHistory = self.requestHistory[policy] + requestHistory.lastCheck = requestHistory.lastCheck or now + if (requestHistory.lastCheck == now) then + return + end + for i = #requestHistory.timestamps, 1 , -1 do + local timestamp = requestHistory.timestamps[i] + for _, rule in pairs(self.policies[policy]) do + for window, windowValue in pairs(rule.state) do + if timestamp >= (requestHistory.lastCheck - window) and timestamp < (now - window) then + -- timestamp that used to be in the window on last check + windowValue.request = math.max(windowValue.request - 1, 0) + end + end + end + if timestamp < now - requestHistory.maxWindow then + table.remove(requestHistory.timestamps, i) + end + end + requestHistory.lastCheck = now end -- Reduce limits visible to pob so the user can safely interact with the trade site function TradeQueryRateLimiterClass:ReduceLimits(margin, policies) - for _, policy in pairs(policies) do - for _, rule in pairs(policy) do - for _, window in pairs(rule.limits) do - window.request = math.max(window.request - margin, 1) - end - end - end - return policies + for _, policy in pairs(policies) do + for _, rule in pairs(policy) do + for _, window in pairs(rule.limits) do + window.request = math.max(window.request - margin, 1) + end + end + end + return policies end diff --git a/src/Classes/TradeQueryRequests.lua b/src/Classes/TradeQueryRequests.lua index 9787786c7c..d35f049493 100644 --- a/src/Classes/TradeQueryRequests.lua +++ b/src/Classes/TradeQueryRequests.lua @@ -44,7 +44,7 @@ function TradeQueryRequestsClass:ProcessQueue() end launch:DownloadPage(request.url, onComplete, { header = header, - body = request.body, + body = request.body, }) else break @@ -171,7 +171,7 @@ function TradeQueryRequestsClass:SearchWithQueryWeightAdjusted(realm, league, qu end ---Perform search and run callback function on returned item hashes. ----Item info has to be fetched separately +---Item info has to be fetched separately ---@param league string ---@param query string ---@param callback fun(response:table, errMsg:string) @@ -446,10 +446,10 @@ function TradeQueryRequestsClass:buildUrl(root, realm, league, queryId) local result = root if realm and realm ~='pc' then result = result .. "/" .. realm - end + end result = result .. "/" .. league:gsub(" ", "+") if queryId then result = result .. "/" .. queryId end - return result + return result end diff --git a/src/Classes/TreeTab.lua b/src/Classes/TreeTab.lua index e8ae41f1dd..a4a27f5be5 100644 --- a/src/Classes/TreeTab.lua +++ b/src/Classes/TreeTab.lua @@ -174,7 +174,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.findTimelessJewel = new("ButtonControl", { "LEFT", self.controls.treeSearch, "RIGHT" }, { 8, 0, 150, 20 }, "Find Timeless Jewel", function() self:FindTimelessJewel() end) - + --Default index for Tattoos self.defaultTattoo = { } @@ -184,7 +184,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.treeHeatMapStatSelect.shown = state if state == false then - self.controls.powerReportList.shown = false + self.controls.powerReportList.shown = false end end) @@ -347,15 +347,15 @@ function TreeTabClass:Draw(viewPort, inputEvents) + self.controls.versionText.width() + self.controls.versionText.x + self.controls.versionSelect.width + self.controls.versionSelect.x + (self.isComparing and (self.controls.compareSelect.width + self.controls.compareSelect.x) or 0) - + local widthSecondLineControls = self.controls.treeSearch.width + 8 + self.controls.findTimelessJewel.width + self.controls.findTimelessJewel.x + self.controls.treeHeatMap.width + 130 + self.controls.nodePowerMaxDepthSelect.width + self.controls.nodePowerMaxDepthSelect.x + (self.isCustomMaxDepth and (self.controls.nodePowerMaxDepthCustom.width + self.controls.nodePowerMaxDepthCustom.x) or 0) - + (self.viewer.showHeatMap and (self.controls.treeHeatMapStatSelect.width + self.controls.treeHeatMapStatSelect.x + + (self.viewer.showHeatMap and (self.controls.treeHeatMapStatSelect.width + self.controls.treeHeatMapStatSelect.x + self.controls.powerReport.width + self.controls.powerReport.x) or 0) - + -- Check first line if viewPort.width >= widthFirstLineControls + widthSecondLineControls + rightMargin then linesHeight = 0 @@ -910,7 +910,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) controls.totalTattoos = new("LabelControl", nil, { 0, 95, 0, 16 }, "^7Tattoo Count: ".. getTattooCount() .."/50" ) main:OpenPopup(600, 105, "Replace Modifier of Node", controls, "save") constructUI(modGroups[self.defaultTattoo[nodeName] or 1]) - + -- Show Legacy Tattoos controls.showLegacyTattoo = new("CheckBoxControl", { "LEFT", controls.totalTattoos, "RIGHT" }, { 205, 0, 20 }, "Show Legacy Tattoos:", function(state) self.showLegacyTattoo = state @@ -1461,7 +1461,7 @@ function TreeTabClass:FindTimelessJewel() break end end - + local function clearProtected() -- clear all controls, nodes related to Militant Faith filtering protectedNodesCount = 0 protectedNodes = { } @@ -1928,7 +1928,7 @@ function TreeTabClass:FindTimelessJewel() tooltip:Clear() tooltip:AddLine(16, "^7Optional: Only show results where total weight meets or exceeds this value.") end - + controls.searchListButton = new("ButtonControl", {"TOPLEFT", nil, "TOPLEFT"}, {12, 250, 106, 20}, "^7Desired Nodes", function() if controls.searchListFallback.shown then diff --git a/src/Data/BossSkills.lua b/src/Data/BossSkills.lua index 6bb77b7c4d..38c7e3f92a 100644 --- a/src/Data/BossSkills.lua +++ b/src/Data/BossSkills.lua @@ -168,15 +168,15 @@ return { tooltip = "Cannot be Blocked, Dodged, or Suppressed. \n It is three separate hits, and has a large DoT effect. Neither is taken into account here. \n i.e. Hits before death should be more than 3 to survive" }, },{ - { val = "None", label = "None" }, - { val = "Atziri Flameblast", label = "Atziri Flameblast" }, - { val = "Shaper Ball", label = "Shaper Ball" }, - { val = "Shaper Slam", label = "Shaper Slam" }, - { val = "Shaper Beam", label = "Shaper Beam" }, - { val = "Sirus Meteor", label = "Sirus Meteor" }, - { val = "Cortex Ground Degen", label = "Cortex Ground Degen" }, - { val = "Exarch Ball", label = "Exarch Ball" }, - { val = "Eater Beam", label = "Eater Beam" }, - { val = "Maven Fireball", label = "Maven Fireball" }, - { val = "Maven Memory Game", label = "Maven Memory Game" } + { val = "None", label = "None" }, + { val = "Atziri Flameblast", label = "Atziri Flameblast" }, + { val = "Shaper Ball", label = "Shaper Ball" }, + { val = "Shaper Slam", label = "Shaper Slam" }, + { val = "Shaper Beam", label = "Shaper Beam" }, + { val = "Sirus Meteor", label = "Sirus Meteor" }, + { val = "Cortex Ground Degen", label = "Cortex Ground Degen" }, + { val = "Exarch Ball", label = "Exarch Ball" }, + { val = "Eater Beam", label = "Eater Beam" }, + { val = "Maven Fireball", label = "Maven Fireball" }, + { val = "Maven Memory Game", label = "Maven Memory Game" } } \ No newline at end of file diff --git a/src/Data/Global.lua b/src/Data/Global.lua index c11eb8de67..0f11daf569 100644 --- a/src/Data/Global.lua +++ b/src/Data/Global.lua @@ -72,7 +72,7 @@ colorCodes.PHYS = colorCodes.NORMAL defaultColorCodes = copyTable(colorCodes) function updateColorCode(code, color) - if colorCodes[code] then + if colorCodes[code] then colorCodes[code] = color:gsub("^0", "^") if code == "HIGHLIGHT" then rgbColor = hexToRGB(color) diff --git a/src/Data/Rares.lua b/src/Data/Rares.lua index 79061c852d..f787dc61ff 100644 --- a/src/Data/Rares.lua +++ b/src/Data/Rares.lua @@ -577,7 +577,7 @@ Life Ring Vermillion Ring Crafted: true Prefix: IncreasedLife4 -Suffix: Strength6 +Suffix: Strength6 ]],[[ Mana Ring Paua Ring diff --git a/src/Data/SkillStatMap.lua b/src/Data/SkillStatMap.lua index f8bf248e7e..c3cad2fc53 100644 --- a/src/Data/SkillStatMap.lua +++ b/src/Data/SkillStatMap.lua @@ -1621,13 +1621,13 @@ return { }, -- Impale ["attacks_impale_on_hit_%_chance"] = { - mod("ImpaleChance", "BASE", nil, 0, KeywordFlag.Attack) + mod("ImpaleChance", "BASE", nil, 0, KeywordFlag.Attack) }, ["impale_on_hit_%_chance"] = { - mod("ImpaleChance", "BASE", nil, 0, 0) + mod("ImpaleChance", "BASE", nil, 0, 0) }, ["spells_impale_on_hit_%_chance"] = { - mod("ImpaleChance", "BASE", nil, 0, KeywordFlag.Spell) + mod("ImpaleChance", "BASE", nil, 0, KeywordFlag.Spell) }, ["impale_debuff_effect_+%"] = { mod("ImpaleEffect", "INC", nil) @@ -1796,8 +1796,8 @@ return { mod("TotemPlacementSpeed", "INC", nil), }, ["totems_regenerate_%_life_per_minute"] = { - mod("LifeRegenPercent", "BASE", nil, 0, KeywordFlag.Totem), - div = 60, + mod("LifeRegenPercent", "BASE", nil, 0, KeywordFlag.Totem), + div = 60, }, ["totem_duration_+%"] = { mod("TotemDuration", "INC", nil), @@ -2082,7 +2082,7 @@ return { mod("AdditionalCooldownUses", "BASE", nil) }, ["kill_enemy_on_hit_if_under_10%_life"] = { - mod("CullPercent", "MAX", nil), + mod("CullPercent", "MAX", nil), value = 10 }, ["spell_cast_time_added_to_cooldown_if_triggered"] = { diff --git a/src/Data/Skills/act_dex.lua b/src/Data/Skills/act_dex.lua index b9a485c188..ce31a12ce4 100644 --- a/src/Data/Skills/act_dex.lua +++ b/src/Data/Skills/act_dex.lua @@ -4038,10 +4038,10 @@ skills["ChargedDash"] = { }, }, preDamageFunc = function(activeSkill, output) - if activeSkill.skillPart == 3 then - local finalWaveDamageModifier = activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "chargedDashFinalDamageModifier") - activeSkill.skillModList:NewMod("Damage", "MORE", finalWaveDamageModifier, "Skill:ChargedDash", ModFlag.Attack, { type = "Release Damage", skillPart = 3 }) - end + if activeSkill.skillPart == 3 then + local finalWaveDamageModifier = activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "chargedDashFinalDamageModifier") + activeSkill.skillModList:NewMod("Damage", "MORE", finalWaveDamageModifier, "Skill:ChargedDash", ModFlag.Attack, { type = "Release Damage", skillPart = 3 }) + end end, statMap = { ["base_skill_show_average_damage_instead_of_dps"] = { @@ -11714,7 +11714,7 @@ skills["StormRainAltX"] = { }, statDescriptionScope = "skill_stat_descriptions", castTime = 1, - preDamageFunc = function(activeSkill, output) + preDamageFunc = function(activeSkill, output) if activeSkill.skillPart == 2 then activeSkill.skillData.hitTimeOverride = activeSkill.skillData.hitFrequency / (1 + activeSkill.skillModList:Sum("INC", activeSkill.skillCfg, "StormRainBeamFrequency") / 100) activeSkill.skillData.dpsMultiplier = math.min(activeSkill.skillData.activeArrowMultiplier or 1, activeSkill.skillModList:Sum("BASE", activeSkill.skillCfg, "StormRainAllowedStormArrows")) diff --git a/src/Data/Skills/act_int.lua b/src/Data/Skills/act_int.lua index 7bc5b1a9f0..5a7546846c 100644 --- a/src/Data/Skills/act_int.lua +++ b/src/Data/Skills/act_int.lua @@ -16002,7 +16002,7 @@ skills["SparkAltX"] = { name = "Maximum Hits", }, }, - preDamageFunc = function(activeSkill, output) + preDamageFunc = function(activeSkill, output) local skillData = activeSkill.skillData if activeSkill.skillPart == 2 then skillData.dpsMultiplier = ( skillData.dpsMultiplier or 1 ) * (1 + math.floor( output.Duration / 0.66 )) diff --git a/src/Data/Skills/act_str.lua b/src/Data/Skills/act_str.lua index 907a094bf2..8fd117fa4d 100644 --- a/src/Data/Skills/act_str.lua +++ b/src/Data/Skills/act_str.lua @@ -4521,8 +4521,8 @@ skills["FrozenSweep"] = { local m_max = math.max activeSkill.skillData.showAverage = false activeSkill.skillFlags.showAverage = false - activeSkill.skillFlags.notAverage = true - + activeSkill.skillFlags.notAverage = true + for _, skill in ipairs(activeSkill.actor.activeSkillList) do if skill.activeEffect.grantedEffect.name == "Frozen Legion" and activeSkill.actor.mainSkill.socketGroup.slot == activeSkill.socketGroup.slot then parentSkill = skill diff --git a/src/Data/Skills/spectre.lua b/src/Data/Skills/spectre.lua index 78688473d9..d8b1401947 100644 --- a/src/Data/Skills/spectre.lua +++ b/src/Data/Skills/spectre.lua @@ -6648,43 +6648,43 @@ skills["DelveMonsterEnfeebleOnHit"] = { skills["MonsterVulnerabilityOnHit1"] = { name = "Vulnerability", - color = 1, - baseEffectiveness = 0, - description = "Curse all targets in an area, causing them to take increased physical damage. Attacks against the cursed enemies have a chance to inflict bleeding, and ailments inflicted on them will deal damage faster.", - skillTypes = { [SkillType.Spell] = true, [SkillType.Area] = true, [SkillType.Duration] = true, [SkillType.Trappable] = true, [SkillType.Totemable] = true, [SkillType.Mineable] = true, [SkillType.Multicastable] = true, [SkillType.Triggerable] = true, [SkillType.Cascadable] = true, [SkillType.AppliesCurse] = true, [SkillType.CanRapidFire] = true, [SkillType.AreaSpell] = true, [SkillType.Physical] = true, [SkillType.InstantNoRepeatWhenHeld] = true, [SkillType.InstantShiftAttackForLeftMouse] = true, [SkillType.Hex] = true, }, - statDescriptionScope = "curse_skill_stat_descriptions", - castTime = 0.5, - statMap = { - ["receive_bleeding_chance_%_when_hit_by_attack"] = { - mod("SelfBleedChance", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), - }, - ["physical_damage_taken_+%"] = { - mod("PhysicalDamageTaken", "INC", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), - }, - }, - baseFlags = { - spell = true, - curse = true, - area = true, - duration = true, - hex = true, - }, - baseMods = { - skill("debuff", true), - skill("radius", 22), - }, - constantStats = { - { "receive_bleeding_chance_%_when_hit_by_attack", 25 }, - }, - stats = { - "base_skill_effect_duration", - "active_skill_base_radius_+", - "physical_damage_taken_+%", - "base_deal_no_damage", - }, - levels = { - [3] = { 9200, 1, 31, levelRequirement = 1, statInterpolation = { 1, 1, 1, }, cost = { }, }, - }, + color = 1, + baseEffectiveness = 0, + description = "Curse all targets in an area, causing them to take increased physical damage. Attacks against the cursed enemies have a chance to inflict bleeding, and ailments inflicted on them will deal damage faster.", + skillTypes = { [SkillType.Spell] = true, [SkillType.Area] = true, [SkillType.Duration] = true, [SkillType.Trappable] = true, [SkillType.Totemable] = true, [SkillType.Mineable] = true, [SkillType.Multicastable] = true, [SkillType.Triggerable] = true, [SkillType.Cascadable] = true, [SkillType.AppliesCurse] = true, [SkillType.CanRapidFire] = true, [SkillType.AreaSpell] = true, [SkillType.Physical] = true, [SkillType.InstantNoRepeatWhenHeld] = true, [SkillType.InstantShiftAttackForLeftMouse] = true, [SkillType.Hex] = true, }, + statDescriptionScope = "curse_skill_stat_descriptions", + castTime = 0.5, + statMap = { + ["receive_bleeding_chance_%_when_hit_by_attack"] = { + mod("SelfBleedChance", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), + }, + ["physical_damage_taken_+%"] = { + mod("PhysicalDamageTaken", "INC", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), + }, + }, + baseFlags = { + spell = true, + curse = true, + area = true, + duration = true, + hex = true, + }, + baseMods = { + skill("debuff", true), + skill("radius", 22), + }, + constantStats = { + { "receive_bleeding_chance_%_when_hit_by_attack", 25 }, + }, + stats = { + "base_skill_effect_duration", + "active_skill_base_radius_+", + "physical_damage_taken_+%", + "base_deal_no_damage", + }, + levels = { + [3] = { 9200, 1, 31, levelRequirement = 1, statInterpolation = { 1, 1, 1, }, cost = { }, }, + }, } skills["CrucibleIceStormTrap"] = { @@ -8851,13 +8851,13 @@ skills["TalismanT1Vulnerability"] = { statDescriptionScope = "curse_skill_stat_descriptions", castTime = 0.5, statMap = { - ["receive_bleeding_chance_%_when_hit_by_attack"] = { - mod("SelfBleedChance", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), - }, - ["physical_damage_taken_+%"] = { - mod("PhysicalDamageTaken", "INC", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), - }, - }, + ["receive_bleeding_chance_%_when_hit_by_attack"] = { + mod("SelfBleedChance", "BASE", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), + }, + ["physical_damage_taken_+%"] = { + mod("PhysicalDamageTaken", "INC", nil, 0, 0, { type = "GlobalEffect", effectType = "Curse" }), + }, + }, baseFlags = { spell = true, curse = true, diff --git a/src/Data/Skills/sup_dex.lua b/src/Data/Skills/sup_dex.lua index 034b723119..7d4c114119 100644 --- a/src/Data/Skills/sup_dex.lua +++ b/src/Data/Skills/sup_dex.lua @@ -2790,7 +2790,7 @@ skills["SupportMultipleTraps"] = { addSkillTypes = { }, excludeSkillTypes = { }, statDescriptionScope = "gem_stat_descriptions", - statMap = { + statMap = { ["support_multithrow_damage_+%_final"] = { mod("Damage", "MORE", nil), }, @@ -3213,7 +3213,7 @@ skills["SupportSadism"] = { statDescriptionScope = "gem_stat_descriptions", statMap = { ["support_faster_ailments_ailment_duration_+%_final"] = { - mod("EnemyAilmentDuration", "MORE", nil), + mod("EnemyAilmentDuration", "MORE", nil), }, }, qualityStats = { diff --git a/src/Data/TimelessJewelData/LegionTradeIds.lua b/src/Data/TimelessJewelData/LegionTradeIds.lua index be192be900..ee795368ac 100644 --- a/src/Data/TimelessJewelData/LegionTradeIds.lua +++ b/src/Data/TimelessJewelData/LegionTradeIds.lua @@ -25,7 +25,7 @@ return { }, [4] = { keystone = { - [1] = "explicit.pseudo_timeless_jewel_avarius", + [1] = "explicit.pseudo_timeless_jewel_avarius", [2] = "explicit.pseudo_timeless_jewel_dominus", [3] = "explicit.pseudo_timeless_jewel_maxarius" }, diff --git a/src/Data/Uniques/Special/Generated.lua b/src/Data/Uniques/Special/Generated.lua index 3494af6234..2be172788b 100644 --- a/src/Data/Uniques/Special/Generated.lua +++ b/src/Data/Uniques/Special/Generated.lua @@ -778,14 +778,14 @@ function buildKeystoneItems(keystoneMap) local skinOfTheLordsKeystones = {} local seen = {} - for _, node in pairs(keystoneMap) do + for _, node in pairs(keystoneMap) do if isKeystoneNative(node) and not isValueInArray(excludedPassiveKeystones, node.name) and not seen[node] then table.insert(skinOfTheLordsKeystones, node.name) seen[node] = true end end table.sort(skinOfTheLordsKeystones) - + for _, name in ipairs(skinOfTheLordsKeystones) do table.insert(skinOfTheLords, "Variant: "..name) end @@ -800,7 +800,7 @@ function buildKeystoneItems(keystoneMap) end table.insert(skinOfTheLords, "Corrupted") table.insert(data.uniques.generated, table.concat(skinOfTheLords, "\n")) - + local impossibleEscapeKeystones = {} seen = {} for _, node in pairs(keystoneMap) do @@ -893,12 +893,12 @@ for _, gem in pairs(data.gems) do end local replicaDragonfangsFlight = { - [[Replica Dragonfang's Flight - Onyx Amulet - Selected Variant: 2 - Has Alt Variant: true - Selected Alt Variant: 3 - LevelReq: 56 + [[Replica Dragonfang's Flight + Onyx Amulet + Selected Variant: 2 + Has Alt Variant: true + Selected Alt Variant: 3 + LevelReq: 56 ]] } diff --git a/src/Data/Uniques/ring.lua b/src/Data/Uniques/ring.lua index 8893245595..8d3b91f7d4 100644 --- a/src/Data/Uniques/ring.lua +++ b/src/Data/Uniques/ring.lua @@ -565,7 +565,7 @@ Requires Level 64 Attacks inflict Unnerve on Critical Strike for 4 seconds Spells inflict Intimidate on Critical Strike for 4 seconds ]],[[ -The Hateful Accuser +The Hateful Accuser Nameless Ring League: Settlers of Kalguur Requires Level 50 diff --git a/src/Export/Classes/DatFile.lua b/src/Export/Classes/DatFile.lua index f63f80a92e..e3437b44d6 100644 --- a/src/Export/Classes/DatFile.lua +++ b/src/Export/Classes/DatFile.lua @@ -9,13 +9,13 @@ local m_min = math.min local dataTypes = { Bool = { - size = 1, - read = function(b, o, d) - return b:byte(o) == 1 + size = 1, + read = function(b, o, d) + return b:byte(o) == 1 end, - }, - Int = { - size = 4, + }, + Int = { + size = 4, read = function(b, o, d) if o > #b - 3 then return -1337 end return bytesToInt(b, o) @@ -42,8 +42,8 @@ local dataTypes = { return { bytesToInt(b, o), bytesToInt(b, o + 4) } end, }, - Float = { - size = 4, + Float = { + size = 4, read = function(b, o, d) if o > #b - 3 then return -1337 end return bytesToFloat(b, o) @@ -51,23 +51,23 @@ local dataTypes = { }, String = { size = 4, - read = function(b, o, d) + read = function(b, o, d) if o > #b - 3 then return "" end local stro = bytesToUInt(b, o) if stro > #b - 3 then return "" end return convertUTF16to8(b, d + stro) end, }, - Enum = { - size = 4, + Enum = { + size = 4, ref = true, read = function(b, o, d) if o > #b - 3 then return 1337 end return bytesToUInt(b, o) end, }, - Key = { - size = 8, + Key = { + size = 8, ref = true, read = function(b, o, d) if o > #b - 7 then return 1337 end diff --git a/src/Export/Classes/RowListControl.lua b/src/Export/Classes/RowListControl.lua index 08d1e344dc..502c65cba2 100644 --- a/src/Export/Classes/RowListControl.lua +++ b/src/Export/Classes/RowListControl.lua @@ -47,10 +47,10 @@ function RowListClass:BuildColumns() wipeTable(self.colList) self.colList[1] = { width = 50, label = "#", font = "FIXED", sortable = true } for _, specCol in ipairs(main.curDatFile.spec) do - t_insert(self.colList, { - width = specCol.width, + t_insert(self.colList, { + width = specCol.width, specColRef = specCol, -- Link to the original data - label = specCol.name, + label = specCol.name, font = function() return IsKeyDown("ALT") and "FIXED" or "VAR" end, sortable = true }) @@ -108,7 +108,7 @@ function RowListClass:Draw(viewPort) local cursorX, cursorY = GetCursorPos() - local label = self:GetProperty("label") + local label = self:GetProperty("label") if label then DrawString(x + self.labelPositionOffset[1], y - 20 + self.labelPositionOffset[2], "LEFT", 16, self.font, label) end diff --git a/src/Export/Main.lua b/src/Export/Main.lua index 64611ba40e..fd06f5c5a7 100644 --- a/src/Export/Main.lua +++ b/src/Export/Main.lua @@ -176,7 +176,7 @@ function main:Init() self.controls.scripts = new("ButtonControl", nil, {160, 30, 100, 18}, "Scripts >>", function() self:SetCurrentDat() end) - + self.controls.scriptAll = new("ButtonControl", nil, {270, 10, 100, 18}, "Run All", function() do -- run stat desc first local errMsg = PLoadModule("Scripts/".."statdesc"..".lua") @@ -199,7 +199,7 @@ function main:Init() wipeTable(self.scriptOutput) end) { shown = function() - return not self.curDatFile + return not self.curDatFile end, enabled = function() return #self.scriptOutput > 0 @@ -283,8 +283,8 @@ function main:Init() self.controls.colWidth = new("EditControl", {"TOPLEFT",self.controls.colRefTo,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) self.curSpecCol.width = m_max(tonumber(buf) or 150, 20) self.controls.rowList:BuildColumns() - end) { - numberInc = 10, + end) { + numberInc = 10, tooltipFunc = function(tooltip) tooltip:Clear() tooltip:AddLine(16, "^7Column width in the grid") @@ -294,7 +294,7 @@ function main:Init() self.controls.enumBase = new("EditControl", {"TOPLEFT",self.controls.colWidth,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) self.curSpecCol.enumBase = tonumber(buf) or 0 self.curDatFile:OnSpecChanged() - end) { + end) { numberInc = 1, tooltipFunc = function(tooltip) tooltip:Clear() @@ -308,7 +308,7 @@ function main:Init() self.controls.rowList:BuildColumns() self:SetCurrentCol() end) - + self.controls.filter = new("EditControl", nil, {270, 0, 800, 18}, nil, "^8Filter") { y = function() return self.editSpec and 240 or 30 @@ -422,7 +422,7 @@ function main:OnFrame() end wipeTable(self.inputEvents) - + if #remainingScripts > 0 then local startTime = GetTime() repeat @@ -701,7 +701,7 @@ function main:MoveFolder(name, srcPath, dstPath) end -- Move files - handle = NewFileSearch(srcPath..name.."/*") + handle = NewFileSearch(srcPath..name.."/*") while handle do local fileName = handle:GetFileName() local srcName = srcPath..name.."/"..fileName @@ -713,7 +713,7 @@ function main:MoveFolder(name, srcPath, dstPath) end if not handle:NextFile() then break - end + end end -- Remove source folder @@ -743,7 +743,7 @@ function main:CopyFolder(srcName, dstName) end -- Copy files - handle = NewFileSearch(srcName.."/*") + handle = NewFileSearch(srcName.."/*") while handle do local fileName = handle:GetFileName() local srcName = srcName.."/"..fileName @@ -755,7 +755,7 @@ function main:CopyFolder(srcName, dstName) end if not handle:NextFile() then break - end + end end end @@ -825,7 +825,7 @@ function main:OpenNewFolderPopup(path, onClose) end main:ClosePopup() end) - main:OpenPopup(370, 100, "New Folder", controls, "create", "edit", "cancel") + main:OpenPopup(370, 100, "New Folder", controls, "create", "edit", "cancel") end do diff --git a/src/Export/Scripts/bases.lua b/src/Export/Scripts/bases.lua index 5e020700d2..cbc724e7a6 100644 --- a/src/Export/Scripts/bases.lua +++ b/src/Export/Scripts/bases.lua @@ -226,7 +226,7 @@ directiveTable.base = function(state, args, out) end end out:write('},\n}\n') - + if not ((baseItemType.Hidden == 0 or state.forceHide) and not baseTypeId:match("Talisman") and not state.forceShow) then bases[state.type] = bases[state.type] or {} local subtype = state.subType and #state.subType and state.subType or "" @@ -242,7 +242,7 @@ directiveTable.baseMatch = function(state, argstr, out) local key = "Id" local args = {} for i in string.gmatch(argstr, "%S+") do - table.insert(args, i) + table.insert(args, i) end local value = args[1] -- If column name is specified, use that diff --git a/src/Export/Scripts/bossData.lua b/src/Export/Scripts/bossData.lua index 5ed4835ad6..494e416eb3 100644 --- a/src/Export/Scripts/bossData.lua +++ b/src/Export/Scripts/bossData.lua @@ -207,7 +207,7 @@ local function getStat(state, stat) end end end - if skill.statsPerLevel2 then + if skill.statsPerLevel2 then for level, statsPerLevel in ipairs(skill.statsPerLevel2) do for i, additionalStat in ipairs(statsPerLevel.AdditionalStats) do if additionalStat.Id == "base_reduce_enemy_lightning_resistance_%" then @@ -371,16 +371,16 @@ directiveTable.monsters.boss = function(state, args, out) displayName, monsterId = args:match("(%w+) (.+)") end - local monsterType = dat("MonsterTypes"):GetRow("Id", monsterId) - if not monsterType then + local monsterType = dat("MonsterTypes"):GetRow("Id", monsterId) + if not monsterType then print("Invalid Type: "..monsterId) return end - out:write('bosses["', displayName, '"] = {\n') - out:write('\tarmourMult = ', monsterType.Armour, ',\n') - out:write('\tevasionMult = ', monsterType.Evasion, ',\n') - out:write('\tisUber = ', isUber and "true" or "false", ',\n') + out:write('bosses["', displayName, '"] = {\n') + out:write('\tarmourMult = ', monsterType.Armour, ',\n') + out:write('\tevasionMult = ', monsterType.Evasion, ',\n') + out:write('\tisUber = ', isUber and "true" or "false", ',\n') out:write('}\n') end @@ -544,8 +544,8 @@ directiveTable.skills.skill = function(state, args, out) end end - -- #tooltip - directiveTable.skills.tooltip = function(state, args, out) +-- #tooltip +directiveTable.skills.tooltip = function(state, args, out) if args then out:write(',\n tooltip = ', args,'\n') end @@ -553,8 +553,8 @@ end state.skill = nil end - -- #skillList - directiveTable.skills.skillList = function(state, args, out) +-- #skillList +directiveTable.skills.skillList = function(state, args, out) out:write('},{\n') out:write(' { val = "None", label = "None" }') for _, skillName in pairs(state.skillList) do diff --git a/src/Export/Scripts/enchant.lua b/src/Export/Scripts/enchant.lua index f54bd1bff8..1bd6dfa89f 100644 --- a/src/Export/Scripts/enchant.lua +++ b/src/Export/Scripts/enchant.lua @@ -112,14 +112,14 @@ local function doOtherEnchantment(fileName, groupsList) out:write('\t},\n') elseif byDiffFullMods[diff] then out:write('\t["'..diff..'"] = {\n') - for _, mod in ipairs(byDiffFullMods[diff]) do + for _, mod in ipairs(byDiffFullMods[diff]) do out:write('\t\t{ ') out:write('type = "Runecraft", ') local stats, orders = describeMod(mod.AddEnchantment) out:write('modTags = { ', stats.modTags, ' }, ') out:write('"', table.concat(stats, '", "'), '", ') out:write('statOrder = { ', table.concat(orders, ', '), ' }, ') - out:write('types = { ') + out:write('types = { ') local uniqueTypes = { } for _, category in ipairs(mod.ItemCategories) do for _, itemClass in ipairs(category.ItemClasses) do @@ -329,7 +329,7 @@ for _, mod in ipairs(dat("Mods"):GetRowList("GenerationType", 10)) do end end end - + if skillMap[skill] ~= nil then skill = skillMap[skill] end diff --git a/src/Export/Scripts/enums.lua b/src/Export/Scripts/enums.lua index 9326450c1c..aa13c5f413 100644 --- a/src/Export/Scripts/enums.lua +++ b/src/Export/Scripts/enums.lua @@ -42,7 +42,7 @@ local function writeEnum(filename, enumTable) for _, s in ipairs(enumTable) do out:write(convertUTF8to16(s) .. "\0\0") end - + out:close() print("Wrote " .. size .. " enum types to " .. filename) end diff --git a/src/Export/Scripts/legionPassives.lua b/src/Export/Scripts/legionPassives.lua index dd24b40e9b..17041531d1 100644 --- a/src/Export/Scripts/legionPassives.lua +++ b/src/Export/Scripts/legionPassives.lua @@ -185,22 +185,22 @@ for i=1, alternatePassiveSkillDat.rowCount do parseStats(datFileRow, legionPassiveNode) if legionPassiveNode.id == "vaal_keystone_2_v2" then -- Immortal Ambition needs to be manually added - legionPassiveNode.sd = { - [1] = "Energy Shield starts at zero", - [2] = "Cannot Recharge or Regenerate Energy Shield", - [3] = "Lose 5% of Energy Shield per second", - [4] = "Life Leech effects are not removed when Unreserved Life is Filled", - [5] = "Life Leech effects Recover Energy Shield instead while on Full Life" - } - end + legionPassiveNode.sd = { + [1] = "Energy Shield starts at zero", + [2] = "Cannot Recharge or Regenerate Energy Shield", + [3] = "Lose 5% of Energy Shield per second", + [4] = "Life Leech effects are not removed when Unreserved Life is Filled", + [5] = "Life Leech effects Recover Energy Shield instead while on Full Life" + } + end -- Node group, legion nodes don't use it, so we set it arbitrarily legionPassiveNode.g = LEGION_PASSIVE_GROUP - -- + -- -- group orbit distance legionPassiveNode.o = legionPassiveNode.ks and 4 or 3 legionPassiveNode.oidx = legionPassiveNode.ks and ksCount * 3 or math.floor(math.random() * 1e5) - -- attributes granted + -- attributes granted legionPassiveNode.sa = 0 legionPassiveNode.da = 0 legionPassiveNode.ia = 0 @@ -212,10 +212,10 @@ for i=1, alternatePassiveSkillDat.rowCount do end data.groups[LEGION_PASSIVE_GROUP] = { - ["x"] = -6500, - ["y"] = -6500, - ["oo"] = {}, - ["n"] = {} + ["x"] = -6500, + ["y"] = -6500, + ["oo"] = {}, + ["n"] = {} } for k,v in pairs(data.nodes) do diff --git a/src/Export/Scripts/masters.lua b/src/Export/Scripts/masters.lua index 06a31d03f1..0689e1942d 100644 --- a/src/Export/Scripts/masters.lua +++ b/src/Export/Scripts/masters.lua @@ -54,7 +54,7 @@ for _, craft in ipairs(dat("CraftingBenchOptions"):GetRowList("IsDisabled", fals out:write('"', table.concat(stats, '", "'), '", ') out:write('statOrder = { ', table.concat(orders, ', '), ' }, ') out:write('level = ', craft.Mod.Level, ', group = "', craft.Mod.Type.Id, '", ') - out:write('types = { ') + out:write('types = { ') local uniqueTypes = { } for _, category in ipairs(craft.ItemCategories) do for _, itemClass in ipairs(category.ItemClasses) do diff --git a/src/Export/Scripts/mods.lua b/src/Export/Scripts/mods.lua index 502220bb53..678d9ec738 100644 --- a/src/Export/Scripts/mods.lua +++ b/src/Export/Scripts/mods.lua @@ -4,12 +4,12 @@ end loadStatFile("tincture_stat_descriptions.txt") function table.containsId(table, element) - for _, value in pairs(table) do - if value.Id == element then - return true - end - end - return false + for _, value in pairs(table) do + if value.Id == element then + return true + end + end + return false end local function writeMods(outName, condFunc) @@ -71,7 +71,7 @@ local function writeMods(outName, condFunc) table.remove(orders, index) break end - end + end if string.find(mod.Id, "EldritchImplicitUniquePresence") and #stats > 0 and #orders > 0 then for i, stat in ipairs(stats) do stats[i] = "While a Unique Enemy is in your Presence, ".. stat diff --git a/src/Export/Scripts/pantheons.lua b/src/Export/Scripts/pantheons.lua index 08293953ac..ac27fc6c2c 100644 --- a/src/Export/Scripts/pantheons.lua +++ b/src/Export/Scripts/pantheons.lua @@ -14,39 +14,39 @@ out:write('-- The Pantheon data (c) Grinding Gear Games\n\n') out:write('return {\n') for _, p in pairs(dat("PantheonPanelLayout"):GetRowList("IsDisabled", false)) do - out:write('\t["', p.Id, '"] = {\n') - out:write('\t\tisMajorGod = ', tostring(p.IsMajorGod), ',\n') - out:write('\t\tsouls = {\n') - - local gods = { - { name = p.GodName1, statKeys = p.Effect1StatsKey, values = p.Effect1Values }, - { name = p.GodName2, statKeys = p.Effect2StatsKey, values = p.Effect2Values }, - { name = p.GodName3, statKeys = p.Effect3StatsKey, values = p.Effect3Values }, - { name = p.GodName4, statKeys = p.Effect4StatsKey, values = p.Effect4Values }, - } - for god_index, god in pairs(gods) do - if next(god.statKeys) then - out:write('\t\t\t[', god_index, '] = { ') - out:write('name = "', god.name, '",\n') - out:write('\t\t\t\tmods = {\n') - for soul_index, souls in pairs(zip(god.statKeys, god.values)) do - local key = souls[1] - local value = souls[2] - local stats = { } - stats[key.Id] = { min = value, max = value } - out:write('\t\t\t\t\t-- ', key.Id, '\n') - out:write('\t\t\t\t\t[', soul_index, '] = { line = "', table.concat(describeStats(stats), ' '), '", ') - out:write('value = { ', value, ' }, ') - out:write('},\n') - - end - out:write('\t\t\t\t},\n') - out:write('\t\t\t},\n') - end - end - - out:write('\t\t},\n') - out:write('\t},\n') + out:write('\t["', p.Id, '"] = {\n') + out:write('\t\tisMajorGod = ', tostring(p.IsMajorGod), ',\n') + out:write('\t\tsouls = {\n') + + local gods = { + { name = p.GodName1, statKeys = p.Effect1StatsKey, values = p.Effect1Values }, + { name = p.GodName2, statKeys = p.Effect2StatsKey, values = p.Effect2Values }, + { name = p.GodName3, statKeys = p.Effect3StatsKey, values = p.Effect3Values }, + { name = p.GodName4, statKeys = p.Effect4StatsKey, values = p.Effect4Values }, + } + for god_index, god in pairs(gods) do + if next(god.statKeys) then + out:write('\t\t\t[', god_index, '] = { ') + out:write('name = "', god.name, '",\n') + out:write('\t\t\t\tmods = {\n') + for soul_index, souls in pairs(zip(god.statKeys, god.values)) do + local key = souls[1] + local value = souls[2] + local stats = { } + stats[key.Id] = { min = value, max = value } + out:write('\t\t\t\t\t-- ', key.Id, '\n') + out:write('\t\t\t\t\t[', soul_index, '] = { line = "', table.concat(describeStats(stats), ' '), '", ') + out:write('value = { ', value, ' }, ') + out:write('},\n') + + end + out:write('\t\t\t\t},\n') + out:write('\t\t\t},\n') + end + end + + out:write('\t\t},\n') + out:write('\t},\n') end out:write('}') diff --git a/src/Export/Scripts/skillGemList.lua b/src/Export/Scripts/skillGemList.lua index 251726448b..4a82ab3d8e 100644 --- a/src/Export/Scripts/skillGemList.lua +++ b/src/Export/Scripts/skillGemList.lua @@ -9,7 +9,7 @@ local export = false local types = { "Strength", "Dexterity", "Intelligence", "Other" } -local function grantedEffectString(grantedEffect) +local function grantedEffectString(grantedEffect) local s = "#skill "..grantedEffect.Id.."\n" for _, statSet in ipairs(grantedEffect.GrantedEffectStatSets) do if not (statSet.LabelType and statSet.LabelType.Id == "Hidden") then @@ -51,11 +51,11 @@ for i, _ in ipairs(types) do else local gemName = gemEffect.GrantedEffect.ActiveSkill.DisplayName local gemId = gemEffect.Id - if gemName ~= "" and types[i] == colour and not gemId:match("Unknown") and not gemId:match("Playtest") and not gemId:match("Royale") and not gemName:match("%.%.%.") and not gemName:match("DNT") and not gemName:match("UNUSED") and not gemName:match("NOT CURRENTLY USED") and not gemName:match("Unnamed") and not gemEffect.GrantedEffect.Id:match("HardMode") and not skillGem.BaseItemType.Name:match("DNT") - and not (skillGem.IsVaalGem and gemEffect.Variant ~= 4) then + if gemName ~= "" and types[i] == colour and not gemId:match("Unknown") and not gemId:match("Playtest") and not gemId:match("Royale") and not gemName:match("%.%.%.") and not gemName:match("DNT") and not gemName:match("UNUSED") and not gemName:match("NOT CURRENTLY USED") and not gemName:match("Unnamed") and not gemEffect.GrantedEffect.Id:match("HardMode") and not skillGem.BaseItemType.Name:match("DNT") + and not (skillGem.IsVaalGem and gemEffect.Variant ~= 4) then local temp = gemName..string.rep(" ", 45 - string.len(gemName)).."\t\t----\t\t"..gemEffect.GrantedEffect.Id local temp1 = gemName..grantedEffectString(gemEffect.GrantedEffect) - if gemEffect.GrantedEffect2 and not skillGem.IsVaalGem then + if gemEffect.GrantedEffect2 and not skillGem.IsVaalGem then temp = temp.."\t"..gemEffect.GrantedEffect2.Id temp1 = temp1..grantedEffectString(gemEffect.GrantedEffect2) end @@ -69,7 +69,7 @@ for i, _ in ipairs(types) do table.sort(support) table.sort(supportExport) table.sort(activeExport) - + for i, row in ipairs(supportExport) do -- Remove text before "#skill" only if it is at the start of the string supportExport[i] = string.gsub(row, "^(.-)#skill", "#skill") @@ -78,7 +78,7 @@ for i, _ in ipairs(types) do -- Remove text before "#skill" only if it is at the start of the string activeExport[i] = string.gsub(row, "^(.-)#skill", "#skill") end - + out:write("\t\t\t\t\t\t--------- Active "..types[i].." ---------\n") if export == false then out:write(table.concat(active, "\n")) diff --git a/src/Export/Scripts/skills.lua b/src/Export/Scripts/skills.lua index a3eef04077..907d18bc18 100644 --- a/src/Export/Scripts/skills.lua +++ b/src/Export/Scripts/skills.lua @@ -203,7 +203,7 @@ directiveTable.skill = function(state, args, out) local secondaryEffect if not gemEffect then gemEffect = dat("GemEffects"):GetRow("GrantedEffect2", granted) - if gemEffect then + if gemEffect then secondaryEffect = true end end diff --git a/src/Export/Scripts/statdesc.lua b/src/Export/Scripts/statdesc.lua index dbc3c79728..fc9e927f3a 100644 --- a/src/Export/Scripts/statdesc.lua +++ b/src/Export/Scripts/statdesc.lua @@ -20,7 +20,7 @@ local function processStatFile(name) if noDesc then table.insert(statDescriptor, { stats = { noDesc } }) statDescriptor[noDesc] = #statDescriptor - elseif line:match("handed_description") or (line:match("description") and not line:match("_description")) then + elseif line:match("handed_description") or (line:match("description") and not line:match("_description")) then local name = line:match("description ([%w_]+)") curLang = { } curDescriptor = { curLang, order = order, name = name } @@ -47,7 +47,7 @@ local function processStatFile(name) local desc = { text = text, limit = { } } for statLimit in statLimits:gmatch("[!%d%-#|]+") do local limit = { } - + if statLimit == "#" then limit[1] = "#" limit[2] = "#" diff --git a/src/Export/Scripts/tattooPassives.lua b/src/Export/Scripts/tattooPassives.lua index 8765861502..b3b32f78c0 100644 --- a/src/Export/Scripts/tattooPassives.lua +++ b/src/Export/Scripts/tattooPassives.lua @@ -103,12 +103,12 @@ data.groups = { } local tattooDatRows = {} for i=1, passiveSkillTattoosDat.rowCount do - local tattooDatRow = {} - for j=1, #passiveSkillTattoosDat.cols-1 do - local key = passiveSkillTattoosDat.spec[j].name - tattooDatRow[key] = passiveSkillTattoosDat:ReadCell(i, j) - end - tattooDatRows[tattooDatRow.Override.Id] = tattooDatRow + local tattooDatRow = {} + for j=1, #passiveSkillTattoosDat.cols-1 do + local key = passiveSkillTattoosDat.spec[j].name + tattooDatRow[key] = passiveSkillTattoosDat:ReadCell(i, j) + end + tattooDatRows[tattooDatRow.Override.Id] = tattooDatRow end @@ -189,10 +189,10 @@ for i=1, passiveSkillOverridesDat.rowCount do end data.groups[tattoo_PASSIVE_GROUP] = { - ["x"] = -6500, - ["y"] = -6500, - ["oo"] = {}, - ["n"] = {} + ["x"] = -6500, + ["y"] = -6500, + ["oo"] = {}, + ["n"] = {} } for k,v in pairs(data.nodes) do diff --git a/src/Export/psg.lua b/src/Export/psg.lua index fd807cc253..79469395e8 100644 --- a/src/Export/psg.lua +++ b/src/Export/psg.lua @@ -187,7 +187,7 @@ for _, sheet in ipairs(sheets) do local rRow = imageIconSmall[0][row] local gRow = imageIconSmall[1][row] local bRow = imageIconSmall[2][row] - for col = 0, imageIconSmall:Width() - 1 do + for col = 0, imageIconSmall:Width() - 1 do local r = rRow[col] * 0.58 local g = gRow[col] * 0.58 local b = bRow[col] * 0.58 diff --git a/src/Export/statdesc.lua b/src/Export/statdesc.lua index f1b9ae2c31..9c0ff775b0 100644 --- a/src/Export/statdesc.lua +++ b/src/Export/statdesc.lua @@ -8,7 +8,7 @@ function loadStatFile(fileName) return end statDescriptor = { } - statDescriptors[fileName] = statDescriptor + statDescriptors[fileName] = statDescriptor local curLang local curDescriptor = { } local order = 1 @@ -24,7 +24,7 @@ function loadStatFile(fileName) local noDesc = line:match("no_description ([%w_%+%-%%]+)") if noDesc then statDescriptor[noDesc] = { order = 0 } - elseif line:match("handed_description") or (line:match("description") and not line:match("_description")) then + elseif line:match("handed_description") or (line:match("description") and not line:match("_description")) then local name = line:match("description ([%w_]+)") curLang = { } curDescriptor = { curLang, order = order, name = name } @@ -49,7 +49,7 @@ function loadStatFile(fileName) local desc = { text = text, limit = { } } for statLimit in statLimits:gmatch("[!%d%-#|]+") do local limit = { } - + if statLimit == "#" then limit[1] = "#" limit[2] = "#" @@ -223,7 +223,7 @@ function describeStats(stats) elseif spec.k == "milliseconds_to_seconds_2dp_if_required" or spec.k == "milliseconds_to_seconds_2dp" then val[spec.v].min = round(val[spec.v].min / 1000, 2) val[spec.v].max = round(val[spec.v].max / 1000, 2) - val[spec.v].fmt = "g" + val[spec.v].fmt = "g" elseif spec.k == "deciseconds_to_seconds" then val[spec.v].min = val[spec.v].min / 10 val[spec.v].max = val[spec.v].max / 10 @@ -262,14 +262,14 @@ function describeStats(stats) ConPrintf("Unknown description function: %s", spec.k) end end - local statDesc = desc.text:gsub("{(%d)}", function(n) + local statDesc = desc.text:gsub("{(%d)}", function(n) local v = val[tonumber(n)+1] if v.min == v.max then return string.format("%"..v.fmt, v.min) else return string.format("(%"..v.fmt.."-%"..v.fmt..")", v.min, v.max) end - end):gsub("{}", function() + end):gsub("{}", function() local v = val[1] if v.min == v.max then return string.format("%"..v.fmt, v.min) diff --git a/src/HeadlessWrapper.lua b/src/HeadlessWrapper.lua index 4bee744be1..272d49a7e5 100644 --- a/src/HeadlessWrapper.lua +++ b/src/HeadlessWrapper.lua @@ -139,7 +139,7 @@ function PCall(func, ...) return nil, unpack(ret) else return ret[2] - end + end end function ConPrintf(fmt, ...) -- Optional @@ -168,7 +168,7 @@ dofile("Launch.lua") -- Prevents loading of ModCache -- Allows running mod parsing related tests without pushing ModCache --- The CI env var will be true when run from github workflows but should be false for other tools using the headless wrapper +-- The CI env var will be true when run from github workflows but should be false for other tools using the headless wrapper mainObject.continuousIntegrationMode = os.getenv("CI") runCallback("OnInit") diff --git a/src/Launch.lua b/src/Launch.lua index c5ba5f6847..564720befc 100644 --- a/src/Launch.lua +++ b/src/Launch.lua @@ -261,7 +261,7 @@ function launch:DownloadPage(url, callback, params) if requestHeader then local header = {} for s in requestHeader:gmatch("[^\r\n]+") do - table.insert(header, s) + table.insert(header, s) end easy:setopt(curl.OPT_HTTPHEADER, header) end @@ -359,7 +359,7 @@ end function launch:ShowErrMsg(fmt, ...) if not self.promptMsg then - local version = self.versionNumber and + local version = self.versionNumber and "^8v"..self.versionNumber..(self.versionBranch and " "..self.versionBranch or "") or "" self:ShowPrompt(1, 0, 0, "^1Error:\n\n^0"..string.format(fmt, ...).."\n"..version.."\n^0Press Enter/Escape to dismiss, or F5 to restart the application.") diff --git a/src/LaunchInstall.lua b/src/LaunchInstall.lua index 0ca3acacf9..c0b6657b21 100644 --- a/src/LaunchInstall.lua +++ b/src/LaunchInstall.lua @@ -38,8 +38,8 @@ for _, name in ipairs(basicFiles) do local easy = curl.easy() easy:setopt_url(localSource..name) easy:setopt_writefunction(function(data) - text = text..data - return true + text = text..data + return true end) easy:perform() local size = easy:getinfo(curl.INFO_SIZE_DOWNLOAD) diff --git a/src/Modules/Build.lua b/src/Modules/Build.lua index a54fa533e6..cde5ac6015 100644 --- a/src/Modules/Build.lua +++ b/src/Modules/Build.lua @@ -228,7 +228,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin end if mult > 0.01 then local line = level - if level >= 68 then + if level >= 68 then line = line .. string.format(" (Tier %d)", level - 67) end line = line .. string.format(": %.1f%%", mult * 100) @@ -249,7 +249,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.spec:SelectClass(value.classId) self.spec:AddUndoState() self.spec:SetWindowTitleWithBuildClass() - self.buildFlag = true + self.buildFlag = true end) end end @@ -391,7 +391,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin -- tooltip:AddLine(16, "Search for builds similar to your current character.") -- tooltip:AddLine(16, "For best results, make sure to select your main item set, tree, and skills before opening the popup.") --end - + if buildName == "~~temp~~" then -- Remove temporary build file os.remove(self.dbFileName) @@ -588,7 +588,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.legacyLoaders = { -- Special loaders for legacy sections ["Spec"] = self.treeTab, } - + --special rebuild to properly initialise boss placeholders self.configTab:BuildModList() self:UpdateClassDropdowns() @@ -850,7 +850,7 @@ function buildMode:EstimatePlayerProgress() act = act + 1 level = m_min(m_max(PointsUsed + 1 - acts[act].questPoints - actExtra(act, extra), acts[act].level), 100) until act == 11 or level <= acts[act + 1].level - + if self.characterLevelAutoMode and self.characterLevel ~= level then self.characterLevel = level self.controls.characterLevel:SetText(self.characterLevel) @@ -865,12 +865,12 @@ function buildMode:EstimatePlayerProgress() or level < 75 and "\nLabyrinth: Merciless Lab" or level < 90 and "\nLabyrinth: Uber Lab" or "" - + if PointsUsed > usedMax then InsertIfNew(self.controls.warnings.lines, "You have too many passive points allocated") end if AscUsed > ascMax then InsertIfNew(self.controls.warnings.lines, "You have too many ascendancy points allocated") end if SecondaryAscUsed > secondaryAscMax then InsertIfNew(self.controls.warnings.lines, "You have too many secondary ascendancy points allocated") end self.Act = level < 90 and act <= 10 and act or "Endgame" - + return string.format("%s%3d / %3d %s%d / %d", PointsUsed > usedMax and colorCodes.NEGATIVE or "^7", PointsUsed, usedMax, AscUsed > ascMax and colorCodes.NEGATIVE or "^7", AscUsed, ascMax), "Required Level: "..level.."\nEstimated Progress:\nAct: "..self.Act.."\nQuestpoints: "..acts[act].questPoints.."\nExtra Skillpoints: "..actExtra(act, extra)..labSuggest end @@ -887,7 +887,7 @@ function buildMode:Shutdown() if launch.devMode and (not main.disableDevAutoSave) and self.targetVersion and not self.abortSave then if self.dbFileName then self:SaveDBFile() - elseif self.unsaved then + elseif self.unsaved then self.dbFileName = main.buildPath.."~~temp~~.xml" self.buildName = "~~temp~~" self.dbFileSubPath = "" @@ -1138,7 +1138,7 @@ function buildMode:OnFrame(inputEvents) height = main.screenH - 32 } if self.viewMode == "IMPORT" then - self.importTab:Draw(tabViewPort, inputEvents) + self.importTab:Draw(tabViewPort, inputEvents) elseif self.viewMode == "NOTES" then self.notesTab:Draw(tabViewPort, inputEvents) elseif self.viewMode == "PARTY" then @@ -1295,7 +1295,7 @@ function buildMode:OpenSpectreLibrary() for id in pairs(self.data.spectres) do t_insert(sourceList, id) end - table.sort(sourceList, function(a,b) + table.sort(sourceList, function(a,b) if self.data.minions[a].name == self.data.minions[b].name then return a < b else @@ -1391,7 +1391,7 @@ function buildMode:RefreshSkillSelectControls(controls, mainGroup, suffix) for i, socketGroup in pairs(self.skillsTab.socketGroupList) do controls.mainSocketGroup.list[i] = { val = i, label = socketGroup.displayLabel } end - controls.mainSocketGroup:CheckDroppedWidth(true) + controls.mainSocketGroup:CheckDroppedWidth(true) if controls.warnings then controls.warnings.shown = #controls.warnings.lines > 0 end if #controls.mainSocketGroup.list == 0 then controls.mainSocketGroup.list[1] = { val = 1, label = "" } @@ -1492,7 +1492,7 @@ function buildMode:FormatStat(statData, statVal, overCapStatVal, colorOverride) if statData.label == "Unreserved Life" and statVal == 0 then color = colorCodes.NEGATIVE end - + local valStr = s_format("%"..statData.fmt, val) valStr:gsub("%.", main.decimalSeparator) valStr = color .. formatNumSep(valStr) @@ -1576,8 +1576,8 @@ function buildMode:AddDisplayStatList(statList, actor) end end elseif statData.label and statData.condFunc and statData.condFunc(actor.output) then - t_insert(statBoxList, { - height = 16, labelColor..statData.label..":", + t_insert(statBoxList, { + height = 16, labelColor..statData.label..":", "^7"..actor.output[statData.labelStat].."%^x808080" .. " (" .. statData.val .. ")",}) elseif not statBoxList[#statBoxList] or statBoxList[#statBoxList][1] then t_insert(statBoxList, { height = 6 }) @@ -1756,7 +1756,7 @@ do if omni and (omni > 0 or omni > self.calcsTab.mainOutput.Omni) then t_insert(req, s_format("%s%d ^x7F7F7FOmni", main:StatColor(omni, 0, self.calcsTab.mainOutput.Omni), omni)) end - else + else if str and (str > 14 or str > self.calcsTab.mainOutput.Str) then t_insert(req, s_format("%s%d ^x7F7F7FStr", main:StatColor(str, strBase, self.calcsTab.mainOutput.Str), str)) end @@ -1766,11 +1766,11 @@ do if int and (int > 14 or int > self.calcsTab.mainOutput.Int) then t_insert(req, s_format("%s%d ^x7F7F7FInt", main:StatColor(int, intBase, self.calcsTab.mainOutput.Int), int)) end - end + end if req[1] then tooltip:AddLine(16, "^x7F7F7FRequires "..table.concat(req, "^x7F7F7F, ")) tooltip:AddSeparator(10) - end + end wipeTable(req) end end diff --git a/src/Modules/BuildSiteTools.lua b/src/Modules/BuildSiteTools.lua index 4a03cfad28..e9797f298b 100644 --- a/src/Modules/BuildSiteTools.lua +++ b/src/Modules/BuildSiteTools.lua @@ -98,7 +98,7 @@ end -- @param uri String Example: pob://pobbin/ or pob://poeninja/ function buildSites.ParseImportLinkFromURI(uri) local importLink = nil - + -- Check if it's an URI from protocol handler for _, siteInfo in ipairs(buildSites.websiteList) do if uri:match("^pob:[/\\]*" .. siteInfo.id:lower() .. "[/\\]+(.+)") then diff --git a/src/Modules/CalcActiveSkill.lua b/src/Modules/CalcActiveSkill.lua index 01a1896c4e..ce6b5a026a 100644 --- a/src/Modules/CalcActiveSkill.lua +++ b/src/Modules/CalcActiveSkill.lua @@ -51,7 +51,7 @@ end -- Merge skill modifiers with given mod list function calcs.mergeSkillInstanceMods(env, modList, skillEffect, extraStats) calcLib.validateGemLevel(skillEffect) - local grantedEffect = skillEffect.grantedEffect + local grantedEffect = skillEffect.grantedEffect local stats = calcLib.buildSkillInstanceStats(skillEffect, grantedEffect) if extraStats and extraStats[1] then for _, stat in pairs(extraStats) do @@ -91,7 +91,7 @@ function calcs.createActiveSkill(activeEffect, supportList, actor, socketGroup, } local activeGrantedEffect = activeEffect.grantedEffect - + -- Initialise skill types activeSkill.skillTypes = copyTable(activeGrantedEffect.skillTypes) if activeGrantedEffect.minionSkillTypes then @@ -134,7 +134,7 @@ function calcs.createActiveSkill(activeEffect, supportList, actor, socketGroup, end end until (notAddedNewSupport) - + for _, supportEffect in ipairs(supportList) do -- Pass 2: Add all compatible supports if calcLib.canGrantedEffectSupportActiveSkill(supportEffect.grantedEffect, activeSkill) then @@ -156,8 +156,8 @@ end -- Copy an Active Skill function calcs.copyActiveSkill(env, mode, skill) - local activeEffect = { - grantedEffect = skill.activeEffect.grantedEffect, + local activeEffect = { + grantedEffect = skill.activeEffect.grantedEffect, level = skill.activeEffect.level, quality = skill.activeEffect.quality } @@ -455,9 +455,9 @@ function calcs.buildActiveSkillModList(env, activeSkill) local skillModList = new("ModList", activeSkill.actor.modDB) activeSkill.skillModList = skillModList activeSkill.baseSkillModList = skillModList - + -- The damage fixup stat applies x% less base Attack Damage and x% more base Attack Speed as confirmed by Openarl Jan 4th 2024 - -- Implemented in this manner as the stat exists on the minion not the skills + -- Implemented in this manner as the stat exists on the minion not the skills if activeSkill.actor and activeSkill.actor.minionData and activeSkill.actor.minionData.damageFixup then skillModList:NewMod("Damage", "MORE", -100 * activeSkill.actor.minionData.damageFixup, "Damage Fixup", ModFlag.Attack) skillModList:NewMod("Speed", "MORE", 100 * activeSkill.actor.minionData.damageFixup, "Damage Fixup", ModFlag.Attack) @@ -488,7 +488,7 @@ function calcs.buildActiveSkillModList(env, activeSkill) end if level.manaReservationPercent then activeSkill.skillData.manaReservationPercent = level.manaReservationPercent - end + end -- Handle multiple triggers situation and if triggered by a trigger skill save a reference to the trigger. local match = skillEffect.grantedEffect.addSkillTypes and (not skillFlags.disable) if match and skillEffect.grantedEffect.isTrigger then @@ -552,7 +552,7 @@ function calcs.buildActiveSkillModList(env, activeSkill) if level.PvPDamageMultiplier then skillModList:NewMod("PvpDamageMultiplier", "MORE", level.PvPDamageMultiplier, activeEffect.grantedEffect.modSource) end - + -- Add extra modifiers from other sources activeSkill.extraSkillModList = { } for _, value in ipairs(skillModList:List(activeSkill.skillCfg, "ExtraSkillMod")) do @@ -576,13 +576,13 @@ function calcs.buildActiveSkillModList(env, activeSkill) activeEffect.srcInstance.skillMineCountCalcs = nil activeEffect.srcInstance.skillMineCount = nil end - + -- Determine if it possible to have a stage on this skill based upon skill parts. local noPotentialStage = true if activeEffect.grantedEffect.parts then for _, part in ipairs(activeEffect.grantedEffect.parts) do - if part.stages then + if part.stages then noPotentialStage = false break end @@ -656,18 +656,18 @@ function calcs.buildActiveSkillModList(env, activeSkill) minion.enemy = env.enemy minion.type = minionType minion.minionData = env.data.minions[minionType] - minion.level = activeSkill.skillData.minionLevelIsEnemyLevel and env.enemyLevel or - activeSkill.skillData.minionLevelIsPlayerLevel and (m_min(env.build and env.build.characterLevel or activeSkill.skillData.minionLevel or activeEffect.grantedEffectLevel.levelRequirement, activeSkill.skillData.minionLevelIsPlayerLevel)) or + minion.level = activeSkill.skillData.minionLevelIsEnemyLevel and env.enemyLevel or + activeSkill.skillData.minionLevelIsPlayerLevel and (m_min(env.build and env.build.characterLevel or activeSkill.skillData.minionLevel or activeEffect.grantedEffectLevel.levelRequirement, activeSkill.skillData.minionLevelIsPlayerLevel)) or minionSupportLevel[minion.type] or activeSkill.skillData.minionLevel or activeEffect.grantedEffectLevel.levelRequirement -- fix minion level between 1 and 100 - minion.level = m_min(m_max(minion.level,1),100) + minion.level = m_min(m_max(minion.level,1),100) minion.itemList = { } minion.uses = activeGrantedEffect.minionUses minion.lifeTable = (minion.minionData.lifeScaling == "AltLife1" and env.data.monsterLifeTable2) or (minion.minionData.lifeScaling == "AltLife2" and env.data.monsterLifeTable3) or (isSpectre and env.data.monsterLifeTable) or env.data.monsterAllyLifeTable local attackTime = minion.minionData.attackTime local damage = (isSpectre and env.data.monsterDamageTable[minion.level] or env.data.monsterAllyDamageTable[minion.level]) * minion.minionData.damage if not minion.minionData.baseDamageIgnoresAttackSpeed then -- minions with this flag do not factor attack time into their base damage - damage = damage * attackTime + damage = damage * attackTime end if activeGrantedEffect.minionHasItemSet then if env.mode == "CALCS" and activeSkill == env.player.mainSkill then @@ -711,7 +711,7 @@ function calcs.buildActiveSkillModList(env, activeSkill) minion.weaponData1 = env.player.weaponData1 end end - if minion.uses["Weapon 2"] then + if minion.uses["Weapon 2"] then if minion.itemSet then local item = env.build.itemsTab.items[minion.itemSet[minion.itemSet.useSecondWeaponSet and "Weapon 2 Swap" or "Weapon 2"].selItemId] if item and item.weaponData then @@ -851,7 +851,7 @@ function calcs.createMinionSkills(env, activeSkill) minionSkill.skillData.damageEffectiveness = 1 + (activeSkill.skillData.minionDamageEffectiveness or 0) / 100 t_insert(minion.activeSkillList, minionSkill) end - local skillIndex + local skillIndex if env.mode == "CALCS" then skillIndex = m_max(m_min(activeEffect.srcInstance.skillMinionSkillCalcs or 1, #minion.activeSkillList), 1) activeEffect.srcInstance.skillMinionSkillCalcs = skillIndex diff --git a/src/Modules/CalcBreakdown.lua b/src/Modules/CalcBreakdown.lua index c1cdd7bfa6..a3b7a78b70 100644 --- a/src/Modules/CalcBreakdown.lua +++ b/src/Modules/CalcBreakdown.lua @@ -70,7 +70,7 @@ function breakdown.mod(modList, cfg, ...) local inc = modList:Sum("INC", cfg, ...) local more = modList:More(cfg, ...) if inc ~= 0 and more ~= 1 then - return { + return { s_format("%.2f ^8(increased/reduced)", 1 + inc/100), s_format("x %.2f ^8(more/less)", more), s_format("= %.2f", (1 + inc/100) * more), @@ -132,7 +132,7 @@ function breakdown.effMult(damageType, resist, pen, taken, mult, takenMore, sour if not useRes then t_insert(out, s_format("x %d%% ^8(resistance ignored)", 0)) t_insert(out, s_format("= %d%%", (0))) - else + else t_insert(out, s_format("= %d%%", (resist - pen))) end end @@ -153,7 +153,7 @@ end function breakdown.dot(out, baseVal, inc, more, mult, rate, aura, effMult, total) breakdown.multiChain(out, { - base = { "%.1f ^8(base damage per second)", baseVal }, + base = { "%.1f ^8(base damage per second)", baseVal }, { "%.2f ^8(increased/reduced)", 1 + inc/100 }, { "%.2f ^8(more/less)", more }, { "%.2f ^8(multiplier)", 1 + (mult or 0)/100 }, @@ -185,13 +185,13 @@ function breakdown.critDot(dotMulti, critMulti, dotChance, critChance) t_insert(out, s_format("= %.2f", combined)) end return out -end - +end + function breakdown.leech(instant, instantRate, instances, pool, rate, max, dur, instantLeechProportion, hitRate) local out = { } if actor.mainSkill.skillData.showAverage then if instant > 0 then - if instantLeechProportion ~= 1 then + if instantLeechProportion ~= 1 then t_insert(out, s_format("Instant Leech: %.1f ^8(%d%% x %.1f)", instant, instantLeechProportion * 100, dur * pool * data.misc.LeechRateBase / (1-instantLeechProportion))) else t_insert(out, s_format("Instant Leech: %.1f", instant)) @@ -210,7 +210,7 @@ function breakdown.leech(instant, instantRate, instances, pool, rate, max, dur, end else if instantRate > 0 then - if instantLeechProportion ~= 1 then + if instantLeechProportion ~= 1 then t_insert(out, s_format("Instant Leech: %.1f ^8(%d%% x %.1f)", instant, instantLeechProportion * 100, dur * pool * data.misc.LeechRateBase / (1-instantLeechProportion))) else t_insert(out, s_format("Instant Leech: %.1f", instant)) diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index bed0ba0f0f..61e936a62d 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -34,7 +34,7 @@ function calcs.hitChance(evasion, accuracy) return 5 end local rawChance = accuracy / (accuracy + (evasion / 5) ^ 0.9) * 125 - return m_max(m_min(round(rawChance), 100), 5) + return m_max(m_min(round(rawChance), 100), 5) end -- Calculate damage reduction from armour, float @@ -163,7 +163,7 @@ function calcs.reducePoolsByDamage(poolTable, damageTable, actor) for damageType, damage in pairs(damageTable) do damageTable[damageType] = damage > 0 and m_ceil(damage) or nil end - + local alliesTakenBeforeYou = poolTbl.AlliesTakenBeforeYou if not alliesTakenBeforeYou then alliesTakenBeforeYou = {} @@ -189,7 +189,7 @@ function calcs.reducePoolsByDamage(poolTable, damageTable, actor) alliesTakenBeforeYou["soulLink"] = { remaining = output.AlliedEnergyShield, percent = output.SoulLinkMitigation / 100 } end end - + local damageTakenThatCanBeRecouped = poolTbl.damageTakenThatCanBeRecouped or { } local aegis = poolTbl.Aegis if not aegis then @@ -208,10 +208,10 @@ function calcs.reducePoolsByDamage(poolTable, damageTable, actor) guard[damageType] = output[damageType.."GuardAbsorb"] or 0 end end - + local ward = poolTbl.Ward or output.Ward or 0 local restoreWard = modDB:Flag(nil, "WardNotBreak") and ward or 0 - + local energyShield = poolTbl.EnergyShield or output.EnergyShieldRecoveryCap local mana = poolTbl.Mana or output.ManaUnreserved or 0 local life = poolTbl.Life or output.LifeRecoverable or 0 @@ -376,7 +376,7 @@ function calcs.reducePoolsByDamage(poolTable, damageTable, actor) resourcesLostToTypeDamage[damageType].overkill = damageRemainder >= 1 and damageRemainder or nil end end - + local MoMPoolRemaining = m_huge local esPoolRemaining = m_huge for damageType, _ in pairs(damageTable) do @@ -482,7 +482,7 @@ function calcs.defence(env, actor) -- Action Speed output.ActionSpeedMod = calcs.actionSpeedMod(actor) - + -- Armour defence types for conditionals for _, slot in pairs({"Helmet","Gloves","Boots","Body Armour","Weapon 2","Weapon 3"}) do local armourData = actor.itemList[slot] and actor.itemList[slot].armourData @@ -508,7 +508,7 @@ function calcs.defence(env, actor) -- Resistances output["PhysicalResist"] = 0 - + -- Process Resistance conversion mods for _, resFrom in ipairs(resistTypeList) do local maxRes @@ -529,7 +529,7 @@ function calcs.defence(env, actor) end end end - + for _, resFrom in ipairs(resistTypeList) do local res for _, resTo in ipairs(resistTypeList) do @@ -555,7 +555,7 @@ function calcs.defence(env, actor) end end end - + -- Highest Maximum Elemental Resistance for Melding of the Flesh if modDB:Flag(nil, "ElementalResistMaxIsHighestResistMax") then local highestResistMax = 0; @@ -573,7 +573,7 @@ function calcs.defence(env, actor) end end end - + for _, elem in ipairs(resistTypeList) do local min, max, total, dotTotal, totemTotal, totemMax min = data.misc.ResistFloor @@ -592,7 +592,7 @@ function calcs.defence(env, actor) local base = modDB:Sum("BASE", nil, "Totem"..elem.."Resist", isElemental[elem] and "TotemElementalResist") totemTotal = base * m_max(calcLib.mod(modDB, nil, "Totem"..elem.."Resist", isElemental[elem] and "TotemElementalResist"), 0) end - + -- Fractional resistances are truncated total = m_modf(total) dotTotal = dotTotal and m_modf(dotTotal) or total @@ -600,7 +600,7 @@ function calcs.defence(env, actor) min = m_modf(min) max = m_modf(max) totemMax = m_modf(totemMax) - + local final = m_max(m_min(total, max), min) local dotFinal = m_max(m_min(dotTotal, max), min) local totemFinal = m_max(m_min(totemTotal, totemMax), min) @@ -646,7 +646,7 @@ function calcs.defence(env, actor) local baseBlockChance = 0 if actor.itemList["Weapon 2"] and actor.itemList["Weapon 2"].armourData then baseBlockChance = baseBlockChance + actor.itemList["Weapon 2"].armourData.BlockChance - + end if actor.itemList["Weapon 3"] and actor.itemList["Weapon 3"].armourData then baseBlockChance = baseBlockChance + actor.itemList["Weapon 3"].armourData.BlockChance @@ -675,7 +675,7 @@ function calcs.defence(env, actor) else output.SpellBlockChanceMax = m_min(modDB:Sum("BASE", nil, "SpellBlockChanceMax"), data.misc.BlockChanceCap) end - if modDB:Flag(nil, "MaxSpellBlockIfNotBlockedRecently") then + if modDB:Flag(nil, "MaxSpellBlockIfNotBlockedRecently") then output.SpellBlockChance = output.SpellBlockChanceMax output.SpellProjectileBlockChance = output.SpellBlockChanceMax elseif modDB:Flag(nil, "SpellBlockChanceIsBlockChance") then @@ -737,7 +737,7 @@ function calcs.defence(env, actor) end end output.EffectiveAverageBlockChance = (output.EffectiveBlockChance + output.EffectiveProjectileBlockChance + output.EffectiveSpellBlockChance + output.EffectiveSpellProjectileBlockChance) / 4 - output.BlockEffect = 100 - modDB:Sum("BASE", nil, "BlockEffect") + output.BlockEffect = 100 - modDB:Sum("BASE", nil, "BlockEffect") if output.BlockEffect ~= 0 then output.ShowBlockEffect = true output.DamageTakenOnBlock = 100 - output.BlockEffect @@ -763,21 +763,21 @@ function calcs.defence(env, actor) if modDB:Flag(nil, "ArmourIncreasedByOvercappedFireRes") then for i, value in ipairs(modDB:Tabulate("FLAG", nil, "ArmourIncreasedByOvercappedFireRes")) do local mod = value.mod - modDB:NewMod("Armour", "INC", output.FireResistOverCap, mod.source) + modDB:NewMod("Armour", "INC", output.FireResistOverCap, mod.source) break end end if modDB:Flag(nil, "EvasionRatingIncreasedByUncappedColdRes") then for i, value in ipairs(modDB:Tabulate("FLAG", nil, "EvasionRatingIncreasedByUncappedColdRes")) do local mod = value.mod - modDB:NewMod("Evasion", "INC", output.ColdResistTotal, mod.source) + modDB:NewMod("Evasion", "INC", output.ColdResistTotal, mod.source) break end end if modDB:Flag(nil, "EvasionRatingIncreasedByOvercappedColdRes") then for i, value in ipairs(modDB:Tabulate("FLAG", nil, "EvasionRatingIncreasedByOvercappedColdRes")) do local mod = value.mod - modDB:NewMod("Evasion", "INC", output.ColdResistOverCap, mod.source) + modDB:NewMod("Evasion", "INC", output.ColdResistOverCap, mod.source) break end end @@ -964,7 +964,7 @@ function calcs.defence(env, actor) local convManaToES = modDB:Sum("BASE", nil, "ManaGainAsEnergyShield") if convManaToES > 0 then energyShieldBase = modDB:Sum("BASE", nil, "Mana") * convManaToES / 100 - energyShield = energyShield + energyShieldBase * calcLib.mod(modDB, nil, "Mana", "EnergyShield", "Defences") + energyShield = energyShield + energyShieldBase * calcLib.mod(modDB, nil, "Mana", "EnergyShield", "Defences") if breakdown then breakdown.slot("Conversion", "Mana to Energy Shield", nil, energyShieldBase, nil, "EnergyShield", "Defences", "Mana") end @@ -976,7 +976,7 @@ function calcs.defence(env, actor) if modDB:Flag(nil, "ChaosInoculation") then total = 1 else - total = armourBase * calcLib.mod(modDB, nil, "Life", "Armour", "ArmourAndEvasion", "Defences") + total = armourBase * calcLib.mod(modDB, nil, "Life", "Armour", "ArmourAndEvasion", "Defences") end armour = armour + total if breakdown then @@ -1080,10 +1080,10 @@ function calcs.defence(env, actor) if modDB:Flag(nil, "ConvertSpellSuppressionToSpellDodge") then modDB:NewMod("SpellDodgeChance", "BASE", spellSuppressionChance / 2, "Acrobatics") end - + output.SpellSuppressionChance = m_min(totalSpellSuppressionChance, data.misc.SuppressionChanceCap) output.SpellSuppressionEffect = m_max(data.misc.SuppressionEffect + modDB:Sum("BASE", nil, "SpellSuppressionEffect"), 0) - + output.EffectiveSpellSuppressionChance = enemyDB:Flag(nil, "CannotBeSuppressed") and 0 or output.SpellSuppressionChance local suppressRolls = 0 if env.mode_effective then @@ -1111,7 +1111,7 @@ function calcs.defence(env, actor) output.EffectiveSpellSuppressionChance = (output.EffectiveSpellSuppressionChance / 100) ^ m_abs(suppressRolls) * output.EffectiveSpellSuppressionChance end end - + output.SpellSuppressionChanceOverCap = m_max(0, totalSpellSuppressionChance - data.misc.SuppressionChanceCap) -- Dodge @@ -1266,11 +1266,11 @@ function calcs.defence(env, actor) end end end - + -- Energy Shield Recharge - output.EnergyShieldRechargeAppliesToLife = modDB:Flag(nil, "EnergyShieldRechargeAppliesToLife") and not modDB:Flag(nil, "CannotRecoverLifeOutsideLeech") + output.EnergyShieldRechargeAppliesToLife = modDB:Flag(nil, "EnergyShieldRechargeAppliesToLife") and not modDB:Flag(nil, "CannotRecoverLifeOutsideLeech") output.EnergyShieldRechargeAppliesToEnergyShield = not (modDB:Flag(nil, "NoEnergyShieldRecharge") or modDB:Flag(nil, "CannotGainEnergyShield") or output.EnergyShieldRechargeAppliesToLife) - + if output.EnergyShieldRechargeAppliesToLife or output.EnergyShieldRechargeAppliesToEnergyShield then local inc = modDB:Sum("INC", nil, "EnergyShieldRecharge") local more = modDB:More(nil, "EnergyShieldRecharge") @@ -1291,7 +1291,7 @@ function calcs.defence(env, actor) base = { "%.1f", recharge }, { "%.2f ^8(recovery rate modifier)", output.LifeRecoveryRateMod }, total = s_format("= %.1f ^8per second", output.LifeRecharge), - }) + }) end else local recharge = output.EnergyShield * data.misc.EnergyShieldRechargeBase * (1 + inc/100) * more @@ -1326,7 +1326,7 @@ function calcs.defence(env, actor) else output.EnergyShieldRecharge = 0 end - + -- recoup do output["anyRecoup"] = 0 @@ -1366,7 +1366,7 @@ function calcs.defence(env, actor) breakdown.ElementalEnergyShieldRecoup = { s_format("%d%% over %d seconds", output.ElementalEnergyShieldRecoup, (modDB:Flag(nil, "3SecondEnergyShieldRecoup") or modDB:Flag(nil, "3SecondRecoup")) and 3 or 4) } end end - + for _, damageType in ipairs(dmgTypeList) do local LifeRecoup = modDB:Sum("BASE", nil, damageType.."LifeRecoup") output[damageType.."LifeRecoup"] = LifeRecoup * output.LifeRecoveryRateMod @@ -1383,7 +1383,7 @@ function calcs.defence(env, actor) end end end - + -- pseudo recoup (eg %physical damage prevented from hits regenerated) for _, resource in ipairs(recoupTypeList) do if not modDB:Flag(nil, "No"..resource.."Regen") and not modDB:Flag(nil, "CannotGain"..resource) then @@ -1453,7 +1453,7 @@ function calcs.defence(env, actor) if enemyDB:Flag(nil, "Blind") then output.BlindEffectMod = calcLib.mod(enemyDB, nil, "BlindEffect", "BuffEffectOnSelf") * 100 end - + -- recovery on block, needs to be after primary defences output.LifeOnBlock = 0 output.LifeOnSuppress = 0 @@ -1467,7 +1467,7 @@ function calcs.defence(env, actor) output.EnergyShieldOnBlock = modDB:Sum("BASE", nil, "EnergyShieldOnBlock") output.EnergyShieldOnSpellBlock = modDB:Sum("BASE", nil, "EnergyShieldOnSpellBlock") output.EnergyShieldOnSuppress = modDB:Sum("BASE", nil, "EnergyShieldOnSuppress") - + -- damage avoidances output.specificTypeAvoidance = false for _, damageType in ipairs(dmgTypeList) do @@ -1565,7 +1565,7 @@ function calcs.buildDefenceEstimations(env, actor) local condList = modDB.conditions local damageCategoryConfig = env.configInput.enemyDamageType or "Average" - + -- chance to not be hit calculations if damageCategoryConfig ~= "DamageOverTime" then local worstOf = env.configInput.EHPUnluckyWorstOf or 1 @@ -1601,7 +1601,7 @@ function calcs.buildDefenceEstimations(env, actor) end else if breakdown then - breakdown["totalEnemyDamage"] = { + breakdown["totalEnemyDamage"] = { label = "Total damage from the enemy", rowList = { }, colList = { @@ -1637,10 +1637,10 @@ function calcs.buildDefenceEstimations(env, actor) if enemyOverwhelm == nil then enemyOverwhelm = tonumber(env.configPlaceholder["enemy"..damageType.."enemyOverwhelm"]) or 0 end - + -- Add min-max enemy damage from mods enemyDamage = enemyDamage + (enemyDB:Sum("BASE", enemyCfg, (damageType.."Min")) + enemyDB:Sum("BASE", enemyCfg, (damageType.."Max"))) / 2 - + -- Conversion and Gain As Mods local conversionTotal = 0 if damageType == "Physical" then @@ -1677,7 +1677,7 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + enemyOverwhelm = enemyOverwhelm + enemyDB:Sum("BASE", nil, "PhysicalOverwhelm") + modDB:Sum("BASE", nil, "EnemyPhysicalOverwhelm") output[damageType.."EnemyPen"] = enemyPen @@ -1716,7 +1716,7 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + --Damage Taken as do actor.damageShiftTable = wipeTable(actor.damageShiftTable) @@ -1739,11 +1739,11 @@ function calcs.buildDefenceEstimations(env, actor) actor.damageOverTimeShiftTable[damageType] = dotShiftTable shiftTable[damageType] = m_max(100 - destTotal, 0) actor.damageShiftTable[damageType] = shiftTable - + --add same type damage output[damageType.."TakenDamage"] = output[damageType.."EnemyDamage"] * actor.damageShiftTable[damageType][damageType] / 100 if breakdown then - breakdown[damageType.."TakenDamage"] = { + breakdown[damageType.."TakenDamage"] = { label = "Taken", rowList = { }, colList = { @@ -1775,7 +1775,7 @@ function calcs.buildDefenceEstimations(env, actor) --total output["totalTakenDamage"] = 0 if breakdown then - breakdown["totalTakenDamage"] = { + breakdown["totalTakenDamage"] = { label = "Total damage taken from the enemy after taken as", rowList = { }, colList = { @@ -1812,7 +1812,7 @@ function calcs.buildDefenceEstimations(env, actor) takenMore = takenMore * modDB:More(nil, "ElementalDamageTakenWhenHit") end output[damageType.."TakenHitMult"] = m_max((1 + takenInc / 100) * takenMore, 0) - + for _, hitType in ipairs(hitSourceList) do local baseTakenIncType = takenInc + modDB:Sum("INC", nil, hitType.."DamageTaken") local baseTakenMoreType = takenMore * modDB:More(nil, hitType.."DamageTaken") @@ -1860,7 +1860,7 @@ function calcs.buildDefenceEstimations(env, actor) -- Incoming hit damage multipliers output["totalTakenHit"] = 0 if breakdown then - breakdown["totalTakenHit"] = { + breakdown["totalTakenHit"] = { label = "Total damage taken after mitigation", rowList = { }, colList = { @@ -2018,7 +2018,7 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + -- stun do local stunThresholdBase = 0 @@ -2045,13 +2045,13 @@ function calcs.buildDefenceEstimations(env, actor) end local StunThresholdMod = (1 + modDB:Sum("INC", nil, "StunThreshold") / 100) output.StunThreshold = stunThresholdBase * StunThresholdMod - + local notAvoidChance = modDB:Flag(nil, "StunImmune") and 0 or 100 - m_min(modDB:Sum("BASE", nil, "AvoidStun"), 100) if output.EnergyShield > output["totalTakenHit"] and not env.modDB:Flag(nil, "EnergyShieldProtectsMana") then notAvoidChance = notAvoidChance * 0.5 end output.StunAvoidChance = 100 - notAvoidChance - + if breakdown then breakdown.StunThreshold = { s_format("%d ^8(base from %s)", stunThresholdBase, stunThresholdSource) } if StunThresholdMod ~= 1 then @@ -2092,7 +2092,7 @@ function calcs.buildDefenceEstimations(env, actor) end t_insert(breakdown.StunDuration, s_format("rounded up to nearest server tick")) t_insert(breakdown.StunDuration, s_format("= %.2fs", output.StunDuration)) - + t_insert(breakdown.BlockDuration, s_format("rounded up to nearest server tick")) t_insert(breakdown.BlockDuration, s_format("= %.2fs", output.BlockDuration)) end @@ -2123,7 +2123,7 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + -- Life Recoverable output.LifeRecoverable = output.LifeUnreserved if env.configInput["conditionLowLife"] then @@ -2134,12 +2134,12 @@ function calcs.buildDefenceEstimations(env, actor) end -- Dissolution of the flesh life pool change - if modDB:Flag(nil, "DamageInsteadReservesLife") then + if modDB:Flag(nil, "DamageInsteadReservesLife") then output.LifeRecoverable = (output.LifeCancellableReservation / 100) * output.Life end - + output.LifeRecoverable = m_max(output.LifeRecoverable, 1) - + -- Prevented life loss taken over 4 seconds (and Petrified Blood) do local recoverable = output.LifeRecoverable @@ -2156,7 +2156,7 @@ function calcs.buildDefenceEstimations(env, actor) output["preventedLifeLossTotal"] = output["preventedLifeLoss"] + output["preventedLifeLossBelowHalf"] end output.LifeHitPool = calcLifeHitPoolWithLossPrevention(recoverable, output.Life, preventedLifeLoss, initialLifeLossBelowHalfPrevented) - + if breakdown then breakdown["preventedLifeLossTotal"] = { s_format("Total life protected:"), @@ -2233,7 +2233,7 @@ function calcs.buildDefenceEstimations(env, actor) if output["sharedMindOverMatter"] > 0 then local MindOverMatter = output["sharedMindOverMatter"] / 100 local esBypass = output.MinimumBypass / 100 - + local sharedMoMPool, breakdownMaxMana, breakdownMana, breakdownES = calcMoMEBPool(output.LifeRecoverable, MindOverMatter, esBypass) output["sharedManaEffectiveLife"] = sharedMoMPool output["sharedMoMHitPool"] = calcMoMEBPool(output.LifeHitPool, MindOverMatter, esBypass) @@ -2325,7 +2325,7 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + --aegis output.AnyAegis = false output["sharedAegis"] = modDB:Max(nil, "AegisValue") or 0 @@ -2350,13 +2350,13 @@ function calcs.buildDefenceEstimations(env, actor) output[damageType.."AegisDisplay"] = output[damageType.."Aegis"] + output["sharedElementalAegis"] end end - + -- taken from allies before you, eg. frost shield do -- frost shield output["FrostShieldLife"] = modDB:Sum("BASE", nil, "FrostGlobeHealth") output["FrostShieldDamageMitigation"] = modDB:Sum("BASE", nil, "FrostGlobeDamageMitigation") - + local lifeProtected = output["FrostShieldLife"] / (output["FrostShieldDamageMitigation"] / 100) * (1 - output["FrostShieldDamageMitigation"] / 100) if breakdown then breakdown["FrostShieldLife"] = { @@ -2367,37 +2367,37 @@ function calcs.buildDefenceEstimations(env, actor) s_format("= %d", lifeProtected), } end - + -- from spectres output["SpectreAllyDamageMitigation"] = modDB:Sum("BASE", nil, "takenFromSpectresBeforeYou") if output["SpectreAllyDamageMitigation"] ~= 0 then output["TotalSpectreLife"] = modDB:Sum("BASE", nil, "TotalSpectreLife") end - + -- from totems output["TotemAllyDamageMitigation"] = modDB:Sum("BASE", nil, "takenFromTotemsBeforeYou") if output["TotemAllyDamageMitigation"] ~= 0 then output["TotalTotemLife"] = modDB:Sum("BASE", nil, "TotalTotemLife") end - + -- from VaalRejuveTotem output["VaalRejuvenationTotemAllyDamageMitigation"] = modDB:Sum("BASE", nil, "takenFromVaalRejuvenationTotemsBeforeYou") + output["TotemAllyDamageMitigation"] if output["VaalRejuvenationTotemAllyDamageMitigation"] ~= output["TotemAllyDamageMitigation"] then output["TotalVaalRejuvenationTotemLife"] = modDB:Sum("BASE", nil, "TotalVaalRejuvenationTotemLife") end - + -- from Sentinel of Radiance output["RadianceSentinelAllyDamageMitigation"] = modDB:Sum("BASE", nil, "takenFromRadianceSentinelBeforeYou") if output["RadianceSentinelAllyDamageMitigation"] ~= 0 then output["TotalRadianceSentinelLife"] = modDB:Sum("BASE", nil, "TotalRadianceSentinelLife") end - + -- from Void Spawn output["VoidSpawnAllyDamageMitigation"] = modDB:Sum("BASE", nil, "takenFromVoidSpawnBeforeYou") if output["VoidSpawnAllyDamageMitigation"] ~= 0 then output["TotalVoidSpawnLife"] = modDB:Sum("BASE", nil, "TotalVoidSpawnLife") end - + -- from Allied Energy Shield output["SoulLinkMitigation"] = modDB:Sum("BASE", nil, "TakenFromParentESBeforeYou") if output["SoulLinkMitigation"] ~= 0 then @@ -2409,7 +2409,7 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + -- Vaal Arctic Armour do output["VaalArcticArmourLife"] = modDB:Sum("BASE", nil, "VaalArcticArmourMaxHits") @@ -2421,7 +2421,7 @@ function calcs.buildDefenceEstimations(env, actor) output[damageType.."TotalPool"] = output[damageType.."ManaEffectiveLife"] output[damageType.."TotalHitPool"] = output[damageType.."MoMHitPool"] local manatext = "Mana" - if output[damageType.."EnergyShieldBypass"] < 100 then + if output[damageType.."EnergyShieldBypass"] < 100 then if modDB:Flag(nil, "EnergyShieldProtectsMana") then manatext = manatext.." and non-bypassed Energy Shield" else @@ -2448,13 +2448,13 @@ function calcs.buildDefenceEstimations(env, actor) t_insert(breakdown[damageType.."TotalPool"], s_format("TotalPool: %d", output[damageType.."TotalPool"])) end end - + -- helper function that iteratively reduces pools until life hits 0 to determine the number of hits it would take with given damage to die local function numberOfHitsToDie(DamageIn) local numHits = 0 DamageIn["cycles"] = DamageIn["cycles"] or 1 DamageIn["iterations"] = DamageIn["iterations"] or 0 - + -- check damage in isn't 0 and that ward doesn't mitigate all damage for _, damageType in ipairs(dmgTypeList) do numHits = numHits + DamageIn[damageType] @@ -2503,7 +2503,7 @@ function calcs.buildDefenceEstimations(env, actor) if output.AlliedEnergyShield then alliesTakenBeforeYou["soulLink"] = { remaining = output.AlliedEnergyShield, percent = output.SoulLinkMitigation / 100 } end - + local poolTable = { AlliesTakenBeforeYou = alliesTakenBeforeYou, Aegis = aegis, @@ -2516,7 +2516,7 @@ function calcs.buildDefenceEstimations(env, actor) LifeBelowHalfLossLostOverTime = output.LifeBelowHalfLossLostOverTime or 0, damageTakenThatCanBeRecouped = { } } - + if DamageIn["cycles"] == 1 then DamageIn["TrackRecoupable"] = DamageIn["TrackRecoupable"] or false DamageIn["TrackLifeLossOverTime"] = DamageIn["TrackLifeLossOverTime"] or false @@ -2525,7 +2525,7 @@ function calcs.buildDefenceEstimations(env, actor) DamageIn["TrackLifeLossOverTime"] = false end DamageIn["WardBypass"] = DamageIn["WardBypass"] or modDB:Sum("BASE", nil, "WardBypass") or 0 - + local VaalArcticArmourHitsLeft = output.VaalArcticArmourLife if DamageIn["cycles"] > 1 then VaalArcticArmourHitsLeft = 0 @@ -2561,7 +2561,7 @@ function calcs.buildDefenceEstimations(env, actor) poolTable.Life = m_min(poolTable.Life + DamageIn.MissingLifeBeforeEnemyHit * ((output.LifeUnreserved or 0) - poolTable.Life) / 100, output.LifeRecoverable or 0) end poolTable = calcs.reducePoolsByDamage(poolTable, Damage, actor) - + -- If still living and the amount of damage exceeds maximum threshold we survived infinite number of hits. if poolTable.Life > 0 and damageTotal >= maxDamage then return m_huge @@ -2606,7 +2606,7 @@ function calcs.buildDefenceEstimations(env, actor) output.LifeLossLostOverTime = output.LifeLossLostOverTime + poolTable.LifeLossLostOverTime output.LifeBelowHalfLossLostOverTime = output.LifeBelowHalfLossLostOverTime + poolTable.LifeBelowHalfLossLostOverTime end - + if poolTable.Life == 0 and DamageIn["cycles"] == 1 then -- Don't count overkill damage and only on final pass as to not break speedup. numHits = numHits - poolTable.OverkillDamage / damageTotal end @@ -2620,7 +2620,7 @@ function calcs.buildDefenceEstimations(env, actor) end return numHits end - + if damageCategoryConfig ~= "DamageOverTime" then -- number of damaging hits needed to be taken to die do @@ -2689,9 +2689,9 @@ function calcs.buildDefenceEstimations(env, actor) DamageIn.EnergyShieldWhenHit = 0 end for _, damageType in ipairs(dmgTypeList) do - -- Emperor's Vigilance (this needs to fail with divine flesh as it can't override it, hence the check for high bypass) + -- Emperor's Vigilance (this needs to fail with divine flesh as it can't override it, hence the check for high bypass) if modDB:Flag(nil, "BlockedDamageDoesntBypassES") and (output[damageType.."EnergyShieldBypass"] < 100 and damageType ~= "Chaos") then - DamageIn[damageType.."EnergyShieldBypass"] = output[damageType.."EnergyShieldBypass"] * (1 - BlockChance) + DamageIn[damageType.."EnergyShieldBypass"] = output[damageType.."EnergyShieldBypass"] * (1 - BlockChance) end local AvoidChance = 0 if output.specificTypeAvoidance then @@ -2727,7 +2727,7 @@ function calcs.buildDefenceEstimations(env, actor) if breakdown then breakdown["ConfiguredDamageChance"] = { s_format("%.2f ^8(chance for block to fail)", 1 - BlockChance) - } + } if output.ShowBlockEffect then t_insert(breakdown["ConfiguredDamageChance"], s_format("x %.2f ^8(block effect)", output.BlockEffect / 100)) end @@ -2740,7 +2740,7 @@ function calcs.buildDefenceEstimations(env, actor) t_insert(breakdown["ConfiguredDamageChance"], s_format("= %.1f%% ^8(of damage taken from a%s hit)", output["ConfiguredDamageChance"], (damageCategoryConfig == "Average" and "n " or (damageCategoryConfig == "Untyped" and "n " or " "))..damageCategoryConfig)) end end - + -- chance to not be hit breakdown do output["TotalNumberOfHits"] = output["NumberOfMitigatedDamagingHits"] / (1 - output["ConfiguredNotHitChance"] / 100) @@ -2789,7 +2789,7 @@ function calcs.buildDefenceEstimations(env, actor) } end end - + -- effective hit pool output["TotalEHP"] = output["TotalNumberOfHits"] * output["totalEnemyDamageIn"] if breakdown then @@ -2799,7 +2799,7 @@ function calcs.buildDefenceEstimations(env, actor) s_format("= %d ^8(total damage you can take)", output["TotalEHP"]), } end - + -- survival time do output.enemySkillTime = (env.configInput.enemySpeed or env.configPlaceholder.enemySpeed or 700) / (1 + enemyDB:Sum("INC", nil, "Speed") / 100) @@ -2815,7 +2815,7 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + -- recoup if output["anyRecoup"] > 0 and damageCategoryConfig ~= "DamageOverTime" then local totalDamage = 0 @@ -2904,7 +2904,7 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + -- petrified blood "degen" if output.preventedLifeLossTotal > 0 and (output["LifeLossLostOverTime"] and output["LifeBelowHalfLossLostOverTime"]) then local LifeLossBelowHalfLost = modDB:Sum("BASE", nil, "LifeLossBelowHalfLost") / 100 @@ -2933,7 +2933,7 @@ function calcs.buildDefenceEstimations(env, actor) t_insert(breakdown["LifeLossLostAvg"], s_format("= %.2f per second", output["LifeLossLostAvg"])) end end - + -- net recovery over time from enemy hits if (output["LifeRecoupRecoveryAvg"] or 0) > 0 or output.preventedLifeLossTotal > 0 then output["netLifeRecoupAndLossLostOverTimeMax"] = (output["LifeRecoupRecoveryMax"] or 0) - (output["LifeLossLostMax"] or 0) @@ -2954,12 +2954,12 @@ function calcs.buildDefenceEstimations(env, actor) end end end - + -- pvp if env.configInput.PvpScaling then local PvpTvalue = output.enemySkillTime local PvpMultiplier = (env.configInput.enemyMultiplierPvpDamage or 100) / 100 - + local PvpNonElemental1 = data.misc.PvpNonElemental1 local PvpNonElemental2 = data.misc.PvpNonElemental2 local PvpElemental1 = data.misc.PvpElemental1 @@ -3002,7 +3002,7 @@ function calcs.buildDefenceEstimations(env, actor) t_insert(breakdown.PvPTotalTakenHit, s_format("= %.1f", output.PvPTotalTakenHit)) end end - + -- maximum hit taken do -- fix total pools, as they aren't used anymore @@ -3146,12 +3146,12 @@ function calcs.buildDefenceEstimations(env, actor) break end end - + finalMaxHit = round(passIncomingDamage / enemyDamageMult) else finalMaxHit = round(partMin / enemyDamageMult) end - + local maxHitCurType = damageType.."MaximumHitTaken" output[maxHitCurType] = finalMaxHit @@ -3167,10 +3167,10 @@ function calcs.buildDefenceEstimations(env, actor) { label = "Taken", key = "taken" }, }, } - + local fullTaken, takenDamages = calcs.takenHitFromDamage(finalMaxHit * enemyDamageMult, damageType, actor) fullTaken = fullTaken == fullTaken and fullTaken or 0 - + for takenType, takenAmt in pairs(takenDamages) do local conversion = actor.damageShiftTable[damageType][takenType] local incoming = finalMaxHit * enemyDamageMult * conversion / 100 @@ -3227,7 +3227,7 @@ function calcs.buildDefenceEstimations(env, actor) } end end - + -- degens do output.TotalBuildDegen = 0 @@ -3240,7 +3240,7 @@ function calcs.buildDefenceEstimations(env, actor) output[damageConvertedType.."BuildDegen"] = (output[damageConvertedType.."BuildDegen"] or 0) + total output.TotalBuildDegen = output.TotalBuildDegen + total if breakdown then - breakdown.TotalBuildDegen = breakdown.TotalBuildDegen or { + breakdown.TotalBuildDegen = breakdown.TotalBuildDegen or { rowList = { }, colList = { { label = "Base Type", key = "type" }, @@ -3259,7 +3259,7 @@ function calcs.buildDefenceEstimations(env, actor) mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]), total = s_format("%.1f", total), }) - breakdown[damageConvertedType.."BuildDegen"] = breakdown[damageConvertedType.."BuildDegen"] or { + breakdown[damageConvertedType.."BuildDegen"] = breakdown[damageConvertedType.."BuildDegen"] or { rowList = { }, colList = { { label = "Base Type", key = "type" }, @@ -3291,7 +3291,7 @@ function calcs.buildDefenceEstimations(env, actor) local totalManaDegen = 0 local totalEnergyShieldDegen = 0 if breakdown then - breakdown.NetLifeRegen = { + breakdown.NetLifeRegen = { label = "Total Life Degen", rowList = { }, colList = { @@ -3299,7 +3299,7 @@ function calcs.buildDefenceEstimations(env, actor) { label = "Degen", key = "degen" }, }, } - breakdown.NetManaRegen = { + breakdown.NetManaRegen = { label = "Total Mana Degen", rowList = { }, colList = { @@ -3307,7 +3307,7 @@ function calcs.buildDefenceEstimations(env, actor) { label = "Degen", key = "degen" }, }, } - breakdown.NetEnergyShieldRegen = { + breakdown.NetEnergyShieldRegen = { label = "Total Energy Shield Degen", rowList = { }, colList = { @@ -3317,12 +3317,12 @@ function calcs.buildDefenceEstimations(env, actor) } end for _, damageType in ipairs(dmgTypeList) do - if output[damageType.."BuildDegen"] then + if output[damageType.."BuildDegen"] then local energyShieldDegen = 0 local lifeDegen = 0 local manaDegen = 0 local takenFromMana = output[damageType.."MindOverMatter"] + output["sharedMindOverMatter"] - if output.EnergyShieldRegenRecovery > 0 then + if output.EnergyShieldRegenRecovery > 0 then if modDB:Flag(nil, "EnergyShieldProtectsMana") then lifeDegen = output[damageType.."BuildDegen"] * (1 - takenFromMana / 100) energyShieldDegen = output[damageType.."BuildDegen"] * (1 - output[damageType.."EnergyShieldBypass"] / 100) * (takenFromMana / 100) @@ -3407,7 +3407,7 @@ function calcs.buildDefenceEstimations(env, actor) output[damageConvertedType.."EnemyDegen"] = (output[damageConvertedType.."EnemyDegen"] or 0) + total output.TotalDegen = output.TotalDegen + total if breakdown then - breakdown.TotalDegen = breakdown.TotalDegen or { + breakdown.TotalDegen = breakdown.TotalDegen or { rowList = { }, colList = { { label = "Source", key = "source" }, @@ -3428,7 +3428,7 @@ function calcs.buildDefenceEstimations(env, actor) mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]), total = s_format("%.1f", total), }) - breakdown[damageConvertedType.."EnemyDegen"] = breakdown[damageConvertedType.."EnemyDegen"] or { + breakdown[damageConvertedType.."EnemyDegen"] = breakdown[damageConvertedType.."EnemyDegen"] or { rowList = { }, colList = { { label = "Source", key = "source" }, @@ -3476,7 +3476,7 @@ function calcs.buildDefenceEstimations(env, actor) output[damageConvertedType.."EnemyDegen"] = (output[damageConvertedType.."EnemyDegen"] or 0) + total output.TotalDegen = output.TotalDegen + total if breakdown then - breakdown.TotalDegen = breakdown.TotalDegen or { + breakdown.TotalDegen = breakdown.TotalDegen or { rowList = { }, colList = { { label = "Source", key = "source" }, @@ -3497,7 +3497,7 @@ function calcs.buildDefenceEstimations(env, actor) mult = s_format("x %.2f", output[damageConvertedType.."TakenDotMult"]), total = s_format("%.1f", total), }) - breakdown[damageConvertedType.."EnemyDegen"] = breakdown[damageConvertedType.."EnemyDegen"] or { + breakdown[damageConvertedType.."EnemyDegen"] = breakdown[damageConvertedType.."EnemyDegen"] or { rowList = { }, colList = { { label = "Source", key = "source" }, @@ -3532,7 +3532,7 @@ function calcs.buildDefenceEstimations(env, actor) local totalManaDegen = 0 local totalEnergyShieldDegen = 0 if breakdown then - breakdown.ComprehensiveNetLifeRegen = { + breakdown.ComprehensiveNetLifeRegen = { label = "Total Life Degen", rowList = { }, colList = { @@ -3540,7 +3540,7 @@ function calcs.buildDefenceEstimations(env, actor) { label = "Degen", key = "degen" }, }, } - breakdown.ComprehensiveNetManaRegen = { + breakdown.ComprehensiveNetManaRegen = { label = "Total Mana Degen", rowList = { }, colList = { @@ -3548,7 +3548,7 @@ function calcs.buildDefenceEstimations(env, actor) { label = "Degen", key = "degen" }, }, } - breakdown.ComprehensiveNetEnergyShieldRegen = { + breakdown.ComprehensiveNetEnergyShieldRegen = { label = "Total Energy Shield Degen", rowList = { }, colList = { @@ -3559,12 +3559,12 @@ function calcs.buildDefenceEstimations(env, actor) end for _, damageType in ipairs(dmgTypeList) do local typeDegen = (output[damageType.."BuildDegen"] or 0) + (output[damageType.."EnemyDegen"] or 0) - if typeDegen ~= 0 then + if typeDegen ~= 0 then local energyShieldDegen = 0 local lifeDegen = 0 local manaDegen = 0 local takenFromMana = output[damageType.."MindOverMatter"] + output["sharedMindOverMatter"] - if output.EnergyShieldRegenRecovery > 0 then + if output.EnergyShieldRegenRecovery > 0 then if modDB:Flag(nil, "EnergyShieldProtectsMana") then lifeDegen = typeDegen * (1 - takenFromMana / 100) energyShieldDegen = typeDegen * (1 - output[damageType.."EnergyShieldBypass"] / 100) * (takenFromMana / 100) @@ -3646,7 +3646,7 @@ function calcs.buildDefenceEstimations(env, actor) }) end local poolsRemaining = calcs.reducePoolsByDamage(nil, takenHit, actor) - + t_insert(breakdown["totalTakenHit"], "Such a hit would drain the following resources:") breakdown["totalTakenHit"] = incomingDamageBreakdown(breakdown["totalTakenHit"], poolsRemaining, output) diff --git a/src/Modules/CalcMirages.lua b/src/Modules/CalcMirages.lua index 9d14cf1427..504f375e19 100644 --- a/src/Modules/CalcMirages.lua +++ b/src/Modules/CalcMirages.lua @@ -189,7 +189,7 @@ function calcs.mirages(env) config = { compareFunc = function(skill, env, config, mirageSkill) local isDisabled = skill.skillFlags and skill.skillFlags.disable - local skillTypeMatch = (skill.skillTypes[SkillType.Slam] or skill.skillTypes[SkillType.Melee]) and skill.skillTypes[SkillType.Attack] + local skillTypeMatch = (skill.skillTypes[SkillType.Slam] or skill.skillTypes[SkillType.Melee]) and skill.skillTypes[SkillType.Attack] local skillTypeExcludes = skill.skillTypes[SkillType.Vaal] or skill.skillTypes[SkillType.Totem] or skill.skillTypes[SkillType.SummonsTotem] if skill ~= env.player.mainSkill and not isTriggered(skill) and not isDisabled and skillTypeMatch and not skillTypeExcludes and not skill.skillCfg.skillCond["usedByMirage"] then local uuid = cacheSkillUUID(skill, env) @@ -207,7 +207,7 @@ function calcs.mirages(env) end, preCalcFunc = function(env, newSkill, newEnv) icdrSkill = calcLib.mod(newSkill.skillModList, newSkill.skillCfg, "CooldownRecovery") - + triggeredCD = newSkill.skillData.cooldown or 0 triggeredCDAdjusted = triggeredCD / icdrSkill triggeredCDTickRounded = m_ceil(triggeredCDAdjusted * data.misc.ServerTickRate) / data.misc.ServerTickRate @@ -215,9 +215,9 @@ function calcs.mirages(env) triggerCD = env.player.mainSkill.skillData.cooldown or 0 triggerCDAdjusted = triggerCD / icdrSkill triggerCDTickRounded = m_ceil(triggerCDAdjusted * data.misc.ServerTickRate) / data.misc.ServerTickRate - + actionCooldown = m_max( triggeredCDTickRounded or 0, triggerCDTickRounded or 0 ) - + TriggerRateCap = m_huge if actionCooldown ~= 0 then TriggerRateCap = 1 / actionCooldown @@ -298,7 +298,7 @@ function calcs.mirages(env) local lessDamage = newSkill.skillModList:Sum("BASE", env.player.mainSkill.skillCfg, "SacredWispsLessDamage") local wispsMaxCount local wispsCastChance - + -- Find Wisps summoning skill for cast chance and wisp count for _, skill in ipairs(env.player.activeSkillList) do if skill.activeEffect.grantedEffect.name == "Summon Sacred Wisps" then diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index 851a260e60..9787468cd8 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -1264,14 +1264,14 @@ function calcs.offence(env, actor, activeSkill) output.MineLayingSpeed = m_min(output.MineLayingSpeed, data.misc.ServerTickRate) output.MineLayingTime = 1 / output.MineLayingSpeed - + -- Trap mine interaction where the Character throws mines, mine throws traps if skillFlags.trap then skillData.timeOverride = output.MineLayingTime / output.MineThrowCount / output.TrapThrowCount else skillData.timeOverride = output.MineLayingTime / output.MineThrowCount end - + if breakdown then breakdown.MineLayingTime = { } breakdown.multiChain(breakdown.MineLayingTime, { @@ -1643,7 +1643,7 @@ function calcs.offence(env, actor, activeSkill) elseif val.type == "ES" then local manaType = getCostIndexByName(resource:gsub("ES", "Mana")) local lifeType = getCostIndexByName(resource:gsub("ES", "Life")) - if skillModList:Flag(skillCfg, "CostESInsteadOfManaOrLife") then -- Whispers of Infinity + if skillModList:Flag(skillCfg, "CostESInsteadOfManaOrLife") then -- Whispers of Infinity val.baseCost = val.baseCost + costs[manaType].baseCost+ costs[lifeType].baseCost val.baseCostNoMult = val.baseCostNoMult + costs[manaType].baseCostNoMult + costs[lifeType].baseCostNoMult val.finalBaseCost = val.finalBaseCost + costs[manaType].finalBaseCost + costs[lifeType].finalBaseCost @@ -1656,8 +1656,8 @@ function calcs.offence(env, actor, activeSkill) costs[lifeType].finalBaseCost = 0 costs[lifeType].baseCostNoMult = 0 elseif additionalESCost > 0 then - val.baseCost = costs[manaType].baseCost - val.finalBaseCost = val.finalBaseCost + round(costs[manaType].finalBaseCost * additionalESCost) + val.baseCost = costs[manaType].baseCost + val.finalBaseCost = val.finalBaseCost + round(costs[manaType].finalBaseCost * additionalESCost) end elseif val.type == "Rage" then if skillModList:Flag(skillCfg, "CostRageInsteadOfSouls") then -- Hateforge @@ -2228,12 +2228,12 @@ function calcs.offence(env, actor, activeSkill) skillModList:NewMod("Multiplier:TraumaStacks", "BASE", skillModList:Sum("BASE", skillCfg, "Multiplier:SustainableTraumaStacks"), "Maximum Sustainable Trauma Stacks") end local inc = skillModList:Sum("INC", cfg, "Speed") - + if skillFlags.warcry then output.Speed = 1 / output.WarcryCastTime else output.Speed = 1 / (baseTime / round((1 + inc/100) * more, 2) + skillModList:Sum("BASE", cfg, "TotalAttackTime") + skillModList:Sum("BASE", cfg, "TotalCastTime")) - + end output.CastRate = output.Speed if skillFlags.selfCast then @@ -2833,7 +2833,7 @@ function calcs.offence(env, actor, activeSkill) output.PreEffectiveCritChance = output.CritChance local preLuckyCritChance = output.CritChance local critRolls = 0 - + if env.mode_effective and skillModList:Flag(cfg, "CritChanceLucky") then critRolls = critRolls + 1 end @@ -2974,7 +2974,7 @@ function calcs.offence(env, actor, activeSkill) --Calculate reservation DPS globalOutput.ReservationDpsMultiplier = 100 / (100 - enemyDB:Sum("BASE", nil, "LifeReservationPercent")) - + runSkillFunc("postCritFunc") -- Calculate base hit damage @@ -3665,7 +3665,7 @@ function calcs.offence(env, actor, activeSkill) t_insert(breakdown.PvpTotalDPS, s_format("= %.1f", output.PvpTotalDPS)) end end - + if activeSkill.minion then skillData.summonSpeed = output.SummonedMinionsPerCast * (output.HitSpeed or output.Speed) * skillData.dpsMultiplier end @@ -4279,7 +4279,7 @@ function calcs.offence(env, actor, activeSkill) local PoisonStacks = output.HitChance / 100 * poisonChance * doublePoisonChance * skillData.dpsMultiplier * (skillData.stackMultiplier or 1) * quantityMultiplier if (globalOutput.HitSpeed or globalOutput.Speed) > 0 then --assume skills with no cast, attack, or cooldown time are single cast - PoisonStacks = PoisonStacks * globalOutput.PoisonDuration * (globalOutput.HitSpeed or globalOutput.Speed) + PoisonStacks = PoisonStacks * globalOutput.PoisonDuration * (globalOutput.HitSpeed or globalOutput.Speed) end if PoisonStacks < 1 and (env.configInput.multiplierPoisonOnEnemy or 0) <= 1 then skillModList:NewMod("Condition:SinglePoison", "FLAG", true, "poison") @@ -4927,7 +4927,7 @@ function calcs.offence(env, actor, activeSkill) end end end - -- Cycle through all non-damage ailments here, modifying them if needed + -- Cycle through all non-damage ailments here, modifying them if needed for ailment, val in pairs(ailments) do if (output[ailment.."ChanceOnHit"] + output[ailment.."ChanceOnCrit"]) > 0 then if globalBreakdown then @@ -5370,7 +5370,7 @@ function calcs.offence(env, actor, activeSkill) end end end - + if skillModList:Flag(nil, "DotCanStack") then skillFlags.DotCanStack = true local speed = output.Speed diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 90e543af86..a3226c6a67 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -765,7 +765,7 @@ local function doActorMisc(env, actor) local avoidChill = modDB:Flag(nil, "ChillImmune", "ElementalAilmentImmune") and 100 or m_floor(m_min(modDB:Sum("BASE", nil, "AvoidChill", "AvoidAilments", "AvoidElementalAilments") + (modDB:Flag(nil, "ShockAvoidAppliesToElementalAilments") and modDB:Sum("BASE", nil, "AvoidShock") or 0) + (modDB:Flag(nil, "SpellSuppressionAppliesToAilmentAvoidance") and modDB:Sum("BASE", nil, "SpellSuppressionChance") / 2 or 0), 100)) - + local effect = avoidChill == 100 and 0 or m_min(m_max(m_floor(chillValue * totalChillSelfEffect), 0), modDB:Override(nil, "ChillMax") or ailmentData.Chill.max) if modDB:Flag(nil, "SkitterbotBonechill") then modDB:NewMod("ColdDamageTaken", "INC", effect * (modDB:Flag(nil, "SelfChillEffectIsReversed") and -1 or 1), "Bonechill") @@ -778,7 +778,7 @@ local function doActorMisc(env, actor) local totalShockSelfEffect = calcLib.mod(modDB, nil, "SelfShockEffect") local avoidShock = modDB:Flag(nil, "ShockImmune", "ElementalAilmentImmune") and 100 or m_floor(m_min(modDB:Sum("BASE", nil, "AvoidShock", "AvoidAilments", "AvoidElementalAilments") + (modDB:Flag(nil, "SpellSuppressionAppliesToAilmentAvoidance") and modDB:Sum("BASE", nil, "SpellSuppressionChance") / 2 or 0), 100)) - + local effect = avoidShock == 100 and 0 or m_min(m_max(m_floor(shockValue * totalShockSelfEffect), 0), modDB:Override(nil, "ShockMax") or ailmentData.Shock.max) modDB:NewMod("DamageTaken", "INC", effect, "Shock") end @@ -873,7 +873,7 @@ local function doActorCharges(env, actor) -- Calculate current and maximum charges output.PowerChargesMin = m_max(modDB:Sum("BASE", nil, "PowerChargesMin"), 0) output.PowerChargesMax = m_max(modDB:Sum("BASE", nil, "PowerChargesMax"), 0) - output.PowerChargesDuration = m_floor(modDB:Sum("BASE", nil, "ChargeDuration") * calcLib.mod(modDB, nil, "PowerChargesDuration", "ChargeDuration")) + output.PowerChargesDuration = m_floor(modDB:Sum("BASE", nil, "ChargeDuration") * calcLib.mod(modDB, nil, "PowerChargesDuration", "ChargeDuration")) if modDB:Flag(nil, "MaximumFrenzyChargesIsMaximumPowerCharges") then local source = modDB.mods["MaximumFrenzyChargesIsMaximumPowerCharges"][1].source if not modDB:HasMod("OVERRIDE", {source = source:match("[^:]+")}, "FrenzyChargesMax") then @@ -978,7 +978,7 @@ local function doActorCharges(env, actor) end if actor == env.player then output.InspirationCharges = modDB:Override(nil, "InspirationCharges") or output.InspirationChargesMax - end + end if modDB:Flag(nil, "UseGhostShrouds") then output.GhostShrouds = modDB:Override(nil, "GhostShrouds") or 3 end @@ -1163,7 +1163,7 @@ function calcs.perform(env, skipEHP) end local hasGuaranteedBonechill = false - + -- Banners if modDB:Flag(nil,"Condition:BannerPlanted") then local max = modDB:Sum("BASE", nil, "MaximumValour") @@ -1544,7 +1544,7 @@ function calcs.perform(env, skipEHP) end end end - + local effectInc = modDB:Sum("INC", {actor = "player"}, "TinctureEffect") local effectIncMagic = modDB:Sum("INC", {actor = "player"}, "MagicTinctureEffect") local tinctureLimit = modDB:Sum("BASE", nil, "TinctureLimit") @@ -1554,8 +1554,8 @@ function calcs.perform(env, skipEHP) output.TinctureEffect = effectInc output.TinctureLimit = tinctureLimit end - - + + local function mergeTinctures(tinctures) local tinctureBuffs = { } local tinctureConditions = {} @@ -1568,7 +1568,7 @@ function calcs.perform(env, skipEHP) end -- Compute tincture effect multiplier. -- Tincture effect multiplier is rounded to 2 decimal places before applying it. - local effectMod = math.floor((1 + (tinctureEffectInc) / 100) * (1 + (item.quality or 0) / 100) * 100) / 100 + local effectMod = math.floor((1 + (tinctureEffectInc) / 100) * (1 + (item.quality or 0) / 100) * 100) / 100 -- same deal as flasks, go look at the comment there if buffModList[1] then @@ -1953,7 +1953,7 @@ function calcs.perform(env, skipEHP) if env.mode_buffs and (not activeSkill.skillFlags.totem or buff.allowTotemBuff) then local skillCfg = buff.activeSkillBuff and skillCfg local modStore = buff.activeSkillBuff and skillModList or modDB - if not buff.applyNotPlayer then + if not buff.applyNotPlayer then activeSkill.buffSkill = true modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true local srcList = new("ModList") @@ -1985,7 +1985,7 @@ function calcs.perform(env, skipEHP) if env.mode_buffs and (not activeSkill.skillFlags.totem or buff.allowTotemBuff) then local skillCfg = buff.activeSkillBuff and skillCfg local modStore = buff.activeSkillBuff and skillModList or modDB - if not buff.applyNotPlayer then + if not buff.applyNotPlayer then activeSkill.buffSkill = true local srcList = new("ModList") local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnSelf", "BuffEffectOnPlayer") @@ -3094,10 +3094,10 @@ function calcs.perform(env, skipEHP) if breakdown then t_insert(mods, modLib.createMod("DamageTakenByShock", "INC", num, "Shock Stacks", { type = "Condition", var = "Shocked" }, { type = "Multiplier", var = "ShockStacks", limit = modDB:Override(nil, "ShockStacksMax") or modDB:Sum("BASE", nil, "ShockStacksMax")})) end - else + else t_insert(mods, modLib.createMod("DamageTaken", "INC", num, "Shock", { type = "Condition", var = "Shocked" })) end - return mods + return mods end }, ["Scorch"] = { @@ -3110,10 +3110,10 @@ function calcs.perform(env, skipEHP) if breakdown then t_insert(mods, modLib.createMod("ElementalResistByScorch", "BASE", -num, "Scorch Stacks", { type = "Condition", var = "Scorched" }, { type = "Multiplier", var = "ScorchStacks", limit = modDB:Override(nil, "ScorchStacksMax") or modDB:Sum("BASE", nil, "ScorchStacksMax")})) end - else + else t_insert(mods, modLib.createMod("ElementalResist", "BASE", -num, "Scorch", { type = "Condition", var = "Scorched" })) end - return mods + return mods end }, ["Brittle"] = { @@ -3243,14 +3243,14 @@ function calcs.perform(env, skipEHP) calcs.offence(env, env.minion, env.minion.mainSkill) end - -- Export modifiers to enemy conditions and stats for party tab + -- Export modifiers to enemy conditions and stats for party tab if partyTabEnableExportBuffs then - for k, mod in pairs(enemyDB.mods) do - if k:find("Condition") and not k:find("Party") then - buffExports["EnemyConditions"][k] = true - elseif (k:find("Resist") and not k:find("Totem") and not k:find("Max")) or k:find("Damage") or k:find("ActionSpeed") or k:find("SelfCrit") or (k:find("Multiplier") and not k:find("Max") and not k:find("Impale")) then - for _, v in ipairs(mod) do - if not v.party and v.value ~= 0 and v.source ~= "EnemyConfig" and v.source ~= "Base" and not v.source:find("Delirious") and not v.source:find("^Party") then + for k, mod in pairs(enemyDB.mods) do + if k:find("Condition") and not k:find("Party") then + buffExports["EnemyConditions"][k] = true + elseif (k:find("Resist") and not k:find("Totem") and not k:find("Max")) or k:find("Damage") or k:find("ActionSpeed") or k:find("SelfCrit") or (k:find("Multiplier") and not k:find("Max") and not k:find("Impale")) then + for _, v in ipairs(mod) do + if not v.party and v.value ~= 0 and v.source ~= "EnemyConfig" and v.source ~= "Base" and not v.source:find("Delirious") and not v.source:find("^Party") then local skipValue = false for _, tag in ipairs(v) do if tag.effectType == "Curse" or tag.effectType == "AuraDebuff" then @@ -3258,10 +3258,10 @@ function calcs.perform(env, skipEHP) break end end - if not skipValue and (not v[1] or ( + if not skipValue and (not v[1] or ( (v[1].type ~= "Condition" or (v[1].var and (enemyDB.mods["Condition:"..v[1].var] and enemyDB.mods["Condition:"..v[1].var][1].value) or v[1].varList and (enemyDB.mods["Condition:"..v[1].varList[1]] and enemyDB.mods["Condition:"..v[1].varList[1]][1].value))) and (v[1].type ~= "Multiplier" or (enemyDB.mods["Multiplier:"..v[1].var] and enemyDB.mods["Multiplier:"..v[1].var][1].value)))) then - if buffExports["EnemyMods"][k] then + if buffExports["EnemyMods"][k] then if not buffExports["EnemyMods"][k].MultiStat then buffExports["EnemyMods"][k] = { MultiStat = true, buffExports["EnemyMods"][k] } end @@ -3269,11 +3269,11 @@ function calcs.perform(env, skipEHP) else buffExports["EnemyMods"][k] = v end - end - end - end - end - end + end + end + end + end + end for _, damageType in ipairs({"Physical", "Lightning", "Cold", "Fire", "Chaos"}) do if env.modDB:Flag(nil, "Enemy"..damageType.."ResistEqualToYours") and output[damageType.."Resist"] then @@ -3287,7 +3287,7 @@ function calcs.perform(env, skipEHP) end buffExports.PlayerMods["MovementSpeedMod|percent|max="..tostring(output["MovementSpeedMod"] * 100)] = true - + for _, mod in ipairs(buffExports["Aura"]["extraAura"].modList) do -- leaving comment to make it easier for future similar mods --if mod.name:match("Parent") then @@ -3376,7 +3376,7 @@ function calcs.perform(env, skipEHP) output.GemHasLevel = true output.GemLevel = baseLevel + totalSupportLevel + totalItemLevel - + if env.player.breakdown then env.player.breakdown.GemLevel = {} t_insert(env.player.breakdown.GemLevel, s_format("%d ^8(level from gem)", baseLevel)) diff --git a/src/Modules/CalcSections.lua b/src/Modules/CalcSections.lua index 0f05680fa9..547d05714a 100644 --- a/src/Modules/CalcSections.lua +++ b/src/Modules/CalcSections.lua @@ -20,24 +20,24 @@ local fireHitTaken = { local chaosHitTaken = { "DamageTaken", "ChaosDamageTaken", "ChaosResist", "CurseEffectOnSelf" } -local physicalConvert = { - "SkillPhysicalDamageConvertToLightning", "SkillPhysicalDamageConvertToCold", "SkillPhysicalDamageConvertToFire", "SkillPhysicalDamageConvertToChaos", - "PhysicalDamageConvertToLightning", "PhysicalDamageConvertToCold", "PhysicalDamageConvertToFire", "PhysicalDamageConvertToChaos", "NonChaosDamageConvertToChaos", - "PhysicalDamageGainAsLightning", "PhysicalDamageGainAsCold", "PhysicalDamageGainAsFire", "PhysicalDamageGainAsChaos", "NonChaosDamageGainAsChaos" +local physicalConvert = { + "SkillPhysicalDamageConvertToLightning", "SkillPhysicalDamageConvertToCold", "SkillPhysicalDamageConvertToFire", "SkillPhysicalDamageConvertToChaos", + "PhysicalDamageConvertToLightning", "PhysicalDamageConvertToCold", "PhysicalDamageConvertToFire", "PhysicalDamageConvertToChaos", "NonChaosDamageConvertToChaos", + "PhysicalDamageGainAsLightning", "PhysicalDamageGainAsCold", "PhysicalDamageGainAsFire", "PhysicalDamageGainAsChaos", "NonChaosDamageGainAsChaos" } local lightningConvert = { "SkillLightningDamageConvertToCold", "SkillLightningDamageConvertToFire", "SkillLightningDamageConvertToChaos", - "LightningDamageConvertToCold", "LightningDamageConvertToFire", "LightningDamageConvertToChaos", "ElementalDamageConvertToChaos", "NonChaosDamageConvertToChaos", + "LightningDamageConvertToCold", "LightningDamageConvertToFire", "LightningDamageConvertToChaos", "ElementalDamageConvertToChaos", "NonChaosDamageConvertToChaos", "LightningDamageGainAsCold", "LightningDamageGainAsFire", "LightningDamageGainAsChaos", "ElementalDamageGainAsChaos", "NonChaosDamageGainAsChaos" } -local coldConvert = { +local coldConvert = { "SkillColdDamageConvertToFire", "SkillColdDamageConvertToChaos", "ColdDamageConvertToFire", "ColdDamageConvertToChaos", "ElementalDamageConvertToChaos", "NonChaosDamageConvertToChaos", "ColdDamageGainAsFire", "ColdDamageGainAsChaos", "ElementalDamageGainAsChaos", "NonChaosDamageGainAsChaos" } local fireConvert = { "SkillFireDamageConvertToChaos", - "FireDamageConvertToChaos", "ElementalDamageConvertToChaos", "NonChaosDamageConvertToChaos", + "FireDamageConvertToChaos", "ElementalDamageConvertToChaos", "NonChaosDamageConvertToChaos", "FireDamageGainAsChaos", "ElementalDamageGainAsChaos", "NonChaosDamageGainAsChaos" } @@ -57,46 +57,46 @@ return { }, { label = "Added Min", { }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "PhysicalMin", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfPhysicalMin", modType = "BASE", enemy = true, cfg = "skill" }, }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "LightningMin", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfLightningMin", modType = "BASE", enemy = true, cfg = "skill" }, }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "ColdMin", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfColdMin", modType = "BASE", enemy = true, cfg = "skill" }, }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "FireMin", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfFireMin", modType = "BASE", enemy = true, cfg = "skill" }, }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "ChaosMin", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfChaosMin", modType = "BASE", enemy = true, cfg = "skill" }, }, }, { label = "Added Max", { }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "PhysicalMax", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfPhysicalMax", modType = "BASE", enemy = true, cfg = "skill" }, }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "LightningMax", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfLightningMax", modType = "BASE", enemy = true, cfg = "skill" }, }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "ColdMax", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfColdMax", modType = "BASE", enemy = true, cfg = "skill" }, }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "FireMax", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfFireMax", modType = "BASE", enemy = true, cfg = "skill" }, }, - { format = "{0:mod:1,2}", + { format = "{0:mod:1,2}", { label = "Player modifiers", modName = "ChaosMax", modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfChaosMax", modType = "BASE", enemy = true, cfg = "skill" }, }, @@ -122,7 +122,7 @@ return { { }, { format = "x {3:output:PhysicalEffMult}", { breakdown = "PhysicalEffMult" }, - { label = "Enemy modifiers", modName = physicalHitTaken, enemy = true, cfg = "skill" }, + { label = "Enemy modifiers", modName = physicalHitTaken, enemy = true, cfg = "skill" }, }, { format = "x {3:output:LightningEffMult}", { breakdown = "LightningEffMult" }, @@ -147,30 +147,30 @@ return { }, { label = "Skill Hit Damage", textSize = 12, notFlag = "attack", { format = "{0:output:TotalMin} to {0:output:TotalMax}", }, - { format = "{0:output:PhysicalMin} to {0:output:PhysicalMax}", - { breakdown = "Physical" }, - { label = "Conversions", modType = "BASE", cfg = "skill", modName = physicalConvert }, + { format = "{0:output:PhysicalMin} to {0:output:PhysicalMax}", + { breakdown = "Physical" }, + { label = "Conversions", modType = "BASE", cfg = "skill", modName = physicalConvert }, }, - { format = "{0:output:LightningMin} to {0:output:LightningMax}", - { breakdown = "Lightning" }, - { label = "Conversions", modType = "BASE", cfg = "skill", modName = lightningConvert }, + { format = "{0:output:LightningMin} to {0:output:LightningMax}", + { breakdown = "Lightning" }, + { label = "Conversions", modType = "BASE", cfg = "skill", modName = lightningConvert }, }, - { format = "{0:output:ColdMin} to {0:output:ColdMax}", - { breakdown = "Cold" }, - { label = "Conversions", modType = "BASE", cfg = "skill", modName = coldConvert }, + { format = "{0:output:ColdMin} to {0:output:ColdMax}", + { breakdown = "Cold" }, + { label = "Conversions", modType = "BASE", cfg = "skill", modName = coldConvert }, }, - { format = "{0:output:FireMin} to {0:output:FireMax}", - { breakdown = "Fire" }, - { label = "Conversions", modType = "BASE", cfg = "skill", modName = fireConvert }, + { format = "{0:output:FireMin} to {0:output:FireMax}", + { breakdown = "Fire" }, + { label = "Conversions", modType = "BASE", cfg = "skill", modName = fireConvert }, }, - { format = "{0:output:ChaosMin} to {0:output:ChaosMax}", - { breakdown = "Chaos" }, + { format = "{0:output:ChaosMin} to {0:output:ChaosMax}", + { breakdown = "Chaos" }, }, }, { label = "Skill Average Hit", notFlag = "attack", { format = "{1:output:AverageHit}", { breakdown = "AverageHit" }, }, }, - { label = "Skill PvP Average Hit", flag = "notAttackPvP", { format = "{1:output:PvpAverageHit}", { breakdown = "PvpAverageHit" }, - { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, - { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, + { label = "Skill PvP Average Hit", flag = "notAttackPvP", { format = "{1:output:PvpAverageHit}", { breakdown = "PvpAverageHit" }, + { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, + { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, }, }, -- Main Hand Hit Damage { label = "MH Total Increased", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", @@ -193,7 +193,7 @@ return { { }, { format = "x {3:output:MainHand.PhysicalEffMult}", { breakdown = "MainHand.PhysicalEffMult" }, - { label = "Enemy modifiers", modName = physicalHitTaken, enemy = true, cfg = "weapon1" }, + { label = "Enemy modifiers", modName = physicalHitTaken, enemy = true, cfg = "weapon1" }, }, { format = "x {3:output:MainHand.LightningEffMult}", { breakdown = "MainHand.LightningEffMult" }, @@ -218,31 +218,31 @@ return { }, { label = "MH Hit Damage", bgCol = colorCodes.MAINHANDBG, textSize = 12, flag = "weapon1Attack", { format = "{0:output:MainHand.TotalMin} to {0:output:MainHand.TotalMax}", }, - { format = "{0:output:MainHand.PhysicalMin} to {0:output:MainHand.PhysicalMax}", - { breakdown = "MainHand.Physical" }, + { format = "{0:output:MainHand.PhysicalMin} to {0:output:MainHand.PhysicalMax}", + { breakdown = "MainHand.Physical" }, { label = "Conversions", modType = "BASE", cfg = "weapon1", modName = physicalConvert }, }, - { format = "{0:output:MainHand.LightningMin} to {0:output:MainHand.LightningMax}", - { breakdown = "MainHand.Lightning" }, - { label = "Conversions", modType = "BASE", cfg = "weapon1", modName = lightningConvert }, + { format = "{0:output:MainHand.LightningMin} to {0:output:MainHand.LightningMax}", + { breakdown = "MainHand.Lightning" }, + { label = "Conversions", modType = "BASE", cfg = "weapon1", modName = lightningConvert }, }, - { format = "{0:output:MainHand.ColdMin} to {0:output:MainHand.ColdMax}", - { breakdown = "MainHand.Cold" }, - { label = "Conversions", modType = "BASE", cfg = "weapon1", modName = coldConvert }, + { format = "{0:output:MainHand.ColdMin} to {0:output:MainHand.ColdMax}", + { breakdown = "MainHand.Cold" }, + { label = "Conversions", modType = "BASE", cfg = "weapon1", modName = coldConvert }, }, - { format = "{0:output:MainHand.FireMin} to {0:output:MainHand.FireMax}", - { breakdown = "MainHand.Fire" }, - { label = "Conversions", modType = "BASE", cfg = "weapon1", modName = fireConvert }, + { format = "{0:output:MainHand.FireMin} to {0:output:MainHand.FireMax}", + { breakdown = "MainHand.Fire" }, + { label = "Conversions", modType = "BASE", cfg = "weapon1", modName = fireConvert }, }, - { format = "{0:output:MainHand.ChaosMin} to {0:output:MainHand.ChaosMax}", - { breakdown = "MainHand.Chaos" }, + { format = "{0:output:MainHand.ChaosMin} to {0:output:MainHand.ChaosMax}", + { breakdown = "MainHand.Chaos" }, }, }, { label = "MH Average Hit", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{1:output:MainHand.AverageHit}", { breakdown = "MainHand.AverageHit" }, }, }, - { label = "MH PvP Average Hit", bgCol = colorCodes.MAINHANDBG, flag = "weapon1AttackPvP", { format = "{1:output:MainHand.PvpAverageHit}", { breakdown = "MainHand.PvpAverageHit" }, - { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, - { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, - }, }, + { label = "MH PvP Average Hit", bgCol = colorCodes.MAINHANDBG, flag = "weapon1AttackPvP", { format = "{1:output:MainHand.PvpAverageHit}", { breakdown = "MainHand.PvpAverageHit" }, + { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, + { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, + }, }, -- Off Hand Hit Damage { label = "OH Total Increased", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "{0:mod:1}%", { modName = "Damage", modType = "INC", cfg = "weapon2" }, }, @@ -264,7 +264,7 @@ return { { }, { format = "x {3:output:OffHand.PhysicalEffMult}", { breakdown = "OffHand.PhysicalEffMult" }, - { label = "Enemy modifiers", modName = physicalHitTaken, enemy = true, cfg = "weapon2" }, + { label = "Enemy modifiers", modName = physicalHitTaken, enemy = true, cfg = "weapon2" }, }, { format = "x {3:output:OffHand.LightningEffMult}", { breakdown = "OffHand.LightningEffMult" }, @@ -289,60 +289,60 @@ return { }, { label = "OH Hit Damage", bgCol = colorCodes.OFFHANDBG, textSize = 12, flag = "weapon2Attack", { format = "{0:output:OffHand.TotalMin} to {0:output:OffHand.TotalMax}", }, - { format = "{0:output:OffHand.PhysicalMin} to {0:output:OffHand.PhysicalMax}", - { breakdown = "OffHand.Physical" }, + { format = "{0:output:OffHand.PhysicalMin} to {0:output:OffHand.PhysicalMax}", + { breakdown = "OffHand.Physical" }, { label = "Conversions", modType = "BASE", cfg = "weapon2", modName = physicalConvert }, }, - { format = "{0:output:OffHand.LightningMin} to {0:output:OffHand.LightningMax}", - { breakdown = "OffHand.Lightning" }, - { label = "Conversions", modType = "BASE", cfg = "weapon2", modName = lightningConvert }, + { format = "{0:output:OffHand.LightningMin} to {0:output:OffHand.LightningMax}", + { breakdown = "OffHand.Lightning" }, + { label = "Conversions", modType = "BASE", cfg = "weapon2", modName = lightningConvert }, }, - { format = "{0:output:OffHand.ColdMin} to {0:output:OffHand.ColdMax}", - { breakdown = "OffHand.Cold" }, - { label = "Conversions", modType = "BASE", cfg = "weapon2", modName = coldConvert }, + { format = "{0:output:OffHand.ColdMin} to {0:output:OffHand.ColdMax}", + { breakdown = "OffHand.Cold" }, + { label = "Conversions", modType = "BASE", cfg = "weapon2", modName = coldConvert }, }, - { format = "{0:output:OffHand.FireMin} to {0:output:OffHand.FireMax}", - { breakdown = "OffHand.Fire" }, - { label = "Conversions", modType = "BASE", cfg = "weapon2", modName = fireConvert }, + { format = "{0:output:OffHand.FireMin} to {0:output:OffHand.FireMax}", + { breakdown = "OffHand.Fire" }, + { label = "Conversions", modType = "BASE", cfg = "weapon2", modName = fireConvert }, }, - { format = "{0:output:OffHand.ChaosMin} to {0:output:OffHand.ChaosMax}", + { format = "{0:output:OffHand.ChaosMin} to {0:output:OffHand.ChaosMax}", { breakdown = "OffHand.Chaos" }, }, }, { label = "OH Average Hit", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "{1:output:OffHand.AverageHit}", { breakdown = "OffHand.AverageHit" }, }, }, - { label = "OH PvP Average Hit", bgCol = colorCodes.OFFHANDBG, flag = "weapon2AttackPvP", { format = "{1:output:OffHand.PvpAverageHit}", { breakdown = "OffHand.PvpAverageHit" }, - { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, - { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, + { label = "OH PvP Average Hit", bgCol = colorCodes.OFFHANDBG, flag = "weapon2AttackPvP", { format = "{1:output:OffHand.PvpAverageHit}", { breakdown = "OffHand.PvpAverageHit" }, + { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, + { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, }, }, - { label = "Average Damage", flag = "attack", { format = "{1:output:AverageDamage}", + { label = "Average Damage", flag = "attack", { format = "{1:output:AverageDamage}", { breakdown = "MainHand.AverageDamage" }, { breakdown = "OffHand.AverageDamage" }, { breakdown = "AverageDamage" }, }, }, { label = "Chance to Hit", haveOutput = "enemyHasSpellBlock", { format = "{0:output:HitChance}%", - { breakdown = "HitChance" }, + { breakdown = "HitChance" }, { label = "Enemy Block", modName = { "BlockChance" }, enemy = true }, { label = "Block Chance Reduction", cfg = "skill", modName = { "reduceEnemyBlock" } }, }, }, - { label = "Average Damage", haveOutput = "enemyHasSpellBlock", { format = "{1:output:AverageDamage}", + { label = "Average Damage", haveOutput = "enemyHasSpellBlock", { format = "{1:output:AverageDamage}", { breakdown = "AverageDamage" }, }, }, { label = "Chance to Explode", haveOutput = "ExplodeChance", { format = "{0:output:ExplodeChance}%" }, }, { label = "Average Damage", haveOutput = "ExplodeChance", { format = "{1:output:AverageDamage}", { breakdown = "AverageDamage" }, }, }, - { label = "PvP Average Dmg", flag = "attackPvP", { format = "{1:output:PvpAverageDamage}", + { label = "PvP Average Dmg", flag = "attackPvP", { format = "{1:output:PvpAverageDamage}", { breakdown = "MainHand.PvpAverageDamage" }, { breakdown = "OffHand.PvpAverageDamage" }, { breakdown = "PvpAverageDamage" }, - { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, - { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, + { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, + { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, }, }, { label = "Skill DPS", flag = "notAverage", notFlag = "triggered", { format = "{1:output:TotalDPS}", { breakdown = "TotalDPS" }, { label = "DPS Multiplier", modName = "DPS" }, }, }, - { label = "Skill PvP DPS", flag = "notAveragePvP", { format = "{1:output:PvpTotalDPS}", { breakdown = "PvpTotalDPS" }, - { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, - { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, - { label = "DPS Multiplier", modName = "DPS" }, + { label = "Skill PvP DPS", flag = "notAveragePvP", { format = "{1:output:PvpTotalDPS}", { breakdown = "PvpTotalDPS" }, + { label = "Tvalue Override (ms)", modName = "MultiplierPvpTvalueOverride" }, + { label = "PvP Multiplier", cfg = "skill", modName = "PvpDamageMultiplier" }, + { label = "DPS Multiplier", modName = "DPS" }, }, }, { label = "Skill DPS", flag = "triggered", { format = "{1:output:TotalDPS}", { breakdown = "TotalDPS" }, { label = "DPS Multiplier", modName = "DPS" }, }, }, } } @@ -358,42 +358,42 @@ return { { format = "Number of Exerts" }, { format = "Max 1-Hit Impact"}, }, - { label = "Seismic Cry", haveOutput = "SeismicUpTimeRatio", + { label = "Seismic Cry", haveOutput = "SeismicUpTimeRatio", { format = "{2:output:SeismicHitEffect}", { breakdown = "SeismicHitEffect"}, }, { format = "{2:output:SeismicAvgDmg}", { breakdown = "SeismicAvgDmg"}, }, { format = "{0:output:SeismicUpTimeRatio}%", { breakdown = "SeismicUpTimeRatio" }, }, { format = "{0:output:SeismicExertsCount}" }, { format = "{2:output:SeismicMaxHitEffect}" }, }, - { label = "Intimidating Cry", haveOutput = "IntimidatingUpTimeRatio", + { label = "Intimidating Cry", haveOutput = "IntimidatingUpTimeRatio", { format = "{2:output:IntimidatingHitEffect}", { breakdown = "IntimidatingHitEffect"}, }, { format = "{2:output:IntimidatingAvgDmg}", { breakdown = "IntimidatingAvgDmg"}, }, { format = "{0:output:IntimidatingUpTimeRatio}%", { breakdown = "IntimidatingUpTimeRatio" }, }, { format = "{0:output:IntimidatingExertsCount}" }, { format = "{2:output:IntimidatingMaxHitEffect}" }, }, - { label = "Rallying Cry", haveOutput = "RallyingUpTimeRatio", + { label = "Rallying Cry", haveOutput = "RallyingUpTimeRatio", { format = "{2:output:RallyingHitEffect}", { breakdown = "RallyingHitEffect"}, }, { format = "{2:output:RallyingAvgDmg}", { breakdown = "RallyingAvgDmg"}, }, { format = "{0:output:RallyingUpTimeRatio}%", { breakdown = "RallyingUpTimeRatio" }, }, { format = "{0:output:RallyingExertsCount}" }, { format = "{2:output:RallyingMaxHitEffect}" }, }, - { label = "Infernal Cry", haveOutput = "InfernalUpTimeRatio", + { label = "Infernal Cry", haveOutput = "InfernalUpTimeRatio", { format = "" }, { format = "" }, { format = "{0:output:InfernalUpTimeRatio}%", { breakdown = "InfernalUpTimeRatio" }, }, { format = "{0:output:InfernalExertsCount}" }, { format = "" }, }, - { label = "Battlemage's Cry", haveOutput = "BattlemageUpTimeRatio", + { label = "Battlemage's Cry", haveOutput = "BattlemageUpTimeRatio", { format = "" }, { format = "" }, { format = "{0:output:BattlemageUpTimeRatio}%", { breakdown = "BattlemageUpTimeRatio" }, }, { format = "{0:output:BattleCryExertsCount}" }, { format = "" }, }, - { label = "Ancestral Cry", haveOutput = "AncestralUpTimeRatio", + { label = "Ancestral Cry", haveOutput = "AncestralUpTimeRatio", { format = "" }, { format = "" }, { format = "{0:output:AncestralUpTimeRatio}%", { breakdown = "AncestralUpTimeRatio" }, }, @@ -449,7 +449,7 @@ return { { }, { format = "x {3:output:PhysicalDotEffMult}", { breakdown = "PhysicalDotEffMult" }, - { label = "Enemy modifiers", modName = { "DamageTaken", "DamageTakenOverTime", "PhysicalDamageTaken", "PhysicalDamageTakenOverTime", "PhysicalDamageReduction" }, enemy = true }, + { label = "Enemy modifiers", modName = { "DamageTaken", "DamageTakenOverTime", "PhysicalDamageTaken", "PhysicalDamageTakenOverTime", "PhysicalDamageReduction" }, enemy = true }, }, { format = "x {3:output:LightningDotEffMult}", { breakdown = "LightningDotEffMult" }, @@ -513,57 +513,57 @@ return { extra = "{2:output:CritChance}% x{2:output:CritMultiplier}", flag = "hit", -- Skill - { label = "Inc. Crit Chance", notFlag = "attack", { format = "{0:mod:1,2}%", - { label = "Player modifiers", modName = "CritChance", modType = "INC", cfg = "skill" }, - { label = "Enemy modifiers", modName = "SelfCritChance", modType = "INC", enemy = true }, - }, }, - { label = "Crit Chance", notFlag = "attack", { format = "{2:output:CritChance}%", - { breakdown = "CritChance" }, - { label = "Player modifiers", modName = {"CritChance", "SpellSkillsCannotDealCriticalStrikesExceptOnFinalRepeat", "SpellSkillsAlwaysDealCriticalStrikesOnFinalRepeat"}, cfg = "skill" }, - { label = "Enemy modifiers", modName = "SelfCritChance", enemy = true }, - }, }, - { label = "Crit Multiplier", notFlag = "attack", { format = "x {2:output:CritMultiplier}", - { breakdown = "CritMultiplier" }, - { label = "Player modifiers", modName = "CritMultiplier", cfg = "skill" }, - { label = "Enemy modifiers", modName = "SelfCritMultiplier", enemy = true }, + { label = "Inc. Crit Chance", notFlag = "attack", { format = "{0:mod:1,2}%", + { label = "Player modifiers", modName = "CritChance", modType = "INC", cfg = "skill" }, + { label = "Enemy modifiers", modName = "SelfCritChance", modType = "INC", enemy = true }, + }, }, + { label = "Crit Chance", notFlag = "attack", { format = "{2:output:CritChance}%", + { breakdown = "CritChance" }, + { label = "Player modifiers", modName = {"CritChance", "SpellSkillsCannotDealCriticalStrikesExceptOnFinalRepeat", "SpellSkillsAlwaysDealCriticalStrikesOnFinalRepeat"}, cfg = "skill" }, + { label = "Enemy modifiers", modName = "SelfCritChance", enemy = true }, + }, }, + { label = "Crit Multiplier", notFlag = "attack", { format = "x {2:output:CritMultiplier}", + { breakdown = "CritMultiplier" }, + { label = "Player modifiers", modName = "CritMultiplier", cfg = "skill" }, + { label = "Enemy modifiers", modName = "SelfCritMultiplier", enemy = true }, }, }, { label = "Crit Effect Mod", notFlag = "attack", { format = "x {3:output:CritEffect}", { breakdown = "CritEffect" }, }, }, -- Main Hand - { label = "MH Inc. Crit Chance", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{0:mod:1,2}%", - { label = "Player modifiers", modName = "CritChance", modType = "INC", cfg = "weapon1" }, - { label = "Enemy modifiers", modName = "SelfCritChance", modType = "INC", enemy = true }, - }, }, - { label = "MH Crit Chance", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{2:output:MainHand.CritChance}%", - { breakdown = "MainHand.CritChance" }, - { label = "Player modifiers", modName = { "CritChance", "WeaponBaseCritChance", "MainHandCritIsEqualToParent", "MainHandCritIsEqualToPartyMember", "AttackCritIsEqualToParentMainHand" }, cfg = "weapon1" }, - { label = "Enemy modifiers", modName = "SelfCritChance", enemy = true }, - }, }, - { label = "MH Crit Multiplier", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "x {2:output:MainHand.CritMultiplier}", - { breakdown = "MainHand.CritMultiplier" }, - { label = "Player modifiers", modName = "CritMultiplier", cfg = "weapon1" }, + { label = "MH Inc. Crit Chance", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{0:mod:1,2}%", + { label = "Player modifiers", modName = "CritChance", modType = "INC", cfg = "weapon1" }, + { label = "Enemy modifiers", modName = "SelfCritChance", modType = "INC", enemy = true }, + }, }, + { label = "MH Crit Chance", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{2:output:MainHand.CritChance}%", + { breakdown = "MainHand.CritChance" }, + { label = "Player modifiers", modName = { "CritChance", "WeaponBaseCritChance", "MainHandCritIsEqualToParent", "MainHandCritIsEqualToPartyMember", "AttackCritIsEqualToParentMainHand" }, cfg = "weapon1" }, + { label = "Enemy modifiers", modName = "SelfCritChance", enemy = true }, + }, }, + { label = "MH Crit Multiplier", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "x {2:output:MainHand.CritMultiplier}", + { breakdown = "MainHand.CritMultiplier" }, + { label = "Player modifiers", modName = "CritMultiplier", cfg = "weapon1" }, { label = "Enemy modifiers", modName = "SelfCritMultiplier", enemy = true }, }, }, { label = "MH Crit Effect Mod", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "x {3:output:MainHand.CritEffect}", { breakdown = "MainHand.CritEffect" }, }, }, -- Off Hand - { label = "OH Inc. Crit Chance", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "{0:mod:1,2}%", - { label = "Player modifiers", modName = "CritChance", modType = "INC", cfg = "weapon2" }, - { label = "Enemy modifiers", modName = "SelfCritChance", modType = "INC", enemy = true }, + { label = "OH Inc. Crit Chance", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "{0:mod:1,2}%", + { label = "Player modifiers", modName = "CritChance", modType = "INC", cfg = "weapon2" }, + { label = "Enemy modifiers", modName = "SelfCritChance", modType = "INC", enemy = true }, }, }, - { label = "OH Crit Chance", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "{2:output:OffHand.CritChance}%", - { breakdown = "OffHand.CritChance" }, + { label = "OH Crit Chance", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "{2:output:OffHand.CritChance}%", + { breakdown = "OffHand.CritChance" }, { label = "Player modifiers", modName = { "CritChance", "WeaponBaseCritChance", "AttackCritIsEqualToParentMainHand" }, cfg = "weapon2" }, - { label = "Enemy modifiers", modName = "SelfCritChance", enemy = true }, + { label = "Enemy modifiers", modName = "SelfCritChance", enemy = true }, }, }, - { label = "OH Crit Multiplier", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "x {2:output:OffHand.CritMultiplier}", - { breakdown = "OffHand.CritMultiplier" }, - { label = "Player modifiers", modName = "CritMultiplier", cfg = "weapon2" }, + { label = "OH Crit Multiplier", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "x {2:output:OffHand.CritMultiplier}", + { breakdown = "OffHand.CritMultiplier" }, + { label = "Player modifiers", modName = "CritMultiplier", cfg = "weapon2" }, { label = "Enemy modifiers", modName = "SelfCritMultiplier", enemy = true }, }, }, { label = "OH Crit Effect Mod", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "x {3:output:OffHand.CritEffect}", { breakdown = "OffHand.CritEffect" }, }, }, } } } }, { 1, "Impale", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Impale", data = { - flag = "impale", + flag = "impale", extra = "{0:output:ImpaleChance}%", { label = "Max Impale Stacks", { format = "{1:output:ImpaleStacksMax}", { modName = { "ImpaleStacksMax", "ImpaleAdditionalDurationChance" } } }, }, { label = "Stacks on Enemy", { format = "{1:output:ImpaleStacks}" }}, @@ -622,11 +622,11 @@ return { { label = "Soul Cost", color = colorCodes.RAGE, haveOutput = "SoulHasCost", { format = "{0:output:SoulCost}", { breakdown = "SoulCost" }, { modName = { "SoulCost" }, cfg = "skill" }, }, }, { label = "Active Minion Limit", haveOutput = "ActiveMinionLimit", { format = "{0:output:ActiveMinionLimit}" } }, { label = "Quantity Multiplier", haveOutput = "QuantityMultiplier", { format = "{0:output:QuantityMultiplier}", - { breakdown = "QuantityMultiplier" }, - { modName = { "QuantityMultiplier" }, cfg = "skill" }, + { breakdown = "QuantityMultiplier" }, + { modName = { "QuantityMultiplier" }, cfg = "skill" }, }, }, { label = "Skill Cooldown", haveOutput = "Cooldown", notFlag = "skipEffectiveRate", { format = "{3:output:Cooldown}s", - { breakdown = "Cooldown" }, + { breakdown = "Cooldown" }, { modName = "CooldownRecovery", cfg = "skill" }, }, }, { label = "Stored Uses", haveOutput = "StoredUses", { format = "{output:StoredUses}", @@ -634,7 +634,7 @@ return { { modName = "AdditionalCooldownUses", cfg = "skill" }, }, }, { label = "Duration Mod", flag = "duration", { format = "x {4:output:DurationMod}", - { breakdown = "DurationMod" }, + { breakdown = "DurationMod" }, { breakdown = "SecondaryDurationMod" }, { breakdown = "TertiaryDurationMod" }, { modName = { "Duration", "PrimaryDuration", "SecondaryDuration", "TertiaryDuration" }, cfg = "skill" }, @@ -656,9 +656,9 @@ return { { label = "Pierce Count", haveOutput = "PierceCount", { format = "{output:PierceCountString}", { modName = { "CannotPierce", "PierceCount", "PierceAllTargets" }, cfg = "skill" }, }, }, { label = "Fork Count", haveOutput = "ForkCountMax", { format = "{output:ForkCountString}", { modName = { "CannotFork", "ForkCountMax" }, cfg = "skill" }, }, }, { label = "Max Chain Count", haveOutput = "ChainMax", { format = "{output:ChainMaxString}", { modName = { "CannotChain", "ChainCountMax", "NoAdditionalChains" }, cfg = "skill" }, }, }, - { label = "Split Count", haveOutput = "SplitCountString", { format = "{output:SplitCountString}", + { label = "Split Count", haveOutput = "SplitCountString", { format = "{output:SplitCountString}", { label = "Player modifiers", modName = { "CannotSplit", "SplitCount", "AdditionalProjectilesAddSplitsInstead", "AdditionalChainsAddSplitsInstead" }, cfg = "skill" }, - { label = "Enemy modifiers", modName = { "SelfSplitCount" }, enemy = true, cfg = "skill" }, + { label = "Enemy modifiers", modName = { "SelfSplitCount" }, enemy = true, cfg = "skill" }, }, }, { label = "Proj. Speed Mod", flag = "projectile", { format = "x {2:output:ProjectileSpeedMod}", { breakdown = "ProjectileSpeedMod" }, @@ -694,8 +694,8 @@ return { { breakdown = "LinkEffectMod" }, { modName = { "LinkEffect", "BuffEffect" }, cfg = "skill" }, }, }, - { label = "Area of Effect Mod", haveOutput = "AreaOfEffectMod", { format = "x {2:output:AreaOfEffectMod}", - { breakdown = "AreaOfEffectMod" }, + { label = "Area of Effect Mod", haveOutput = "AreaOfEffectMod", { format = "x {2:output:AreaOfEffectMod}", + { breakdown = "AreaOfEffectMod" }, { modName = "AreaOfEffect", cfg = "skill" }, }, }, { label = "Radius", haveOutput = "AreaOfEffectRadius", { format = "{1:output:AreaOfEffectRadiusMetres}m", { breakdown = "AreaOfEffectRadius" }, }, }, @@ -709,7 +709,7 @@ return { }, }, { label = "Weapon Range", haveOutput = "WeaponRange", { format = "{1:output:WeaponRangeMetre}m", { breakdown = "WeaponRange" }, }, }, { label = "Strike Targets", haveOutput = "StrikeTargets", { format = "{1:output:StrikeTargets}", - { breakdown = "StrikeTargets" }, + { breakdown = "StrikeTargets" }, { modName = "AdditionalStrikeTarget", cfg = "skill" } }, }, { label = "Attachment Range", haveOutput = "BrandAttachmentRangeMetre", { format = "{1:output:BrandAttachmentRangeMetre}m", @@ -725,7 +725,7 @@ return { }, }, { label = "Wave Pulse Rate", haveOutput = "WavePulseRate", { format = "{2:output:WavePulseRate}/s", { breakdown = "WavePulseRate" }, { modName = { "TrapThrowingSpeed", "SeismicPulseFrequency" }, cfg = "skill" }, }, }, { label = "Pulses Per Trap", haveOutput = "PulsesPerTrap", { format = "{0:output:PulsesPerTrap}", { breakdown = "PulsesPerTrap" }, }, }, - { label = "Small Explosions", haveOutput = "SmallExplosionsPerTrap", { format = "{0:output:SmallExplosionsPerTrap}", + { label = "Small Explosions", haveOutput = "SmallExplosionsPerTrap", { format = "{0:output:SmallExplosionsPerTrap}", { label = "Small Explosions", modName = "SmallExplosions", cfg = "skill" }, }, }, { label = "Normal Hits/Cast", haveOutput = "NormalHitsPerCast", { format = "{3:output:NormalHitsPerCast}", { breakdown = "NormalHitsPerCast" }, }, }, @@ -745,15 +745,15 @@ return { { label = "Area of Effect modifiers", modName = "TrapTriggerAreaOfEffect", cfg = "skill" }, }, }, -- Seal (Unleash) - { label = "Seal Gain Rate", haveOutput = "SealMax", { format = "{2:output:SealCooldown}s", + { label = "Seal Gain Rate", haveOutput = "SealMax", { format = "{2:output:SealCooldown}s", { breakdown = "SealGainTime" }, - { modName = "SealGainFrequency", cfg = "skill" }, + { modName = "SealGainFrequency", cfg = "skill" }, }, }, -- Mines { label = "Active Mine Limit", flag = "mine", { format = "{0:output:ActiveMineLimit}", { modName = "ActiveMineLimit", cfg = "skill" }, }, }, - { label = "Mine Throw Rate", flag = "mine", { format = "{2:output:MineLayingSpeed}", + { label = "Mine Throw Rate", flag = "mine", { format = "{2:output:MineLayingSpeed}", { breakdown = "MineLayingTime" }, - { modName = "MineLayingSpeed", cfg = "skill" }, + { modName = "MineLayingSpeed", cfg = "skill" }, }, }, { label = "Mine Throw Time", flag = "mine", { format = "{2:output:MineLayingTime}s", { breakdown = "MineThrowingTime" }, }, }, { label = "Avg. Mines per Throw", flag = "mine", { format = "{2:output:MineThrowCount}", { modName = "MineThrowCount", cfg = "skill"}, }, }, @@ -762,44 +762,44 @@ return { { label = "Area of Effect modifiers", modName = "MineDetonationAreaOfEffect", cfg = "skill" }, }, }, { label = "Mine Aura Radius", haveOutput = "MineAuraRadius", { format = "{1:output:MineAuraRadiusMetre}m", { breakdown = "MineAuraRadius" }, }, }, - { label = "Totem Place Time", flag = "totem", notFlag = "triggered", { format = "{2:output:TotemPlacementTime}s", + { label = "Totem Place Time", flag = "totem", notFlag = "triggered", { format = "{2:output:TotemPlacementTime}s", { breakdown = "TotemPlacementTime" }, - { modName = "TotemPlacementSpeed", cfg = "skill" }, + { modName = "TotemPlacementSpeed", cfg = "skill" }, }, }, - { label = "Active Totem Limit", flag = "totem", notFlag = "triggered", { format = "{0:output:ActiveTotemLimit}", + { label = "Active Totem Limit", flag = "totem", notFlag = "triggered", { format = "{0:output:ActiveTotemLimit}", { breakdown = "ActiveTotemLimit" }, - { modName = { "ActiveTotemLimit", "ActiveBallistaLimit" }, cfg = "skill" }, + { modName = { "ActiveTotemLimit", "ActiveBallistaLimit" }, cfg = "skill" }, }, }, { label = "Totem Dur. Mod", flagList = {"duration", "totem"}, { format = "x {4:output:TotemDurationMod}", - { breakdown = "TotemDurationMod" }, - { modName = { "Duration", "PrimaryDuration", "TotemDuration" }, cfg = "skill" }, + { breakdown = "TotemDurationMod" }, + { modName = { "Duration", "PrimaryDuration", "TotemDuration" }, cfg = "skill" }, }, }, { label = "Totem Duration", flagList = {"duration", "totem"}, { format = "{3:output:TotemDuration}s", { breakdown = "TotemDuration" }, }, }, - { label = "Totem Life Mod", flag = "totem", notFlag = "triggered", { format = "x {2:output:TotemLifeMod}", + { label = "Totem Life Mod", flag = "totem", notFlag = "triggered", { format = "x {2:output:TotemLifeMod}", { breakdown = "TotemLifeMod" }, { modName = "TotemLife", cfg = "skill" }, }, }, { label = "Totem Life", flag = "totem", notFlag = "triggered", { format = "{0:output:TotemLife}", { breakdown = "TotemLife" }, }, }, - { label = "Totem ES", haveOutput = "TotemEnergyShield", { format = "{0:output:TotemEnergyShield}", + { label = "Totem ES", haveOutput = "TotemEnergyShield", { format = "{0:output:TotemEnergyShield}", { breakdown = "TotemEnergyShield" }, { modName = "TotemEnergyShield", cfg = "skill" }, }, }, - { label = "Totem Block Chance", haveOutput = "TotemBlockChance", { format = "{0:output:TotemBlockChance}%", + { label = "Totem Block Chance", haveOutput = "TotemBlockChance", { format = "{0:output:TotemBlockChance}%", { breakdown = "TotemBlockChance" }, { modName = "TotemBlockChance", cfg = "skill" }, }, }, - { label = "Totem Armour", haveOutput = "TotemArmour", { format = "{0:output:TotemArmour}", + { label = "Totem Armour", haveOutput = "TotemArmour", { format = "{0:output:TotemArmour}", { breakdown = "TotemArmour" }, { modName = "TotemArmour", cfg = "skill" }, }, }, { label = "Active Brand Limit", haveOutput = "ActiveBrandLimit", { format = "{0:output:ActiveBrandLimit}", { modName = "ActiveBrandLimit", cfg = "skill" }, }, }, { label = "Totem Fire Res", flag = "totem", notFlag = "triggered",{ format = "{0:output:TotemFireResist}% (+{0:output:TotemFireResistOverCap}%)", - { breakdown = "TotemFireResist" }, + { breakdown = "TotemFireResist" }, { modName = { "TotemFireResistMax", "TotemElementalResistMax", "TotemFireResist", "TotemElementalResist" }, }, }, }, - { label = "Totem Cold Res", flag = "totem", notFlag = "triggered", { format = "{0:output:TotemColdResist}% (+{0:output:TotemColdResistOverCap}%)", + { label = "Totem Cold Res", flag = "totem", notFlag = "triggered", { format = "{0:output:TotemColdResist}% (+{0:output:TotemColdResistOverCap}%)", { breakdown = "TotemColdResist" }, { modName = { "TotemColdResistMax", "TotemElementalResistMax", "TotemColdResist", "TotemElementalResist" }, }, }, }, @@ -809,7 +809,7 @@ return { }, }, { label = "Totem Chaos Res", flag = "totem", notFlag = "triggered", { format = "{0:output:TotemChaosResist}% (+{0:output:TotemChaosResistOverCap}%)", { breakdown = "TotemChaosResist" }, - { modName = { "TotemChaosResistMax", "TotemChaosResist" }, }, + { modName = { "TotemChaosResistMax", "TotemChaosResist" }, }, }, }, { label = "Corpse Level", haveOutput = "CorpseLevel", { format = "{0:output:CorpseLevel}", { breakdown = "CorpseLevel" }, @@ -825,24 +825,24 @@ return { { 1, "HitChance", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Accuracy", data = { extra = "{0:output:HitChance}%", flag = "attack", - { label = "MH Accuracy", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{0:output:MainHand.Accuracy}", - { breakdown = "MainHand.Accuracy" }, - { modName = "Accuracy", cfg = "weapon1" }, + { label = "MH Accuracy", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{0:output:MainHand.Accuracy}", + { breakdown = "MainHand.Accuracy" }, + { modName = "Accuracy", cfg = "weapon1" }, }, }, { label = "MH Chance to Hit", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{0:output:MainHand.AccuracyHitChance}%", - { breakdown = "MainHand.AccuracyHitChance" }, + { breakdown = "MainHand.AccuracyHitChance" }, { label = "Enemy Evasion modifiers", modName = { "Evasion", "CannotEvade" }, enemy = true }, { label = "Player modifiers", modName = { "HitChance", "CannotBeEvaded", "IgnoreBlindHitChance" } }, }, }, { label = "MH Chance to Hit", haveOutput = "MainHand.enemyBlockChance", bgCol = colorCodes.MAINHANDBG, flag = "weapon1Attack", { format = "{0:output:MainHand.HitChance}%", - { breakdown = "MainHand.HitChance" }, + { breakdown = "MainHand.HitChance" }, { label = "Enemy Evasion modifiers", modName = { "Evasion", "CannotEvade" }, enemy = true }, { label = "Enemy Block", modName = { "BlockChance" }, enemy = true }, { label = "Block Chance Reduction", cfg = "skill", modName = { "reduceEnemyBlock" } }, { label = "Player modifiers", modName = { "HitChance", "CannotBeEvaded", "IgnoreBlindHitChance" } }, }, }, { label = "OH Accuracy", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "{0:output:OffHand.Accuracy}", - { breakdown = "OffHand.Accuracy" }, + { breakdown = "OffHand.Accuracy" }, { modName = "Accuracy", cfg = "weapon2" }, }, }, { label = "OH Chance to Hit", bgCol = colorCodes.OFFHANDBG, flag = "weapon2Attack", { format = "{0:output:OffHand.AccuracyHitChance}%", @@ -866,7 +866,7 @@ return { { label = "Max Bleed Stacks", { format = "{0:output:BleedStacksMax}", { modName = "BleedStacksMax" } }, }, { label = "Stack Potential", { format = "{2:output:BleedStackPotential}", { breakdown = "BleedStackPotential" } }}, { label = "Average Bleed Roll", { format = "{2:output:BleedRollAverage}%", { breakdown = "BleedRollAverage" } }}, - { label = "Chance to Bleed", { format = "{0:output:BleedChance}%", + { label = "Chance to Bleed", { format = "{0:output:BleedChance}%", { breakdown = "MainHand.BleedChance" }, { breakdown = "OffHand.BleedChance" }, { breakdown = "BleedChance" }, @@ -882,9 +882,9 @@ return { { label = "OH Source Physical", bgCol = colorCodes.OFFHANDBG, textSize = 12, flag = "weapon2Attack", { format = "{0:output:OffHand.BleedPhysicalMin} to {0:output:OffHand.BleedPhysicalMax}", { breakdown = "OffHand.BleedPhysical" }, }, }, { label = "Effective DPS Mod", flag = "effective", { format = "x {3:output:BleedEffMult}", { breakdown = "BleedEffMult" }, { label = "Enemy modifiers", modName = { "DamageTaken", "DamageTakenOverTime", "PhysicalDamageTaken", "PhysicalDamageTakenOverTime", "PhysicalDamageReduction" }, enemy = true, cfg = "bleed" }, }, }, { label = "Bleed DPS", { format = "{1:output:BleedDPS}", { breakdown = "BleedDPS" }, { breakdown = "MainHand.BleedDPS" }, { breakdown = "OffHand.BleedDPS" }, }, }, - { label = "Bleed Duration", { format = "{2:output:BleedDuration}s", - { breakdown = "BleedDuration" }, - { label = "Player modifiers", modName = { "EnemyBleedDuration", "EnemyAilmentDuration", "DamagingAilmentDuration", "BleedFaster" }, cfg = "bleed" }, + { label = "Bleed Duration", { format = "{2:output:BleedDuration}s", + { breakdown = "BleedDuration" }, + { label = "Player modifiers", modName = { "EnemyBleedDuration", "EnemyAilmentDuration", "DamagingAilmentDuration", "BleedFaster" }, cfg = "bleed" }, { label = "Enemy modifiers", modName = { "SelfBleedDuration", "SelfAilmentDuration", "SelfBleedFaster", "BleedExpireRate" }, enemy = true }, }, }, } } @@ -892,11 +892,11 @@ return { { 1, "Poison", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Poison", data = { extra = "{0:output:PoisonChance}% {1:output:PoisonDPS} {2:output:PoisonDuration}s", flag = "poison", - { label = "Chance to Poison", { format = "{0:output:PoisonChance}%", - { breakdown = "MainHand.PoisonChance" }, - { breakdown = "OffHand.PoisonChance" }, - { breakdown = "PoisonChance" }, - { notFlag = "attack", modName = "PoisonChance", modType = "BASE", cfg = "skill" }, + { label = "Chance to Poison", { format = "{0:output:PoisonChance}%", + { breakdown = "MainHand.PoisonChance" }, + { breakdown = "OffHand.PoisonChance" }, + { breakdown = "PoisonChance" }, + { notFlag = "attack", modName = "PoisonChance", modType = "BASE", cfg = "skill" }, { label = "Main Hand", flag = "weapon1Attack", modName = "PoisonChance", modType = "BASE", cfg = "weapon1" }, { label = "Off Hand", flag = "weapon2Attack", modName = "PoisonChance", modType = "BASE", cfg = "weapon2" }, }, }, @@ -921,26 +921,26 @@ return { { label = "Source Chaos", textSize = 12, notFlag = "attack", haveOutput = "PoisonChaosMax", { format = "{0:output:PoisonChaosMin} to {0:output:PoisonChaosMax}", { breakdown = "PoisonChaos" }, }, }, { label = "MH Source Chaos", bgCol = colorCodes.MAINHANDBG, textSize = 12, flag = "weapon1Attack", haveOutput = "MainHand.PoisonChaosMax", { format = "{0:output:MainHand.PoisonChaosMin} to {0:output:MainHand.PoisonChaosMax}", { breakdown = "MainHand.PoisonChaos" }, }, }, { label = "OH Source Chaos", bgCol = colorCodes.OFFHANDBG, textSize = 12, flag = "weapon2Attack", haveOutput = "OffHand.PoisonChaosMax", { format = "{0:output:OffHand.PoisonChaosMin} to {0:output:OffHand.PoisonChaosMax}", { breakdown = "OffHand.PoisonChaos" }, }, }, - { label = "Effective DPS Mod", flag = "effective", { format = "x {3:output:PoisonEffMult}", - { breakdown = "PoisonEffMult" }, + { label = "Effective DPS Mod", flag = "effective", { format = "x {3:output:PoisonEffMult}", + { breakdown = "PoisonEffMult" }, { label = "Enemy modifiers", modName = { "ChaosResist", "DamageTaken", "DamageTakenOverTime", "ChaosDamageTaken", "ChaosDamageTakenOverTime" }, enemy = true }, }, }, - { label = "Poison DPS", { format = "{1:output:PoisonDPS}", - { breakdown = "PoisonDPS" }, + { label = "Poison DPS", { format = "{1:output:PoisonDPS}", + { breakdown = "PoisonDPS" }, { breakdown = "MainHand.PoisonDPS" }, { breakdown = "OffHand.PoisonDPS" }, }, }, - { label = "Caustic Ground", haveOutput = "CausticGroundFromPoison", { format = "{0:output:CausticGroundDPS}", - { breakdown = "CausticGroundDPS" }, + { label = "Caustic Ground", haveOutput = "CausticGroundFromPoison", { format = "{0:output:CausticGroundDPS}", + { breakdown = "CausticGroundDPS" }, { breakdown = "MainHand.CausticGroundDPS" }, { breakdown = "OffHand.CausticGroundDPS" }, }, }, - { label = "Poison Duration", { format = "{2:output:PoisonDuration}s", + { label = "Poison Duration", { format = "{2:output:PoisonDuration}s", { breakdown = "PoisonDuration" }, { label = "Player modifiers", modName = { "EnemyPoisonDuration", "EnemyAilmentDuration", "DamagingAilmentDuration", "PoisonFaster" }, cfg = "poison" }, { label = "Enemy modifiers", modName = { "SelfPoisonDuration", "SelfAilmentDuration", "SelfPoisonFaster" }, enemy = true }, }, }, - { label = "Dmg. per Poison", { format = "{1:output:PoisonDamage}", + { label = "Dmg. per Poison", { format = "{1:output:PoisonDamage}", { breakdown = "MainHand.PoisonDamage" }, { breakdown = "OffHand.PoisonDamage" }, { breakdown = "PoisonDamage" }, @@ -952,14 +952,14 @@ return { }, }, } } } }, -{ 1, "Ignite", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Ignite", data = { +{ 1, "Ignite", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Ignite", data = { extra = "{0:output:IgniteChancePerHit}% {1:output:IgniteDPS} {2:output:IgniteDuration}s", flag = "ignite", { label = "Max Ignite Stacks", { format = "{1:output:IgniteStacksMax}", { modName = "IgniteStacks" }, }, }, { label = "Stack Potential", { format = "{2:output:IgniteStackPotential}", { breakdown = "IgniteStackPotential" } }}, { label = "Average Ignite Roll", { format = "{2:output:IgniteRollAverage}%", { breakdown = "IgniteRollAverage" } }}, - { label = "Chance to Ignite", { format = "{0:output:IgniteChancePerHit}%", - { breakdown = "MainHand.IgniteChance" }, + { label = "Chance to Ignite", { format = "{0:output:IgniteChancePerHit}%", + { breakdown = "MainHand.IgniteChance" }, { breakdown = "OffHand.IgniteChance" }, { breakdown = "IgniteChance" }, { label = "Player modifiers", modName = "EnemyIgniteChance", cfg = "skill" }, @@ -985,22 +985,22 @@ return { { label = "Source Chaos", textSize = 12, notFlag = "attack", haveOutput = "IgniteChaosMax", { format = "{0:output:IgniteChaosMin} to {0:output:IgniteChaosMax}", { breakdown = "IgniteChaos" }, }, }, { label = "MH Source Chaos", bgCol = colorCodes.MAINHANDBG, textSize = 12, flag = "weapon1Attack", haveOutput = "MainHand.IgniteChaosMax", { format = "{0:output:MainHand.IgniteChaosMin} to {0:output:MainHand.IgniteChaosMax}", { breakdown = "MainHand.IgniteChaos" }, }, }, { label = "OH Source Chaos", bgCol = colorCodes.OFFHANDBG, textSize = 12, flag = "weapon2Attack", haveOutput = "OffHand.IgniteChaosMax", { format = "{0:output:OffHand.IgniteChaosMin} to {0:output:OffHand.IgniteChaosMax}", { breakdown = "OffHand.IgniteChaos" }, }, }, - { label = "Effective DPS Mod", flag = "effective", notFlag = "igniteToChaos", { format = "x {3:output:IgniteEffMult}", - { breakdown = "IgniteEffMult" }, + { label = "Effective DPS Mod", flag = "effective", notFlag = "igniteToChaos", { format = "x {3:output:IgniteEffMult}", + { breakdown = "IgniteEffMult" }, { label = "Enemy modifiers", modName = { "FireResist", "ElementalResist", "DamageTaken", "DamageTakenOverTime", "FireDamageTaken", "FireDamageTakenOverTime", "ElementalDamageTaken" }, enemy = true }, }, }, - { label = "Effective DPS Mod", flagList = { "effective", "igniteToChaos" }, { format = "x {3:output:IgniteEffMult}", - { breakdown = "IgniteEffMult" }, + { label = "Effective DPS Mod", flagList = { "effective", "igniteToChaos" }, { format = "x {3:output:IgniteEffMult}", + { breakdown = "IgniteEffMult" }, { label = "Enemy modifiers", modName = { "ChaosResist", "DamageTaken", "DamageTakenOverTime", "ChaosDamageTaken", "ChaosDamageTakenOverTime" }, enemy = true }, }, }, - { label = "Ignite DPS", { format = "{1:output:IgniteDPS}", - { breakdown = "IgniteDPS" }, + { label = "Ignite DPS", { format = "{1:output:IgniteDPS}", + { breakdown = "IgniteDPS" }, { breakdown = "MainHand.IgniteDPS" }, { breakdown = "OffHand.IgniteDPS" }, - { modName = { "IgniteBurnRate" }, cfg = "skill" }, + { modName = { "IgniteBurnRate" }, cfg = "skill" }, }, }, { label = "Burning Ground", haveOutput = "BurningGroundFromIgnite", { format = "{0:output:BurningGroundDPS}", { breakdown = "BurningGroundDPS" } } }, - { label = "Ignite Duration", { format = "{2:output:IgniteDuration}s", + { label = "Ignite Duration", { format = "{2:output:IgniteDuration}s", { breakdown = "IgniteDuration" }, { label = "Player modifiers", modName = { "EnemyIgniteDuration", "EnemyAilmentDuration", "EnemyElementalAilmentDuration", "DamagingAilmentDuration", "IgniteBurnFaster", "IgniteBurnSlower" }, cfg = "skill" }, { label = "Enemy modifiers", modName = {"SelfIgniteDuration", "SelfAilmentDuration", "SelfElementalAilmentDuration", "SelfIgniteBurnFaster"}, enemy = true }, @@ -1017,121 +1017,121 @@ return { flag = "decay", { label = "Total Increased", { format = "{0:mod:1}%", { modName = { "Damage", "ChaosDamage" }, modType = "INC", cfg = "decay" }, }, }, { label = "Total More", { format = "{0:mod:1}%", { modName = { "Damage", "ChaosDamage" }, modType = "MORE", cfg = "decay" }, }, }, - { label = "Effective DPS Mod", flag = "effective", { format = "x {3:output:DecayEffMult}", - { breakdown = "DecayEffMult" }, + { label = "Effective DPS Mod", flag = "effective", { format = "x {3:output:DecayEffMult}", + { breakdown = "DecayEffMult" }, { label = "Enemy modifiers", modName = { "ChaosResist", "DamageTaken", "DamageTakenOverTime", "ChaosDamageTaken", "ChaosDamageTakenOverTime" }, enemy = true }, }, }, - { label = "Decay DPS", { format = "{1:output:DecayDPS}", - { breakdown = "DecayDPS" }, + { label = "Decay DPS", { format = "{1:output:DecayDPS}", + { breakdown = "DecayDPS" }, }, }, - { label = "Decay Duration", { format = "{2:output:DecayDuration}s", + { label = "Decay Duration", { format = "{2:output:DecayDuration}s", { breakdown = "DecayDuration" }, }, }, } } } }, { 1, "LeechGain", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Leech & Gain on Hit", data = { - { label = "Life Leech Cap", flag = "leechLife", { format = "{1:output:MaxLifeLeechRate}", + { label = "Life Leech Cap", flag = "leechLife", { format = "{1:output:MaxLifeLeechRate}", { breakdown = "MaxLifeLeechRate" }, { modName = "MaxLifeLeechRate" }, }, }, - { label = "Life Leech Rate", flag = "leechLife", notFlag = "showAverage", { format = "{1:output:LifeLeechRate}", - { breakdown = "LifeLeech" }, - { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "skill" }, - { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Life Leech Rate", flag = "leechLife", notFlag = "showAverage", { format = "{1:output:LifeLeechRate}", + { breakdown = "LifeLeech" }, + { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon2" }, { label = "Totem modifiers", flag = "totem", modName = { "DamageLifeLeechToPlayer" }, modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = { "SelfDamageLifeLeech" }, modType = "BASE", enemy = true }, }, }, - { label = "Life Leech per Hit", flagList = { "leechLife", "showAverage" }, { format = "{1:output:LifeLeechPerHit}", + { label = "Life Leech per Hit", flagList = { "leechLife", "showAverage" }, { format = "{1:output:LifeLeechPerHit}", { breakdown = "LifeLeech" }, - { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "skill" }, - { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageLeech", "DamageLifeLeech", "PhysicalDamageLifeLeech", "LightningDamageLifeLeech", "ColdDamageLifeLeech", "FireDamageLifeLeech", "ChaosDamageLifeLeech", "ElementalDamageLifeLeech" }, modType = "BASE", cfg = "weapon2" }, { label = "Totem modifiers", flag = "totem", modName = { "DamageLifeLeechToPlayer" }, modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = { "SelfDamageLifeLeech" }, modType = "BASE", enemy = true }, }, }, - { label = "Life Gain Rate", notFlag = "showAverage", haveOutput = "LifeOnHitRate", { format = "{1:output:LifeOnHitRate}", - { label = "Player modifiers", notFlag = "attack", modName = "LifeOnHit", modType = "BASE", cfg = "skill" }, - { label = "Main Hand", flag = "weapon1Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", flag = "weapon2Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Life Gain Rate", notFlag = "showAverage", haveOutput = "LifeOnHitRate", { format = "{1:output:LifeOnHitRate}", + { label = "Player modifiers", notFlag = "attack", modName = "LifeOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "SelfLifeOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, }, }, - { label = "Life Gain per Hit", flag = "showAverage", haveOutput = "LifeOnHit", { format = "{1:output:LifeOnHit}", - { label = "Player modifiers", notFlag = "attack", modName = "LifeOnHit", modType = "BASE", cfg = "skill" }, - { label = "Main Hand", flag = "weapon1Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", flag = "weapon2Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Life Gain per Hit", flag = "showAverage", haveOutput = "LifeOnHit", { format = "{1:output:LifeOnHit}", + { label = "Player modifiers", notFlag = "attack", modName = "LifeOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "LifeOnHit", modType = "BASE", cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "SelfLifeOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, }, }, - { label = "Life Gain on Kill", haveOutput = "LifeOnKill", { format = "{1:output:LifeOnKill}", - {modName = "LifeOnKill"}, + { label = "Life Gain on Kill", haveOutput = "LifeOnKill", { format = "{1:output:LifeOnKill}", + {modName = "LifeOnKill"}, }, }, - { label = "ES Leech Cap", flag = "leechES", { format = "{1:output:MaxEnergyShieldLeechRate}", + { label = "ES Leech Cap", flag = "leechES", { format = "{1:output:MaxEnergyShieldLeechRate}", { breakdown = "MaxEnergyShieldLeechRate" }, { modName = "MaxEnergyShieldLeechRate" }, }, }, - { label = "ES Leech Rate", flag = "leechES", notFlag = "showAverage", { format = "{1:output:EnergyShieldLeechRate}", + { label = "ES Leech Rate", flag = "leechES", notFlag = "showAverage", { format = "{1:output:EnergyShieldLeechRate}", { breakdown = "EnergyShieldLeech" }, - { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "skill" }, - { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "weapon2" }, { label = "Totem modifiers", flag = "totem", modName = { "DamageEnergyShieldLeechToPlayer" }, modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = { "SelfDamageEnergyShieldLeech" }, modType = "BASE", enemy = true }, }, }, { label = "ES Leech per Hit", flagList = { "leechES", "showAverage" }, { format = "{1:output:EnergyShieldLeechPerHit}", { breakdown = "EnergyShieldLeech" }, - { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "skill" }, - { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Player modifiers", notFlagList = { "totem", "attack" }, modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", notFlag = "totem", flag = "weapon1Attack", modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", notFlag = "totem", flag = "weapon2Attack", modName = { "DamageEnergyShieldLeech", "PhysicalDamageEnergyShieldLeech", "LightningDamageEnergyShieldLeech", "ColdDamageEnergyShieldLeech", "FireDamageEnergyShieldLeech", "ChaosDamageEnergyShieldLeech", "ElementalDamageEnergyShieldLeech" }, modType = "BASE", cfg = "weapon2" }, { label = "Totem modifiers", flag = "totem", modName = { "DamageEnergyShieldLeechToPlayer" }, modType = "BASE", cfg = "skill" }, { label = "Enemy modifiers", modName = { "SelfDamageEnergyShieldLeech" }, modType = "BASE", enemy = true }, }, }, - { label = "ES Gain Rate", notFlag = "showAverage", haveOutput = "EnergyShieldOnHitRate", { format = "{1:output:EnergyShieldOnHitRate}", - { label = "Player modifiers", notFlag = "attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "skill" }, - { label = "Main Hand", flag = "weapon1Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", flag = "weapon2Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "ES Gain Rate", notFlag = "showAverage", haveOutput = "EnergyShieldOnHitRate", { format = "{1:output:EnergyShieldOnHitRate}", + { label = "Player modifiers", notFlag = "attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "SelfEnergyShieldOnHit" }, modType = "BASE", enemy = true }, }, }, - { label = "ES Gain per Hit", flag = "showAverage", haveOutput = "EnergyShieldOnHit", { format = "{1:output:EnergyShieldOnHit}", - { label = "Player modifiers", notFlag = "attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "skill" }, - { label = "Main Hand", flag = "weapon1Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", flag = "weapon2Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "ES Gain per Hit", flag = "showAverage", haveOutput = "EnergyShieldOnHit", { format = "{1:output:EnergyShieldOnHit}", + { label = "Player modifiers", notFlag = "attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "EnergyShieldOnHit", modType = "BASE", cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "SelfEnergyShieldOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, }, }, - { label = "ES Gain on Kill", haveOutput = "EnergyShieldOnKill", { format = "{1:output:EnergyShieldOnKill}", - {modName = "EnergyShieldOnKill"}, + { label = "ES Gain on Kill", haveOutput = "EnergyShieldOnKill", { format = "{1:output:EnergyShieldOnKill}", + {modName = "EnergyShieldOnKill"}, }, }, - { label = "Mana Leech Cap", flag = "leechMana", { format = "{1:output:MaxManaLeechRate}", + { label = "Mana Leech Cap", flag = "leechMana", { format = "{1:output:MaxManaLeechRate}", { breakdown = "MaxManaLeechRate" }, { modName = "MaxManaLeechRate" }, }, }, - { label = "Mana Leech Rate", flag = "leechMana", notFlag = "showAverage", { format = "{1:output:ManaLeechRate}", - { breakdown = "ManaLeech" }, - { label = "Player modifiers", notFlag = "attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "skill" }, - { label = "Main Hand", flag = "weapon1Attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", flag = "weapon2Attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Mana Leech Rate", flag = "leechMana", notFlag = "showAverage", { format = "{1:output:ManaLeechRate}", + { breakdown = "ManaLeech" }, + { label = "Player modifiers", notFlag = "attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "SelfDamageManaLeech" }, modType = "BASE", cfg = "skill", enemy = true }, }, }, - { label = "Mana Leech per Hit", flagList = { "leechMana", "showAverage" }, { format = "{1:output:ManaLeechPerHit}", - { breakdown = "ManaLeech" }, - { label = "Player modifiers", notFlag = "attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "skill" }, - { label = "Main Hand", flag = "weapon1Attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", flag = "weapon2Attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon2" }, + { label = "Mana Leech per Hit", flagList = { "leechMana", "showAverage" }, { format = "{1:output:ManaLeechPerHit}", + { breakdown = "ManaLeech" }, + { label = "Player modifiers", notFlag = "attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = { "DamageLeech", "DamageManaLeech", "PhysicalDamageManaLeech", "LightningDamageManaLeech", "ColdDamageManaLeech", "FireDamageManaLeech", "ChaosDamageManaLeech", "ElementalDamageManaLeech" }, modType = "BASE", cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "SelfDamageManaLeech" }, modType = "BASE", enemy = true }, }, }, - { label = "Mana Gain Rate", notFlag = "showAverage", haveOutput = "ManaOnHitRate", { format = "{1:output:ManaOnHitRate}", - { label = "Player modifiers", notFlag = "attack", modName = "ManaOnHit", modType = "BASE", cfg = "skill" }, - { label = "Main Hand", flag = "weapon1Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", flag = "weapon2Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Mana Gain Rate", notFlag = "showAverage", haveOutput = "ManaOnHitRate", { format = "{1:output:ManaOnHitRate}", + { label = "Player modifiers", notFlag = "attack", modName = "ManaOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "SelfManaOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, }, }, { label = "Mana Gain per Hit", flag = "showAverage", haveOutput = "ManaOnHit", { format = "{1:output:ManaOnHit}", - { label = "Player modifiers", notFlag = "attack", modName = "ManaOnHit", modType = "BASE", cfg = "skill" }, - { label = "Main Hand", flag = "weapon1Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon1" }, - { label = "Off Hand", flag = "weapon2Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon2" }, + { label = "Player modifiers", notFlag = "attack", modName = "ManaOnHit", modType = "BASE", cfg = "skill" }, + { label = "Main Hand", flag = "weapon1Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon1" }, + { label = "Off Hand", flag = "weapon2Attack", modName = "ManaOnHit", modType = "BASE", cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "SelfManaOnHit" }, modType = "BASE", cfg = "skill", enemy = true }, }, }, - { label = "Mana Gain on Kill", haveOutput = "ManaOnKill", { format = "{1:output:ManaOnKill}", - {modName = "ManaOnKill"}, + { label = "Mana Gain on Kill", haveOutput = "ManaOnKill", { format = "{1:output:ManaOnKill}", + {modName = "ManaOnKill"}, }, }, } } } }, @@ -1153,7 +1153,7 @@ return { }, }, { label = "Scorch Duration", bgCol = colorCodes.SCORCHBG, flag = "scorch", { format = "{2:output:ScorchDuration}s", { breakdown = "MainHand.ScorchDuration" }, - { breakdown = "OffHand.ScorchDuration" }, + { breakdown = "OffHand.ScorchDuration" }, { breakdown = "ScorchDuration" }, { label = "Player modifiers", modName = { "EnemyScorchDuration", "EnemyAilmentDuration", "EnemyElementalAilmentDuration" }, cfg = "skill" }, { label = "Enemy modifiers", modName = { "SelfScorchDuration", "SelfAilmentDuration", "SelfElementalAilmentDuration", "BuffExpireFaster" }, enemy = true }, @@ -1298,32 +1298,32 @@ return { } }, { 1, "MiscEffects", 1, colorCodes.OFFENCE, {{ defaultCollapsed = false, label = "Other Effects", data = { { label = "Stun Threshold", flag = "hit", notFlag = "attack", { format = "x {2:output:EnemyStunThresholdMod}", { modName = "EnemyStunThreshold", cfg = "skill" }, }, }, - { label = "Stun Duration", flag = "hit", notFlag = "attack", { format = "{2:output:EnemyStunDuration}s", - { breakdown = "EnemyStunDuration" }, + { label = "Stun Duration", flag = "hit", notFlag = "attack", { format = "{2:output:EnemyStunDuration}s", + { breakdown = "EnemyStunDuration" }, { label = "Player modifiers", modName = { "EnemyStunDuration", "EnemyStunDurationOnCrit", "DoubleEnemyStunDurationChance" }, cfg = "skill" }, { label = "Enemy modifiers", modName = { "StunRecovery", "SelfDoubleStunDurationChance" }, enemy = true }, }, }, { label = "MH Stun Threshold", bgCol = colorCodes.MAINHANDBG, flagList = {"hit","weapon1Attack"}, { format = "x {2:output:MainHand.EnemyStunThresholdMod}", { modName = "EnemyStunThreshold", cfg = "weapon1" }, }, }, - { label = "MH Stun Duration", bgCol = colorCodes.MAINHANDBG, flagList = {"hit","weapon1Attack"}, { format = "{2:output:MainHand.EnemyStunDuration}s", - { breakdown = "MainHand.EnemyStunDuration" }, + { label = "MH Stun Duration", bgCol = colorCodes.MAINHANDBG, flagList = {"hit","weapon1Attack"}, { format = "{2:output:MainHand.EnemyStunDuration}s", + { breakdown = "MainHand.EnemyStunDuration" }, { label = "Player modifiers", modName = { "EnemyStunDuration", "EnemyStunDurationOnCrit", "DoubleEnemyStunDurationChance" }, cfg = "weapon1" }, { label = "Enemy modifiers", modName = { "StunRecovery", "SelfDoubleStunDurationChance" }, enemy = true }, }, }, { label = "OH Stun Threshold", bgCol = colorCodes.OFFHANDBG, flagList = {"hit","weapon2Attack"}, { format = "x {2:output:OffHand.EnemyStunThresholdMod}", { modName = "EnemyStunThreshold", cfg = "weapon2" }, }, }, - { label = "OH Stun Duration", bgCol = colorCodes.OFFHANDBG, flagList = {"hit","weapon2Attack"}, { format = "{2:output:OffHand.EnemyStunDuration}s", - { breakdown = "OffHand.EnemyStunDuration" }, + { label = "OH Stun Duration", bgCol = colorCodes.OFFHANDBG, flagList = {"hit","weapon2Attack"}, { format = "{2:output:OffHand.EnemyStunDuration}s", + { breakdown = "OffHand.EnemyStunDuration" }, { label = "Player modifiers", modName = { "EnemyStunDuration", "EnemyStunDurationOnCrit", "DoubleEnemyStunDurationChance" }, cfg = "weapon2" }, { label = "Enemy modifiers", modName = { "StunRecovery", "SelfDoubleStunDurationChance" }, enemy = true }, }, }, - { label = "Knockback Chance", haveOutput = "KnockbackChance", { format = "{0:output:KnockbackChance}%", - { label = "Player modifiers", modName = "EnemyKnockbackChance", cfg = "skill" }, + { label = "Knockback Chance", haveOutput = "KnockbackChance", { format = "{0:output:KnockbackChance}%", + { label = "Player modifiers", modName = "EnemyKnockbackChance", cfg = "skill" }, { label = "Enemy modifiers", modName = "SelfKnockbackChance", enemy = true }, }, }, - { label = "Knockback Dist.", haveOutput = "KnockbackChance", { format = "{0:output:KnockbackDistance}", + { label = "Knockback Dist.", haveOutput = "KnockbackChance", { format = "{0:output:KnockbackDistance}", { breakdown = "KnockbackDistance" }, - { modName = "EnemyKnockbackDistance", cfg = "skill" }, + { modName = "EnemyKnockbackDistance", cfg = "skill" }, }, }, - { label = "MH K.B. Chance", bgCol = colorCodes.MAINHANDBG, haveOutput = "MainHand.KnockbackChance", { format = "{0:output:MainHand.KnockbackChance}%", + { label = "MH K.B. Chance", bgCol = colorCodes.MAINHANDBG, haveOutput = "MainHand.KnockbackChance", { format = "{0:output:MainHand.KnockbackChance}%", { label = "Player modifiers", modName = "EnemyKnockbackChance", cfg = "weapon1" }, { label = "Enemy modifiers", modName = "SelfKnockbackChance", enemy = true }, }, }, @@ -1331,7 +1331,7 @@ return { { breakdown = "MainHand.KnockbackDistance" }, { modName = "EnemyKnockbackDistance", cfg = "weapon1" }, }, }, - { label = "OH K.B. Chance", bgCol = colorCodes.OFFHANDBG, haveOutput = "OffHand.KnockbackChance", { format = "{0:output:OffHand.KnockbackChance}%", + { label = "OH K.B. Chance", bgCol = colorCodes.OFFHANDBG, haveOutput = "OffHand.KnockbackChance", { format = "{0:output:OffHand.KnockbackChance}%", { label = "Player modifiers", modName = "EnemyKnockbackChance", cfg = "weapon2" }, { label = "Enemy modifiers", modName = "SelfKnockbackChance", enemy = true }, }, }, @@ -1374,52 +1374,52 @@ return { { label = "Reserved", { format = "{0:output:LifeReserved} ({0:output:LifeReservedPercent}%)", { breakdown = "LifeReserved" }, }, }, { label = "Unreserved", { format = "{0:output:LifeUnreserved} ({0:output:LifeUnreservedPercent}%)" }, }, { label = "Total Recoverable", haveOutput = "CappingLife", { format = "{0:output:LifeRecoverable}", { breakdown = "LifeUnreserved" }, }, }, - { label = "Recharge Rate", haveOutput = "EnergyShieldRechargeAppliesToLife", { format = "{1:output:LifeRecharge}", + { label = "Recharge Rate", haveOutput = "EnergyShieldRechargeAppliesToLife", { format = "{1:output:LifeRecharge}", { breakdown = "LifeRecharge" }, { modName = { "EnergyShieldRecharge", "LifeRecoveryRate", "EnergyShieldRechargeAppliesToLife" }, }, }, }, - { label = "Recharge Delay", haveOutput = "EnergyShieldRechargeAppliesToLife", { format = "{2:output:EnergyShieldRechargeDelay}s", + { label = "Recharge Delay", haveOutput = "EnergyShieldRechargeAppliesToLife", { format = "{2:output:EnergyShieldRechargeDelay}s", { breakdown = "EnergyShieldRechargeDelay" }, { modName = "EnergyShieldRechargeFaster" }, }, }, { label = "Recovery", { format = "{1:output:LifeRegenRecovery} ({1:output:LifeRegenPercent}%)", - { breakdown = "LifeRegenRecovery" }, + { breakdown = "LifeRegenRecovery" }, { label = "Sources", modName = { "LifeRegen", "LifeRegenPercent", "LifeDegen", "LifeDegenPercent", "LifeRecovery" }, modType = "BASE" }, { label = "Increased Life Regeneration Rate", modName = { "LifeRegen" }, modType = "INC" }, { label = "More Life Regeneration Rate", modName = { "LifeRegen" }, modType = "MORE" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, }, }, - { label = "Recoup", haveOutput = "LifeRecoup", { format = "{1:output:LifeRecoup}%", { breakdown = "LifeRecoup" }, + { label = "Recoup", haveOutput = "LifeRecoup", { format = "{1:output:LifeRecoup}%", { breakdown = "LifeRecoup" }, { label = "Sources", modName = "LifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, }, }, - { label = "Phys Recoup", haveOutput = "PhysicalLifeRecoup", { format = "{1:output:PhysicalLifeRecoup}%", { breakdown = "PhysicalLifeRecoup" }, + { label = "Phys Recoup", haveOutput = "PhysicalLifeRecoup", { format = "{1:output:PhysicalLifeRecoup}%", { breakdown = "PhysicalLifeRecoup" }, { label = "Sources", modName = "PhysicalLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, }, }, - { label = "Light Recoup", haveOutput = "LightningLifeRecoup", { format = "{1:output:LightningLifeRecoup}%", { breakdown = "LightningLifeRecoup" }, + { label = "Light Recoup", haveOutput = "LightningLifeRecoup", { format = "{1:output:LightningLifeRecoup}%", { breakdown = "LightningLifeRecoup" }, { label = "Sources", modName = "LightningLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, }, }, - { label = "Cold Recoup", haveOutput = "ColdLifeRecoup", { format = "{1:output:ColdLifeRecoup}%", { breakdown = "ColdLifeRecoup" }, + { label = "Cold Recoup", haveOutput = "ColdLifeRecoup", { format = "{1:output:ColdLifeRecoup}%", { breakdown = "ColdLifeRecoup" }, { label = "Sources", modName = "ColdLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, }, }, - { label = "Fire Recoup", haveOutput = "FireLifeRecoup", { format = "{1:output:FireLifeRecoup}%", { breakdown = "FireLifeRecoup" }, + { label = "Fire Recoup", haveOutput = "FireLifeRecoup", { format = "{1:output:FireLifeRecoup}%", { breakdown = "FireLifeRecoup" }, { label = "Sources", modName = "FireLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, }, }, - { label = "Chaos Recoup", haveOutput = "ChaosLifeRecoup", { format = "{1:output:ChaosLifeRecoup}%", { breakdown = "ChaosLifeRecoup" }, + { label = "Chaos Recoup", haveOutput = "ChaosLifeRecoup", { format = "{1:output:ChaosLifeRecoup}%", { breakdown = "ChaosLifeRecoup" }, { label = "Sources", modName = "ChaosLifeRecoup" }, { label = "Recovery modifiers", modName = "LifeRecoveryRate" }, { label = "FasterRecoup", modName = { "3SecondRecoup", "3SecondLifeRecoup" } }, }, }, - { label = "Dmg. Mit. Regen", haveOutput = "PhysicalDamageMitigatedLifePseudoRecoup", { format = "{1:output:PhysicalDamageMitigatedLifePseudoRecoup}%", { breakdown = "PhysicalDamageMitigatedLifePseudoRecoup" }, + { label = "Dmg. Mit. Regen", haveOutput = "PhysicalDamageMitigatedLifePseudoRecoup", { format = "{1:output:PhysicalDamageMitigatedLifePseudoRecoup}%", { breakdown = "PhysicalDamageMitigatedLifePseudoRecoup" }, { label = "Sources", modName = "PhysicalDamageMitigatedLifePseudoRecoup" }, { label = "Increased Life Regeneration Rate", modName = { "LifeRegen" }, modType = "INC" }, { label = "More Life Regeneration Rate", modName = { "LifeRegen" }, modType = "MORE" }, @@ -1438,13 +1438,13 @@ return { { label = "Reserved", { format = "{0:output:ManaReserved} ({0:output:ManaReservedPercent}%)", { breakdown = "ManaReserved" }, }, }, { label = "Unreserved", { format = "{0:output:ManaUnreserved} ({0:output:ManaUnreservedPercent}%)" }, }, { label = "Recovery", { format = "{1:output:ManaRegenRecovery} ({1:output:ManaRegenPercent}%)", - { breakdown = "ManaRegenRecovery" }, + { breakdown = "ManaRegenRecovery" }, { label = "Sources", modName = { "ManaRegen", "ManaRegenPercent", "ManaDegen", "ManaDegenPercent", "ManaRecovery" }, modType = "BASE" }, { label = "Increased Mana Regeneration Rate", modName = { "ManaRegen" }, modType = "INC" }, { label = "More Mana Regeneration Rate", modName = { "ManaRegen" }, modType = "MORE" }, { label = "Recovery modifiers", modName = "ManaRecoveryRate" }, }, }, - { label = "Recoup", haveOutput = "ManaRecoup", { format = "{1:output:ManaRecoup}%", { breakdown = "ManaRecoup" }, + { label = "Recoup", haveOutput = "ManaRecoup", { format = "{1:output:ManaRecoup}%", { breakdown = "ManaRecoup" }, { label = "Sources", modName = "ManaRecoup" }, { label = "Recovery modifiers", modName = "ManaRecoveryRate" }, { label = "FasterRecoup", modName = "3SecondRecoup" }, @@ -1460,32 +1460,32 @@ return { { label = "Total More", { format = "{0:mod:1}%", { modName = { "EnergyShield", "Defences" }, modType = "MORE" }, }, }, { label = "Total", { format = "{0:output:EnergyShield}", { breakdown = "EnergyShield" }, }, }, { label = "Total Recoverable", haveOutput = "CappingES", { format = "{0:output:EnergyShieldRecoveryCap}", { breakdown = "EnergyShield" }, }, }, - { label = "Recharge Rate", haveOutput = "EnergyShieldRechargeAppliesToEnergyShield", { format = "{1:output:EnergyShieldRecharge}", + { label = "Recharge Rate", haveOutput = "EnergyShieldRechargeAppliesToEnergyShield", { format = "{1:output:EnergyShieldRecharge}", { breakdown = "EnergyShieldRecharge" }, { modName = { "EnergyShieldRecharge", "EnergyShieldRecoveryRate", "NoEnergyShieldRecharge", "CannotGainEnergyShield" }, }, }, }, - { label = "Recharge Delay", haveOutput = "EnergyShieldRechargeAppliesToEnergyShield", { format = "{2:output:EnergyShieldRechargeDelay}s", + { label = "Recharge Delay", haveOutput = "EnergyShieldRechargeAppliesToEnergyShield", { format = "{2:output:EnergyShieldRechargeDelay}s", { breakdown = "EnergyShieldRechargeDelay" }, { modName = "EnergyShieldRechargeFaster" }, }, }, { label = "Recovery", { format = "{1:output:EnergyShieldRegenRecovery} ({1:output:EnergyShieldRegenPercent}%)", - { breakdown = "EnergyShieldRegenRecovery" }, + { breakdown = "EnergyShieldRegenRecovery" }, { label = "Sources", modName = { "EnergyShieldRegen", "EnergyShieldRegenPercent", "EnergyShieldDegen", "EnergyShieldDegenPercent", "EnergyShieldRecovery" }, modType = "BASE" }, { label = "Increased Energy Shield Regeneration Rate", modName = { "EnergyShieldRegen" }, modType = "INC" }, { label = "More Energy Shield Regeneration Rate", modName = { "EnergyShieldRegen" }, modType = "MORE" }, { label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" }, }, }, - { label = "Recoup", haveOutput = "EnergyShieldRecoup", { format = "{1:output:EnergyShieldRecoup}%", { breakdown = "EnergyShieldRecoup" }, + { label = "Recoup", haveOutput = "EnergyShieldRecoup", { format = "{1:output:EnergyShieldRecoup}%", { breakdown = "EnergyShieldRecoup" }, { label = "Sources", modName = "EnergyShieldRecoup" }, { label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" }, { label = "FasterRecoup", modName = "3SecondRecoup" }, }, }, - { label = "Ele Recoup", haveOutput = "ElementalEnergyShieldRecoup", { format = "{1:output:ElementalEnergyShieldRecoup}%", { breakdown = "ElementalEnergyShieldRecoup" }, + { label = "Ele Recoup", haveOutput = "ElementalEnergyShieldRecoup", { format = "{1:output:ElementalEnergyShieldRecoup}%", { breakdown = "ElementalEnergyShieldRecoup" }, { label = "Sources", modName = "ElementalEnergyShieldRecoup" }, { label = "Recovery modifiers", modName = "EnergyShieldRecoveryRate" }, { label = "FasterRecoup", modName = "3SecondRecoup" }, }, }, - { label = "Dmg. Mit. Regen", haveOutput = "PhysicalDamageMitigatedEnergyShieldPseudoRecoup", { format = "{1:output:PhysicalDamageMitigatedEnergyShieldPseudoRecoup}%", { breakdown = "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" }, + { label = "Dmg. Mit. Regen", haveOutput = "PhysicalDamageMitigatedEnergyShieldPseudoRecoup", { format = "{1:output:PhysicalDamageMitigatedEnergyShieldPseudoRecoup}%", { breakdown = "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" }, { label = "Sources", modName = "PhysicalDamageMitigatedEnergyShieldPseudoRecoup" }, { label = "Increased Energy Shield Regeneration Rate", modName = { "EnergyShieldRegen" }, modType = "INC" }, { label = "More Energy Shield Regeneration Rate", modName = { "EnergyShieldRegen" }, modType = "MORE" }, @@ -1567,20 +1567,20 @@ return { { label = "Total Increased", { format = "{0:mod:1}%", { modName = { "Evasion", "ArmourAndEvasion", "Defences" }, modType = "INC" }, }, }, { label = "Total More", { format = "{0:mod:1}%", { modName = { "Evasion", "ArmourAndEvasion", "Defences" }, modType = "MORE" }, }, }, { label = "Total", { format = "{0:output:Evasion}", { breakdown = "Evasion" }, }, }, - { label = "Evade Chance", haveOutput = "noSplitEvade", { format = "{0:output:EvadeChance}%", - { breakdown = "EvadeChance" }, - { label = "Player modifiers", modName = { "CannotEvade", "EvadeChance", "MeleeEvadeChance", "ProjectileEvadeChance" } }, - { label = "Enemy modifiers", modName = { "Accuracy", "HitChance" }, enemy = true }, + { label = "Evade Chance", haveOutput = "noSplitEvade", { format = "{0:output:EvadeChance}%", + { breakdown = "EvadeChance" }, + { label = "Player modifiers", modName = { "CannotEvade", "EvadeChance", "MeleeEvadeChance", "ProjectileEvadeChance" } }, + { label = "Enemy modifiers", modName = { "Accuracy", "HitChance" }, enemy = true }, }, }, - { label = "Melee Evade Ch.", haveOutput = "splitEvade", { format = "{0:output:MeleeEvadeChance}%", - { breakdown = "MeleeEvadeChance" }, - { label = "Player modifiers", modName = { "CannotEvade", "EvadeChance", "MeleeEvadeChance" } }, - { label = "Enemy modifiers", modName = { "Accuracy", "HitChance" }, enemy = true }, + { label = "Melee Evade Ch.", haveOutput = "splitEvade", { format = "{0:output:MeleeEvadeChance}%", + { breakdown = "MeleeEvadeChance" }, + { label = "Player modifiers", modName = { "CannotEvade", "EvadeChance", "MeleeEvadeChance" } }, + { label = "Enemy modifiers", modName = { "Accuracy", "HitChance" }, enemy = true }, }, }, { label = "Proj. Evade Ch.", haveOutput = "splitEvade", { format = "{0:output:ProjectileEvadeChance}%", - { breakdown = "ProjectileEvadeChance" }, - { label = "Player modifiers", modName = { "CannotEvade", "EvadeChance", "ProjectileEvadeChance" } }, - { label = "Enemy modifiers", modName = { "Accuracy", "HitChance" }, enemy = true }, + { breakdown = "ProjectileEvadeChance" }, + { label = "Player modifiers", modName = { "CannotEvade", "EvadeChance", "ProjectileEvadeChance" } }, + { label = "Enemy modifiers", modName = { "Accuracy", "HitChance" }, enemy = true }, }, }, { label = "Effect of Blind", haveOutput = "BlindEffectMod", { format = "{0:output:BlindEffectMod}%", { breakdown = "BlindEffectMod" }, { modName = { "BlindEffect", "BuffEffectOnSelf" }, }, } }, } } @@ -1597,14 +1597,14 @@ return { extra = "{0:output:EffectiveBlockChance}%/{0:output:EffectiveSpellBlockChance}%", { label = "Block Chance", { format = "{0:output:BlockChance}% (+{0:output:BlockChanceOverCap}%)", { breakdown = "BlockChance" }, - { modName = { "BlockChance", "ReplaceShieldBlock" } }, + { modName = { "BlockChance", "ReplaceShieldBlock" } }, }, }, - { label = "Spell Block Chance", { format = "{0:output:SpellBlockChance}% (+{0:output:SpellBlockChanceOverCap}%)", - { breakdown = "SpellBlockChance" }, + { label = "Spell Block Chance", { format = "{0:output:SpellBlockChance}% (+{0:output:SpellBlockChanceOverCap}%)", + { breakdown = "SpellBlockChance" }, { modName = { "SpellBlockChance", "SpellBlockChanceIsBlockChance", "SpellBlockChanceMaxIsBlockChanceMax" }, }, }, }, - { label = "Taken From Block", haveOutput = "ShowBlockEffect", { format = "{0:output:DamageTakenOnBlock}%", - { breakdown = "BlockEffect" }, + { label = "Taken From Block", haveOutput = "ShowBlockEffect", { format = "{0:output:DamageTakenOnBlock}%", + { breakdown = "BlockEffect" }, { modName = { "BlockEffect" }, }, }, }, { label = "Life on Block", haveOutput = "LifeOnBlock", { format = "{0:output:LifeOnBlock}", { modName = "LifeOnBlock" }, }, }, @@ -1731,13 +1731,13 @@ return { { label = "Stun Threshold", { format = "{0:output:StunThreshold}", { breakdown = "StunThreshold" }, { modName = { "StunThreshold", "StunThresholdManaPercent", "StunThresholdEnergyShieldPercent" } }, }, }, { label = "Stun Chance", { format = "{0:output:SelfStunChance}%", { breakdown = "SelfStunChance" }, }, }, { label = "Interrupt Avoid Ch.", haveOutput = "InterruptStunAvoidChance", { format = "{0:output:InterruptStunAvoidChance}%", { modName = "AvoidInterruptStun" }, }, }, - { label = "Stun Duration", { format = "{2:output:StunDuration}s", + { label = "Stun Duration", { format = "{2:output:StunDuration}s", { breakdown = "StunDuration" }, { modName = { "StunDuration", "StunRecovery" } }, }, }, - { label = "Block Stun Duration", { format = "{2:output:BlockDuration}s", + { label = "Block Stun Duration", { format = "{2:output:BlockDuration}s", { breakdown = "BlockDuration" }, - { modName = { "StunDuration", "StunRecovery", "BlockRecovery" }, }, + { modName = { "StunDuration", "StunRecovery", "BlockRecovery" }, }, }, }, } }, { defaultCollapsed = true, label = "Other Avoidance", data = { { label = "Blind Avoid Ch.", haveOutput = "BlindAvoidChance", { format = "{0:output:BlindAvoidChance}%", { modName = { "AvoidBlind", "BlindImmune" } }, }, }, @@ -1792,20 +1792,20 @@ return { { format = colorCodes.CHAOS.."Chaos:" }, }, { label = "Enemy Damage", - { format = "{2:output:totalEnemyDamage}", - { breakdown = "totalEnemyDamage" }, - { label = "Enemy modifiers", modName = {"Damage", "CritChance", "CritMultiplier"}, enemy = true }, - { label = "Enemy Conversion modifiers", modName = { + { format = "{2:output:totalEnemyDamage}", + { breakdown = "totalEnemyDamage" }, + { label = "Enemy modifiers", modName = {"Damage", "CritChance", "CritMultiplier"}, enemy = true }, + { label = "Enemy Conversion modifiers", modName = { "PhysicalDamageGainAsLightning", "PhysicalDamageSkillConvertToLightning", "PhysicalDamageConvertToLightning", "PhysicalDamageGainAsCold", "PhysicalDamageSkillConvertToCold", "PhysicalDamageConvertToCold", "PhysicalDamageGainAsFire", "PhysicalDamageSkillConvertToFire", "PhysicalDamageConvertToFire", "PhysicalDamageGainAsChaos", "PhysicalDamageSkillConvertToChaos", "PhysicalDamageConvertToChaos" }, enemy = true }, }, - { format = "{2:output:PhysicalEnemyDamage}", - { breakdown = "PhysicalEnemyDamage" }, - { label = "Enemy modifiers", modName = {"Damage", "PhysicalDamage", "CritChance", "CritMultiplier"}, enemy = true }, - { label = "Enemy Conversion modifiers", modName = { + { format = "{2:output:PhysicalEnemyDamage}", + { breakdown = "PhysicalEnemyDamage" }, + { label = "Enemy modifiers", modName = {"Damage", "PhysicalDamage", "CritChance", "CritMultiplier"}, enemy = true }, + { label = "Enemy Conversion modifiers", modName = { "PhysicalDamageGainAsLightning", "PhysicalDamageSkillConvertToLightning", "PhysicalDamageConvertToLightning", "PhysicalDamageGainAsCold", "PhysicalDamageSkillConvertToCold", "PhysicalDamageConvertToCold", "PhysicalDamageGainAsFire", "PhysicalDamageSkillConvertToFire", "PhysicalDamageConvertToFire", @@ -1813,39 +1813,39 @@ return { }, enemy = true }, }, { format = "{2:output:LightningEnemyDamage}", - { breakdown = "LightningEnemyDamage" }, - { label = "Enemy modifiers", modName = {"Damage", "LightningDamage", "ElementalDamage", "CritChance", "CritMultiplier"}, enemy = true }, - { label = "Enemy Conversion modifiers", modName = {"PhysicalDamageGainAsLightning", "PhysicalDamageSkillConvertToLightning", "PhysicalDamageConvertToLightning"}, enemy = true }, + { breakdown = "LightningEnemyDamage" }, + { label = "Enemy modifiers", modName = {"Damage", "LightningDamage", "ElementalDamage", "CritChance", "CritMultiplier"}, enemy = true }, + { label = "Enemy Conversion modifiers", modName = {"PhysicalDamageGainAsLightning", "PhysicalDamageSkillConvertToLightning", "PhysicalDamageConvertToLightning"}, enemy = true }, }, { format = "{2:output:ColdEnemyDamage}", - { breakdown = "ColdEnemyDamage" }, - { label = "Enemy modifiers", modName = {"Damage", "ColdDamage", "ElementalDamage", "CritChance", "CritMultiplier"}, enemy = true }, - { label = "Enemy Conversion modifiers", modName = {"PhysicalDamageGainAsCold", "PhysicalDamageSkillConvertToCold", "PhysicalDamageConvertToCold"}, enemy = true }, + { breakdown = "ColdEnemyDamage" }, + { label = "Enemy modifiers", modName = {"Damage", "ColdDamage", "ElementalDamage", "CritChance", "CritMultiplier"}, enemy = true }, + { label = "Enemy Conversion modifiers", modName = {"PhysicalDamageGainAsCold", "PhysicalDamageSkillConvertToCold", "PhysicalDamageConvertToCold"}, enemy = true }, }, - { format = "{2:output:FireEnemyDamage}", - { breakdown = "FireEnemyDamage" }, - { label = "Enemy modifiers", modName = {"Damage", "FireDamage", "ElementalDamage", "CritChance", "CritMultiplier"}, enemy = true }, - { label = "Enemy Conversion modifiers", modName = {"PhysicalDamageGainAsFire", "PhysicalDamageSkillConvertToFire", "PhysicalDamageConvertToFire"}, enemy = true }, + { format = "{2:output:FireEnemyDamage}", + { breakdown = "FireEnemyDamage" }, + { label = "Enemy modifiers", modName = {"Damage", "FireDamage", "ElementalDamage", "CritChance", "CritMultiplier"}, enemy = true }, + { label = "Enemy Conversion modifiers", modName = {"PhysicalDamageGainAsFire", "PhysicalDamageSkillConvertToFire", "PhysicalDamageConvertToFire"}, enemy = true }, }, { format = "{2:output:ChaosEnemyDamage}", - { breakdown = "ChaosEnemyDamage" }, - { label = "Enemy modifiers", modName = {"Damage", "ChaosDamage", "CritChance", "CritMultiplier"}, enemy = true }, - { label = "Enemy Conversion modifiers", modName = {"PhysicalDamageGainAsChaos", "PhysicalDamageSkillConvertToChaos", "PhysicalDamageConvertToChaos"}, enemy = true }, + { breakdown = "ChaosEnemyDamage" }, + { label = "Enemy modifiers", modName = {"Damage", "ChaosDamage", "CritChance", "CritMultiplier"}, enemy = true }, + { label = "Enemy Conversion modifiers", modName = {"PhysicalDamageGainAsChaos", "PhysicalDamageSkillConvertToChaos", "PhysicalDamageConvertToChaos"}, enemy = true }, }, }, { label = "Taken As", - { format = "{2:output:totalTakenDamage}", - { breakdown = "totalTakenDamage" }, + { format = "{2:output:totalTakenDamage}", + { breakdown = "totalTakenDamage" }, }, - { format = "{2:output:PhysicalTakenDamage}", - { breakdown = "PhysicalTakenDamage" }, + { format = "{2:output:PhysicalTakenDamage}", + { breakdown = "PhysicalTakenDamage" }, { label = "Physical Taken as", modName = { "PhysicalDamageTakenAsLightning", "PhysicalDamageFromHitsTakenAsLightning", "PhysicalDamageTakenAsCold", "PhysicalDamageFromHitsTakenAsCold", "PhysicalDamageTakenAsFire", "PhysicalDamageFromHitsTakenAsFire", "PhysicalDamageTakenAsChaos", "PhysicalDamageFromHitsTakenAsChaos" } }, - { label = "Taken as Physical", modName = { + { label = "Taken as Physical", modName = { "LightningDamageTakenAsPhysical", "LightningDamageFromHitsTakenAsPhysical", "ColdDamageTakenAsPhysical", "ColdDamageFromHitsTakenAsPhysical", "FireDamageTakenAsPhysical", "FireDamageFromHitsTakenAsPhysical", @@ -1854,7 +1854,7 @@ return { } }, }, { format = "{2:output:LightningTakenDamage}", - { breakdown = "LightningTakenDamage" }, + { breakdown = "LightningTakenDamage" }, { label = "Lightning Taken as", modName = { "LightningDamageTakenAsPhysical", "LightningDamageFromHitsTakenAsPhysical", "LightningDamageTakenAsCold", "LightningDamageFromHitsTakenAsCold", @@ -1862,7 +1862,7 @@ return { "ElementalDamageTakenAsPhysical", "ElementalDamageFromHitsTakenAsPhysical", "ElementalDamageTakenAsChaos", "ElementalDamageFromHitsTakenAsChaos", "LightningDamageTakenAsChaos", "LightningDamageFromHitsTakenAsChaos" } }, - { label = "Taken as Lightning", modName = { + { label = "Taken as Lightning", modName = { "PhysicalDamageTakenAsLightning", "PhysicalDamageFromHitsTakenAsLightning", "ColdDamageTakenAsLightning", "ColdDamageFromHitsTakenAsLightning", "FireDamageTakenAsLightning", "FireDamageFromHitsTakenAsLightning", @@ -1870,7 +1870,7 @@ return { } }, }, { format = "{2:output:ColdTakenDamage}", - { breakdown = "ColdTakenDamage" }, + { breakdown = "ColdTakenDamage" }, { label = "Cold Taken as", modName = { "ColdDamageTakenAsPhysical", "ColdDamageFromHitsTakenAsPhysical", "ColdDamageTakenAsLightning", "ColdDamageFromHitsTakenAsLightning", @@ -1878,15 +1878,15 @@ return { "ElementalDamageTakenAsPhysical", "ElementalDamageFromHitsTakenAsPhysical", "ElementalDamageTakenAsChaos", "ElementalDamageFromHitsTakenAsChaos", "ColdDamageTakenAsChaos", "ColdDamageFromHitsTakenAsChaos" } }, - { label = "Taken as Cold", modName = { + { label = "Taken as Cold", modName = { "PhysicalDamageTakenAsCold", "PhysicalDamageFromHitsTakenAsCold", "LightningDamageTakenAsCold", "LightningDamageFromHitsTakenAsCold", "FireDamageTakenAsCold", "FireDamageFromHitsTakenAsCold", "ChaosDamageTakenAsCold", "ChaosDamageFromHitsTakenAsCold" } }, }, - { format = "{2:output:FireTakenDamage}", - { breakdown = "FireTakenDamage" }, + { format = "{2:output:FireTakenDamage}", + { breakdown = "FireTakenDamage" }, { label = "Fire Taken as", modName = { "FireDamageTakenAsPhysical", "FireDamageFromHitsTakenAsPhysical", "FireDamageTakenAsLightning", "FireDamageFromHitsTakenAsLightning", @@ -1894,7 +1894,7 @@ return { "ElementalDamageTakenAsPhysical", "ElementalDamageFromHitsTakenAsPhysical", "ElementalDamageTakenAsChaos", "ElementalDamageFromHitsTakenAsChaos", "FireDamageTakenAsChaos", "FireDamageFromHitsTakenAsChaos" } }, - { label = "Taken as Fire", modName = { + { label = "Taken as Fire", modName = { "PhysicalDamageTakenAsFire", "PhysicalDamageFromHitsTakenAsFire", "LightningDamageTakenAsFire", "LightningDamageFromHitsTakenAsFire", "ColdDamageTakenAsFire", "ColdDamageFromHitsTakenAsFire", @@ -1902,14 +1902,14 @@ return { } }, }, { format = "{2:output:ChaosTakenDamage}", - { breakdown = "ChaosTakenDamage" }, + { breakdown = "ChaosTakenDamage" }, { label = "Chaos Taken as", modName = { "ChaosDamageTakenAsPhysical", "ChaosDamageFromHitsTakenAsPhysical", "ChaosDamageTakenAsLightning", "ChaosDamageFromHitsTakenAsLightning", "ChaosDamageTakenAsCold", "ChaosDamageFromHitsTakenAsCold", "ChaosDamageTakenAsFire", "ChaosDamageFromHitsTakenAsFire" } }, - { label = "Taken as Chaos", modName = { + { label = "Taken as Chaos", modName = { "PhysicalDamageTakenAsChaos", "PhysicalDamageFromHitsTakenAsChaos", "LightningDamageTakenAsChaos", "LightningDamageFromHitsTakenAsChaos", "ColdDamageTakenAsChaos", "ColdDamageFromHitsTakenAsChaos", @@ -1922,97 +1922,97 @@ return { colWidth = 95, { label = "Hit taken Mult.", { format = "" }, - { format = "x {3:output:PhysicalTakenHitMult}", - { breakdown = "PhysicalTakenHitMult" }, - { modName = { "DamageTaken", "DamageTakenWhenHit", "AttackDamageTaken", "SpellDamageTaken", "PhysicalDamageTaken", "PhysicalDamageTakenWhenHit", "PhysicalDamageTakenAsFire", "PhysicalDamageTakenAsCold", "PhysicalDamageTakenAsLightning", "PhysicalDamageTakenAsChaos" } } + { format = "x {3:output:PhysicalTakenHitMult}", + { breakdown = "PhysicalTakenHitMult" }, + { modName = { "DamageTaken", "DamageTakenWhenHit", "AttackDamageTaken", "SpellDamageTaken", "PhysicalDamageTaken", "PhysicalDamageTakenWhenHit", "PhysicalDamageTakenAsFire", "PhysicalDamageTakenAsCold", "PhysicalDamageTakenAsLightning", "PhysicalDamageTakenAsChaos" } } }, { format = "x {3:output:LightningTakenHitMult}", - { breakdown = "LightningTakenHitMult" }, + { breakdown = "LightningTakenHitMult" }, { modName = { "DamageTaken", "DamageTakenWhenHit", "AttackDamageTaken", "SpellDamageTaken", "LightningDamageTaken", "LightningDamageTakenWhenHit", "ElementalDamageTaken", "ElementalDamageTakenWhenHit", "LightningDamageTakenAsPhysical", "LightningDamageTakenAsFire", "LightningDamageTakenAsCold", "LightningDamageTakenAsChaos", "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos", "SelfIgnoreLightningResistance" } } }, { format = "x {3:output:ColdTakenHitMult}", - { breakdown = "ColdTakenHitMult" }, + { breakdown = "ColdTakenHitMult" }, { modName = { "DamageTaken", "DamageTakenWhenHit", "AttackDamageTaken", "SpellDamageTaken", "ColdDamageTaken", "ColdDamageTakenWhenHit", "ElementalDamageTaken", "ElementalDamageTakenWhenHit", "ColdDamageTakenAsPhysical", "ColdDamageTakenAsFire", "ColdDamageTakenAsLightning", "ColdDamageTakenAsChaos", "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos", "SelfIgnoreColdResistance" } } }, - { format = "x {3:output:FireTakenHitMult}", - { breakdown = "FireTakenHitMult" }, - { modName = { "DamageTaken", "DamageTakenWhenHit", "AttackDamageTaken", "SpellDamageTaken", "FireDamageTaken", "FireDamageTakenWhenHit", "ElementalDamageTaken", "ElementalDamageTakenWhenHit", "FireDamageTakenAsPhysical", "FireDamageTakenAsCold", "FireDamageTakenAsLightning", "FireDamageTakenAsChaos", "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos", "SelfIgnoreFireResistance" } } + { format = "x {3:output:FireTakenHitMult}", + { breakdown = "FireTakenHitMult" }, + { modName = { "DamageTaken", "DamageTakenWhenHit", "AttackDamageTaken", "SpellDamageTaken", "FireDamageTaken", "FireDamageTakenWhenHit", "ElementalDamageTaken", "ElementalDamageTakenWhenHit", "FireDamageTakenAsPhysical", "FireDamageTakenAsCold", "FireDamageTakenAsLightning", "FireDamageTakenAsChaos", "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos", "SelfIgnoreFireResistance" } } }, { format = "x {3:output:ChaosTakenHitMult}", - { breakdown = "ChaosTakenHitMult" }, + { breakdown = "ChaosTakenHitMult" }, { modName = { "DamageTaken", "DamageTakenWhenHit", "AttackDamageTaken", "SpellDamageTaken", "ChaosDamageTaken", "ChaosDamageTakenWhenHit", "ChaosDamageTakenAsPhysical", "ChaosDamageTakenAsFire", "ChaosDamageTakenAsCold", "ChaosDamageTakenAsLightning", "SelfIgnoreChaosResistance" } } }, }, { label = "Reflect taken", haveOutput = "AnyTakenReflect", { format = "" }, - { format = "x {2:output:PhysicalTakenReflectMult}", - { breakdown = "PhysicalTakenReflectMult" }, - { modName = { "DamageTaken", "DamageTakenWhenHit", "PhysicalDamageTaken", "PhysicalDamageTakenWhenHit", "PhysicalReflectedDamageTaken", "PhysicalDamageTakenAsFire", "PhysicalDamageTakenAsCold", "PhysicalDamageTakenAsLightning", "PhysicalDamageTakenAsChaos" } } + { format = "x {2:output:PhysicalTakenReflectMult}", + { breakdown = "PhysicalTakenReflectMult" }, + { modName = { "DamageTaken", "DamageTakenWhenHit", "PhysicalDamageTaken", "PhysicalDamageTakenWhenHit", "PhysicalReflectedDamageTaken", "PhysicalDamageTakenAsFire", "PhysicalDamageTakenAsCold", "PhysicalDamageTakenAsLightning", "PhysicalDamageTakenAsChaos" } } }, { format = "x {2:output:LightningTakenReflectMult}", - { breakdown = "LightningTakenReflectMult" }, + { breakdown = "LightningTakenReflectMult" }, { modName = { "DamageTaken", "DamageTakenWhenHit", "LightningDamageTaken", "LightningDamageTakenWhenHit", "LightningReflectedDamageTaken", "ElementalDamageTaken", "ElementalDamageTakenWhenHit", "ElementalReflectedDamageTaken", "LightningDamageTakenAsPhysical", "LightningDamageTakenAsFire", "LightningDamageTakenAsCold", "LightningDamageTakenAsChaos", "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos" } } }, { format = "x {2:output:ColdTakenReflectMult}", - { breakdown = "ColdTakenReflectMult" }, + { breakdown = "ColdTakenReflectMult" }, { modName = { "DamageTaken", "DamageTakenWhenHit", "ColdDamageTaken", "ColdDamageTakenWhenHit", "ColdReflectedDamageTaken", "ElementalDamageTaken", "ElementalDamageTakenWhenHit", "ElementalReflectedDamageTaken", "ColdDamageTakenAsPhysical", "ColdDamageTakenAsFire", "ColdDamageTakenAsLightning", "ColdDamageTakenAsChaos", "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos" } } }, - { format = "x {2:output:FireTakenReflectMult}", - { breakdown = "FireTakenReflectMult" }, - { modName = { "DamageTaken", "DamageTakenWhenHit", "FireDamageTaken", "FireDamageTakenWhenHit", "FireReflectedDamageTaken", "ElementalDamageTaken", "ElementalDamageTakenWhenHit", "ElementalReflectedDamageTaken", "ElementalDamageTakenOverTime", "FireDamageTakenAsPhysical", "FireDamageTakenAsCold", "FireDamageTakenAsLightning", "FireDamageTakenAsChaos", "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos" } } + { format = "x {2:output:FireTakenReflectMult}", + { breakdown = "FireTakenReflectMult" }, + { modName = { "DamageTaken", "DamageTakenWhenHit", "FireDamageTaken", "FireDamageTakenWhenHit", "FireReflectedDamageTaken", "ElementalDamageTaken", "ElementalDamageTakenWhenHit", "ElementalReflectedDamageTaken", "ElementalDamageTakenOverTime", "FireDamageTakenAsPhysical", "FireDamageTakenAsCold", "FireDamageTakenAsLightning", "FireDamageTakenAsChaos", "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos" } } }, { format = "x {2:output:ChaosTakenReflectMult}", - { breakdown = "ChaosTakenReflectMult" }, + { breakdown = "ChaosTakenReflectMult" }, { modName = { "DamageTaken", "DamageTakenWhenHit", "ChaosDamageTaken", "ChaosDamageTakenWhenHit", "ChaosDamageTakenAsPhysical", "ChaosDamageTakenAsFire", "ChaosDamageTakenAsCold", "ChaosDamageTakenAsLightning" } } }, }, { label = "Hit taken", - { format = "{2:output:totalTakenHit}", - { breakdown = "totalTakenHit" }, + { format = "{2:output:totalTakenHit}", + { breakdown = "totalTakenHit" }, }, - { format = "{2:output:PhysicalTakenHit}", - { breakdown = "PhysicalTakenHit" }, + { format = "{2:output:PhysicalTakenHit}", + { breakdown = "PhysicalTakenHit" }, }, { format = "{2:output:LightningTakenHit}", - { breakdown = "LightningTakenHit" }, + { breakdown = "LightningTakenHit" }, }, { format = "{2:output:ColdTakenHit}", - { breakdown = "ColdTakenHit" }, + { breakdown = "ColdTakenHit" }, }, - { format = "{2:output:FireTakenHit}", - { breakdown = "FireTakenHit" }, + { format = "{2:output:FireTakenHit}", + { breakdown = "FireTakenHit" }, }, { format = "{2:output:ChaosTakenHit}", - { breakdown = "ChaosTakenHit" }, + { breakdown = "ChaosTakenHit" }, }, }, { label = "PvP Hit taken", haveOutput = "PvPTotalTakenHit", - { format = "{2:output:PvPTotalTakenHit}", - { breakdown = "PvPTotalTakenHit" }, - { label = "Enemy PvP Multiplier", modName = "MultiplierPvpDamage", enemy = true }, + { format = "{2:output:PvPTotalTakenHit}", + { breakdown = "PvPTotalTakenHit" }, + { label = "Enemy PvP Multiplier", modName = "MultiplierPvpDamage", enemy = true }, }, }, { label = "ES Bypass %", haveOutput = "AnyBypass", { format = " "}, - { format = "{0:output:PhysicalEnergyShieldBypass}%", + { format = "{0:output:PhysicalEnergyShieldBypass}%", { breakdown = "PhysicalEnergyShieldBypass" }, - { modName = {"PhysicalEnergyShieldBypass", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, + { modName = {"PhysicalEnergyShieldBypass", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, }, { format = "{0:output:LightningEnergyShieldBypass}%", - { breakdown = "LightningEnergyShieldBypass" }, - { modName = {"LightningEnergyShieldBypass", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, + { breakdown = "LightningEnergyShieldBypass" }, + { modName = {"LightningEnergyShieldBypass", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, }, { format = "{0:output:ColdEnergyShieldBypass}%", { breakdown = "ColdEnergyShieldBypass" }, - { modName = {"ColdEnergyShieldBypass", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, + { modName = {"ColdEnergyShieldBypass", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, }, - { format = "{0:output:FireEnergyShieldBypass}%", - { breakdown = "FireEnergyShieldBypass" }, - { modName = {"FireEnergyShieldBypass", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, + { format = "{0:output:FireEnergyShieldBypass}%", + { breakdown = "FireEnergyShieldBypass" }, + { modName = {"FireEnergyShieldBypass", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, }, { format = "{0:output:ChaosEnergyShieldBypass}%", - { breakdown = "ChaosEnergyShieldBypass" }, - { modName = {"ChaosEnergyShieldBypass", "ChaosNotBypassEnergyShield", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, + { breakdown = "ChaosEnergyShieldBypass" }, + { modName = {"ChaosEnergyShieldBypass", "ChaosNotBypassEnergyShield", "BlockedDamageDoesntBypassES", "UnblockedDamageDoesBypassES"} }, }, }, { haveOutput = "ehpSectionAnySpecificTypes", @@ -2030,35 +2030,35 @@ return { }, }, { label = "Mind over Matter %", haveOutput = "OnlySharedMindOverMatter", - { format = "{0:output:sharedMindOverMatter}%", + { format = "{0:output:sharedMindOverMatter}%", { breakdown = "sharedMindOverMatter" }, - { modName = "DamageTakenFromManaBeforeLife" }, + { modName = "DamageTakenFromManaBeforeLife" }, }, }, { label = "Mind over Matter %", haveOutput = "AnySpecificMindOverMatter", - { format = "{0:output:sharedMindOverMatter}%", + { format = "{0:output:sharedMindOverMatter}%", { breakdown = "sharedMindOverMatter" }, - { modName = "DamageTakenFromManaBeforeLife" }, + { modName = "DamageTakenFromManaBeforeLife" }, }, - { format = "+{0:output:PhysicalMindOverMatter}%", + { format = "+{0:output:PhysicalMindOverMatter}%", { breakdown = "PhysicalMindOverMatter" }, - { modName = "DamageTakenFromManaBeforeLife" }, + { modName = "DamageTakenFromManaBeforeLife" }, }, { format = "+{0:output:LightningMindOverMatter}%", - { breakdown = "LightningMindOverMatter" }, - { modName = {"DamageTakenFromManaBeforeLife", "LightningDamageTakenFromManaBeforeLife"} }, + { breakdown = "LightningMindOverMatter" }, + { modName = {"DamageTakenFromManaBeforeLife", "LightningDamageTakenFromManaBeforeLife"} }, }, { format = "+{0:output:ColdMindOverMatter}%", { breakdown = "ColdMindOverMatter" }, - { modName = "DamageTakenFromManaBeforeLife" }, + { modName = "DamageTakenFromManaBeforeLife" }, }, - { format = "+{0:output:FireMindOverMatter}%", - { breakdown = "FireMindOverMatter" }, - { modName = "DamageTakenFromManaBeforeLife" }, + { format = "+{0:output:FireMindOverMatter}%", + { breakdown = "FireMindOverMatter" }, + { modName = "DamageTakenFromManaBeforeLife" }, }, { format = "+{0:output:ChaosMindOverMatter}%", - { breakdown = "ChaosMindOverMatter" }, - { modName = {"DamageTakenFromManaBeforeLife", "ChaosDamageTakenFromManaBeforeLife"} }, + { breakdown = "ChaosMindOverMatter" }, + { modName = {"DamageTakenFromManaBeforeLife", "ChaosDamageTakenFromManaBeforeLife"} }, }, }, { label = "Guard", haveOutput = "OnlySharedGuard", @@ -2153,19 +2153,19 @@ return { } }, }, { defaultCollapsed = false, label = "Effective \"Health\" Pool", data = { extra = "{0:output:TotalEHP}", - { label = "Unmitigated %", { format = "{0:output:ConfiguredDamageChance}%", - { breakdown = "ConfiguredDamageChance" }, + { label = "Unmitigated %", { format = "{0:output:ConfiguredDamageChance}%", + { breakdown = "ConfiguredDamageChance" }, { label = "Enemy modifiers", modName = { "CannotBeSuppressed", "CannotBeBlocked", "reduceEnemyBlock" }, enemy = true }, }, }, { label = "Mitigated hits", { format = "{2:output:NumberOfMitigatedDamagingHits}", }, }, - { label = "Enemy miss chance", { format = "{0:output:ConfiguredNotHitChance}%", - { breakdown = "ConfiguredNotHitChance" }, + { label = "Enemy miss chance", { format = "{0:output:ConfiguredNotHitChance}%", + { breakdown = "ConfiguredNotHitChance" }, { label = "Enemy modifiers", modName = { "CannotBeEvaded", "CannotBeDodged", "reduceEnemyDodge" }, enemy = true }, }, }, { label = "Hits before death", { format = "{2:output:TotalNumberOfHits}", { breakdown = "TotalNumberOfHits" }}, }, { label = "Effective Hit Pool",{ format = "{0:output:TotalEHP}", { breakdown = "TotalEHP" }, },}, - { label = "Time before death",{ format = "{2:output:EHPSurvivalTime}s", - { breakdown = "EHPSurvivalTime" }, + { label = "Time before death",{ format = "{2:output:EHPSurvivalTime}s", + { breakdown = "EHPSurvivalTime" }, { label = "Enemy modifiers", modName = { "TemporalChainsActionSpeed", "ActionSpeed", "Speed", "MinimumActionSpeed" }, enemy = true }, },} }, }, { defaultCollapsed = false, label = "Maximum Hit Taken", data = { @@ -2178,20 +2178,20 @@ return { { format = colorCodes.CHAOS.."Chaos:" }, }, { label = "Maximum Hit Taken", - { format = "{0:output:PhysicalMaximumHitTaken}", - { breakdown = "PhysicalMaximumHitTaken" }, + { format = "{0:output:PhysicalMaximumHitTaken}", + { breakdown = "PhysicalMaximumHitTaken" }, }, { format = "{0:output:LightningMaximumHitTaken}", - { breakdown = "LightningMaximumHitTaken" }, + { breakdown = "LightningMaximumHitTaken" }, }, { format = "{0:output:ColdMaximumHitTaken}", - { breakdown = "ColdMaximumHitTaken" }, + { breakdown = "ColdMaximumHitTaken" }, }, - { format = "{0:output:FireMaximumHitTaken}", - { breakdown = "FireMaximumHitTaken" }, + { format = "{0:output:FireMaximumHitTaken}", + { breakdown = "FireMaximumHitTaken" }, }, { format = "{0:output:ChaosMaximumHitTaken}", - { breakdown = "ChaosMaximumHitTaken" }, + { breakdown = "ChaosMaximumHitTaken" }, }, } } }, { defaultCollapsed = true, label = "Recoup and Hit Taken Over Time", data = { @@ -2202,7 +2202,7 @@ return { { format = colorCodes.MANA.."Mana:" }, { format = colorCodes.ES.."Energy Shield:" }, }, - { label = "Recoup Max.", haveOutput = "anyRecoup", + { label = "Recoup Max.", haveOutput = "anyRecoup", { format = "{0:output:LifeRecoupRecoveryMax}", { breakdown = "LifeRecoupRecoveryMax" }, { label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup", "PhysicalDamageMitigatedLifePseudoRecoup" } }, @@ -2222,7 +2222,7 @@ return { { label = "Faster Recoup", modName = "3SecondRecoup" }, }, }, - { label = "Recoup Avg.", haveOutput = "anyRecoup", + { label = "Recoup Avg.", haveOutput = "anyRecoup", { format = "{0:output:LifeRecoupRecoveryAvg}", { breakdown = "LifeRecoupRecoveryAvg" }, { label = "Sources", modName = { "LifeRecoup", "PhysicalLifeRecoup", "LightningLifeRecoup", "ColdLifeRecoup", "FireLifeRecoup", "ChaosLifeRecoup", "PhysicalDamageMitigatedLifePseudoRecoup" } }, @@ -2242,24 +2242,24 @@ return { { label = "Faster Recoup", modName = "3SecondRecoup" }, }, }, - { label = "Hit Over Time Max.", haveOutput = "preventedLifeLossTotal", + { label = "Hit Over Time Max.", haveOutput = "preventedLifeLossTotal", { format = "{0:output:LifeLossLostMax}", { breakdown = "LifeLossLostMax" }, { modName = { "LifeLossPrevented", "LifeLossBelowHalfPrevented", "LifeLossBelowHalfLost" } }, }, }, - { label = "Hit Over Time Avg.", haveOutput = "preventedLifeLossTotal", + { label = "Hit Over Time Avg.", haveOutput = "preventedLifeLossTotal", { format = "{0:output:LifeLossLostAvg}", { breakdown = "LifeLossLostAvg" }, { modName = { "LifeLossPrevented", "LifeLossBelowHalfPrevented", "LifeLossBelowHalfLost" } }, }, }, - { label = "Net Max.", haveOutput = "showNetRecoup", + { label = "Net Max.", haveOutput = "showNetRecoup", { format = "{0:output:netLifeRecoupAndLossLostOverTimeMax}", { breakdown = "netLifeRecoupAndLossLostOverTimeMax" }, }, }, - { label = "Net Avg.", haveOutput = "showNetRecoup", + { label = "Net Avg.", haveOutput = "showNetRecoup", { format = "{0:output:netLifeRecoupAndLossLostOverTimeAvg}", { breakdown = "netLifeRecoupAndLossLostOverTimeAvg" }, }, @@ -2274,8 +2274,8 @@ return { { format = colorCodes.CHAOS.."Chaos:" }, }, { label = "DoT taken", - { format = "x {2:output:PhysicalTakenDotMult}", - { breakdown = "PhysicalTakenDotMult" }, + { format = "x {2:output:PhysicalTakenDotMult}", + { breakdown = "PhysicalTakenDotMult" }, { modName = { "DamageTaken", "DamageTakenOverTime", "PhysicalDamageTaken", "PhysicalDamageTakenOverTime" } }, { label = "Physical Taken as", modName = { "PhysicalDamageTakenAsLightning", @@ -2283,7 +2283,7 @@ return { "PhysicalDamageTakenAsFire", "PhysicalDamageTakenAsChaos" } }, - { label = "Taken as Physical", modName = { + { label = "Taken as Physical", modName = { "LightningDamageTakenAsPhysical", "ColdDamageTakenAsPhysical", "FireDamageTakenAsPhysical", @@ -2292,7 +2292,7 @@ return { } }, }, { format = "x {2:output:LightningTakenDotMult}", - { breakdown = "LightningTakenDotMult" }, + { breakdown = "LightningTakenDotMult" }, { modName = { "DamageTaken", "DamageTakenOverTime", "LightningDamageTaken", "LightningDamageTakenOverTime", "ElementalDamageTaken", "ElementalDamageTakenOverTime", "SelfIgnoreLightningResistance" } }, { label = "Lightning Taken as", modName = { "LightningDamageTakenAsPhysical", @@ -2301,7 +2301,7 @@ return { "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos", "LightningDamageTakenAsChaos" } }, - { label = "Taken as Lightning", modName = { + { label = "Taken as Lightning", modName = { "PhysicalDamageTakenAsLightning", "ColdDamageTakenAsLightning", "FireDamageTakenAsLightning", @@ -2309,7 +2309,7 @@ return { } }, }, { format = "x {2:output:ColdTakenDotMult}", - { breakdown = "ColdTakenDotMult" }, + { breakdown = "ColdTakenDotMult" }, { modName = { "DamageTaken", "DamageTakenOverTime", "ColdDamageTaken", "ColdDamageTakenOverTime", "ElementalDamageTaken", "ElementalDamageTakenOverTime", "SelfIgnoreColdResistance" } }, { label = "Cold Taken as", modName = { "ColdDamageTakenAsPhysical", @@ -2318,24 +2318,24 @@ return { "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos", "ColdDamageTakenAsChaos" } }, - { label = "Taken as Cold", modName = { + { label = "Taken as Cold", modName = { "PhysicalDamageTakenAsCold", "LightningDamageTakenAsCold", "FireDamageTakenAsCold", "ChaosDamageTakenAsCold" } }, }, - { format = "x {2:output:FireTakenDotMult}", - { breakdown = "FireTakenDotMult" }, + { format = "x {2:output:FireTakenDotMult}", + { breakdown = "FireTakenDotMult" }, { modName = { "DamageTaken", "DamageTakenOverTime", "FireDamageTaken", "FireDamageTakenOverTime", "ElementalDamageTaken", "ElementalDamageTakenOverTime", "SelfIgnoreFireResistance" } }, { label = "Fire Taken as", modName = { "FireDamageTakenAsPhysical", "FireDamageTakenAsLightning", "FireDamageTakenAsCold", - "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos", + "ElementalDamageTakenAsPhysical", "ElementalDamageTakenAsChaos", "FireDamageTakenAsChaos" } }, - { label = "Taken as Fire", modName = { + { label = "Taken as Fire", modName = { "PhysicalDamageTakenAsFire", "LightningDamageTakenAsFire", "ColdDamageTakenAsFire", "FireDamageTakenAsCold", @@ -2343,7 +2343,7 @@ return { } }, }, { format = "x {2:output:ChaosTakenDotMult}", - { breakdown = "ChaosTakenDotMult" }, + { breakdown = "ChaosTakenDotMult" }, { modName = { "DamageTaken", "DamageTakenOverTime", "ChaosDamageTaken", "ChaosDamageTakenOverTime", "SelfIgnoreChaosResistance" } }, { label = "Chaos Taken as", modName = { "ChaosDamageTakenAsPhysical", @@ -2351,7 +2351,7 @@ return { "ChaosDamageTakenAsCold", "ChaosDamageTakenAsFire", } }, - { label = "Taken as Chaos", modName = { + { label = "Taken as Chaos", modName = { "PhysicalDamageTakenAsChaos", "LightningDamageTakenAsChaos", "ColdDamageTakenAsChaos", @@ -2361,62 +2361,62 @@ return { }, }, { label = "Total Pool", - { format = "{0:output:PhysicalTotalPool}", - { breakdown = "PhysicalTotalPool" }, + { format = "{0:output:PhysicalTotalPool}", + { breakdown = "PhysicalTotalPool" }, }, { format = "{0:output:LightningTotalPool}", - { breakdown = "LightningTotalPool" }, + { breakdown = "LightningTotalPool" }, }, { format = "{0:output:ColdTotalPool}", { breakdown = "ColdTotalPool" }, }, - { format = "{0:output:FireTotalPool}", - { breakdown = "FireTotalPool" }, + { format = "{0:output:FireTotalPool}", + { breakdown = "FireTotalPool" }, }, { format = "{0:output:ChaosTotalPool}", - { breakdown = "ChaosTotalPool" }, + { breakdown = "ChaosTotalPool" }, }, - }, + }, { label = "Effective DoT Pool", - { format = "{0:output:PhysicalDotEHP}", - { breakdown = "PhysicalDotEHP" }, + { format = "{0:output:PhysicalDotEHP}", + { breakdown = "PhysicalDotEHP" }, }, { format = "{0:output:LightningDotEHP}", - { breakdown = "LightningDotEHP" }, + { breakdown = "LightningDotEHP" }, }, { format = "{0:output:ColdDotEHP}", - { breakdown = "ColdDotEHP" }, + { breakdown = "ColdDotEHP" }, }, - { format = "{0:output:FireDotEHP}", - { breakdown = "FireDotEHP" }, + { format = "{0:output:FireDotEHP}", + { breakdown = "FireDotEHP" }, }, { format = "{0:output:ChaosDotEHP}", - { breakdown = "ChaosDotEHP" }, + { breakdown = "ChaosDotEHP" }, }, }, { label = "Degens", haveOutput = "TotalBuildDegen", - { format = "{0:output:PhysicalBuildDegen}", - { breakdown = "PhysicalBuildDegen" }, + { format = "{0:output:PhysicalBuildDegen}", + { breakdown = "PhysicalBuildDegen" }, { modName = "PhysicalDegen", } }, { format = "{0:output:LightningBuildDegen}", - { breakdown = "LightningBuildDegen" }, + { breakdown = "LightningBuildDegen" }, { modName = "LightningDegen", } }, { format = "{0:output:ColdBuildDegen}", - { breakdown = "ColdBuildDegen" }, + { breakdown = "ColdBuildDegen" }, { modName = "ColdDegen", } }, - { format = "{0:output:FireBuildDegen}", - { breakdown = "FireBuildDegen" }, + { format = "{0:output:FireBuildDegen}", + { breakdown = "FireBuildDegen" }, { modName = "FireDegen", } }, { format = "{0:output:ChaosBuildDegen}", - { breakdown = "ChaosBuildDegen" }, + { breakdown = "ChaosBuildDegen" }, { modName = "ChaosDegen", } }, }, - { label = "Total Degen", haveOutput = "TotalBuildDegen", { format = "{1:output:TotalBuildDegen}", + { label = "Total Degen", haveOutput = "TotalBuildDegen", { format = "{1:output:TotalBuildDegen}", { breakdown = "TotalBuildDegen" }, { label = "Sources", modName = { "PhysicalDegen", "FireDegen", "ColdDegen", "LightningDegen", "ChaosDegen" }, modType = "BASE" }, }, }, @@ -2436,23 +2436,23 @@ return { { format = colorCodes.CHAOS.."Chaos:" }, }, { label = "Degens", haveOutput = "TotalDegen", - { format = "{0:output:PhysicalEnemyDegen}", - { breakdown = "PhysicalEnemyDegen" }, + { format = "{0:output:PhysicalEnemyDegen}", + { breakdown = "PhysicalEnemyDegen" }, }, { format = "{0:output:LightningEnemyDegen}", - { breakdown = "LightningEnemyDegen" }, + { breakdown = "LightningEnemyDegen" }, }, { format = "{0:output:ColdEnemyDegen}", - { breakdown = "ColdEnemyDegen" }, + { breakdown = "ColdEnemyDegen" }, }, - { format = "{0:output:FireEnemyDegen}", - { breakdown = "FireEnemyDegen" }, + { format = "{0:output:FireEnemyDegen}", + { breakdown = "FireEnemyDegen" }, }, { format = "{0:output:ChaosEnemyDegen}", - { breakdown = "ChaosEnemyDegen" }, + { breakdown = "ChaosEnemyDegen" }, }, }, - { label = "Total Degen", haveOutput = "TotalDegen", { format = "{1:output:TotalDegen}", + { label = "Total Degen", haveOutput = "TotalDegen", { format = "{1:output:TotalDegen}", { breakdown = "TotalDegen" }, }, }, { label = "Total Net Recovery", haveOutput = "ComprehensiveTotalNetRegen", { format = "{1:output:ComprehensiveTotalNetRegen}", diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 33f1dcb0c5..5516820def 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -1056,7 +1056,7 @@ function calcs.initEnv(build, mode, override, specEnv) local combinedList = new("ModList") for _, mod in ipairs(srcList) do combinedList:MergeMod(mod) - end + end env.itemModDB:ScaleAddList(combinedList, scale) elseif item.type == "Gloves" and calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromGloves") ~=1 then scale = calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromGloves") - 1 @@ -1115,7 +1115,7 @@ function calcs.initEnv(build, mode, override, specEnv) end env.itemModDB.multipliers[item.type:gsub(" ", ""):gsub(".+Handed", "").."Item"] = (env.itemModDB.multipliers[item.type:gsub(" ", ""):gsub(".+Handed", "").."Item"] or 0) + 1 -- Calculate socket counts - local slotEmptySocketsCount = { R = 0, G = 0, B = 0, W = 0} + local slotEmptySocketsCount = { R = 0, G = 0, B = 0, W = 0} local slotGemSocketsCount = 0 local socketedGems = 0 -- Loop through socket groups to calculate number of socketed gems @@ -1390,7 +1390,7 @@ function calcs.initEnv(build, mode, override, specEnv) for index, group in ipairs(build.skillsTab.socketGroupList) do local slot = group.slot and build.itemsTab.slots[group.slot] group.slotEnabled = not slot or not slot.weaponSet or slot.weaponSet == (build.itemsTab.activeItemSet.useSecondWeaponSet and 2 or 1) - -- if group is main skill or group is enabled + -- if group is main skill or group is enabled if index == env.mainSocketGroup or (group.enabled and group.slotEnabled) then local slotName = group.slot and group.slot:gsub(" Swap","") groupCfgList[slotName or "noSlot"] = groupCfgList[slotName or "noSlot"] or {} @@ -1545,7 +1545,7 @@ function calcs.initEnv(build, mode, override, specEnv) -- add displayGemList for tooltip to display all gems linked to active skills group.displayGemList = copyTable(group.gemList, true) -- if skill granted by unique item, go through all support groups in slot - if group.source then + if group.source then if supportLists[slotName] then -- add socketed supports from other socketGroups for _, otherSocketGroup in ipairs(build.skillsTab.socketGroupList) do @@ -1568,8 +1568,8 @@ function calcs.initEnv(build, mode, override, specEnv) for crossLinkedSupportSlot, crossLinkedSupportGroup in pairs(env.crossLinkedSupportGroups) do for _, crossLinkedSupportedSlot in ipairs(crossLinkedSupportGroup) do if crossLinkedSupportedSlot == slotName and supportLists[crossLinkedSupportSlot] then - for _, otherSocketGroup in ipairs(build.skillsTab.socketGroupList) do - if otherSocketGroup.slot and otherSocketGroup.slot == crossLinkedSupportSlot then + for _, otherSocketGroup in ipairs(build.skillsTab.socketGroupList) do + if otherSocketGroup.slot and otherSocketGroup.slot == crossLinkedSupportSlot then for _, gem in ipairs(otherSocketGroup.gemList) do if gem.gemData and gem.gemData.grantedEffect and gem.gemData.grantedEffect.support then t_insert(group.displayGemList, gem) @@ -1605,7 +1605,7 @@ function calcs.initEnv(build, mode, override, specEnv) end end end - + if not slotHasActiveSkill and group.displayGemList then group.displayGemList = nil end diff --git a/src/Modules/CalcTools.lua b/src/Modules/CalcTools.lua index 9a733a1a9f..01826c4bef 100644 --- a/src/Modules/CalcTools.lua +++ b/src/Modules/CalcTools.lua @@ -111,8 +111,8 @@ end -- Check if given gem is of the given type ("all", "strength", "melee", etc) function calcLib.gemIsType(gem, type, includeTransfigured) - return (type == "all" or - (type == "elemental" and (gem.tags.fire or gem.tags.cold or gem.tags.lightning)) or + return (type == "all" or + (type == "elemental" and (gem.tags.fire or gem.tags.cold or gem.tags.lightning)) or (type == "aoe" and gem.tags.area) or (type == "trap or mine" and (gem.tags.trap or gem.tags.mine)) or ((type == "active skill" or type == "grants_active_skill" or type == "skill") and gem.tags.grants_active_skill and not gem.tags.support) or @@ -235,7 +235,7 @@ function calcLib.getGameIdFromGemName(gemName, dropVaal) end local gemId = data.gemForBaseName[gemName:lower()] if not gemId then return end - local gameId + local gameId if dropVaal and data.gems[gemId].vaalGem then gameId = data.gems[data.gemVaalGemIdForBaseGemId[gemId]].gameId else @@ -247,7 +247,7 @@ end --- Use getGameIdFromGemName to get gameId from the gemName and passed in type. Return true if they're the same and not nil --- @param gemName string --- @param type string ---- @param dropVaal boolean +--- @param dropVaal boolean --- @return boolean function calcLib.isGemIdSame(gemName, typeName, dropVaal) local gemNameId = calcLib.getGameIdFromGemName(gemName, dropVaal) diff --git a/src/Modules/CalcTriggers.lua b/src/Modules/CalcTriggers.lua index bff9f11cf4..2ed2a15437 100644 --- a/src/Modules/CalcTriggers.lua +++ b/src/Modules/CalcTriggers.lua @@ -912,7 +912,7 @@ local configTable = { end end, ["the hidden blade"] = function(env) - env.player.mainSkill.skillFlags.globalTrigger = true + env.player.mainSkill.skillFlags.globalTrigger = true env.player.mainSkill.skillData.triggerRateCapOverride = 2 if env.player.modDB:Flag(nil, "Condition:Phasing") then if env.player.breakdown then @@ -927,11 +927,11 @@ local configTable = { env.player.mainSkill.disableReason = "This skill is requires you to be phasing" end, ["replica eternity shroud"] = function(env) - env.player.mainSkill.skillFlags.globalTrigger = true + env.player.mainSkill.skillFlags.globalTrigger = true return {source = env.player.mainSkill} end, ["shroud of the lightless"] = function(env) - env.player.mainSkill.skillFlags.globalTrigger = true + env.player.mainSkill.skillFlags.globalTrigger = true return {source = env.player.mainSkill} end, ["limbsplit"] = function() @@ -1131,9 +1131,9 @@ local configTable = { ["nova"] = function(env) if env.minion and env.minion.mainSkill then return {triggerName = "Summon Holy Relic", - actor = env.minion, - triggeredSkills = {{ uuid = cacheSkillUUID(env.minion.mainSkill, env), cd = env.minion.mainSkill.skillData.cooldown}}, - triggerSkillCond = function(env, skill) return skill.skillTypes[SkillType.Attack] end} + actor = env.minion, + triggeredSkills = {{ uuid = cacheSkillUUID(env.minion.mainSkill, env), cd = env.minion.mainSkill.skillData.cooldown}}, + triggerSkillCond = function(env, skill) return skill.skillTypes[SkillType.Attack] end} end end, ["cast when damage taken"] = function(env) @@ -1152,7 +1152,7 @@ local configTable = { end end, ["cast when stunned"] = function(env) - env.player.mainSkill.skillFlags.globalTrigger = true + env.player.mainSkill.skillFlags.globalTrigger = true return {triggerChance = env.player.mainSkill.skillData.chanceToTriggerOnStun, source = env.player.mainSkill} end, @@ -1241,11 +1241,11 @@ local configTable = { end} end, ["tempest shield"] = function(env) - env.player.mainSkill.skillFlags.globalTrigger = true + env.player.mainSkill.skillFlags.globalTrigger = true return {source = env.player.mainSkill} end, ["shattershard"] = function(env) - env.player.mainSkill.skillFlags.globalTrigger = true + 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}) @@ -1292,7 +1292,7 @@ local configTable = { end end, ["cast on death"] = function(env) - env.player.mainSkill.skillFlags.globalTrigger = true + env.player.mainSkill.skillFlags.globalTrigger = true env.player.mainSkill.skillData.triggered = true env.player.mainSkill.infoMessage = env.player.mainSkill.activeEffect.grantedEffect.name .. " Triggered on Death" end, @@ -1476,17 +1476,17 @@ function calcs.triggers(env, actor) local awakenedTriggerNameLower = triggerNameLower and triggerNameLower:gsub("^awakened ", "") local uniqueNameLower = uniqueName and uniqueName:lower() local config = skillNameLower and configTable[skillNameLower] and configTable[skillNameLower](env) - config = config or triggerNameLower and configTable[triggerNameLower] and configTable[triggerNameLower](env) - config = config or awakenedTriggerNameLower and configTable[awakenedTriggerNameLower] and configTable[awakenedTriggerNameLower](env) - config = config or uniqueNameLower and configTable[uniqueNameLower] and configTable[uniqueNameLower](env) + config = config or triggerNameLower and configTable[triggerNameLower] and configTable[triggerNameLower](env) + config = config or awakenedTriggerNameLower and configTable[awakenedTriggerNameLower] and configTable[awakenedTriggerNameLower](env) + config = config or uniqueNameLower and configTable[uniqueNameLower] and configTable[uniqueNameLower](env) if config then - config.actor = config.actor or actor + config.actor = config.actor or actor config.triggerName = config.triggerName or triggerName or skillName or uniqueName config.triggerChance = config.triggerChance or (actor.mainSkill.activeEffect.srcInstance and actor.mainSkill.activeEffect.srcInstance.triggerChance) local triggerHandler = config.customHandler or defaultTriggerHandler - triggerHandler(env, config) + triggerHandler(env, config) else actor.mainSkill.skillData.triggered = nil - end + end end end diff --git a/src/Modules/Calcs.lua b/src/Modules/Calcs.lua index 222daf5c5b..83c095c14a 100644 --- a/src/Modules/Calcs.lua +++ b/src/Modules/Calcs.lua @@ -99,7 +99,7 @@ local function getCalculator(build, fullInit, modFunc) -- Call function to make modifications to the environment modFunc(env, ...) - + -- Run calculation pass calcs.perform(env) fullDPS = calcs.calcFullDPS(build, "CALCULATOR", {}, { cachedPlayerDB = cachedPlayerDB, cachedEnemyDB = cachedEnemyDB, cachedMinionDB = cachedMinionDB, env = nil}) @@ -108,7 +108,7 @@ local function getCalculator(build, fullInit, modFunc) env.player.output.FullDotDPS = fullDPS.TotalDotDPS return env.player.output - end, baseOutput + end, baseOutput end -- Get fast calculator for adding tree node modifiers @@ -135,7 +135,7 @@ function calcs.getMiscCalculator(build) local env, cachedPlayerDB, cachedEnemyDB, cachedMinionDB = calcs.initEnv(build, "CALCULATOR", override) calcs.perform(env) if (useFullDPS ~= false or build.viewMode == "TREE") and usedFullDPS then - -- prevent upcoming calculation from using Cached Data and thus forcing it to re-calculate new FullDPS roll-up + -- prevent upcoming calculation from using Cached Data and thus forcing it to re-calculate new FullDPS roll-up -- without this, FullDPS increase/decrease when for node/item/gem comparison would be all 0 as it would be comparing -- A with A (due to cache reuse) instead of A with B local fullDPS = calcs.calcFullDPS(build, "CALCULATOR", override, { cachedPlayerDB = cachedPlayerDB, cachedEnemyDB = cachedEnemyDB, cachedMinionDB = cachedMinionDB, env = nil}) @@ -198,7 +198,7 @@ function calcs.calcFullDPS(build, mode, override, specEnv) local igniteSource = "" local burningGroundSource = "" local causticGroundSource = "" - + for _, activeSkill in ipairs(fullEnv.player.activeSkillList) do if activeSkill.socketGroup and activeSkill.socketGroup.includeInFullDPS then local activeSkillCount, enabled = getActiveSkillCount(activeSkill) @@ -462,7 +462,7 @@ function calcs.buildOutput(build, mode) end end end - + output.ExtraPoints = env.modDB:Sum("BASE", nil, "ExtraPoints") local specCfg = { @@ -525,7 +525,7 @@ function calcs.buildOutput(build, mode) end local function addModTags(actor, mod) addTo(env.modsUsed, mod.name, mod) - + -- Imply enemy conditionals based on damage type -- Needed to preemptively show config options for elemental ailments for dmgType, conditions in pairs({["[fi][ig][rn][ei]t?e?"] = {"Ignited", "Burning"}, ["[cf][or][le][de]z?e?"] = {"Frozen"}}) do @@ -535,7 +535,7 @@ function calcs.buildOutput(build, mode) end end end - + for _, tag in ipairs(mod) do addTo(env.tagTypesUsed, tag.type, mod) if tag.type == "IgnoreCond" then diff --git a/src/Modules/Common.lua b/src/Modules/Common.lua index 3132480edd..c3ef60ee43 100644 --- a/src/Modules/Common.lua +++ b/src/Modules/Common.lua @@ -225,7 +225,7 @@ function convertUTF8to16(text, offset) else t_insert(out, "?\z") end - else + else t_insert(out, "?\z") end end @@ -842,9 +842,9 @@ function stringify(thing) end -- Class function to split a string on a single character (??) separator. - -- returns a list of fields, not including the separator. - -- Will return the first field as blank if the first character of the string is the separator - -- Separator defaults to colon +-- returns a list of fields, not including the separator. +-- Will return the first field as blank if the first character of the string is the separator +-- Separator defaults to colon function string:split(sep) -- Initially from http://lua-users.org/wiki/SplitJoin -- function will ignore duplicate separators diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index 58d9ac9bc5..c793cd7cac 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -1494,7 +1494,7 @@ Huge sets the radius to 11. { var = "conditionHaveArborix", type = "check", label = "Do you have Iron Reflexes?", ifFlag = "Condition:HaveArborix", tooltip = "This option is specific to Arborix.",apply = function(val, modList, enemyModList) modList:NewMod("Condition:HaveIronReflexes", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) modList:NewMod("Keystone", "LIST", "Iron Reflexes", "Config") - end }, + end }, { var = "conditionHaveAugyre", type = "list", label = "Augyre rotating buff:", ifFlag = "Condition:HaveAugyre", list = {{val="EleOverload",label="Elemental Overload"},{val="ResTechnique",label="Resolute Technique"}}, tooltip = "This option is specific to Augyre.", apply = function(val, modList, enemyModList) if val == "EleOverload" then modList:NewMod("Condition:HaveElementalOverload", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) @@ -1503,7 +1503,7 @@ Huge sets the radius to 11. modList:NewMod("Condition:HaveResoluteTechnique", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) modList:NewMod("Keystone", "LIST", "Resolute Technique", "Config") end - end }, + end }, { var = "conditionHaveVulconus", type = "check", label = "Do you have Avatar Of Fire?", ifFlag = "Condition:HaveVulconus", tooltip = "This option is specific to Vulconus.", apply = function(val, modList, enemyModList) modList:NewMod("Condition:HaveAvatarOfFire", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) modList:NewMod("Keystone", "LIST", "Avatar of Fire", "Config") @@ -2053,7 +2053,7 @@ Huge sets the radius to 11. build.configTab.varControls['enemyColdDamage']:SetPlaceholder(defaultDamage, true) build.configTab.varControls['enemyFireDamage']:SetPlaceholder(defaultDamage, true) build.configTab.varControls['enemyChaosDamage']:SetPlaceholder(defaultDamage, true) - + local rollRangeMult = m_min(m_max(build.configTab.input['enemyDamageRollRange'] or build.configTab.varControls['enemyDamageRollRange'].placeholder, 0), 100) for damageType, damageMult in pairs(bossData.DamageMultipliers) do if isUber and bossData.UberDamageMultiplier then @@ -2068,7 +2068,7 @@ Huge sets the radius to 11. build.configTab.varControls['enemyLightningPen']:SetPlaceholder(defaultPen, true) build.configTab.varControls['enemyColdPen']:SetPlaceholder(defaultPen, true) build.configTab.varControls['enemyFirePen']:SetPlaceholder(defaultPen, true) - + if bossData.DamagePenetrations then for penType, pen in pairs(bossData.DamagePenetrations) do if isUber and bossData.UberDamagePenetrations and bossData.UberDamagePenetrations[penType] then @@ -2078,13 +2078,13 @@ Huge sets the radius to 11. end end end - + if bossData.DamageType then build.configTab.varControls['enemyDamageType']:SelByValue(bossData.DamageType, "val") build.configTab.input['enemyDamageType'] = bossData.DamageType end build.configTab.varControls['enemyDamageType'].enabled = false - + if isUber and bossData.UberSpeed then build.configTab.varControls['enemySpeed']:SetPlaceholder(bossData.UberSpeed, true) elseif bossData.speed then @@ -2093,7 +2093,7 @@ Huge sets the radius to 11. if bossData.critChance then build.configTab.varControls['enemyCritChance']:SetPlaceholder(bossData.critChance, true) end - + modList:NewMod("BossSkillActive", "FLAG", true, "Config") -- boss specific mods @@ -2145,7 +2145,7 @@ Huge sets the radius to 11. { var = "enemyFireDamage", type = "countAllowZero", label = "Enemy Skill ^xB97123Fire Damage:"}, { var = "enemyFirePen", type = "countAllowZero", label = "Enemy Skill ^xB97123Fire Pen:"}, { var = "enemyChaosDamage", type = "countAllowZero", label = "Enemy Skill ^xD02090Chaos Damage:"}, - + -- Section: Custom mods { section = "Custom Modifiers", col = 1 }, { var = "customMods", type = "text", label = "", doNotHighlight = true, resizable = true, diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index 5d183d14c4..b802cd3783 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -590,7 +590,7 @@ do end end end - end + end end data.essences = LoadModule("Data/Essence") data.veiledMods = LoadModule("Data/ModVeiled") @@ -805,10 +805,10 @@ if not data.nodeIDList.size and launch.devMode then end -- Load bosses -do +do data.bosses = { } LoadModule("Data/Bosses", data.bosses) - + local count, uberCount = 0, 0 local armourTotal, evasionTotal = 0, 0 local uberArmourTotal, uberEvasionTotal = 0, 0 @@ -951,43 +951,43 @@ end local toAddGems = { } for gemId, gem in pairs(data.gems) do - gem.name = sanitiseText(gem.name) - setupGem(gem, gemId) - local loc, _ = gemId:find('Vaal') + gem.name = sanitiseText(gem.name) + setupGem(gem, gemId) + local loc, _ = gemId:find('Vaal') if loc then data.gemGrantedEffectIdForVaalGemId[gem.secondaryGrantedEffectId] = gemId for otherGemId, otherGem in pairs(data.gems) do if otherGem.grantedEffectId == gem.secondaryGrantedEffectId then - data.gemVaalGemIdForBaseGemId[gemId] = otherGemId + data.gemVaalGemIdForBaseGemId[gemId] = otherGemId break end end end - for _, alt in ipairs{"AltX", "AltY"} do - if loc and data.skills[gem.secondaryGrantedEffectId..alt] then + for _, alt in ipairs{"AltX", "AltY"} do + if loc and data.skills[gem.secondaryGrantedEffectId..alt] then data.gemGrantedEffectIdForVaalGemId[gem.secondaryGrantedEffectId..alt] = gemId..alt data.gemVaalGemIdForBaseGemId[gemId..alt] = data.gemVaalGemIdForBaseGemId[gemId]..alt - local newGem = { name, gameId, variantId, grantedEffectId, secondaryGrantedEffectId, vaalGem, tags = {}, tagString, reqStr, reqDex, reqInt, naturalMaxLevel } + local newGem = { name, gameId, variantId, grantedEffectId, secondaryGrantedEffectId, vaalGem, tags = {}, tagString, reqStr, reqDex, reqInt, naturalMaxLevel } -- Hybrid gems (e.g. Vaal gems) use the display name of the active skill e.g. Vaal Summon Skeletons of Sorcery - newGem.name = "Vaal " .. data.skills[gem.secondaryGrantedEffectId..alt].baseTypeName - newGem.gameId = gem.gameId - newGem.variantId = gem.variantId..alt - newGem.grantedEffectId = gem.grantedEffectId - newGem.secondaryGrantedEffectId = gem.secondaryGrantedEffectId..alt - newGem.vaalGem = gem.vaalGem - newGem.tags = copyTable(gem.tags) - newGem.tagString = gem.tagString - newGem.reqStr = gem.reqStr - newGem.reqDex = gem.reqDex - newGem.reqInt = gem.reqInt - newGem.naturalMaxLevel = gem.naturalMaxLevel - setupGem(newGem, gemId..alt) - toAddGems[gemId..alt] = newGem - end - end + newGem.name = "Vaal " .. data.skills[gem.secondaryGrantedEffectId..alt].baseTypeName + newGem.gameId = gem.gameId + newGem.variantId = gem.variantId..alt + newGem.grantedEffectId = gem.grantedEffectId + newGem.secondaryGrantedEffectId = gem.secondaryGrantedEffectId..alt + newGem.vaalGem = gem.vaalGem + newGem.tags = copyTable(gem.tags) + newGem.tagString = gem.tagString + newGem.reqStr = gem.reqStr + newGem.reqDex = gem.reqDex + newGem.reqInt = gem.reqInt + newGem.naturalMaxLevel = gem.naturalMaxLevel + setupGem(newGem, gemId..alt) + toAddGems[gemId..alt] = newGem + end + end end for id, gem in pairs(toAddGems) do - data.gems[id] = gem + data.gems[id] = gem end -- Load minions diff --git a/src/Modules/DataLegionLookUpTableHelper.lua b/src/Modules/DataLegionLookUpTableHelper.lua index cf9cf29a63..552f219318 100644 --- a/src/Modules/DataLegionLookUpTableHelper.lua +++ b/src/Modules/DataLegionLookUpTableHelper.lua @@ -178,8 +178,8 @@ local function generateLUT(jewelType) end --]] - -- this doesn't rebuilt the list with the correct sizes, likely an issue with lua indexing from 1 instead of 0, but cbf debugging so just generated the index mapping in c# - -- is disabled on the data side atm, needs to be setup correctly if we ever setup generation on the LUA side +-- this doesn't rebuild the list with the correct sizes, likely an issue with lua indexing from 1 instead of 0, but cbf debugging so just generated the index mapping in c# +-- is disabled on the data side atm, needs to be setup correctly if we ever setup generation on the LUA side local function repairLUTs() ConPrintf("Error NodeIndexMapping file empty") local nodeIDList = { } @@ -224,7 +224,7 @@ local function repairLUTs() ConPrintf("csv found") local nodeData = compressedFile:read("*a") compressedFile:close() - + tempIndList = {} nodeIDList["size"] = 0 nodeIDList["sizeNotable"] = 0 @@ -245,8 +245,8 @@ local function repairLUTs() nodeIDList["size"] = nodeIDList["size"] - 2 ConPrintf(nodeIDList["sizeNotable"]) ConPrintf(nodeIDList["size"]) - - + + local seedSize = data.timelessJewelSeedMax[1] - data.timelessJewelSeedMin[1] + 1 local sizeOffset = nodeIDList.size * seedSize data.timelessJewelLUTs[1] = {} @@ -264,7 +264,7 @@ local function repairLUTs() end nodeIDList[nodeID] = { index = nodeIndex, size = count } end - + local file = assert(io.open("Data/TimelessJewelData/NodeIndexMapping.lua", "wb+")) file:write("nodeIDList = { }\n") file:write("nodeIDList[\"size\"] = " .. tostring(nodeIDList["size"]) .. "\n") @@ -288,7 +288,7 @@ local function readLUT(seed, nodeID, jewelType) else assert(data.timelessJewelLUTs[jewelType].data, "Error occurred loading Timeless Jewel data") end - -- "Elegant Hubris" + -- "Elegant Hubris" if jewelType == 5 then seed = seed / 20 end diff --git a/src/Modules/Main.lua b/src/Modules/Main.lua index d807c5796c..f800e3cab4 100644 --- a/src/Modules/Main.lua +++ b/src/Modules/Main.lua @@ -455,7 +455,7 @@ function main:OnFrame() SetDrawColor(0, 0, 0) DrawImage(nil, par + 500, 200, 2, 750) DrawImage(nil, 500, par + 200, 759, 2)]] - + if self.inputEvents and not itemLib.wiki.triggered then for _, event in ipairs(self.inputEvents) do if event.type == "KeyUp" and event.key == "F1" then @@ -887,7 +887,7 @@ function main:OpenOptionsPopup() "The default value is " .. tostring(defaultColorCodes.NEGATIVE:gsub('^(^)', '0')) .. ".\nIf updating while inside a build, please re-load the build after saving." nextRow() - + controls.colorHighlight = new("EditControl", { "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, currentY, 100, 18 }, tostring(self.colorHighlight:gsub('^(^)', '0')), nil, nil, 8, function(buf) local match = string.match(buf, "0x%x+") if match and #match == 8 then @@ -908,7 +908,7 @@ function main:OpenOptionsPopup() controls.edgeSearchHighlight = new("CheckBoxControl", { "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, currentY, 20}, "^7Show search circles at viewport edge", function(state) self.edgeSearchHighlight = state end) - + nextRow() controls.showPublicBuilds = new("CheckBoxControl", { "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, currentY, 20 }, "^7Show Latest/Trending builds:", function(state) self.showPublicBuilds = state @@ -974,21 +974,21 @@ function main:OpenOptionsPopup() self.slotOnlyTooltips = state end) controls.slotOnlyTooltips.state = self.slotOnlyTooltips - + nextRow() controls.notSupportedModTooltips = new("CheckBoxControl", { "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, currentY, 20 }, "^7Show tooltip for unsupported mods :", function(state) self.notSupportedModTooltips = state end) controls.notSupportedModTooltips.tooltipText = "Show ^8(Not supported in PoB yet) ^7next to unsupported mods" controls.notSupportedModTooltips.state = self.notSupportedModTooltips - + nextRow() controls.invertSliderScrollDirection = new("CheckBoxControl", { "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, currentY, 20 }, "^7Invert slider scroll direction:", function(state) self.invertSliderScrollDirection = state end) controls.invertSliderScrollDirection.tooltipText = "Default scroll direction is:\nScroll Up = Move right\nScroll Down = Move left" controls.invertSliderScrollDirection.state = self.invertSliderScrollDirection - + if launch.devMode then nextRow() controls.disableDevAutoSave = new("CheckBoxControl", { "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, currentY, 20 }, "^7Disable Dev AutoSave:", function(state) diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 33d59c0c0e..cd386e58c0 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -2414,7 +2414,7 @@ local specialModList = { ["non%-unique jewels cause increases and reductions to other damage types in a (%a+) radius to be transformed to apply to (%a+) damage"] = function(_, radius, dmgType) return { mod("ExtraJewelFunc", "LIST", {radius = firstToUpper(radius), type = "Other", func = function(node, out, data) -- Ignore Timeless Jewels - if node and not node.conqueredBy then + if node and not node.conqueredBy then getSimpleConv({ "PhysicalDamage","FireDamage","ColdDamage","LightningDamage","ChaosDamage","ElementalDamage" }, (dmgType:gsub("^%l", string.upper)).."Damage", "INC", true)(node, out, data) end end}, {type = "ItemCondition", itemSlot = "{SlotName}", rarityCond = "UNIQUE", neg = true}), @@ -2638,7 +2638,7 @@ local specialModList = { mod("Speed", "INC", num, { type = "SkillType", skillType = SkillType.Retaliation }), mod("WarcrySpeed", "INC", num, nil, 0, KeywordFlag.Warcry, { type = "SkillType", skillType = SkillType.Retaliation }), } end, - -- Guardian + -- Guardian ["grants armour equal to (%d+)%% of your reserved life to you and nearby allies"] = function(num) return { mod("GrantReservedLifeAsAura", "LIST", { mod = mod("Armour", "BASE", num / 100) }) } end, ["grants armour equal to (%d+)%% of your reserved mana to you and nearby allies"] = function(num) return { mod("GrantReservedManaAsAura", "LIST", { mod = mod("Armour", "BASE", num / 100) }) } end, ["grants maximum energy shield equal to (%d+)%% of your reserved mana to you and nearby allies"] = function(num) return { mod("GrantReservedManaAsAura", "LIST", { mod = mod("EnergyShield", "BASE", num / 100) }) } end, @@ -2796,7 +2796,7 @@ local specialModList = { } end, -- Warden ["prevent %+(%d+)%% of suppressed spell damage per bark below maximum"] = function(num) return { - mod("SpellSuppressionEffect", "BASE", num, { type = "Multiplier", var = "MissingBarkskinStacks" }) + mod("SpellSuppressionEffect", "BASE", num, { type = "Multiplier", var = "MissingBarkskinStacks" }) } end, ["hits that would ignite instead scorch"] = { flag("IgniteCanScorch"), flag("CannotIgnite") }, ["you can inflict an additional scorch on each enemy"] = { flag("ScorchCanStack"), mod("ScorchStacksMax", "BASE", 1) }, @@ -2965,10 +2965,10 @@ local specialModList = { ["attack skills gain (%d+)%% of physical damage as extra fire damage per socketed red gem"] = function(num) return { mod("SocketProperty", "LIST", { value = mod("PhysicalDamageGainAsFire", "BASE", num, nil, ModFlag.Attack) }, { type = "SocketedIn", slotName = "{SlotName}", keyword = "strength", sockets = {1,2,3,4,5,6} }) } end, ["you have vaal pact while all socketed gems are red"] = { mod("GroupProperty", "LIST", { value = mod("Keystone", "LIST", "Vaal Pact") }, { type = "SocketedIn", slotName = "{SlotName}", socketColor = "R", sockets = "all" }) }, -- Mahuxotl's Machination Steel Kite Shield - ["everlasting sacrifice"] = { + ["everlasting sacrifice"] = { flag("Condition:EverlastingSacrifice") }, - -- Self hit dmg + -- Self hit dmg ["take (%d+) (.+) damage when you ignite an enemy"] = function(dmg, _, dmgType) return { mod("EyeOfInnocenceSelfDamage", "LIST", {baseDamage = dmg, damageType = dmgType}) } end, @@ -3582,12 +3582,12 @@ local specialModList = { ["y?o?u?r? ?chance to suppress spell damage is unlucky"] = { flag("SpellSuppressionChanceIsUnlucky") }, ["prevent %+(%d+)%% of suppressed spell damage"] = function(num) return { mod("SpellSuppressionEffect", "BASE", num) } end, ["prevent %+(%d+)%% of suppressed spell damage per hit suppressed recently"] = function(num) return { - mod("SpellSuppressionEffect", "BASE", num, { type = "Multiplier", var = "HitsSuppressedRecently" }) + mod("SpellSuppressionEffect", "BASE", num, { type = "Multiplier", var = "HitsSuppressedRecently" }) } end, ["inflict fire, cold and lightning exposure on enemies when you suppress their spell damage"] = { - mod("EnemyModifier", "LIST", { mod = mod("FireExposure", "BASE", -10) }, { type = "Condition", var = "Effective" }, { type = "Condition", var = "SuppressedRecently" }), - mod("EnemyModifier", "LIST", { mod = mod("ColdExposure", "BASE", -10) }, { type = "Condition", var = "Effective" }, { type = "Condition", var = "SuppressedRecently" }), - mod("EnemyModifier", "LIST", { mod = mod("LightningExposure", "BASE", -10) }, { type = "Condition", var = "Effective" }, { type = "Condition", var = "SuppressedRecently" }) + mod("EnemyModifier", "LIST", { mod = mod("FireExposure", "BASE", -10) }, { type = "Condition", var = "Effective" }, { type = "Condition", var = "SuppressedRecently" }), + mod("EnemyModifier", "LIST", { mod = mod("ColdExposure", "BASE", -10) }, { type = "Condition", var = "Effective" }, { type = "Condition", var = "SuppressedRecently" }), + mod("EnemyModifier", "LIST", { mod = mod("LightningExposure", "BASE", -10) }, { type = "Condition", var = "Effective" }, { type = "Condition", var = "SuppressedRecently" }) }, ["critical strike chance is increased by chance to suppress spell damage"] = { flag("CritChanceIncreasedBySpellSuppressChance") }, ["you take (%d+)%% reduced extra damage from suppressed critical strikes"] = function(num) return { mod("ReduceSuppressedCritExtraDamage", "BASE", num) } end, @@ -3955,7 +3955,7 @@ local specialModList = { ["(%d+)%% chance to throw up to (%d+) additional traps?"] = function(chance, _, num) return { mod("TrapThrowCount", "BASE", tonumber(num) * tonumber(chance) / 100.0) } end, ["throw an additional mine"] = { mod("MineThrowCount", "BASE", 1) }, ["(%d+)%% chance to throw up to (%d+) additional mines?"] = function(chance, _, num) return { mod("MineThrowCount", "BASE", tonumber(num) * tonumber(chance) / 100.0) } end, - ["(%d+)%% chance to throw up to (%d+) additional traps? or mines?"] = function(chance, _, num) return { + ["(%d+)%% chance to throw up to (%d+) additional traps? or mines?"] = function(chance, _, num) return { mod("TrapThrowCount", "BASE", tonumber(num) * tonumber(chance) / 100.0), mod("MineThrowCount", "BASE", tonumber(num) * tonumber(chance) / 100.0), } end, @@ -4332,8 +4332,8 @@ local specialModList = { ["(%d+)%% of damage taken while frozen recouped as life"] = function(num) return { mod("LifeRecoup", "BASE", num, { type = "Condition", var = "Frozen" }) } end, ["recoup effects instead occur over 3 seconds"] = { flag("3SecondRecoup") }, ["life recoup effects instead occur over 3 seconds"] = { flag("3SecondLifeRecoup") }, - ["([%d%.]+)%% of physical damage prevented from hits in the past (%d+) seconds is regenerated as life per second"] = function(num, _, duration) return { - mod("PhysicalDamageMitigatedLifePseudoRecoup", "BASE", num * duration), + ["([%d%.]+)%% of physical damage prevented from hits in the past (%d+) seconds is regenerated as life per second"] = function(num, _, duration) return { + mod("PhysicalDamageMitigatedLifePseudoRecoup", "BASE", num * duration), mod("PhysicalDamageMitigatedLifePseudoRecoupDuration", "BASE", duration), } end, ["([%d%.]+)%% of physical damage prevented from hits recently is regenerated as energy shield per second"] = function(num) return { mod("PhysicalDamageMitigatedEnergyShieldPseudoRecoup", "BASE", num * 4) } end, @@ -4349,7 +4349,7 @@ local specialModList = { ["cannot gain energy shield"] = { flag("CannotGainEnergyShield") }, ["cannot gain life"] = { flag("CannotGainLife") }, ["cannot gain mana"] = { flag("CannotGainMana") }, - ["cannot recover life other than from leech"] = { + ["cannot recover life other than from leech"] = { flag("CannotRecoverLifeOutsideLeech"), flag("NoLifeRegen"), }, @@ -4790,7 +4790,7 @@ local specialModList = { ["cannot recover energy shield to above evasion rating"] = { flag("EvasionESRecoveryCap") }, ["warcries exert (%d+) additional attacks?"] = function(num) return { mod("ExtraExertedAttacks", "BASE", num) } end, ["battlemage's cry exerts (%d+) additional attack"] = function(num) return { mod("BattlemageExertedAttacks", "BASE", num) } end, - ["rallying cry exerts (%d+) additional attack"] = function(num) return { mod("RallyingExertedAttacks", "BASE", num) } end, + ["rallying cry exerts (%d+) additional attack"] = function(num) return { mod("RallyingExertedAttacks", "BASE", num) } end, ["warcries have (%d+)%% chance to exert (%d+) additional attacks?"] = function(num, _, var) return { mod("ExtraExertedAttacks", "BASE", (num*var/100)) } end, ["skills deal (%d+)%% more damage for each warcry exerting them"] = function(num) return { mod("EchoesExertAverageIncrease", "MORE", num, nil) } end, ["iron will"] = { flag("IronWill") }, @@ -4816,8 +4816,8 @@ local specialModList = { ["spell skills deal no damage"] = { flag("DealNoDamage", { type = "SkillType", skillType = SkillType.Spell }) }, ["attacks have blood magic"] = { flag("CostLifeInsteadOfMana", nil, ModFlag.Attack) }, ["attacks cost life instead of mana"] = { flag("CostLifeInsteadOfMana", nil, ModFlag.Attack) }, - ["attack skills cost life instead of (%d+)%% of mana cost"] = function(num) return { - mod("HybridManaAndLifeCost_Life", "BASE", num, nil, ModFlag.Attack) + ["attack skills cost life instead of (%d+)%% of mana cost"] = function(num) return { + mod("HybridManaAndLifeCost_Life", "BASE", num, nil, ModFlag.Attack) } end, ["skills cost energy shield instead of mana or life"] = { flag("CostESInsteadOfManaOrLife") }, ["spells have an additional life cost equal to (%d+)%% of your maximum life"] = function(num) return { @@ -4848,9 +4848,9 @@ local specialModList = { ["reserves (%d+)%% of life"] = function(num) return { mod("ExtraLifeReserved", "BASE", num) } end, ["(%d+)%% of cold damage taken as lightning"] = function(num) return { mod("ColdDamageTakenAsLightning", "BASE", num) } end, ["(%d+)%% of fire damage taken as lightning"] = function(num) return { mod("FireDamageTakenAsLightning", "BASE", num) } end, - ["(%d+)%% of fire and lightning damage from hits taken as cold damage during effect"] = function(num) return { - mod("FireDamageFromHitsTakenAsCold", "BASE", num, { type = "Condition", var = "UsingFlask" }), - mod("LightningDamageFromHitsTakenAsCold", "BASE", num, { type = "Condition", var = "UsingFlask" }), + ["(%d+)%% of fire and lightning damage from hits taken as cold damage during effect"] = function(num) return { + mod("FireDamageFromHitsTakenAsCold", "BASE", num, { type = "Condition", var = "UsingFlask" }), + mod("LightningDamageFromHitsTakenAsCold", "BASE", num, { type = "Condition", var = "UsingFlask" }), } end, ["items and gems have (%d+)%% reduced attribute requirements"] = function(num) return { mod("GlobalAttributeRequirements", "INC", -num) } end, ["items and gems have (%d+)%% increased attribute requirements"] = function(num) return { mod("GlobalAttributeRequirements", "INC", num) } end, @@ -5084,11 +5084,11 @@ local specialModList = { ["you count as dual wielding while you are unencumbered"] = { flag("Condition:DualWielding", { type = "Condition", var = "Unencumbered" }) }, ["dual wielding does not inherently grant chance to block attack damage"] = { flag("Condition:NoInherentBlock") }, ["inherent attack speed bonus from dual wielding is doubled while wielding two claws"] = { - flag("Condition:DoubledInherentDualWieldingSpeed", { type = "Condition", var = "DualWieldingClaws" }) + flag("Condition:DoubledInherentDualWieldingSpeed", { type = "Condition", var = "DualWieldingClaws" }) }, ["inherent bonuses from dual wielding are doubled"] = { - flag("Condition:DoubledInherentDualWieldingSpeed"), - flag("Condition:DoubledInherentDualWieldingBlock") + flag("Condition:DoubledInherentDualWieldingSpeed"), + flag("Condition:DoubledInherentDualWieldingBlock") }, ["(%d+)%% reduced enemy chance to block sword attacks"] = function(num) return { mod("reduceEnemyBlock", "BASE", num, nil, ModFlag.Sword) } end, ["you do not inherently take less damage for having fortification"] = { flag("Condition:NoFortificationMitigation") }, @@ -5139,9 +5139,9 @@ local specialModList = { ["skills gain a base energy shield cost equal to (%d+)%% of base mana cost"] = function(num) return { mod("ManaCostAsEnergyShieldCost", "BASE", num), } end, - ["skills cost life instead of (%d+)%% of mana cost"] = function(num) return { - mod("HybridManaAndLifeCost_Life", "BASE", num), - } end, + ["skills cost life instead of (%d+)%% of mana cost"] = function(num) return { + mod("HybridManaAndLifeCost_Life", "BASE", num), + } end, ["(%d+)%% increased cost of arc and crackling lance"] = function(num) return { mod("Cost", "INC", num, { type = "SkillName", skillNameList = { "Arc", "Crackling Lance" }, includeTransfigured = true }), } end, diff --git a/src/Modules/ModTools.lua b/src/Modules/ModTools.lua index a7810bc9fb..5440447701 100644 --- a/src/Modules/ModTools.lua +++ b/src/Modules/ModTools.lua @@ -211,7 +211,7 @@ function modLib.formatMod(mod) end function modLib.formatSourceMod(mod) - return s_format("%s|%s|%s", modLib.formatValue(mod.value), mod.source, modLib.formatModParams(mod)) + return s_format("%s|%s|%s", modLib.formatValue(mod.value), mod.source, modLib.formatModParams(mod)) end function modLib.setSource(mod, source) diff --git a/src/Modules/StatDescriber.lua b/src/Modules/StatDescriber.lua index 1c676f199a..5fe7e11f46 100644 --- a/src/Modules/StatDescriber.lua +++ b/src/Modules/StatDescriber.lua @@ -28,7 +28,7 @@ local function getScope(scopeName) end end -local function matchLimit(lang, val) +local function matchLimit(lang, val) for _, desc in ipairs(lang) do local match = true for i, limit in ipairs(desc.limit) do @@ -140,11 +140,11 @@ local function applySpecial(val, spec) elseif spec.k == "milliseconds_to_seconds_2dp" then val[spec.v].min = round(val[spec.v].min / 1000, 2) val[spec.v].max = round(val[spec.v].max / 1000, 2) - val[spec.v].fmt = "g" + val[spec.v].fmt = "g" elseif spec.k == "milliseconds_to_seconds_2dp_if_required" then val[spec.v].min = round(val[spec.v].min / 1000, 2) val[spec.v].max = round(val[spec.v].max / 1000, 2) - val[spec.v].fmt = "g" + val[spec.v].fmt = "g" elseif spec.k == "deciseconds_to_seconds" then val[spec.v].min = val[spec.v].min / 10 val[spec.v].max = val[spec.v].max / 10 @@ -190,7 +190,7 @@ return function(stats, scopeName) -- Figure out which descriptions we need, and identify them by the first stat that they describe local describeStats = { } for s, v in pairs(stats) do - if (type(v) == "number" and v ~= 0) or (type(v) == "table" and (v.min ~= 0 or v.max ~= 0)) then + if (type(v) == "number" and v ~= 0) or (type(v) == "table" and (v.min ~= 0 or v.max ~= 0)) then for depth, scope in ipairs(rootScope.scopeList) do if scope[s] then local descriptor = scope[scope[s]] @@ -234,21 +234,21 @@ return function(stats, scopeName) for _, spec in ipairs(desc) do applySpecial(val, spec) end - local statDesc = desc.text:gsub("{(%d)}", function(n) + local statDesc = desc.text:gsub("{(%d)}", function(n) local v = val[tonumber(n)+1] if v.min == v.max then return s_format("%"..v.fmt, v.min) else return s_format("(%"..v.fmt.."-%"..v.fmt..")", v.min, v.max) end - end):gsub("{}", function() + end):gsub("{}", function() local v = val[1] if v.min == v.max then return s_format("%"..v.fmt, v.min) else return s_format("(%"..v.fmt.."-%"..v.fmt..")", v.min, v.max) end - end):gsub("{:%+?d}", function() + end):gsub("{:%+?d}", function() local v = val[1] if v.min == v.max then return s_format("%"..v.fmt, v.min) diff --git a/src/UpdateCheck.lua b/src/UpdateCheck.lua index d3bc6ebabd..c57d40b673 100644 --- a/src/UpdateCheck.lua +++ b/src/UpdateCheck.lua @@ -29,7 +29,7 @@ local function downloadFileText(source, file) easy:setopt(curl.OPT_PROXY, proxyURL) end easy:setopt_writefunction(function(data) - text = text..data + text = text..data return true end) local _, error = easy:perform() @@ -191,7 +191,7 @@ for name, data in pairs(localFiles) do table.insert(deleteFiles, data) end end - + if #updateFiles == 0 and #deleteFiles == 0 then ConPrintf("No update available.") return "none" @@ -284,7 +284,7 @@ for part, platforms in pairs(remoteSources) do end for name, data in pairs(remoteFiles) do table.insert(localManXML, { elem = "File", attrib = { name = data.name, sha1 = data.sha1, part = data.part, platform = data.platform } }) -end +end xml.SaveXMLFile(localManXML, scriptPath.."/Update/manifest.xml") -- Build list of operations to apply the update