diff --git a/Classes/ConfigTab.lua b/Classes/ConfigTab.lua index a8dc2696..4cdcc93d 100644 --- a/Classes/ConfigTab.lua +++ b/Classes/ConfigTab.lua @@ -7,9 +7,10 @@ local launch, main = ... local t_insert = table.insert local m_max = math.max +local m_floor = math.floor local varList = { - { section = "General" }, + { section = "General", col = 1 }, { var = "enemyLevel", type = "number", label = "Enemy Level:", tooltip = "This overrides the default enemy level used to estimate your hit and evade chances.\nThe default level is your character level, capped at 84, which is the same value\nused in-game to calculate the stats on the character sheet." }, { var = "conditionLowLife", type = "check", label = "Are you always on Low Life?", ifCond = "LowLife", tooltip = "You will automatically be considered to be on Low Life if you have at least 65% life reserved,\nbut you can use this option to force it if necessary.", apply = function(val, modList, enemyModList) modList:NewMod("Condition:LowLife", "FLAG", true, "Config") @@ -21,7 +22,125 @@ local varList = { modList:NewMod("Condition:FullEnergyShield", "FLAG", true, "Config") end }, { var = "igniteMode", type = "list", label = "Ignite calculation mode:", tooltip = "Controls how the base damage for ignite is calculated:\nAverage Damage: Ignite is based on the average damage dealt, factoring in crits and non-crits.\nCrit Damage: Ignite is based on crit damage only.", list = {{val="AVERAGE",label="Average Damage"},{val="CRIT",label="Crit Damage"}} }, - { section = "When In Combat" }, + { section = "Skill Options", col = 2 }, + { label = "Raise Spectre:", ifSkill = "Raise Spectre" }, + { var = "raiseSpectreSpectreLevel", type = "number", label = "Spectre Level:", ifSkill = "Raise Spectre", tooltip = "Sets the level of the raised spectre.\nThe default level is the level requirement of the Raise Spectre skill.", apply = function(val, modList, enemyModList) + modList:NewMod("SkillData", "LIST", { key = "minionLevel", value = val }, "Config", { type = "SkillName", skillName = "Raise Spectre" }) + end }, + { var = "raiseSpectreEnableCurses", type = "check", label = "Enable curses:", ifSkill = "Raise Spectre", tooltip = "Enable any curse skills that your spectres have.", apply = function(val, modList, enemyModList) + modList:NewMod("SkillData", "LIST", { key = "enable", value = true }, "Config", { type = "SkillType", skillType = SkillType.Curse }, { type = "SkillName", skillName = "Raise Spectre", summonSkill = true }) + end }, + { var = "raiseSpectreBladeVortexBladeCount", type = "number", label = "Blade Vortex blade count:", ifSkillList = {"DemonModularBladeVortexSpectre","GhostPirateBladeVortexSpectre"}, tooltip = "Sets the blade count for Blade Vortex skills used by spectres.\nDefault is 1; maximum is 5.", apply = function(val, modList, enemyModList) + modList:NewMod("SkillData", "LIST", { key = "dpsMultiplier", value = val }, "Config", { type = "SkillId", skillId = "DemonModularBladeVortexSpectre" }) + modList:NewMod("SkillData", "LIST", { key = "dpsMultiplier", value = val }, "Config", { type = "SkillId", skillId = "GhostPirateBladeVortexSpectre" }) + end }, + { label = "Summon Lightning Golem:", ifSkill = "Summon Lightning Golem" }, + { var = "summonLightningGolemEnableWrath", type = "check", label = "Enable Wrath Aura:", ifSkill = "Summon Lightning Golem", apply = function(val, modList, enemyModList) + modList:NewMod("SkillData", "LIST", { key = "enable", value = true }, "Config", { type = "SkillId", skillId = "LightningGolemWrath" }) + end }, +--[[ { section = "Map Modifiers and Player Debuffs", col = 2 }, + { label = "Player is cursed by:" }, + { var = "playerCursedWithAssassinsMark", type = "number", label = "Assassin's Mark:", tooltip = "Sets the level of Assassin's Mark to apply to the player.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Assassin's Mark", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithConductivity", type = "number", label = "Conductivity:", tooltip = "Sets the level of Conductivity to apply to the player.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Conductivity", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithElementalWeakness", type = "number", label = "Elemental Weakness:", tooltip = "Sets the level of Elemental Weakness to apply to the player.\nIn mid tier maps, 'of Elemental Weakness' applies level 10.\nIn high tier maps, 'of Elemental Weakness' applies level 15.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Elemental Weakness", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithEnfeeble", type = "number", label = "Enfeeble:", tooltip = "Sets the level of Enfeeble to apply to the player.\nIn mid tier maps, 'of Enfeeblement' applies level 10.\nIn high tier maps, 'of Enfeeblement' applies level 15.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Enfeeble", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithFlammability", type = "number", label = "Flammability:", tooltip = "Sets the level of Flammability to apply to the player.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Flammability", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithFrostbite", type = "number", label = "Frostbite:", tooltip = "Sets the level of Frostbite to apply to the player.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Frostbite", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithPoachersMark", type = "number", label = "Poacher's Mark:", tooltip = "Sets the level of Poacher's Mark to apply to the player.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Poacher's Mark", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithProjectileWeakness", type = "number", label = "Projectile Weakness:", tooltip = "Sets the level of Projectile Weakness to apply to the player.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Projectile Weakness", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithTemporalChains", type = "number", label = "Temporal Chains:", tooltip = "Sets the level of Temporal Chains to apply to the player.\nIn mid tier maps, 'of Temporal Chains' applies level 10.\nIn high tier maps, 'of Temporal Chains' applies level 15.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Temporal Chains", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithVulnerability", type = "number", label = "Vulnerability:", tooltip = "Sets the level of Vulnerability to apply to the player.\nIn mid tier maps, 'of Vulnerability' applies level 10.\nIn high tier maps, 'of Vulnerability' applies level 15.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Vulnerability", level = val, applyToPlayer = true }) + end }, + { var = "playerCursedWithWarlordsMark", type = "number", label = "Warlord's Mark:", tooltip = "Sets the level of Warlord's Mark to apply to the player.", apply = function(val, modList, enemyModList) + modList:NewMod("ExtraCurse", "LIST", { name = "Warlord's Mark", level = val, applyToPlayer = true }) + end }, + { label = "Map Prefix Modifiers:" }, + { var = "enemyHasPhysicalReduction", type = "list", label = "Enemy Physical Damage reduction:", list = {{val=0,label="No"},{val=20,label="20% (Low tier)"},{val=30,label="30% (Mid tier)"},{val=40,label="40% (High tier)"}}, apply = function(val, modList, enemyModList) + enemyModList:NewMod("PhysicalDamageReduction", "INC", val, "Config") + end }, + { var = "enemyHasLessCurseEffectOnSelf", type = "list", label = "Less effect of Curses on Enemy:", list = {{val=0,label="No"},{val=25,label="25% (Low tier)"},{val=40,label="40% (Mid tier)"},{val=60,label="60% (High tier)"}}, apply = function(val, modList, enemyModList) + if val ~= 0 then + enemyModList:NewMod("CurseEffectOnSelf", "MORE", -val, "Config") + end + end }, + { label = "Map Suffix Modifiers:" }, + { var = "playerHasElementalEquilibrium", type = "check", label = "Player has Elemental Equilibrium?", apply = function(val, modList, enemyModList) + modList:NewMod("Keystone", "LIST", "Elemental Equilibrium", "Config") + end }, + { var = "playerHasPointBlank", type = "check", label = "Player has Point Blank?", apply = function(val, modList, enemyModList) + modList:NewMod("Keystone", "LIST", "Point Blank", "Config") + end }, + { var = "playerGainsReducedFlaskCharges", type = "list", label = "Gains reduced Flask Charges:", list = {{val=0,label="No"},{val=30,label="30% (Low tier)"},{val=40,label="40% (Mid tier)"},{val=50,label="50% (High tier)"}}, apply = function(val, modList, enemyModList) + if val ~= 0 then + modList:NewMod("FlaskChargesGained", "INC", -val, "Config") + end + end }, + { var = "playerHasLessAreaOfEffect", type = "list", label = "Less Area of Effect:", list = {{val=0,label="No"},{val=15,label="15% (Low tier)"},{val=20,label="20% (Mid tier)"},{val=25,label="25% (High tier)"}}, apply = function(val, modList, enemyModList) + if val ~= 0 then + modList:NewMod("AreaOfEffect", "MORE", -val, "Config") + end + end }, + { var = "enemyHasIncreasedAccuracy", type = "list", label = "Unlucky Dodge/Enemy has inc. Acc.:", list = {{val=0,label="No"},{val=30,label="30% (Low tier)"},{val=40,label="40% (Mid tier)"},{val=50,label="50% (High tier)"}}, apply = function(val, modList, enemyModList) + if val ~= 0 then + modList:NewMod("DodgeChanceIsUnlucky", "FLAG", true, "Config") + enemyModList:NewMod("Accuracy", "INC", val, "Config") + end + end }, + { var = "playerHasLessArmourandBlock", type = "list", label = "Reduced Block Chance/less Armour:", list = {{val=0,label="No"},{val="LOW",label="20%/20% (Low tier)"},{val="MID",label="30%/25% (Mid tier)"},{val="HIGH",label="40%/30% (High tier)"}}, apply = function(val, modList, enemyModList) + local map = { ["LOW"] = {20,20}, ["MID"] = {30,25}, ["HIGH"] = {40,30} } + if map[val] then + modList:NewMod("BlockChance", "INC", -map[val][1], "Config") + modList:NewMod("Armour", "LESS", -map[val][2], "Config") + end + end }, + { var = "playerHasLessLifeESRecovery", type = "list", label = "Less Recovery of Life & Energy Shield:", list = {{val=0,label="No"},{val=20,label="20% (Low tier)"},{val=40,label="40% (Mid tier)"},{val=60,label="60% (High tier)"}}, apply = function(val, modList, enemyModList) + if val ~= 0 then + modList:NewMod("LifeRecovery", "MORE", -val, "Config") + modList:NewMod("EnergyShieldRecovery", "MORE", -val, "Config") + end + end }, + { var = "enemyTakesReducedExtraCritDamage", type = "number", label = "Enemy takes red. Extra Crit Damage:", tooltip = "Low tier: 25-30%\nMid tier: 31-35%\nHigh tier: 36-40%" , apply = function(val, modList, enemyModList) + if val ~= 0 then + enemyModList:NewMod("SelfCritMultiplier", "INC", -val, "Config") + end + end }, + { var = "playerHasMinusMaxResist", type = "number", label = "-X% maximum Resistances:", tooltip = "Mid tier: 5-8%\nHigh tier: 9-12%", apply = function(val, modList, enemyModList) + if val ~= 0 then + modList:NewMod("FireResistMax", "BASE", -val, "Config") + modList:NewMod("ColdResistMax", "BASE", -val, "Config") + modList:NewMod("LightningResistMax", "BASE", -val, "Config") + modList:NewMod("ChaosResistMax", "BASE", -val, "Config") + end + end }, + { var = "playerCannotRegenLifeManaEnergyShield", type = "check", label = "Cannot Regen Life/Mana/ES?", apply = function(val, modList, enemyModList) + modList:NewMod("NoLifeRegen", "FLAG", true, "Config") + modList:NewMod("NoEnergyShieldRegen", "FLAG", true, "Config") + modList:NewMod("NoManaRegen", "FLAG", true, "Config") + end }, + { var = "playerCannotLeech", type = "check", label = "Cannot Leech Life/Mana?", apply = function(val, modList, enemyModList) + enemyModList:NewMod("CannotLeechLifeFromSelf", "FLAG", true, "Config") + enemyModList:NewMod("CannotLeechManaFromSelf", "FLAG", true, "Config") + end },]] + { section = "When In Combat", col = 1 }, { var = "usePowerCharges", type = "check", label = "Do you use Power Charges?", apply = function(val, modList, enemyModList) modList:NewMod("UsePowerCharges", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) end }, @@ -154,7 +273,7 @@ local varList = { { var = "conditionBlockedHitFromUniqueEnemyRecently", type = "check", label = "Blocked hit from a Unique Recently?", ifNode = 63490, apply = function(val, modList, enemyModList) modList:NewMod("Condition:BlockedHitFromUniqueEnemyRecently", "FLAG", true, "Config", { type = "Condition", var = "Combat" }) end }, - { section = "For Effective DPS" }, + { section = "For Effective DPS", col = 1 }, { var = "critChanceLucky", type = "check", label = "Is your Crit Chance Lucky?", apply = function(val, modList, enemyModList) modList:NewMod("CritChanceLucky", "FLAG", true, "Config", { type = "Condition", var = "Effective" }) end }, @@ -257,22 +376,6 @@ local varList = { enemyModList:NewMod("Condition:HitByLightningDamage", "FLAG", true, "Config") end }, { var = "EEIgnoreHitDamage", type = "check", label = "Ignore Skill Hit Damage?", ifNode = 39085, tooltip = "This option prevents EE from being reset by the hit damage of your main skill." }, - { section = "Skill Options" }, - { label = "Raise Spectre:", ifSkill = "Raise Spectre" }, - { var = "raiseSpectreSpectreLevel", type = "number", label = "Spectre Level:", ifSkill = "Raise Spectre", tooltip = "Sets the level of the raised spectre.\nThe default level is the level requirement of the Raise Spectre skill.", apply = function(val, modList, enemyModList) - modList:NewMod("SkillData", "LIST", { key = "minionLevel", value = val }, "Config", { type = "SkillName", skillName = "Raise Spectre" }) - end }, - { var = "raiseSpectreEnableCurses", type = "check", label = "Enable curses:", ifSkill = "Raise Spectre", tooltip = "Enable any curse skills that your spectres have.", apply = function(val, modList, enemyModList) - modList:NewMod("SkillData", "LIST", { key = "enable", value = true }, "Config", { type = "SkillType", skillType = SkillType.Curse }, { type = "SkillName", skillName = "Raise Spectre", summonSkill = true }) - end }, - { var = "raiseSpectreBladeVortexBladeCount", type = "number", label = "Blade Vortex blade count:", ifSkillList = {"DemonModularBladeVortexSpectre","GhostPirateBladeVortexSpectre"}, tooltip = "Sets the blade count for Blade Vortex skills used by spectres.\nDefault is 1; maximum is 5.", apply = function(val, modList, enemyModList) - modList:NewMod("SkillData", "LIST", { key = "dpsMultiplier", value = val }, "Config", { type = "SkillId", skillId = "DemonModularBladeVortexSpectre" }) - modList:NewMod("SkillData", "LIST", { key = "dpsMultiplier", value = val }, "Config", { type = "SkillId", skillId = "GhostPirateBladeVortexSpectre" }) - end }, - { label = "Summon Lightning Golem:", ifSkill = "Summon Lightning Golem" }, - { var = "summonLightningGolemEnableWrath", type = "check", label = "Enable Wrath Aura:", ifSkill = "Summon Lightning Golem", apply = function(val, modList, enemyModList) - modList:NewMod("SkillData", "LIST", { key = "enable", value = true }, "Config", { type = "SkillId", skillId = "LightningGolemWrath" }) - end }, } local ConfigTabClass = common.NewClass("ConfigTab", "UndoHandler", "ControlHost", "Control", function(self, build) @@ -294,6 +397,7 @@ local ConfigTabClass = common.NewClass("ConfigTab", "UndoHandler", "ControlHost" if varData.section then lastSection = common.New("SectionControl", {"TOPLEFT",self,"TOPLEFT"}, 0, 0, 360, 0, varData.section) lastSection.varControlList = { } + lastSection.col = varData.col lastSection.height = function(self) local height = 20 for _, varControl in pairs(self.varControlList) do @@ -392,6 +496,8 @@ local ConfigTabClass = common.NewClass("ConfigTab", "UndoHandler", "ControlHost" t_insert(lastSection.varControlList, control) end end + + self.controls.scrollBar = common.New("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, 0, 0, 18, 0, 50, "VERTICAL", true) end) function ConfigTabClass:Load(xml, fileName) @@ -464,7 +570,18 @@ function ConfigTabClass:Draw(viewPort, inputEvents) end self:ProcessControlsInput(inputEvents, viewPort) + for id, event in ipairs(inputEvents) do + if event.type == "KeyUp" then + if event.key == "WHEELDOWN" then + self.controls.scrollBar:Scroll(1) + elseif event.key == "WHEELUP" then + self.controls.scrollBar:Scroll(-1) + end + end + end + local maxCol = m_floor((viewPort.width - 10) / 370) + local maxColY = 0 local colY = { } for _, section in ipairs(self.sectionList) do local y = 14 @@ -481,20 +598,32 @@ function ConfigTabClass:Draw(viewPort, inputEvents) section.shown = doShow if doShow then local width, height = section:GetSize() - local col = 1 - while true do - colY[col] = colY[col] or 18 - if colY[col] + height + 10 <= viewPort.height then - break + local col + if section.col and (colY[section.col] or 0) + height + 28 <= viewPort.height then + col = section.col + else + col = 1 + for c = 2, maxCol do + colY[c] = colY[c] or 0 + if colY[c] < colY[col] then + col = c + end end - col = col + 1 end - section.x = 10 + (col - 1) * 360 - section.y = colY[col] + colY[col] = colY[col] or 0 + section.x = 10 + (col - 1) * 370 + section.y = colY[col] + 18 colY[col] = colY[col] + height + 18 + maxColY = m_max(maxColY, colY[col]) end end + self.controls.scrollBar.height = viewPort.height + self.controls.scrollBar:SetContentDimension(maxColY + 10, viewPort.height) + for _, section in ipairs(self.sectionList) do + section.y = section.y - self.controls.scrollBar.offset + end + main:DrawBackground(viewPort) self:DrawControls(viewPort) diff --git a/Classes/ItemsTab.lua b/Classes/ItemsTab.lua index 064ec740..f2592ee6 100644 --- a/Classes/ItemsTab.lua +++ b/Classes/ItemsTab.lua @@ -885,7 +885,7 @@ function ItemsTabClass:AddItemTooltip(item, slot, dbMode) for index, modLine in pairs(item.modLines) do if not modLine.buff and (not modLine.variantList or modLine.variantList[item.variant]) then local line = (not dbMode and modLine.range and itemLib.applyRange(modLine.line, modLine.range)) or modLine.line - if not line:match("^%+?0[^%.]") and not line:match(" 0%-0 ") and not line:match(" 0 to 0 ") then -- Hack to hide 0-value modifiers + if not line:match("^%+?0%%? ") and not line:match(" %+?0%%? ") and not line:match(" 0%-0 ") and not line:match(" 0 to 0 ") then -- Hack to hide 0-value modifiers local colorCode if modLine.extra then colorCode = data.colorCodes.UNSUPPORTED diff --git a/Modules/CalcDefence.lua b/Modules/CalcDefence.lua index b9c0cc6b..adba0225 100644 --- a/Modules/CalcDefence.lua +++ b/Modules/CalcDefence.lua @@ -198,36 +198,42 @@ function calcs.defence(env, actor) end -- Mana, life and energy shield regen - do + if modDB:Sum("FLAG", nil, "NoManaRegen") then + output.ManaRegen = 0 + else output.ManaRegen = round((modDB:Sum("BASE", nil, "ManaRegen") + output.Mana * modDB:Sum("BASE", nil, "ManaRegenPercent") / 100) * calcLib.mod(modDB, nil, "ManaRegen", "ManaRecovery"), 1) if breakdown then breakdown.ManaRegen = breakdown.simple(nil, nil, output.ManaRegen, "ManaRegen", "ManaRecovery") end - if modDB:Sum("FLAG", nil, "NoLifeRegen") then - output.LifeRegen = 0 - elseif modDB:Sum("FLAG", nil, "ZealotsOath") then - output.LifeRegen = 0 - local lifeBase = modDB:Sum("BASE", nil, "LifeRegen") - if lifeBase > 0 then - modDB:NewMod("EnergyShieldRegen", "BASE", lifeBase, "Zealot's Oath") - end - local lifePercent = modDB:Sum("BASE", nil, "LifeRegenPercent") - if lifePercent > 0 then - modDB:NewMod("EnergyShieldRegenPercent", "BASE", lifePercent, "Zealot's Oath") - end - else - local lifeBase = modDB:Sum("BASE", nil, "LifeRegen") - local lifePercent = modDB:Sum("BASE", nil, "LifeRegenPercent") - if lifePercent > 0 then - lifeBase = lifeBase + output.Life * lifePercent / 100 - end - if lifeBase > 0 then - output.LifeRegen = lifeBase * calcLib.mod(modDB, nil, "LifeRecovery") - output.LifeRegenPercent = round(output.LifeRegen / output.Life * 100, 1) - else - output.LifeRegen = 0 - end + end + if modDB:Sum("FLAG", nil, "NoLifeRegen") then + output.LifeRegen = 0 + elseif modDB:Sum("FLAG", nil, "ZealotsOath") then + output.LifeRegen = 0 + local lifeBase = modDB:Sum("BASE", nil, "LifeRegen") + if lifeBase > 0 then + modDB:NewMod("EnergyShieldRegen", "BASE", lifeBase, "Zealot's Oath") end + local lifePercent = modDB:Sum("BASE", nil, "LifeRegenPercent") + if lifePercent > 0 then + modDB:NewMod("EnergyShieldRegenPercent", "BASE", lifePercent, "Zealot's Oath") + end + else + local lifeBase = modDB:Sum("BASE", nil, "LifeRegen") + local lifePercent = modDB:Sum("BASE", nil, "LifeRegenPercent") + if lifePercent > 0 then + lifeBase = lifeBase + output.Life * lifePercent / 100 + end + if lifeBase > 0 then + output.LifeRegen = lifeBase * calcLib.mod(modDB, nil, "LifeRecovery") + output.LifeRegenPercent = round(output.LifeRegen / output.Life * 100, 1) + else + output.LifeRegen = 0 + end + end + if modDB:Sum("FLAG", nil, "NoEnergyShieldRegen") then + output.EnergyShieldRegen = 0 + else local esBase = modDB:Sum("BASE", nil, "EnergyShieldRegen") local esPercent = modDB:Sum("BASE", nil, "EnergyShieldRegenPercent") if esPercent > 0 then @@ -289,6 +295,10 @@ function calcs.defence(env, actor) end output.AttackDodgeChance = m_min(modDB:Sum("BASE", nil, "AttackDodgeChance"), 75) output.SpellDodgeChance = m_min(modDB:Sum("BASE", nil, "SpellDodgeChance"), 75) + if modDB:Sum("FLAG", nil, "DodgeChanceIsUnlucky") then + output.AttackDodgeChance = output.AttackDodgeChance / 100 * output.AttackDodgeChance + output.SpellDodgeChance = output.SpellDodgeChance / 100 * output.SpellDodgeChance + end local stunChance = 100 - modDB:Sum("BASE", nil, "AvoidStun") if output.EnergyShield > output.Life * 2 then stunChance = stunChance * 0.5 diff --git a/Modules/CalcOffence.lua b/Modules/CalcOffence.lua index 7ca44034..79b64bd0 100644 --- a/Modules/CalcOffence.lua +++ b/Modules/CalcOffence.lua @@ -716,20 +716,20 @@ function calcs.offence(env, actor) t_insert(breakdown[damageType], s_format("= %d to %d", min, max)) end if skillFlags.mine or skillFlags.trap or skillFlags.totem then - if not modDB:Sum("FLAG", cfg, "CannotLeechLife") then + if not modDB:Sum("FLAG", cfg, "CannotLeechLife") and not enemyDB:Sum("FLAG", nil, "CannotLeechLifeFromSelf") then local lifeLeech = modDB:Sum("BASE", cfg, "DamageLifeLeechToPlayer") if lifeLeech > 0 then lifeLeechTotal = lifeLeechTotal + (min + max) / 2 * lifeLeech / 100 end end else - if not modDB:Sum("FLAG", cfg, "CannotLeechLife") then + if not modDB:Sum("FLAG", cfg, "CannotLeechLife") and not enemyDB:Sum("FLAG", nil, "CannotLeechLifeFromSelf") then local lifeLeech = modDB:Sum("BASE", cfg, "DamageLeech", "DamageLifeLeech", damageType.."DamageLifeLeech", isElemental[damageType] and "ElementalDamageLifeLeech" or nil) + enemyDB:Sum("BASE", nil, "SelfDamageLifeLeech") / 100 if lifeLeech > 0 then lifeLeechTotal = lifeLeechTotal + (min + max) / 2 * lifeLeech / 100 end end - if not modDB:Sum("FLAG", cfg, "CannotLeechMana") then + if not modDB:Sum("FLAG", cfg, "CannotLeechMana") and not enemyDB:Sum("FLAG", nil, "CannotLeechManaFromSelf") then local manaLeech = modDB:Sum("BASE", cfg, "DamageLeech", "DamageManaLeech", damageType.."DamageManaLeech", isElemental[damageType] and "ElementalDamageManaLeech" or nil) + enemyDB:Sum("BASE", nil, "SelfDamageManaLeech") / 100 if manaLeech > 0 then manaLeechTotal = manaLeechTotal + (min + max) / 2 * manaLeech / 100 @@ -801,9 +801,9 @@ function calcs.offence(env, actor) output.EnergyShieldOnHit = 0 output.ManaOnHit = 0 else - output.LifeOnHit = modDB:Sum("BASE", skillCfg, "LifeOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfLifeOnHit") - output.EnergyShieldOnHit = modDB:Sum("BASE", skillCfg, "EnergyShieldOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfEnergyShieldOnHit") - output.ManaOnHit = modDB:Sum("BASE", skillCfg, "ManaOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfManaOnHit") + output.LifeOnHit = (modDB:Sum("BASE", skillCfg, "LifeOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfLifeOnHit")) * calcLib.mod(modDB, nil, "LifeRecovery") + output.EnergyShieldOnHit = (modDB:Sum("BASE", skillCfg, "EnergyShieldOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfEnergyShieldOnHit")) * calcLib.mod(modDB, nil, "EnergyShieldRecovery") + output.ManaOnHit = (modDB:Sum("BASE", skillCfg, "ManaOnHit") + enemyDB:Sum("BASE", skillCfg, "SelfManaOnHit")) * calcLib.mod(modDB, nil, "ManaRecovery") end output.LifeOnHitRate = output.LifeOnHit * hitRate output.EnergyShieldOnHitRate = output.EnergyShieldOnHit * hitRate @@ -895,18 +895,18 @@ function calcs.offence(env, actor) output.LifeLeechRate = 0 output.LifeLeechPerHit = 0 output.EnergyShieldLeechInstanceRate = output.EnergyShield * 0.02 * calcLib.mod(modDB, skillCfg, "LifeLeechRate") - output.EnergyShieldLeechRate = output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.EnergyShieldLeechInstanceRate, output.MaxEnergyShieldLeechRate) - output.EnergyShieldLeechPerHit = m_min(output.EnergyShieldLeechInstanceRate, output.MaxEnergyShieldLeechRate) * output.LifeLeechDuration + output.LifeLeechInstant + output.EnergyShieldLeechRate = (output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.EnergyShieldLeechInstanceRate, output.MaxEnergyShieldLeechRate)) * calcLib.mod(modDB, nil, "EnergyShieldRecovery") + output.EnergyShieldLeechPerHit = (m_min(output.EnergyShieldLeechInstanceRate, output.MaxEnergyShieldLeechRate) * output.LifeLeechDuration + output.LifeLeechInstant) * calcLib.mod(modDB, nil, "EnergyShieldRecovery") else output.LifeLeechInstanceRate = output.Life * 0.02 * calcLib.mod(modDB, skillCfg, "LifeLeechRate") - output.LifeLeechRate = output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.LifeLeechInstanceRate, output.MaxLifeLeechRate) - output.LifeLeechPerHit = m_min(output.LifeLeechInstanceRate, output.MaxLifeLeechRate) * output.LifeLeechDuration + output.LifeLeechInstant + output.LifeLeechRate = (output.LifeLeechInstantRate + m_min(output.LifeLeechInstances * output.LifeLeechInstanceRate, output.MaxLifeLeechRate)) * calcLib.mod(modDB, nil, "LifeRecovery") + output.LifeLeechPerHit = (m_min(output.LifeLeechInstanceRate, output.MaxLifeLeechRate) * output.LifeLeechDuration + output.LifeLeechInstant) * calcLib.mod(modDB, nil, "LifeRecovery") output.EnergyShieldLeechRate = 0 output.EnergyShieldLeechPerHit = 0 end output.ManaLeechInstanceRate = output.Mana * 0.02 * calcLib.mod(modDB, skillCfg, "ManaLeechRate") - output.ManaLeechRate = output.ManaLeechInstantRate + m_min(output.ManaLeechInstances * output.ManaLeechInstanceRate, output.MaxManaLeechRate) - output.ManaLeechPerHit = m_min(output.ManaLeechInstanceRate, output.MaxManaLeechRate) * output.ManaLeechDuration + output.ManaLeechInstant + output.ManaLeechRate = (output.ManaLeechInstantRate + m_min(output.ManaLeechInstances * output.ManaLeechInstanceRate, output.MaxManaLeechRate)) * calcLib.mod(modDB, nil, "ManaRecovery") + output.ManaLeechPerHit = (m_min(output.ManaLeechInstanceRate, output.MaxManaLeechRate) * output.ManaLeechDuration + output.ManaLeechInstant) * calcLib.mod(modDB, nil, "ManaRecovery") skillFlags.leechES = output.EnergyShieldLeechRate > 0 skillFlags.leechLife = output.LifeLeechRate > 0 skillFlags.leechMana = output.ManaLeechRate > 0 diff --git a/Modules/CalcPerform.lua b/Modules/CalcPerform.lua index 31f7a30a..669cc0c5 100644 --- a/Modules/CalcPerform.lua +++ b/Modules/CalcPerform.lua @@ -239,12 +239,12 @@ local function doActorMisc(env, actor) -- Add misc buffs if env.mode_combat then - if condList["Onslaught"] then + if modDB:Sum("FLAG", nil, "Onslaught") then local effect = m_floor(20 * (1 + modDB:Sum("INC", nil, "OnslaughtEffect", "BuffEffect") / 100)) modDB:NewMod("Speed", "INC", effect, "Onslaught") modDB:NewMod("MovementSpeed", "INC", effect, "Onslaught") end - if condList["UnholyMight"] then + if modDB:Sum("FLAG", nil, "UnholyMight") then local effect = m_floor(30 * (1 + modDB:Sum("INC", nil, "BuffEffect") / 100)) modDB:NewMod("PhysicalDamageGainAsChaos", "BASE", effect, "Unholy Might") end @@ -575,11 +575,6 @@ function calcs.perform(env) -- Check for extra curses for _, value in ipairs(modDB:Sum("LIST", nil, "ExtraCurse")) do - local curse = { - name = value.name, - fromPlayer = true, - priority = 2, - } local gemModList = common.New("ModList") calcs.mergeGemMods(gemModList, { level = value.level, @@ -595,9 +590,20 @@ function calcs.perform(env) end end end - curse.modList = common.New("ModList") - curse.modList:ScaleAddList(curseModList, (1 + enemyDB:Sum("INC", nil, "CurseEffectOnSelf") / 100) * enemyDB:Sum("MORE", nil, "CurseEffectOnSelf")) - t_insert(curses, curse) + if value.applyToPlayer then + -- Sources for curses on the player don't usually respect any kind of limit, so there's little point bothering with slots + modDB.multipliers["CurseOnSelf"] = (modDB.multipliers["CurseOnSelf"] or 0) + 1 + modDB:ScaleAddList(curseModList, (1 + modDB:Sum("INC", nil, "CurseEffectOnSelf") / 100) * modDB:Sum("MORE", nil, "CurseEffectOnSelf")) + else + local curse = { + name = value.name, + fromPlayer = true, + priority = 2, + } + curse.modList = common.New("ModList") + curse.modList:ScaleAddList(curseModList, (1 + enemyDB:Sum("INC", nil, "CurseEffectOnSelf") / 100) * enemyDB:Sum("MORE", nil, "CurseEffectOnSelf")) + t_insert(curses, curse) + end end -- Assign curses to slots diff --git a/Modules/CalcSetup.lua b/Modules/CalcSetup.lua index 315d71b8..1dd03236 100644 --- a/Modules/CalcSetup.lua +++ b/Modules/CalcSetup.lua @@ -31,6 +31,8 @@ function calcs.initModDB(env, modDB) modDB:NewMod("HitChance", "MORE", -50, "Base", { type = "Condition", var = "Blinded" }) modDB:NewMod("MovementSpeed", "INC", -30, "Base", { type = "Condition", var = "Maimed" }) modDB:NewMod("Condition:Burning", "FLAG", true, "Base", { type = "Condition", var = "Ignited" }) + modDB:NewMod("Onslaught", "FLAG", true, "Base", { type = "Condition", var = "Onslaught" }) + modDB:NewMod("UnholyMight", "FLAG", true, "Base", { type = "Condition", var = "UnholyMight" }) modDB.conditions["Buffed"] = env.mode_buffs modDB.conditions["Combat"] = env.mode_combat modDB.conditions["Effective"] = env.mode_effective diff --git a/Modules/Calcs.lua b/Modules/Calcs.lua index 8d57e095..5f85d126 100644 --- a/Modules/Calcs.lua +++ b/Modules/Calcs.lua @@ -212,10 +212,10 @@ function calcs.buildOutput(build, mode) if output.EnduranceCharges > 0 then t_insert(combatList, s_format("%d Endurance Charges", output.EnduranceCharges)) end - if env.modDB.conditions.Onslaught then + if env.modDB:Sum("FLAG", nil, "Onslaught") then t_insert(combatList, "Onslaught") end - if env.modDB.conditions.UnholyMight then + if env.modDB:Sum("FLAG", nil, "UnholyMight") then t_insert(combatList, "Unholy Might") end for _, activeSkill in ipairs(env.activeSkillList) do @@ -252,10 +252,10 @@ function calcs.buildOutput(build, mode) if output.Minion.EnduranceCharges > 0 then t_insert(combatList, s_format("%d Endurance Charges", output.Minion.EnduranceCharges)) end - if env.minion.modDB.conditions.Onslaught then + if env.minion.modDB:Sum("FLAG", nil, "Onslaught") then t_insert(combatList, "Onslaught") end - if env.minion.modDB.conditions.UnholyMight then + if env.minion.modDB:Sum("FLAG", nil, "UnholyMight") then t_insert(combatList, "Unholy Might") end for _, activeSkill in ipairs(env.activeSkillList) do diff --git a/Modules/ModParser.lua b/Modules/ModParser.lua index 3098aedb..c27b9417 100644 --- a/Modules/ModParser.lua +++ b/Modules/ModParser.lua @@ -129,6 +129,7 @@ local modNameList = { ["to avoid being ignited"] = "AvoidIgnite", ["to avoid elemental status ailments"] = { "AvoidShock", "AvoidFrozen", "AvoidChilled", "AvoidIgnite" }, ["damage is taken from mana before life"] = "DamageTakenFromManaBeforeLife", + ["effect of curses on you"] = "CurseEffectOnSelf", -- Stun modifiers ["stun recovery"] = "StunRecovery", ["stun and block recovery"] = "StunRecovery", @@ -428,6 +429,7 @@ local modTagList = { ["for each rare item you have equipped"] = { tag = { type = "Multiplier", var = "RareItem" } }, ["for each unique item you have equipped"] = { tag = { type = "Multiplier", var = "UniqueItem" } }, ["per curse on enemy"] = { tag = { type = "Multiplier", var = "CurseOnEnemy" } }, + ["per curse on you"] = { tag = { type = "Multiplier", var = "CurseOnPlayer" } }, ["to you and allies"] = { }, -- Per stat ["per (%d+) strength"] = function(num) return { tag = { type = "PerStat", stat = "Str", div = num } } end, diff --git a/README.md b/README.md index 5dc0d05d..89b821d1 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,10 @@ Head over to the [Releases](https://github.com/Openarl/PathOfBuilding/releases) ![ss3](https://cloud.githubusercontent.com/assets/19189971/18089780/f0ff234a-6f04-11e6-8c88-6193fe59a5c4.png) ## Changelog +### 1.4.6 - 2017/04/20 + * Fixed bug introduced in 1.4.5 that prevented Onslaught and Unholy Might from applying correctly + * The minion modifiers on the jewel templates are now correctly hidden when their value is set to 0 + ### 1.4.5 - 2017/04/19 * Added support for Goatman Fire-raiser's Magma Orb skill * Demigod items and legacy (pre-1.2.0) quiver types can now be imported diff --git a/changelog.txt b/changelog.txt index 67bd6cf6..aac39b1e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +VERSION[1.4.6][2017/04/20] + * Fixed bug introduced in 1.4.5 that prevented Onslaught and Unholy Might from applying correctly + * The minion modifiers on the jewel templates are now correctly hidden when their value is set to 0 VERSION[1.4.5][2017/04/19] * Added support for Goatman Fire-raiser's Magma Orb skill * Demigod items and legacy (pre-1.2.0) quiver types can now be imported diff --git a/manifest.xml b/manifest.xml index dd6024af..fc8562f4 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,20 +1,20 @@ - + - + - + @@ -24,7 +24,7 @@ - + @@ -47,18 +47,18 @@ - - - - + + + + - + - +