diff --git a/src/Classes/ConfigTab.lua b/src/Classes/ConfigTab.lua index 2008815851..3af3b66f0b 100644 --- a/src/Classes/ConfigTab.lua +++ b/src/Classes/ConfigTab.lua @@ -251,35 +251,37 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont end end - local innerShown = control.shown - control.shown = function() - local shown = type(innerShown) == "boolean" and innerShown or innerShown() - return not shown and control.state ~= self:GetDefaultState(varData.var, type(control.state)) or shown - end - local innerLabel = control.label - control.label = function() - local shown = type(innerShown) == "boolean" and innerShown or innerShown() - if not shown and control.state ~= self:GetDefaultState(varData.var, type(control.state)) then - return "^1"..innerLabel + if not varData.hideIfInvalid then + local innerShown = control.shown + control.shown = function() + local shown = type(innerShown) == "boolean" and innerShown or innerShown() + return not shown and control.state ~= self:GetDefaultState(varData.var, type(control.state)) or shown end - return innerLabel - end - local innerTooltipFunc = control.tooltipFunc - control.tooltipFunc = function (tooltip, ...) - tooltip:Clear() - - if innerTooltipFunc then - innerTooltipFunc(tooltip, ...) - else - local tooltipText = control:GetProperty("tooltipText") - if tooltipText then - tooltip:AddLine(14, tooltipText) + local innerLabel = control.label + control.label = function() + local shown = type(innerShown) == "boolean" and innerShown or innerShown() + if not shown and control.state ~= self:GetDefaultState(varData.var, type(control.state)) then + return "^1"..innerLabel end + return innerLabel end + local innerTooltipFunc = control.tooltipFunc + control.tooltipFunc = function (tooltip, ...) + tooltip:Clear() - local shown = type(innerShown) == "boolean" and innerShown or innerShown() - if not shown and control.state ~= self:GetDefaultState(varData.var, type(control.state)) then - tooltip:AddLine(14, "^1This config option is conditional with missing source and is invalid.") + if innerTooltipFunc then + innerTooltipFunc(tooltip, ...) + else + local tooltipText = control:GetProperty("tooltipText") + if tooltipText then + tooltip:AddLine(14, tooltipText) + end + end + + local shown = type(innerShown) == "boolean" and innerShown or innerShown() + if not shown and control.state ~= self:GetDefaultState(varData.var, type(control.state)) then + tooltip:AddLine(14, "^1This config option is conditional with missing source and is invalid.") + end end end diff --git a/src/Data/BossSkills.lua b/src/Data/BossSkills.lua new file mode 100644 index 0000000000..296fcef5d8 --- /dev/null +++ b/src/Data/BossSkills.lua @@ -0,0 +1,105 @@ +-- This file is automatically generated, do not edit! +-- Path of Building +-- +-- Boss Skill Presets +-- Boss Skill data (c) Grinding Gear Games +-- +return { + ["Atziri Flameblast"] = { + DamageType = "Spell", + DamageMultipliers = { + Fire = { 57.29394377618, 0.2864697188809 } + }, + DamagePenetrations = { + FirePen = "" + }, + UberDamagePenetrations = { + FirePen = 10 + }, + speed = 12500, + UberSpeed = 25000, + critChance = 0, + earlierUber = true, + tooltip = "The Uber variant has 10 ^xB97123Fire^7 penetration (Applied on Pinnacle And Uber)" + }, + ["Shaper Ball"] = { + DamageType = "SpellProjectile", + DamageMultipliers = { + Cold = { 11.666076975909, 0.058330384879546 } + }, + DamagePenetrations = { + ColdPen = 25 + }, + UberDamagePenetrations = { + ColdPen = 40 + }, + speed = 1400, + tooltip = "Allocating Cosmic Wounds increases the penetration to 40% (Applied on Uber) and adds 2 projectiles" + }, + ["Shaper Slam"] = { + DamageType = "Melee", + DamageMultipliers = { + Physical = { 12.358683281257, 0.061793416406285 } + }, + UberDamageMultiplier = 1.6666666666667, + speed = 3510, + UberSpeed = 1755, + critChance = 0, + tooltip = "Cannot be Evaded. Allocating Cosmic Wounds increases Damage by a further 100% (Applied on Uber) and cannot be blocked or dodged" + }, + ["Sirus Meteor"] = { + DamageType = "Spell", + DamageMultipliers = { + Physical = { 11.2718900614, 0.056354278291738 }, + Lightning = { 11.2718900614, 0.056354278291738 }, + Fire = { 11.2718900614, 0.056354278291738 }, + Chaos = { 11.2718900614, 0.056354278291738 } + }, + UberDamageMultiplier = 1.52, + speed = 1500, + tooltip = "Earlier ones with less walls do less damage. Allocating The Perfect Storm increases Damage by a further 50% (Applied on Uber)" + }, + ["Exarch Ball"] = { + DamageType = "SpellProjectile", + DamageMultipliers = { + Fire = { 14.924946784635, 0.074624733923175 } + }, + speed = 1000, + critChance = 0, + tooltip = "Spawns 8-18 waves of balls depending on which fight and which ball phase" + }, + ["Eater Beam"] = { + DamageType = "Spell", + DamageMultipliers = { + Lightning = { 12.164923902598, 0.24329847805197 } + }, + speed = 2500, + tooltip = "Allocating Insatiable Appetite causes the beam to always shock for at least 30%" + }, + ["Maven Fireball"] = { + DamageType = "SpellProjectile", + DamageMultipliers = { + Fire = { 14.977416270256, 0.074887081351278 } + }, + UberDamageMultiplier = 2.0273275862069, + DamagePenetrations = { + FirePen = "" + }, + UberDamagePenetrations = { + FirePen = 30 + }, + speed = 3000, + tooltip = "Allocating Throw the Gauntlet increases Damage by a further 100% (Applied on Uber) and causes the fireball to have 30 ^xB97123Fire^7 penetration (Applied on Uber)" + }, + ["Maven MemoryGame"] = { + DamageType = "Melee", + DamageMultipliers = { + Lightning = { 34.763635149472, 0.17381817574736 }, + Cold = { 34.763635149472, 0.17381817574736 }, + Fire = { 34.763635149472, 0.17381817574736 } + }, + UberDamageMultiplier = 1.0086206896552, + speed = 7500, + tooltip = "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" + }, +} diff --git a/src/Export/Scripts/bossSkills.lua b/src/Export/Scripts/bossSkills.lua new file mode 100644 index 0000000000..edeeeb427f --- /dev/null +++ b/src/Export/Scripts/bossSkills.lua @@ -0,0 +1,443 @@ +local m_ceil = math.ceil +local m_min = math.min +local m_max = math.max + +local rarityDamageMult = { + Unique = (1 + dat("Mods"):GetRow("Id", "MonsterUnique5").Stat1Value[1] / 100), + UniqueAttack = (1 + dat("Mods"):GetRow("Id", "MonsterUnique5").Stat1Value[1] / 100) * (1 - dat("Mods"):GetRow("Id", "MonsterUnique8").Stat1Value[1] / 100) +} +local monsterBaseDamage = { 1.59, 4.9899997711182, 5.5599999427795, 6.1599998474121, 6.8099999427795, 7.5, 8.2299995422363, 9, 9.8199996948242, 10.699999809265, 11.619999885559, 12.60000038147, 13.640000343323, 14.739999771118, 15.909999847412, 17.139999389648, 18.450000762939, 19.829999923706, 21.290000915527, 22.840000152588, 24.469999313354, 26.190000534058, 28.010000228882, 29.940000534058, 31.959999084473, 34.110000610352, 36.360000610352, 38.75, 41.259998321533, 43.909999847412, 46.700000762939, 49.650001525879, 52.75, 56.009998321533, 59.450000762939, 63.080001831055, 66.889999389648, 70.910003662109, 75.129997253418, 79.580001831055, 84.26000213623, 89.180000305176, 94.349998474121, 99.800003051758, 105.51999664307, 111.5299987793, 117.86000061035, 124.5, 131.49000549316, 138.83000183105, 146.5299987793, 154.63000488281, 163.13999938965, 172.07000732422, 181.44999694824, 191.30000305176, 201.63000488281, 212.47999572754, 223.86999511719, 235.83000183105, 248.36999511719, 261.5299987793, 275.32998657227, 289.82000732422, 305.01000976562, 320.94000244141, 337.64999389648, 355.17999267578, 373.54998779297, 392.80999755859, 413.01000976562, 434.17999267578, 456.36999511719, 479.61999511719, 504, 529.53997802734, 556.29998779297, 584.34997558594, 613.72998046875, 644.5, 676.75, 710.52001953125, 745.89001464844, 782.94000244141, 821.72998046875, 862.35998535156, 904.90002441406, 949.44000244141, 996.07000732422, 1044.8900146484, 1096, 1149.5, 1205.5, 1264.1099853516, 1325.4499511719, 1389.6400146484, 1456.8199462891, 1527.1199951172, 1600.6800537109, 1677.6400146484, 1758.1700439453, } +local monsterMapDifficultyMult = {} +for row in dat("MonsterMapDifficulty"):Rows() do + monsterMapDifficultyMult[row.AreaLevel] = 1 + row.DamagePercentIncrease / 100 +end +local baseDamage = { + AtziriFlameblast = { index = 1, uberIndex = 2, oldMethod = true }, + AtlasBossAcceleratingProjectiles = { index = 1, uberIndex = 2, oldMethod = true }, + AtlasBossFlickerSlam = { index = 1, uberIndex = 2, oldMethod = true, attack = true }, + AtlasExileOrionCircleMazeBlast3 = { index = 4, uberIndex = 5 }, + CleansingFireWall = { index = 1, oldMethod = true }, + GSConsumeBossDisintegrateBeam = { index = 1, oldMethod = true }, + MavenSuperFireProjectileImpact = { index = 1, uberIndex = 2, oldMethod = true, mapBoss = true }, + MavenMemoryGame = { index = 1, oldMethod = true, mapBoss = true }, +} +local oldMethod = { + AtziriFlameblast = { Fire = { 1210.408, 0 } }, + AtlasBossAcceleratingProjectiles = { Cold = { 3358.0288, 0 } }, + AtlasBossFlickerSlam = { Physical = { 1769.847, 0 } }, + AtlasExileOrionCircleMazeBlast3 = { Physical = { 18154.481, 0 }, SkillUberDamageMult = 152 }, + CleansingFireWall = { Fire = { 3304.677, 20 } }, + GSConsumeBossDisintegrateBeam = { Lightning = { 3735.061, 50 } }, + MavenSuperFireProjectileImpact = { Fire = { 4955.383, 0 }, SkillUberDamageMult = 201 }, + MavenMemoryGame = { Physical = { 34505.376, 0 } }, +} + +-- exports and calculates the damage multipliers of the skill +-- min and max damage equal to damage dealt divided by base monster damage at that level +-- also provides the UberDamageMultiplier if the skill does more in uber form +local function calcSkillDamage(state) + local monsterLevel = 84 + local skill = state.skill + local boss = state.boss + local physConversions = { 1, 0, 0, 0, 0 } + for i, constStat in ipairs(skill.GrantedEffectStatSets.ConstantStats) do + if constStat.Id == "skill_physical_damage_%_to_convert_to_lightning" then + physConversions[2] = skill.GrantedEffectStatSets.ConstantStatsValues[i] + elseif constStat.Id == "skill_physical_damage_%_to_convert_to_cold" then + physConversions[3] = skill.GrantedEffectStatSets.ConstantStatsValues[i] + elseif constStat.Id == "skill_physical_damage_%_to_convert_to_fire" then + physConversions[4] = skill.GrantedEffectStatSets.ConstantStatsValues[i] + elseif constStat.Id == "skill_physical_damage_%_to_convert_to_chaos" then + physConversions[5] = skill.GrantedEffectStatSets.ConstantStatsValues[i] + end + end + local grantedId = skill.grantedId + if not baseDamage[grantedId] and baseDamage[skill.grantedId2] then + grantedId = skill.grantedId2 + end + local rarityType = baseDamage[grantedId].attack and (boss.rarity.."Attack") or boss.rarity + local ExtraDamageMult = { 1, 1 } + for i, levelIndex in ipairs({baseDamage[grantedId].index, baseDamage[grantedId].uberIndex}) do + local statsPerLevel = skill.statsPerLevel[levelIndex] + for j, additionalStat in ipairs(statsPerLevel.AdditionalStats) do + if additionalStat.Id == "active_skill_damage_+%_final" then + ExtraDamageMult[i] = 1 + statsPerLevel.AdditionalStatsValues[j] / 100 + break + end + end + end + if skill.stages then + local stageMulti = 1 + for i, constStat in ipairs(skill.GrantedEffectStatSets.ConstantStats) do + if constStat.Id == "charged_blast_spell_damage_+%_final_per_stack" then + stageMulti = skill.GrantedEffectStatSets.ConstantStatsValues[i] / 100 + break + end + end + ExtraDamageMult = { ExtraDamageMult[1] * (1 + stageMulti * (skill.stages - 1)), ExtraDamageMult[2] * (1 + stageMulti * (skill.stages - 1)) } + end + -- old method with hardcoded values (Still used for Shaper Slam) + if baseDamage[grantedId].oldMethod then + if oldMethod[grantedId].Physical then + local totalConversions = physConversions[2] + physConversions[3] + physConversions[4] + physConversions[5] + local conversionDivisor = m_max(totalConversions, 100) + physConversions = { m_max(1 - totalConversions / 100, 0), physConversions[2] / conversionDivisor, physConversions[3] / conversionDivisor, physConversions[4] / conversionDivisor, physConversions[5] / conversionDivisor } + end + local baseDamageMult = state.SkillExtraDamageMult * ExtraDamageMult[1] * boss.damageMult / 100 * (rarityDamageMult[rarityType] or 1) * (baseDamage[grantedId].mapBoss and monsterMapDifficultyMult[84] or 1) / (monsterBaseDamage[monsterLevel] or 1) + if oldMethod[grantedId].Physical and physConversions[1] ~= 0 then + local damageRange = (oldMethod[grantedId].Physical[2] == 0) and (boss.damageRange / 100) or oldMethod[grantedId].Physical[2] / 100 + local damageMult = oldMethod[grantedId].Physical[1] * physConversions[1] * baseDamageMult + state.DamageData["PhysicalDamageMultMin"], state.DamageData["PhysicalDamageMultMax"] = damageMult * ( 1 - damageRange ), damageMult * ( 1 + damageRange ) + end + for i, damageType in ipairs({"Lightning", "Cold", "Fire", "Chaos"}) do + if oldMethod[grantedId][damageType] or (oldMethod[grantedId].Physical and physConversions[i + 1] ~= 0) then + state.DamageData[damageType.."DamageMultMin"], state.DamageData[damageType.."DamageMultMax"] = 0, 0 + if oldMethod[grantedId][damageType] then + local damageRange = (oldMethod[grantedId][damageType][2] == 0) and (boss.damageRange / 100) or oldMethod[grantedId][damageType][2] / 100 + local damageMult = oldMethod[grantedId][damageType][1] * baseDamageMult + state.DamageData[damageType.."DamageMultMin"], state.DamageData[damageType.."DamageMultMax"] = damageMult * ( 1 - damageRange ), damageMult * ( 1 + damageRange ) + end + if oldMethod[grantedId].Physical and physConversions[i + 1] ~= 0 then + local damageRange = (oldMethod[grantedId].Physical[2] == 0) and (boss.damageRange / 100) or oldMethod[grantedId].Physical[2] / 100 + local damageMult = (oldMethod[grantedId].Physical[1] * physConversions[i + 1]) * baseDamageMult + state.DamageData[damageType.."DamageMultMin"] = state.DamageData[damageType.."DamageMultMin"] + damageMult * ( 1 - damageRange ) + state.DamageData[damageType.."DamageMultMax"] = state.DamageData[damageType.."DamageMultMax"] + damageMult * ( 1 + damageRange ) + end + end + end + if ExtraDamageMult[1] ~= ExtraDamageMult[2] then + state.DamageData.SkillUberDamageMult = 100 * ExtraDamageMult[2] / ExtraDamageMult[1] * (baseDamage[grantedId].mapBoss and (monsterMapDifficultyMult[85] / monsterMapDifficultyMult[84]) or 1) + end + if oldMethod[grantedId].SkillUberDamageMult then + state.DamageData.SkillUberDamageMult = oldMethod[grantedId].SkillUberDamageMult * (baseDamage[grantedId].mapBoss and (monsterMapDifficultyMult[85] / monsterMapDifficultyMult[84]) or 1) + elseif baseDamage[grantedId].mapBoss then + state.DamageData.SkillUberDamageMult = 100 * (monsterMapDifficultyMult[85] / monsterMapDifficultyMult[84]) + end + + else + -- new method + local baseDamages = {} + for i, levelIndex in ipairs({baseDamage[grantedId].index, baseDamage[grantedId].uberIndex}) do + local statsPerLevel = (grantedId == skill.grantedId2) and skill.statsPerLevel2[levelIndex] or skill.statsPerLevel[levelIndex] + for j, floatStat in ipairs(statsPerLevel.FloatStats) do + if floatStat.Id == "spell_minimum_base_physical_damage" then + baseDamages["minPhysical"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_maximum_base_physical_damage" then + baseDamages["maxPhysical"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_minimum_base_lightning_damage" then + baseDamages["minLightning"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_maximum_base_lightning_damage" then + baseDamages["maxLightning"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_minimum_base_cold_damage" then + baseDamages["minCold"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_maximum_base_cold_damage" then + baseDamages["maxCold"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_minimum_base_fire_damage" then + baseDamages["minFire"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_maximum_base_fire_damage" then + baseDamages["maxFire"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_minimum_base_chaos_damage" then + baseDamages["minChaos"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + elseif floatStat.Id == "spell_maximum_base_chaos_damage" then + baseDamages["maxChaos"..i] = 1 + statsPerLevel.BaseResolvedValues[j] + end + end + end + monsterLevel = skill.statsPerLevel[baseDamage[grantedId].index].PlayerLevelReq + 1 + if baseDamages["minPhysical1"] or baseDamages["maxPhysical1"] then + local totalConversions = physConversions[2] + physConversions[3] + physConversions[4] + physConversions[5] + local conversionDivisor = m_max(totalConversions, 100) + physConversions = { m_max(1 - totalConversions / 100, 0), physConversions[2] / conversionDivisor, physConversions[3] / conversionDivisor, physConversions[4] / conversionDivisor, physConversions[5] / conversionDivisor } + end + local baseDamageMult = state.SkillExtraDamageMult * ExtraDamageMult[1] * (rarityDamageMult[rarityType] or 1) * (baseDamage[grantedId].mapBoss and monsterMapDifficultyMult[84] or 1) / (monsterBaseDamage[monsterLevel] or 1) -- * boss.damageMult / 100 + if (baseDamages["minPhysical1"] or baseDamages["maxPhysical1"]) and physConversions[1] ~= 0 then + local damageMult = physConversions[1] * baseDamageMult + state.DamageData["PhysicalDamageMultMin"], state.DamageData["PhysicalDamageMultMax"] = damageMult * (baseDamages["minPhysical1"] or 0), damageMult * (baseDamages["maxPhysical1"] or 0) + end + for i, damageType in ipairs({"Lightning", "Cold", "Fire", "Chaos"}) do + if (baseDamages["min"..damageType.."1"] or baseDamages["max"..damageType.."1"]) or ((baseDamages["minPhysical1"] or baseDamages["maxPhysical1"]) and physConversions[i + 1] ~= 0) then + local damageMult = baseDamageMult + state.DamageData[damageType.."DamageMultMin"], state.DamageData[damageType.."DamageMultMax"] = 0, 0 + if (baseDamages["min"..damageType.."1"] or baseDamages["max"..damageType.."1"]) then + state.DamageData[damageType.."DamageMultMin"], state.DamageData[damageType.."DamageMultMax"] = damageMult * (baseDamages["min"..damageType.."1"] or 0), damageMult * (baseDamages["max"..damageType.."1"] or 0) + end + if (baseDamages["minPhysical1"] or baseDamages["maxPhysical1"]) and physConversions[i + 1] ~= 0 then + damageMult = damageMult * physConversions[i + 1] + state.DamageData[damageType.."DamageMultMin"] = state.DamageData[damageType.."DamageMultMin"] + damageMult * (baseDamages["minPhysical1"] or 0) + state.DamageData[damageType.."DamageMultMax"] = state.DamageData[damageType.."DamageMultMax"] + damageMult * (baseDamages["maxPhysical1"] or 0) + end + end + end + if baseDamage[grantedId].uberIndex then + local SkillUberDamageMult = 0 + local SkillDamageMult = 0 + local uberMonsterLevel = skill.statsPerLevel[baseDamage[grantedId].uberIndex].PlayerLevelReq + 1 + for _, damageType in ipairs({"Physical", "Lightning", "Cold", "Fire", "Chaos"}) do + if (baseDamages["min"..damageType.."1"] or baseDamages["max"..damageType.."1"]) then + SkillDamageMult = SkillDamageMult + baseDamages["min"..damageType.."1"] or baseDamages["max"..damageType.."1"] + SkillUberDamageMult = SkillUberDamageMult + baseDamages["min"..damageType.."2"] or baseDamages["max"..damageType.."2"] + end + end + SkillUberDamageMult = (SkillUberDamageMult / (monsterBaseDamage[uberMonsterLevel] or 1)) / (SkillDamageMult / (monsterBaseDamage[monsterLevel] or 1)) * (baseDamage[grantedId].mapBoss and (monsterMapDifficultyMult[85] / monsterMapDifficultyMult[84]) or 1) + if SkillUberDamageMult > 1.15 or SkillUberDamageMult < 0.85 then + state.DamageData.SkillUberDamageMult = m_ceil(SkillUberDamageMult * 100) + end + end + end +end + +-- exports non-damage stats +-- possible stats: DamageType, Penetration, Speed +local function getStat(state, stat) + local DamageData = state.DamageData + local skill = state.skill + local boss = state.boss + if stat == "DamageType" then + local DamageType = "Melee" + for _, skillType in ipairs(skill.skillData.ActiveSkill.SkillTypes) do + if skillType.Id == "Spell" then + if DamageType == "Projectile" then + DamageType = "SpellProjectile" + else + DamageType = "Spell" + end + elseif skillType.Id == "Projectile" then + if DamageType == "Spell" then + DamageType = "SpellProjectile" + else + DamageType = "Projectile" + end + end + end + if DamageType == "Melee" then + for _, implicitStat in ipairs(skill.GrantedEffectStatSets.ImplicitStats) do + if implicitStat.Id == "base_is_projectile" then + DamageType = "Projectile" + break + end + end + end + return DamageType + elseif stat == "Penetration" then + DamageData["PhysOverwhelm"], DamageData["PhysUberOverwhelm"], DamageData["LightningPen"], DamageData["LightningUberPen"], DamageData["ColdPen"], DamageData["ColdUberPen"], DamageData["FirePen"], DamageData["FireUberPen"], DamageData["ChaosPen"], DamageData["ChaosUberPen"] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + for level, statsPerLevel in ipairs(skill.statsPerLevel) do + for i, additionalStat in ipairs(statsPerLevel.AdditionalStats) do + if additionalStat.Id == "base_reduce_enemy_lightning_resistance_%" then + DamageData["Lightning"..(level > 1 and "Uber" or "").."Pen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_cold_resistance_%" then + DamageData["Cold"..(level > 1 and "Uber" or "").."Pen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_fire_resistance_%" then + DamageData["Fire"..(level > 1 and "Uber" or "").."Pen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_chaos_resistance_%" then + DamageData["Chaos"..(level > 1 and "Uber" or "").."Pen"] = statsPerLevel.AdditionalStatsValues[i] + end + end + end + if boss.earlierUber then + local statsPerLevel = skill.statsPerLevelUber[2] + for i, additionalStat in ipairs(statsPerLevel.AdditionalStats) do + if additionalStat.Id == "base_reduce_enemy_lightning_resistance_%" then + DamageData["LightningUberPen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_cold_resistance_%" then + DamageData["ColdUberPen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_fire_resistance_%" then + DamageData["FireUberPen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_chaos_resistance_%" then + DamageData["ChaosUberPen"] = statsPerLevel.AdditionalStatsValues[i] + end + end + elseif 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 + DamageData["Lightning"..(level > 1 and "Uber" or "").."Pen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_cold_resistance_%" then + DamageData["Cold"..(level > 1 and "Uber" or "").."Pen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_fire_resistance_%" then + DamageData["Fire"..(level > 1 and "Uber" or "").."Pen"] = statsPerLevel.AdditionalStatsValues[i] + elseif additionalStat.Id == "base_reduce_enemy_chaos_resistance_%" then + DamageData["Chaos"..(level > 1 and "Uber" or "").."Pen"] = statsPerLevel.AdditionalStatsValues[i] + end + end + end + end + DamageData["PhysOverwhelm"] = (DamageData["PhysOverwhelm"] == 0) and (DamageData["PhysUberOverwhelm"] ~= 0 and "" or DamageData["PhysOverwhelm"]) or DamageData["PhysOverwhelm"] + for _, damageType in ipairs({"Lightning", "Cold", "Fire"}) do + DamageData[damageType.."Pen"] = (DamageData[damageType.."Pen"] == 0) and (DamageData[damageType.."UberPen"] ~= 0 and "" or DamageData[damageType.."Pen"]) or DamageData[damageType.."Pen"] + end + return (DamageData["PhysOverwhelm"] ~= 0 or DamageData["LightningPen"] ~= 0 or DamageData["ColdPen"] ~= 0 or DamageData["FirePen"] ~= 0) + elseif stat == "Speed" then + local speed = skill.skillData.CastTime + local uberSpeed + if skill.skillDataUber then + uberSpeed = skill.skillDataUber.CastTime + end + local speedMult = { 0, 0 } + for level, statsPerLevel in ipairs(skill.statsPerLevel) do + if level > 2 then + break + end + for i, additionalStat in ipairs(statsPerLevel.AdditionalStats) do + if additionalStat.Id == "active_skill_attack_speed_+%_final" then + speedMult[level] = 100 + statsPerLevel.AdditionalStatsValues[i] + break + elseif additionalStat.Id == "active_skill_cast_speed_+%_final" then + speedMult[level] = 100 + statsPerLevel.AdditionalStatsValues[i] + break + end + end + end + if skill.speedMult then + speed = speed * skill.speedMult / 10000 + if uberSpeed then + uberSpeed = uberSpeed * skill.speedMult / 10000 + end + end + if skill.stages then + speed = speed * skill.stages + if uberSpeed then + uberSpeed = uberSpeed * skill.stages + end + end + if speedMult[1] ~= 0 then + if speedMult[1] ~= speedMult[2] then + return tonumber(m_ceil(speed / speedMult[1] * 100)), tonumber(m_ceil(speed / speedMult[2] * 100)) + end + speed = speed / speedMult[1] * 100 + uberSpeed = uberSpeed / speedMult[1] * 100 + end + if uberSpeed then + return tonumber(m_ceil(speed)), tonumber(m_ceil(uberSpeed)) + end + return tonumber(m_ceil(speed)) + end +end + +local directiveTable = {} + +-- #boss [] +-- Initialises the boss +directiveTable.boss = function(state, args, out) + local displayName, monsterId, earlierUber = args:match("(%w+) (.+) (%w+)") + if not displayName then + displayName = args + monsterId = args + end + local bossData = dat("MonsterVarieties"):GetRow("Id", monsterId) + state.boss = { displayName = displayName, damageRange = bossData.Type.DamageSpread, damageMult = bossData.DamageMultiplier, critChance = m_ceil(bossData.CriticalStrikeChance / 100) } + if earlierUber == "true" then + state.boss.earlierUber = true + end + for _, mod in ipairs(bossData.Mods) do + if mod.Id == "MonsterMapBoss" then + state.boss.rarity = "Unique" + break + end + end +end + +-- #skill [] [] +-- optional# +-- Initialises and emits the skill data +directiveTable.skill = function(state, args, out) + local displayName, grantedId = args:match("(%w+) (%w+)") + if not grantedId then + displayName, grantedId = args + end + local boss = state.boss + local skill = {} + local skillData = dat("GrantedEffects"):GetRow("Id", grantedId) + local GrantedEffectStatSets = dat("GrantedEffectStatSets"):GetRow("Id", grantedId) + local statsPerLevel = dat("GrantedEffectStatSetsPerLevel"):GetRowList("GrantedEffect", skillData) + skill = { skillData = skillData, displayName = displayName, GrantedEffectStatSets = GrantedEffectStatSets, statsPerLevel = statsPerLevel, grantedId = grantedId } + state.skill = skill + local grantedId2 = args:match("GrantedEffectId2 = (%w+),") + if grantedId2 then + skill.skillData2 = dat("GrantedEffects"):GetRow("Id", grantedId2) + skill.statsPerLevel2 = dat("GrantedEffectStatSetsPerLevel"):GetRowList("GrantedEffect", skill.skillData2) + skill.grantedId2 = grantedId2 + end + local grantedIdUber = args:match("GrantedEffectIdUber = (%w+),") + if grantedIdUber then + skill.skillDataUber = dat("GrantedEffects"):GetRow("Id", grantedIdUber) + skill.statsPerLevelUber = dat("GrantedEffectStatSetsPerLevel"):GetRowList("GrantedEffect", skill.skillDataUber) + skill.grantedIdUber = grantedIdUber + end + state.SkillExtraDamageMult = args:match("ExtraDamageMult = (%d+),") + state.SkillExtraDamageMult = state.SkillExtraDamageMult and (state.SkillExtraDamageMult / 100) or 1 + skill.stages = args:match("stages = (%w+),") + local DamageData = {} + state.DamageData = DamageData + calcSkillDamage(state) + -- output + out:write(' ["', boss.displayName, " ", displayName, '"] = {\n') + out:write(' DamageType = "', getStat(state, "DamageType"),'",\n') + out:write(' DamageMultipliers = {\n') + local dCount = 0 + for i, damageType in ipairs({"Physical", "Lightning", "Cold", "Fire", "Chaos"}) do + if DamageData[damageType.."DamageMultMin"] then + dCount = dCount + 1 + out:write(dCount > 1 and ',\n' or '', ' ', damageType, ' = { ', DamageData[damageType.."DamageMultMin"], ', ', (DamageData[damageType.."DamageMultMax"] - DamageData[damageType.."DamageMultMin"]) / 100, ' }') + end + end + if dCount == 0 then + print("error skill: "..skill.displayName.." has no damage") + end + out:write('\n }') + if DamageData.SkillUberDamageMult then + out:write(',\n UberDamageMultiplier = ', (DamageData.SkillUberDamageMult / 100)) + end + if getStat(state, "Penetration") then + out:write(',\n DamagePenetrations = {\n') + dCount = 0 + for _, penType in ipairs({"PhysOverwhelm", "LightningPen", "ColdPen", "FirePen"}) do + if DamageData[penType] ~= 0 then + dCount = dCount + 1 + out:write(dCount > 1 and ',\n' or '', ' ', penType, ' = ', (DamageData[penType] == "" and '""' or DamageData[penType])) + end + end + out:write('\n }') + if DamageData["PhysUberOverwhelm"] ~= 0 or DamageData["LightningUberPen"] ~= 0 or DamageData["ColdUberPen"] ~= 0 or DamageData["FireUberPen"] ~= 0 then + out:write(',\n UberDamagePenetrations = {\n') + dCount = 0 + for _, penType in ipairs({"PhysUberOverwhelm", "LightningUberPen", "ColdUberPen", "FireUberPen"}) do + if DamageData[penType] ~= 0 then + dCount = dCount + 1 + out:write(dCount > 1 and ',\n' or '', ' ', penType:gsub("Uber", ""), ' = ', DamageData[penType]) + end + end + out:write('\n }') + end + end + skill.speedMult = args:match("speedMult = (%d+),") + local speed, uberSpeed = getStat(state, "Speed") + if speed and speed ~= 700 then + out:write(',\n speed = ', speed) + end + if uberSpeed and uberSpeed ~= 700 then + out:write(',\n UberSpeed = ', uberSpeed) + end + local critChance = statsPerLevel[1].AttackCritChance + if critChance or boss.critChance then + critChance = critChance and (m_ceil(critChance / 100)) or boss.critChance + if critChance ~= 5 then + out:write(',\n critChance = ', critChance) + end + end + if boss.earlierUber then + out:write(',\n earlierUber = true') + end +end + + -- #tooltip + directiveTable.tooltip = function(state, args, out) + if args then + out:write(',\n tooltip = ', args,'\n') + end + out:write(' },\n') + state.skill = nil +end + +processTemplateFile("bossSkills", "", "../Data/", directiveTable) + +print("Boss skill data exported.") diff --git a/src/Export/bossSkills.txt b/src/Export/bossSkills.txt new file mode 100644 index 0000000000..2c9d492617 --- /dev/null +++ b/src/Export/bossSkills.txt @@ -0,0 +1,29 @@ +-- Path of Building +-- +-- Boss Skill Presets +-- Boss Skill data (c) Grinding Gear Games +-- +return { +#boss Atziri Metadata/Monsters/Atziri/Atziri true +#skill Flameblast AtziriFlameblast, GrantedEffectIdUber = AtziriFlameblastEmpowered, stages = 10, +#tooltip "The Uber variant has 10 ^xB97123Fire^7 penetration (Applied on Pinnacle And Uber)" +#boss Shaper Metadata/Monsters/AtlasBosses/TheShaperBoss false +#skill Ball AtlasBossAcceleratingProjectiles +#tooltip "Allocating Cosmic Wounds increases the penetration to 40% (Applied on Uber) and adds 2 projectiles" +#skill Slam AtlasBossFlickerSlam, speedMult = 8775, +#tooltip "Cannot be Evaded. Allocating Cosmic Wounds increases Damage by a further 100% (Applied on Uber) and cannot be blocked or dodged" +#boss Sirus Metadata/Monsters/AtlasExiles/AtlasExile5 false +#skill Meteor AtlasExileOrionCircleMazeBlast3 +#tooltip "Earlier ones with less walls do less damage. Allocating The Perfect Storm increases Damage by a further 50% (Applied on Uber)" +#boss Exarch Metadata/Monsters/AtlasInvaders/CleansingMonsters/CleansingBoss false +#skill Ball CleansingFireWall, speedMult = 4545, +#tooltip "Spawns 8-18 waves of balls depending on which fight and which ball phase" +#boss Eater Metadata/Monsters/AtlasInvaders/ConsumeMonsters/ConsumeBoss false +#skill Beam GSConsumeBossDisintegrateBeam +#tooltip "Allocating Insatiable Appetite causes the beam to always shock for at least 30%" +#boss Maven Metadata/Monsters/MavenBoss/TheMaven false +#skill Fireball MavenSuperFireProjectile, GrantedEffectId2 = MavenSuperFireProjectileImpact, +#tooltip "Allocating Throw the Gauntlet increases Damage by a further 100% (Applied on Uber) and causes the fireball to have 30 ^xB97123Fire^7 penetration (Applied on Uber)" +#skill MemoryGame MavenMemoryGame +#tooltip "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" +} \ No newline at end of file diff --git a/src/Export/spec.lua b/src/Export/spec.lua index 4ec6a56f7d..2f8fe7958a 100644 --- a/src/Export/spec.lua +++ b/src/Export/spec.lua @@ -3934,10 +3934,10 @@ return { }, [12]={ list=false, - name="", + name="LifeLeech?", refTo="", type="Int", - width=50 + width=70 }, [13]={ list=false, @@ -3962,10 +3962,10 @@ return { }, [16]={ list=false, - name="", + name="CooldownNotRecoverDuringActive", refTo="", type="Bool", - width=50 + width=180 }, [17]={ list=true, @@ -3983,10 +3983,10 @@ return { }, [19]={ list=false, - name="", - refTo="", + name="MultiPartAchievement", + refTo="MultiPartAchievements", type="Key", - width=40 + width=150 }, [20]={ list=false, @@ -5803,10 +5803,10 @@ return { }, [14]={ list=false, - name="", + name="ModelSizeMultiplier", refTo="", type="Int", - width=50 + width=120 }, [15]={ list=false, @@ -5852,10 +5852,10 @@ return { }, [21]={ list=false, - name="", + name="ExperienceMultiplier", refTo="", type="Int", - width=50 + width=120 }, [22]={ list=true, @@ -5887,10 +5887,10 @@ return { }, [26]={ list=false, - name="", + name="CriticalStrikeChance", refTo="", type="Int", - width=50 + width=120 }, [27]={ list=false, @@ -5915,7 +5915,7 @@ return { }, [30]={ list=true, - name="", + name="ModsKeys2", refTo="Mods", type="Key", width=200 @@ -6114,14 +6114,14 @@ return { name="MonsterSegments", refTo="MonsterSegments", type="Key", - width=50 + width=120 }, [59]={ list=false, name="MonsterArmours", refTo="MonsterArmours", type="Key", - width=50 + width=120 }, [60]={ list=false, @@ -6181,7 +6181,7 @@ return { }, [68]={ list=true, - name="", + name="MultiPartAchievements", refTo="MultiPartAchievements", type="Key", width=150 @@ -6279,10 +6279,10 @@ return { }, [82]={ list=false, - name="", - refTo="", + name="MonsterConditionalEffectPack", + refTo="MonsterConditionalEffectPacks", type="Key", - width=50 + width=150 }, [83]={ list=false, @@ -6311,6 +6311,76 @@ return { refTo="", type="Bool", width=50 + }, + [87]={ + list=false, + name="", + refTo="", + type="Int", + width=50 + }, + [88]={ + list=false, + name="", + refTo="", + type="Int", + width=50 + }, + [89]={ + list=false, + name="", + refTo="", + type="Int", + width=50 + }, + [90]={ + list=false, + name="", + refTo="", + type="Int", + width=50 + }, + [91]={ + list=false, + name="", + refTo="", + type="Int", + width=50 + }, + [92]={ + list=false, + name="", + refTo="", + type="Int", + width=50 + }, + [93]={ + list=true, + name="", + refTo="", + type="Int", + width=50 + }, + [94]={ + list=false, + name="", + refTo="", + type="Int", + width=50 + }, + [95]={ + list=false, + name="", + refTo="", + type="Int", + width=50 + }, + [96]={ + list=false, + name="", + refTo="", + type="Int", + width=50 } }, MonsterVarietiesArtVariations={ diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index ca1cc0950d..f47fcf818d 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -42,6 +42,21 @@ local function banditTooltip(tooltip, mode, index, value) end end +local function bossSkillsTooltip(tooltip, mode, index, value) + local applyModes = { BODY = true, HOVER = true } + tooltip:Clear() + if applyModes[mode] then + tooltip:AddLine(14, [[ +^7Used to fill in defaults for specific boss skills if the boss config is not set + +Bosses' damage is modified by roll range configuration, defaulted at a 70% roll, at the normal monster level for your character level (capped at 85) +Fill in the exact damage numbers if more precision is needed]]) + if value.val ~= "None" then + tooltip:AddLine(14, '\n^7'..value.val..": "..data.bossSkills[value.val].tooltip) + end + end +end + return { -- Section: General options { section = "General", col = 1 }, @@ -1517,7 +1532,7 @@ Uber Pinnacle Boss adds the following modifiers: build.configTab.varControls['enemyLightningDamage']:SetPlaceholder(defaultDamage, true) build.configTab.varControls['enemyColdDamage']:SetPlaceholder(defaultDamage, true) build.configTab.varControls['enemyFireDamage']:SetPlaceholder(defaultDamage, true) - build.configTab.varControls['enemyChaosDamage']:SetPlaceholder(round(defaultDamage / 4), true) + build.configTab.varControls['enemyChaosDamage']:SetPlaceholder(round(defaultDamage / 2.5), true) local defaultPen = "" build.configTab.varControls['enemyPhysicalOverwhelm']:SetPlaceholder(defaultPen, true) @@ -1550,7 +1565,7 @@ Uber Pinnacle Boss adds the following modifiers: build.configTab.varControls['enemyLightningDamage']:SetPlaceholder(defaultDamage, true) build.configTab.varControls['enemyColdDamage']:SetPlaceholder(defaultDamage, true) build.configTab.varControls['enemyFireDamage']:SetPlaceholder(defaultDamage, true) - build.configTab.varControls['enemyChaosDamage']:SetPlaceholder(round(defaultDamage / 4), true) + build.configTab.varControls['enemyChaosDamage']:SetPlaceholder(round(defaultDamage / 2.5), true) build.configTab.varControls['enemyLightningPen']:SetPlaceholder(data.misc.pinnacleBossPen, true) build.configTab.varControls['enemyColdPen']:SetPlaceholder(data.misc.pinnacleBossPen, true) @@ -1642,77 +1657,66 @@ Uber Pinnacle Boss adds the following modifiers: { var = "enemyArmour", type = "count", label = "Enemy Base Armour:", apply = function(val, modList, enemyModList) enemyModList:NewMod("Armour", "BASE", val, "Config") end }, - { var = "presetBossSkills", type = "list", label = "Boss Skill Preset", tooltip = [[ -Used to fill in defaults for specific boss skills if the boss config is not set - -Bosses' damage is assumed at a 2/3 roll, with no Atlas passives, at the normal monster level for your character level (capped at 85) -Fill in the exact damage numbers if more precision is needed - -Caveats for certain skills are below - -Shaper Ball: Allocating Cosmic Wounds increases the penetration to 40% and adds 2 projectiles -Shaper Slam: Cannot be Evaded. Allocating Cosmic Wounds doubles the damage and cannot be blocked or dodged -Maven Memory Game: Is three separate hits, and has a large DoT effect. Neither is taken into account here. i.e. Hits before death should be >= 4 to survive]], list = {{val="None",label="None"},{val="Uber Atziri Flameblast",label="Uber Atziri Flameblast"},{val="Shaper Ball",label="Shaper Ball"},{val="Shaper Slam",label="Shaper Slam"},{val="Maven Memory Game",label="Maven Memory Game"}}, apply = function(val, modList, enemyModList, build) - --reset to empty + { var = "presetBossSkills", type = "list", label = "Boss Skill Preset", tooltipFunc = bossSkillsTooltip, list = data.bossSkillsList, apply = function(val, modList, enemyModList, build) if not (val == "None") then + local bossData = data.bossSkills[val] + local isUber = build.configTab.varControls['enemyIsBoss'].list[build.configTab.varControls['enemyIsBoss'].selIndex].val == "Uber" + if bossData.earlierUber and build.configTab.varControls['enemyIsBoss'].list[build.configTab.varControls['enemyIsBoss'].selIndex].val == "Pinnacle" then + isUber = true + end local defaultDamage = "" build.configTab.varControls['enemyPhysicalDamage']:SetPlaceholder(defaultDamage, true) build.configTab.varControls['enemyLightningDamage']:SetPlaceholder(defaultDamage, true) 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 + build.configTab.varControls['enemy'..damageType..'Damage']:SetPlaceholder(round(data.monsterDamageTable[build.configTab.enemyLevel] * (damageMult[1] + rollRangeMult * damageMult[2]) * bossData.UberDamageMultiplier), true) + else + build.configTab.varControls['enemy'..damageType..'Damage']:SetPlaceholder(round(data.monsterDamageTable[build.configTab.enemyLevel] * (damageMult[1] + rollRangeMult * damageMult[2])), true) + end + end local defaultPen = "" build.configTab.varControls['enemyPhysicalOverwhelm']:SetPlaceholder(defaultPen, true) build.configTab.varControls['enemyLightningPen']:SetPlaceholder(defaultPen, true) build.configTab.varControls['enemyColdPen']:SetPlaceholder(defaultPen, true) build.configTab.varControls['enemyFirePen']:SetPlaceholder(defaultPen, true) - else - build.configTab.varControls['enemyDamageType'].enabled = true - end - - if val == "Uber Atziri Flameblast" then - if build.configTab.enemyLevel then - build.configTab.varControls['enemyFireDamage']:SetPlaceholder(round(data.monsterDamageTable[build.configTab.enemyLevel] * data.bossSkills["Uber Atziri Flameblast"].damageMult), true) - build.configTab.varControls['enemyDamageType']:SelByValue("Spell", "val") - build.configTab.varControls['enemyDamageType'].enabled = false - build.configTab.input['enemyDamageType'] = "Spell" + + if bossData.DamagePenetrations then + for penType, pen in pairs(bossData.DamagePenetrations) do + if isUber and bossData.UberDamagePenetrations and bossData.UberDamagePenetrations[penType] then + build.configTab.varControls['enemy'..penType]:SetPlaceholder(bossData.UberDamagePenetrations[penType], true) + else + build.configTab.varControls['enemy'..penType]:SetPlaceholder(pen, true) + end + end end - build.configTab.varControls['enemyFirePen']:SetPlaceholder(10, true) - - build.configTab.varControls['enemySpeed']:SetPlaceholder(data.bossSkills["Uber Atziri Flameblast"].speed, true) - build.configTab.varControls['enemyCritChance']:SetPlaceholder(0, true) - elseif val == "Shaper Ball" then - if build.configTab.enemyLevel then - build.configTab.varControls['enemyColdDamage']:SetPlaceholder(round(data.monsterDamageTable[build.configTab.enemyLevel] * data.bossSkills["Shaper Ball"].damageMult), true) + + if bossData.DamageType then + build.configTab.varControls['enemyDamageType']:SelByValue(bossData.DamageType, "val") + build.configTab.input['enemyDamageType'] = bossData.DamageType end - - build.configTab.varControls['enemyColdPen']:SetPlaceholder(25, true) - build.configTab.varControls['enemySpeed']:SetPlaceholder(data.bossSkills["Shaper Ball"].speed, true) build.configTab.varControls['enemyDamageType'].enabled = false - build.configTab.varControls['enemyDamageType']:SelByValue("SpellProjectile", "val") - build.configTab.input['enemyDamageType'] = "SpellProjectile" - elseif val == "Shaper Slam" then - if build.configTab.enemyLevel then - build.configTab.varControls['enemyPhysicalDamage']:SetPlaceholder(round(data.monsterDamageTable[build.configTab.enemyLevel] * data.bossSkills["Shaper Slam"].damageMult), true) + + if isUber and bossData.UberSpeed then + build.configTab.varControls['enemySpeed']:SetPlaceholder(bossData.UberSpeed, true) + elseif bossData.speed then + build.configTab.varControls['enemySpeed']:SetPlaceholder(bossData.speed, true) end - build.configTab.varControls['enemyDamageType'].enabled = false - build.configTab.varControls['enemyDamageType']:SelByValue("Melee", "val") - build.configTab.input['enemyDamageType'] = "Melee" - - build.configTab.varControls['enemySpeed']:SetPlaceholder(data.bossSkills["Shaper Slam"].speed, true) - elseif val == "Maven Memory Game" then - if build.configTab.enemyLevel then - local defaultEleDamage = round(data.monsterDamageTable[build.configTab.enemyLevel] * data.bossSkills["Maven Memory Game"].damageMult) - build.configTab.varControls['enemyLightningDamage']:SetPlaceholder(defaultEleDamage, true) - build.configTab.varControls['enemyColdDamage']:SetPlaceholder(defaultEleDamage, true) - build.configTab.varControls['enemyFireDamage']:SetPlaceholder(defaultEleDamage, true) + if bossData.critChance then + build.configTab.varControls['enemyCritChance']:SetPlaceholder(bossData.critChance, true) end - build.configTab.varControls['enemyDamageType'].enabled = false - build.configTab.varControls['enemyDamageType']:SelByValue("Melee", "val") - build.configTab.input['enemyDamageType'] = "Melee" + + modList:NewMod("BossSkillActive", "FLAG", true, "Config") + else + build.configTab.varControls['enemyDamageType'].enabled = true end end }, + { var = "enemyDamageRollRange", type = "integer", label = "Enemy Skill Roll Range %:", ifFlag = "BossSkillActive", tooltip = "The percentage of the roll range the enemy hits for \n eg at 100% the enemy deals its maximum damage", defaultPlaceholderState = 70, hideIfInvalid = true }, { var = "enemyDamageType", type = "list", label = "Enemy Damage Type:", tooltip = "Controls which types of damage the EHP calculation uses:\n\tAverage: uses the Average of all damage types\n\nIf a specific damage type is selected, that will be the only type used.", list = {{val="Average",label="Average"},{val="Melee",label="Melee"},{val="Projectile",label="Projectile"},{val="Spell",label="Spell"},{val="SpellProjectile",label="Projectile Spell"}} }, { var = "enemySpeed", type = "integer", label = "Enemy attack / cast time in ms:", defaultPlaceholderState = 700 }, { var = "enemyMultiplierPvpDamage", type = "count", label = "Custom PvP Damage multiplier percent:", ifFlag = "isPvP", tooltip = "This multiplies the damage of a given skill in pvp, for instance any with damage multiplier specific to pvp (from skill or support or item like sire of shards)", apply = function(val, modList, enemyModList) diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index f1fddb996e..237fc8a177 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -8,6 +8,7 @@ LoadModule("Data/Global") local m_min = math.min local m_max = math.max +local t_insert = table.insert local t_concat = table.concat local skillTypes = { @@ -479,9 +480,9 @@ data.misc = { -- magic numbers BrandAttachmentRangeBase = 30, ProjectileDistanceCap = 150, -- Expected values to calculate EHP - stdBossDPSMult = 4 / 4.25, - pinnacleBossDPSMult = 8 / 4.25, - pinnacleBossPen = 25 / 5, + stdBossDPSMult = 4 / 4.40, + pinnacleBossDPSMult = 8 / 4.40, + pinnacleBossPen = 15 / 5, uberBossDPSMult = 10 / 4.25, uberBossPen = 40 / 5, -- ehp helper function magic numbers @@ -497,23 +498,25 @@ data.misc = { -- magic numbers PvpNonElemental2 = 90, } -data.bossSkills = { - ["Uber Atziri Flameblast"] = { - damageMult = 3.48 * 10.9, - speed = 2500 * 10 - }, - ["Shaper Ball"] = { - damageMult = 9.17, - speed = 1400 - }, - ["Shaper Slam"] = { - damageMult = 15.2, - speed = 3510 - }, - ["Maven Memory Game"] = { - damageMult = 24.69 - } +data.bossSkills = LoadModule("Data/BossSkills") +-- auto generation of skill list using boss skills above, is currently disabled because it messes with the order +data.bossSkillsList = { + { val = "None", label = "None" }, + { val = "Atziri Flameblast", label = "Atziri Flameblast" }, + { val = "Shaper Ball", label = "Shaper Ball" }, + { val = "Shaper Slam", label = "Shaper Slam" }, + --{ val = "Elder Slam", label = "Elder Slam" }, + { val = "Sirus Meteor", label = "Sirus Meteor" }, + { val = "Exarch Ball", label = "Exarch Ball" }, + { val = "Eater Beam", label = "Eater Beam" }, + { val = "Maven Fireball", label = "Maven Fireball" }, + { val = "Maven MemoryGame", label = "Maven Memory Game" } } +--[[ +for bossSkillName, bossSkillData in pairs(data.bossSkills) do + t_insert(data.bossSkillsList, {val = bossSkillName, label = bossSkillName}) +end +--]] -- Misc data tables LoadModule("Data/Misc", data)