diff --git a/src/Data/Misc.lua b/src/Data/Misc.lua index 0f319bc244..298feb64a5 100644 --- a/src/Data/Misc.lua +++ b/src/Data/Misc.lua @@ -100,6 +100,145 @@ data.gameConstants = { ["CullingStrikeRareThreshold"] = 10, ["CullingStrikeUniqueThreshold"] = 5, } +-- From Metadata/Characters/Character.ot +data.characterConstants = { + ["level"] = 1, + ["is_player"] = 1, + ["energy_shield_recharge_rate_per_minute_%"] = 750, + ["character_inherent_mana_regeneration_rate_per_minute_%"] = 240, + ["base_maximum_all_resistances_%"] = 75, + ["maximum_physical_damage_reduction_%"] = 90, + ["object_inherent_base_maximum_block_%_from_ot"] = 75, + ["base_maximum_spell_block_%"] = 75, + ["max_viper_strike_orbs"] = 4, + ["max_fuse_arrow_orbs"] = 5, + ["max_fire_beam_stacks"] = 8, + ["base_evasion_rating"] = 27, + ["base_maximum_chance_to_evade_%"] = 95, + ["life_per_level"] = 12, + ["mana_per_level"] = 4, + ["accuracy_rating_per_level"] = 3, + ["evasion_rating_per_level"] = 300, + ["base_critical_hit_damage_bonus"] = 100, + ["strength_per_level"] = 0, + ["dexterity_per_level"] = 0, + ["intelligence_per_level"] = 0, + ["max_endurance_charges"] = 3, + ["max_frenzy_charges"] = 3, + ["max_power_charges"] = 3, + ["maximum_righteous_charges"] = 5, + ["maximum_blood_scythe_charges"] = 5, + ["base_number_of_traps_allowed"] = 15, + ["base_number_of_remote_mines_allowed"] = 15, + ["max_charged_attack_stacks"] = 6, + ["max_talisman_degen_stacks"] = 20, + ["max_frost_nova_stacks"] = 20, + ["max_rampage_stacks"] = 1000, + ["damage_+%_per_10_rampage_stacks"] = 2, + ["movement_velocity_+%_per_10_rampage_stacks"] = 1, + ["pvp_shield_damage_+%_final"] = -15, + ["minions_have_labyrinth_trap_degen_effect_+%"] = -90, + ["minions_are_immune_to_labyrinth_degen_effect"] = 0, + ["minion_damage_taken_+%_from_spike_traps_final"] = -90, + ["minion_damage_taken_+%_from_arrow_traps_final"] = 0, + ["minion_damage_taken_+%_from_guillotine_traps_final"] = -90, + ["traps_explode_on_timeout"] = 1, + ["maximum_rage"] = 30, + ["max_delve_degen_stacks"] = 5000, + ["max_azurite_debuff_stacks"] = 10, + ["melee_variation"] = 1, + ["base_total_number_of_sigils_allowed"] = 3, + ["enable_movement_skill_animation_skipping"] = 1, + ["melee_hit_damage_stun_multiplier_+%"] = 50, + ["non_physical_hit_damage_stun_multiplier_+%"] = -33, + ["additional_insanity_effects_while_delirious"] = 1, + ["max_steel_ammo"] = 12, + ["chance_to_deal_triple_damage_%_per_brutal_charge"] = 3, + ["stun_threshold_+%_per_brutal_charge"] = 10, + ["elemental_damage_taken_goes_to_energy_shield_over_4_seconds_%_per_absorption_charge"] = 12, + ["actor_scale_+%_limit"] = 100, + ["mines_invulnerable_for_duration_ms"] = 2000, + ["traps_invulnerable_for_duration_ms"] = 2000, + ["damage_taken_when_hit_+%_final_per_fortification"] = -1, + ["base_max_fortification"] = 20, + ["base_presence_radius"] = 40, + ["mtx_max_killstreak_stacks"] = 1000, + ["mtx_max_killcounter_stacks"] = 30000, + ["melee_strike_bonus_attack_distance"] = 2, + ["melee_defer_damage_prediction"] = 1, + ["accuracy_rating_+%_final_at_max_distance_scaled"] = -90, + ["base_weapon_swap_duration_ms"] = 250, + ["poise_decay_%_per_second"] = 50, + ["enable_weapon_sets"] = true, + ["base_number_of_weapon_sets"] = 2, + ["quadruped_head_turn_duration_ms"] = 100, + ["has_quadruped_head_control"] = 0, + ["base_pay_cost_over_start_of_skill_animation"] = 1, + ["base_knockback_speed_+%"] = -30, + ["base_maximum_number_of_stored_corpses"] = 10, + ["base_block_angle_degrees"] = 210, + ["base_heavy_stun_duration_ms"] = 3000, + ["global_resummon_time_ms"] = 7500, + ["disable_minion_formation"] = 1, + ["can_evade_spells"] = 1, + ["crossbow_ammo_switch_time_ms"] = 300, + ["light_stun_threshold_+%_final_per_number_of_times_stunned_in_past_duration_from_ot"] = 50, + ["x_ms_for_number_of_times_stunned_in_past_duration_from_ot"] = 4000, + ["rage_loss_delay_ms"] = 2000, + ["stun_base_duration_override_ms"] = 500, + ["object_inherent_armour_break_amount_+%_final_against_normal_monsters"] = 200, + ["object_inherent_armour_break_amount_+%_final_against_magic_monsters"] = 100, + ["object_inherent_evasion_break_amount_+%_final_against_normal_monsters"] = 200, + ["object_inherent_evasion_break_amount_+%_final_against_magic_monsters"] = 100, + ["fixed_frost_wall_limit"] = 60, + ["player_allow_dodge_roll_cancel"] = 1, + ["maximum_cold_infusion_stacks"] = 6, + ["maximum_fire_infusion_stacks"] = 6, + ["maximum_lightning_infusion_stacks"] = 6, + ["maximum_chaos_infusion_stacks"] = 6, + ["base_infusion_duration_ms"] = 15000, + ["maximum_caltrops_allowed"] = 20, + ["maximum_volatility_allowed"] = 200, + ["base_speed"] = 37, +} +-- From Metadata/Monsters/Monster.ot +data.monsterConstants = { + ["item_drop_slots"] = 1, + ["energy_shield_recharge_rate_per_minute_%"] = 750, + ["base_maximum_mana"] = 200, + ["maximum_physical_damage_reduction_%"] = 75, + ["base_maximum_all_resistances_%"] = 75, + ["monster_base_flask_charges_percent_of_monster_power"] = 50, + ["base_maximum_chance_to_evade_%"] = 95, + ["base_critical_hit_damage_bonus"] = 30, + ["max_endurance_charges"] = 3, + ["max_frenzy_charges"] = 3, + ["max_power_charges"] = 3, + ["object_inherent_base_maximum_block_%_from_ot"] = 75, + ["base_maximum_spell_block_%"] = 75, + ["movement_velocity_cap"] = 128, + ["max_azurite_debuff_stacks"] = 10, + ["ignore_skill_weapon_restrictions"] = 1, + ["melee_hit_damage_stun_multiplier_+%"] = 33, + ["non_physical_hit_damage_stun_multiplier_+%"] = -50, + ["scale_melee_range_to_actor_scale"] = 1, + ["use_melee_pattern_range"] = 1, + ["melee_swing_not_scaled_by_area_modifiers"] = 1, + ["actor_scale_+%_limit"] = 200, + ["base_heavy_stun_duration_ms"] = 2000, + ["melee_defer_damage_prediction"] = 1, + ["poise_decay_delay_ms"] = 8000, + ["poise_decay_%_per_second"] = 5, + ["base_block_angle_degrees"] = 180, + ["action_attack_or_cast_time_uses_animation_length"] = 1, + ["slow_potency_+%_final_per_additional_player"] = -10, + ["check_for_targets_between_initiator_and_projectile_source"] = 1, + ["maximum_life_+%_final_per_additional_player"] = 50, + ["maximum_energy_shield_+%_final_per_additional_player"] = 50, + ["poise_threshold_+%_final_per_additional_player"] = 50, + ["stun_base_duration_override_ms"] = 500, + ["bleeding_moving_damage_%_of_base_override"] = 200, +} -- From PlayerMinionIntrinsicStats.dat data.playerMinionIntrinsicStats = { ["stun_base_duration_override_ms"] = 500, diff --git a/src/Export/Classes/GGPKData.lua b/src/Export/Classes/GGPKData.lua index ebc4c3cb4f..8388264238 100644 --- a/src/Export/Classes/GGPKData.lua +++ b/src/Export/Classes/GGPKData.lua @@ -346,6 +346,10 @@ function GGPKClass:GetNeededFiles() "^Metadata/StatDescriptions/\\w+.csd$", "^Metadata/StatDescriptions/specific_skill_stat_descriptions/\\w+/\\w+.csd$", } + local otFiles = { + "Metadata/Characters/Character.ot", + "Metadata/Monsters/Monster.ot", + } local itFiles = { "Metadata/Items/Equipment.it", "Metadata/Items/Item.it", @@ -391,5 +395,6 @@ function GGPKClass:GetNeededFiles() "Metadata/Items/Armours/BodyArmours/AbstractBodyArmour.it", "Metadata/Items/Amulets/AbstractAmulet.it", } - return datFiles, csdFiles, itFiles + + return datFiles, csdFiles, otFiles, itFiles end diff --git a/src/Export/Scripts/miscdata.lua b/src/Export/Scripts/miscdata.lua index d4ac5e19ce..a93938b20f 100644 --- a/src/Export/Scripts/miscdata.lua +++ b/src/Export/Scripts/miscdata.lua @@ -49,6 +49,48 @@ for row in dat("GameConstants"):Rows() do end out:write('}\n') +out:write('-- From Metadata/Characters/Character.ot\n') +out:write('data.characterConstants = {\n') +local file = getFile("Metadata/Characters/Character.ot") +if not file then return nil end +local text = convertUTF16to8(file) +local inWantedBlock = false +for line in text:gmatch("[^\r\n]+") do + -- Detect start of a block + if line:match("^Stats") or line:match("^Pathfinding") then + inWantedBlock = true + elseif inWantedBlock and line:match("^}") then + inWantedBlock = false + elseif inWantedBlock and line:find("=") then + local key, value = line:gsub("%s+",""):match("^(.-)=(.+)$") + if key and value then + out:write('\t["' .. key .. '"] = ' .. value .. ',\n') + end + end +end +out:write('}\n') + +out:write('-- From Metadata/Monsters/Monster.ot\n') +out:write('data.monsterConstants = {\n') +local file = getFile("Metadata/Monsters/Monster.ot") +if not file then return nil end +local text = convertUTF16to8(file) +local inWantedBlock = false +for line in text:gmatch("[^\r\n]+") do + -- Detect start of a block + if line:match("^Stats") then + inWantedBlock = true + elseif inWantedBlock and line:match("^}") then + inWantedBlock = false + elseif inWantedBlock and line:find("=") then + local key, value = line:gsub("%s+",""):match("^(.-)=(.+)$") + if key and value then + out:write('\t["' .. key .. '"] = ' .. value .. ',\n') + end + end +end +out:write('}\n') + out:write('-- From PlayerMinionIntrinsicStats.dat\n') out:write('data.playerMinionIntrinsicStats = {\n') for row in dat("PlayerMinionIntrinsicStats"):Rows() do diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index fd90e5057b..d3f07bab77 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -2456,7 +2456,7 @@ function calcs.buildDefenceEstimations(env, actor) end else local stunDuration = (1 + modDB:Sum("INC", nil, "StunDuration") / 100) - local baseStunDuration = data.misc.StunBaseDuration + local baseStunDuration = actor == env.minion and data.misc.MinionBaseStunDuration or data.misc.StunBaseDuration local stunRecovery = (1 + modDB:Sum("INC", nil, "StunRecovery") / 100) local stunAndBlockRecovery = (1 + modDB:Sum("INC", nil, "StunRecovery", "BlockRecovery") / 100) output.StunDuration = m_ceil(baseStunDuration * stunDuration / stunRecovery * data.misc.ServerTickRate) / data.misc.ServerTickRate diff --git a/src/Modules/CalcOffence.lua b/src/Modules/CalcOffence.lua index fb117411e7..91a09f7f56 100644 --- a/src/Modules/CalcOffence.lua +++ b/src/Modules/CalcOffence.lua @@ -5008,7 +5008,7 @@ function calcs.offence(env, actor, activeSkill) local enemyArmour = m_max(calcLib.val(enemyDB, "Armour"), 0) local impaleArmourReduction = calcs.armourReductionF(enemyArmour, impaleHitDamageMod * output.PhysicalStoredCombinedAvg) - local impaleResist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction") + skillModList:Sum("BASE", cfg, "EnemyImpalePhysicalDamageReduction") + impaleArmourReduction), data.misc.DamageReductionCap) + local impaleResist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction") + skillModList:Sum("BASE", cfg, "EnemyImpalePhysicalDamageReduction") + impaleArmourReduction), data.misc.EnemyPhysicalDamageReductionCap) if skillModList:Flag(cfg, "IgnoreEnemyImpalePhysicalDamageReduction") then impaleResist = 0 end @@ -5195,7 +5195,7 @@ function calcs.offence(env, actor, activeSkill) local takenInc = enemyDB:Sum("INC", dotTakenCfg, "DamageTaken", "DamageTakenOverTime", damageType.."DamageTaken", damageType.."DamageTakenOverTime") + (isElemental[damageType] and enemyDB:Sum("INC", dotTakenCfg, "ElementalDamageTaken") or 0) local takenMore = enemyDB:More(dotTakenCfg, "DamageTaken", "DamageTakenOverTime", damageType.."DamageTaken", damageType.."DamageTakenOverTime") * (isElemental[damageType] and enemyDB:More(dotTakenCfg, "ElementalDamageTaken") or 1) if damageType == "Physical" then - resist = m_max(0, m_min(enemyDB:Sum("BASE", nil, "PhysicalDamageReduction"), data.misc.DamageReductionCap)) + resist = m_max(0, m_min(enemyDB:Sum("BASE", nil, "PhysicalDamageReduction"), data.misc.EnemyPhysicalDamageReductionCap)) else resist = calcResistForType(damageType, dotTypeCfg) end diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index c7592e9ad2..39571a9bb5 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -895,9 +895,9 @@ function calcs.perform(env, skipEHP) if modDB:Flag(nil, "MinionAccuracyEqualsAccuracy") then env.minion.modDB:NewMod("Accuracy", "BASE", calcLib.val(modDB, "Accuracy") + calcLib.val(modDB, "Dex") * (modDB:Override(nil, "DexAccBonusOverride") or data.misc.AccuracyPerDexBase), "Player") else - env.minion.modDB:NewMod("Accuracy", "BASE", round(env.data.monsterAccuracyTable[env.minion.level] * (env.minion.minionData.accuracy or 1)) + data.playerMinionIntrinsicStats.accuracy_rating_per_level * (env.minion.level - 1), "Base") + env.minion.modDB:NewMod("Accuracy", "BASE", round(env.data.monsterAccuracyTable[env.minion.level] * (env.minion.minionData.accuracy or 1)) + data.playerMinionIntrinsicStats["accuracy_rating_per_level"] * (env.minion.level - 1), "Base") end - env.minion.modDB:NewMod("CritMultiplier", "BASE", 100, "Base") + env.minion.modDB:NewMod("CritMultiplier", "BASE", env.data.monsterConstants["base_critical_hit_damage_bonus"] + env.data.playerMinionIntrinsicStats["base_critical_hit_damage_bonus"], "Base") env.minion.modDB:NewMod("FireResist", "BASE", env.minion.minionData.fireResist, "Base") env.minion.modDB:NewMod("ColdResist", "BASE", env.minion.minionData.coldResist, "Base") env.minion.modDB:NewMod("LightningResist", "BASE", env.minion.minionData.lightningResist, "Base") diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index 27b1956195..96b59f0550 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -16,21 +16,21 @@ local tempTable1 = { } -- Initialise modifier database with stats and conditions common to all actors function calcs.initModDB(env, modDB) - modDB:NewMod("FireResistMax", "BASE", 75, "Base") - modDB:NewMod("ColdResistMax", "BASE", 75, "Base") - modDB:NewMod("LightningResistMax", "BASE", 75, "Base") - modDB:NewMod("ChaosResistMax", "BASE", 75, "Base") + modDB:NewMod("FireResistMax", "BASE", data.characterConstants["base_maximum_all_resistances_%"], "Base") + modDB:NewMod("ColdResistMax", "BASE", data.characterConstants["base_maximum_all_resistances_%"], "Base") + modDB:NewMod("LightningResistMax", "BASE", data.characterConstants["base_maximum_all_resistances_%"], "Base") + modDB:NewMod("ChaosResistMax", "BASE", data.characterConstants["base_maximum_all_resistances_%"], "Base") modDB:NewMod("TotemFireResistMax", "BASE", 75, "Base") modDB:NewMod("TotemColdResistMax", "BASE", 75, "Base") modDB:NewMod("TotemLightningResistMax", "BASE", 75, "Base") modDB:NewMod("TotemChaosResistMax", "BASE", 75, "Base") - modDB:NewMod("BlockChanceMax", "BASE", 75, "Base") - modDB:NewMod("SpellBlockChanceMax", "BASE", 75, "Base") + modDB:NewMod("BlockChanceMax", "BASE", data.characterConstants["object_inherent_base_maximum_block_%_from_ot"], "Base") + modDB:NewMod("SpellBlockChanceMax", "BASE", data.characterConstants["base_maximum_spell_block_%"], "Base") modDB:NewMod("SpellDodgeChanceMax", "BASE", 75, "Base") modDB:NewMod("ChargeDuration", "BASE", 15, "Base") - modDB:NewMod("PowerChargesMax", "BASE", 3, "Base") - modDB:NewMod("FrenzyChargesMax", "BASE", 3, "Base") - modDB:NewMod("EnduranceChargesMax", "BASE", 3, "Base") + modDB:NewMod("PowerChargesMax", "BASE", data.characterConstants["max_power_charges"], "Base") + modDB:NewMod("FrenzyChargesMax", "BASE", data.characterConstants["max_frenzy_charges"], "Base") + modDB:NewMod("EnduranceChargesMax", "BASE", data.characterConstants["max_endurance_charges"], "Base") modDB:NewMod("SiphoningChargesMax", "BASE", 0, "Base") modDB:NewMod("ChallengerChargesMax", "BASE", 0, "Base") modDB:NewMod("BlitzChargesMax", "BASE", 0, "Base") @@ -91,7 +91,7 @@ function calcs.initModDB(env, modDB) modDB:NewMod("Convergence", "FLAG", true, "Base", { type = "Condition", var = "Convergence" }) modDB:NewMod("PhysicalDamageReduction", "BASE", -15, "Base", { type = "Condition", var = "Crushed" }) modDB:NewMod("CritChanceCap", "BASE", 100, "Base") - modDB:NewMod("PresenceRadius", "BASE", data.misc.presenceRadiusBase, "Base") + modDB:NewMod("PresenceRadius", "BASE", data.characterConstants["base_presence_radius"], "Base") modDB.conditions["Buffed"] = env.mode_buffs modDB.conditions["Combat"] = env.mode_combat modDB.conditions["Effective"] = env.mode_effective @@ -561,14 +561,14 @@ function calcs.initEnv(build, mode, override, specEnv) end modDB.multipliers["Level"] = m_max(1, m_min(100, build.characterLevel)) calcs.initModDB(env, modDB) - modDB:NewMod("Life", "BASE", 12, "Base", { type = "Multiplier", var = "Level", base = 16 }) - modDB:NewMod("Mana", "BASE", 4, "Base", { type = "Multiplier", var = "Level", base = 30 }) - modDB:NewMod("ManaRegen", "BASE", 0.04, "Base", { type = "PerStat", stat = "Mana", div = 1 }, { type = "Condition", var = "NoInherentManaRegen", neg = true }) + modDB:NewMod("Life", "BASE", data.characterConstants["life_per_level"], "Base", { type = "Multiplier", var = "Level", base = 16 }) + modDB:NewMod("Mana", "BASE", data.characterConstants["mana_per_level"], "Base", { type = "Multiplier", var = "Level", base = 30 }) + modDB:NewMod("ManaRegen", "BASE", env.data.misc.ManaRegenBase, "Base", { type = "PerStat", stat = "Mana", div = 1 }, { type = "Condition", var = "NoInherentManaRegen", neg = true }) modDB:NewMod("Spirit", "BASE", 0, "Base") modDB:NewMod("Devotion", "BASE", 0, "Base") - modDB:NewMod("Evasion", "BASE", 3, "Base", { type = "Multiplier", var = "Level", base = 27 }) - modDB:NewMod("Accuracy", "BASE", 3, "Base", { type = "Multiplier", var = "Level", base = -3 }) - modDB:NewMod("CritMultiplier", "BASE", 100, "Base") + modDB:NewMod("Evasion", "BASE", data.characterConstants["evasion_rating_per_level"] / 100, "Base", { type = "Multiplier", var = "Level", base = data.characterConstants["base_evasion_rating"] }) + modDB:NewMod("Accuracy", "BASE", data.characterConstants["accuracy_rating_per_level"], "Base", { type = "Multiplier", var = "Level", base = -data.characterConstants["accuracy_rating_per_level"] }) + modDB:NewMod("CritMultiplier", "BASE", data.characterConstants["base_critical_hit_damage_bonus"], "Base") modDB:NewMod("DotMultiplier", "BASE", 50, "Base", { type = "Condition", var = "CriticalStrike" }) modDB:NewMod("FireResist", "BASE", env.configInput.resistancePenalty or -60, "Base") modDB:NewMod("ColdResist", "BASE", env.configInput.resistancePenalty or -60, "Base") @@ -578,17 +578,17 @@ function calcs.initEnv(build, mode, override, specEnv) modDB:NewMod("TotemColdResist", "BASE", 40, "Base") modDB:NewMod("TotemLightningResist", "BASE", 40, "Base") modDB:NewMod("TotemChaosResist", "BASE", 20, "Base") - modDB:NewMod("MaximumRage", "BASE", 30, "Base") - modDB:NewMod("MaximumFortification", "BASE", 20, "Base") + modDB:NewMod("MaximumRage", "BASE", data.characterConstants["maximum_rage"], "Base") + modDB:NewMod("MaximumFortification", "BASE", data.characterConstants["base_max_fortification"], "Base") modDB:NewMod("MaximumValour", "BASE", 50, "Base") modDB:NewMod("SoulEaterMax", "BASE", 45, "Base") modDB:NewMod("Multiplier:IntensityLimit", "BASE", 3, "Base") - modDB:NewMod("Damage", "INC", 2, "Base", { type = "Multiplier", var = "Rampage", limit = 50, div = 20 }) - modDB:NewMod("MovementSpeed", "INC", 1, "Base", { type = "Multiplier", var = "Rampage", limit = 50, div = 20 }) + modDB:NewMod("Damage", "INC", data.characterConstants["damage_+%_per_10_rampage_stacks"], "Base", { type = "Multiplier", var = "Rampage", limit = data.characterConstants["max_rampage_stacks"] / 20, div = 20 }) + modDB:NewMod("MovementSpeed", "INC", data.characterConstants["movement_velocity_+%_per_10_rampage_stacks"], "Base", { type = "Multiplier", var = "Rampage", limit = data.characterConstants["max_rampage_stacks"] / 20, div = 20 }) modDB:NewMod("Speed", "INC", 5, "Base", ModFlag.Attack, { type = "Multiplier", var = "SoulEater"}) modDB:NewMod("Speed", "INC", 5, "Base", ModFlag.Cast, { type = "Multiplier", var = "SoulEater" }) - modDB:NewMod("ActiveTrapLimit", "BASE", 15, "Base") - modDB:NewMod("ActiveMineLimit", "BASE", 15, "Base") + modDB:NewMod("ActiveTrapLimit", "BASE", data.characterConstants["base_number_of_traps_allowed"], "Base") + modDB:NewMod("ActiveMineLimit", "BASE", data.characterConstants["base_number_of_remote_mines_allowed"], "Base") modDB:NewMod("MineThrowCount", "BASE", 1, "Base") modDB:NewMod("TrapThrowCount", "BASE", 1, "Base") modDB:NewMod("ActiveBrandLimit", "BASE", 3, "Base") @@ -600,17 +600,17 @@ function calcs.initEnv(build, mode, override, specEnv) modDB:NewMod("Speed", "MORE", 20, "Base", ModFlag.Attack, { type = "Condition", var = "DualWielding" }, { type = "Condition", var = "DoubledInherentDualWieldingSpeed"}) modDB:NewMod("BlockChance", "BASE", 20, "Base", { type = "Condition", var = "DualWielding" }, { type = "Condition", var = "NoInherentBlock", neg = true}, { type = "Condition", var = "DoubledInherentDualWieldingBlock", neg = true}) modDB:NewMod("BlockChance", "BASE", 40, "Base", { type = "Condition", var = "DualWielding" }, { type = "Condition", var = "NoInherentBlock", neg = true}, { type = "Condition", var = "DoubledInherentDualWieldingBlock"}) - modDB:NewMod("AilmentMagnitude", "MORE", 100, "Base", 0, KeywordFlag.Bleed, { type = "ActorCondition", actor = "enemy", varList = { "Moving", "BleedAggravated" } }, { type = "Condition", var = "NoExtraBleedDamageToMovingEnemy", neg = true }) + modDB:NewMod("AilmentMagnitude", "MORE", data.monsterConstants["bleeding_moving_damage_%_of_base_override"] - 100, "Base", 0, KeywordFlag.Bleed, { type = "ActorCondition", actor = "enemy", varList = { "Moving", "BleedAggravated" } }, { type = "Condition", var = "NoExtraBleedDamageToMovingEnemy", neg = true }) modDB:NewMod("Condition:BloodStance", "FLAG", true, "Base", { type = "Condition", var = "SandStance", neg = true }) modDB:NewMod("Condition:PrideMinEffect", "FLAG", true, "Base", { type = "Condition", var = "PrideMaxEffect", neg = true }) - modDB:NewMod("PerBrutalTripleDamageChance", "BASE", 3, "Base") + modDB:NewMod("PerBrutalTripleDamageChance", "BASE", data.characterConstants["chance_to_deal_triple_damage_%_per_brutal_charge"], "Base") modDB:NewMod("PerAfflictionAilmentDamage", "BASE", 8, "Base") modDB:NewMod("PerAfflictionNonDamageEffect", "BASE", 8, "Base") - modDB:NewMod("PerAbsorptionElementalEnergyShieldRecoup", "BASE", 12, "Base") + modDB:NewMod("PerAbsorptionElementalEnergyShieldRecoup", "BASE", data.characterConstants["elemental_damage_taken_goes_to_energy_shield_over_4_seconds_%_per_absorption_charge"], "Base") modDB:NewMod("CharmLimit", "BASE", 0, "Base") modDB:NewMod("ManaDegenPercent", "BASE", 1, "Base", { type = "Multiplier", var = "EffectiveManaBurnStacks" }) modDB:NewMod("LifeDegenPercent", "BASE", 1, "Base", { type = "Multiplier", var = "WeepingWoundsStacks" }) - modDB:NewMod("WeaponSwapSpeed", "BASE", 250, "Base") -- 250ms + modDB:NewMod("WeaponSwapSpeed", "BASE", data.characterConstants["base_weapon_swap_duration_ms"], "Base") -- 250ms modDB:NewMod("Speed", "INC", 3, "Base", ModFlag.Attack, { type = "Multiplier", var = "Tailwind", limit = 10 }) modDB:NewMod("Speed", "INC", 3, "Base", ModFlag.Cast, { type = "Multiplier", var = "Tailwind", limit = 10 }) modDB:NewMod("MovementSpeed", "INC", 1, "Base", { type = "Multiplier", var = "Tailwind", limit = 10 }) diff --git a/src/Modules/ConfigOptions.lua b/src/Modules/ConfigOptions.lua index 322abf432c..d7cbcdfb2b 100644 --- a/src/Modules/ConfigOptions.lua +++ b/src/Modules/ConfigOptions.lua @@ -1825,7 +1825,7 @@ Huge sets the radius to 11. -- These defaults are here so that the placeholders get reset correctly build.configTab.varControls['enemySpeed']:SetPlaceholder(700, true) build.configTab.varControls['enemyCritChance']:SetPlaceholder(5, true) - build.configTab.varControls['enemyCritDamage']:SetPlaceholder(30, true) + build.configTab.varControls['enemyCritDamage']:SetPlaceholder(data.monsterConstants["base_critical_hit_damage_bonus"], true) if val == "None" then local defaultResist = "" build.configTab.varControls['enemyLightningResist']:SetPlaceholder(defaultResist, true) @@ -2102,7 +2102,7 @@ Huge sets the radius to 11. enemyModList:NewMod("MultiplierPvpDamage", "BASE", val, "Config") end }, { var = "enemyCritChance", type = "countAllowZero", label = "Enemy critical strike chance:", defaultPlaceholderState = 5 }, - { var = "enemyCritDamage", type = "countAllowZero", label = "Enemy critical strike multiplier:", defaultPlaceholderState = 30 }, + { var = "enemyCritDamage", type = "countAllowZero", label = "Enemy critical strike multiplier:", defaultPlaceholderState = data.monsterConstants["base_critical_hit_damage_bonus"] }, { var = "enemyPhysicalDamage", type = "countAllowZero", label = "Enemy Skill Physical Damage:", tooltip = "This overrides the default damage amount used to estimate your damage reduction from armour.\nThe default is 1.5 times the enemy's base damage, which is the same value\nused in-game to calculate the estimate shown on the character sheet.", defaultPlaceholderState = 7 }, { var = "enemyPhysicalOverwhelm", type = "countAllowZero", label = "Enemy Skill Physical Overwhelm:"}, { var = "enemyLightningDamage", type = "countAllowZero", label = "Enemy Skill ^xADAA47Lightning Damage:"}, diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index ecad2b58d4..e08f51473d 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -157,11 +157,11 @@ data.misc = { -- magic numbers LowPoolThreshold = 0.35, TemporalChainsEffectCap = 75, BuffExpirationSlowCap = 0.25, - DamageReductionCap = 90, - EnemyPhysicalDamageReductionCap = 75, + DamageReductionCap = data.characterConstants["maximum_physical_damage_reduction_%"], + EnemyPhysicalDamageReductionCap = data.monsterConstants["maximum_physical_damage_reduction_%"], ResistFloor = -200, MaxResistCap = 90, - EvadeChanceCap = 95, + EvadeChanceCap = data.characterConstants["base_maximum_chance_to_evade_%"], DodgeChanceCap = 75, BlockChanceCap = 90, SuppressionChanceCap = 100, @@ -169,14 +169,15 @@ data.misc = { -- magic numbers AvoidChanceCap = 75, AccuracyFalloffStart = 20, AccuracyFalloffEnd = 120, - MaxAccuracyRangePenalty = 90, + MaxAccuracyRangePenalty = -data.characterConstants["accuracy_rating_+%_final_at_max_distance_scaled"], ArmourRatio = 10, NegArmourDmgBonusCap = 100, - EnergyShieldRechargeBase = 0.125, + ManaRegenBase = data.characterConstants["character_inherent_mana_regeneration_rate_per_minute_%"] / 60 / 100, + EnergyShieldRechargeBase = data.characterConstants["energy_shield_recharge_rate_per_minute_%"] / 60 / 100, EnergyShieldRechargeDelay = 4, WardRechargeDelay = 2, Transfiguration = 0.3, - EnemyMaxResist = 75, + EnemyMaxResist = data.monsterConstants["base_maximum_all_resistances_%"], LeechRateBase = 0.02, DotDpsCap = 35791394, -- (2 ^ 31 - 1) / 60 (int max / 60 seconds) BleedPercentBase = data.gameConstants["BleedingHitDamagePercentPerMinute"] / 60 / 100, @@ -189,13 +190,15 @@ data.misc = { -- magic numbers TrapTriggerRadiusBase = 10, MineDetonationRadiusBase = 60, MineAuraRadiusBase = 35, - MinionRevivalTimeBase = 7.5, + MinionRevivalTimeBase = data.characterConstants["global_resummon_time_ms"] / 1000, BrandAttachmentRangeBase = 30, ProjectileDistanceCap = 150, MinStunChanceNeeded = 20, StunBaseMult = 200, - StunBaseDuration = 0.35, - StunNotMeleeDamageMult = 0.75, + StunBaseDuration = data.characterConstants["stun_base_duration_override_ms"] / 1000, + MinionBaseStunDuration = (data.monsterConstants["stun_base_duration_override_ms"] + data.playerMinionIntrinsicStats["stun_base_duration_override_ms"]) / 1000, + StunNotMeleeDamageMult = 1 / (1 + data.monsterConstants["melee_hit_damage_stun_multiplier_+%"] / 100), + PlayerMovementSpeed = data.characterConstants["base_speed"], MaxEnemyLevel = 85, maxExperiencePenaltyFreeAreaLevel = 70, experiencePenaltyMultiplier = 0.06, @@ -220,7 +223,6 @@ data.misc = { -- magic numbers PvpElemental2 = 150, PvpNonElemental1 = 0.57, PvpNonElemental2 = 90, - presenceRadiusBase = 40, -- in units (base entity "Presence" radius of patch 0.2.0 is 4 meters) } data.skillColorMap = { colorCodes.STRENGTH, colorCodes.DEXTERITY, colorCodes.INTELLIGENCE, colorCodes.NORMAL }