Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions spec/System/TestImpale_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -112,34 +112,34 @@ describe("TestAttacks", function()
build.configTab.input.customMods = "\z
never deal critical strikes\n\z
"
build.configTab.input.enemyPhysicalReduction = 10
build.configTab.input.enemyPhysicalReduction = 8
build.configTab.input.enemyArmour = 1000 -- 50% dr for 200 damage, 66.6% dr for 100 dmg (impale stacks)
build.configTab:BuildModList()
runCallback("OnFrame")

-- dam * (1 - (armourDR + additionalDR)
assert.are.equals(200 * (1 - (0.5 + 0.1)), build.calcsTab.mainOutput.MainHand.PhysicalHitAverage)
assert.are.equals(200 * (1 - (0.5 + 0.08)), build.calcsTab.mainOutput.MainHand.PhysicalHitAverage)
assert.are.equals(200, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg)
assert.are.equals(200, build.calcsTab.mainOutput.impaleStoredHitAvg)
-- [5 impales * 10% stored damage] * 1.3 attacks * (armour mod - phys DR)
assert.are.near(100 * 1.3 * (1 - (2/3 + 0.1)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
assert.are.near(100 * 1.3 * (1 - (2/3 + 0.08)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math


-- 100% crit
build.configTab.input.customMods = "\z
+100% critical strike chance\n\z
"
build.configTab.input.enemyPhysicalReduction = 10
build.configTab.input.enemyPhysicalReduction = 8
build.configTab.input.enemyArmour = 1500 -- 50% dr for 300 damage, 66.6% dr for 150 dmg (impale stacks)
build.configTab:BuildModList()
runCallback("OnFrame")

-- dam * (1 - (armourDR + additionalDR)
assert.are.equals(300 * (1 - (0.5 + 0.1)), build.calcsTab.mainOutput.MainHand.PhysicalCritAverage)
assert.are.equals(300 * (1 - (0.5 + 0.08)), build.calcsTab.mainOutput.MainHand.PhysicalCritAverage)
assert.are.equals(300, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg)
assert.are.equals(300, build.calcsTab.mainOutput.impaleStoredHitAvg)
-- [5 impales * 10% stored damage] * 1.3 attacks * (armour mod - phys DR)
assert.are.near(150 * 1.3 * (1 - (2/3 + 0.1)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
assert.are.near(150 * 1.3 * (1 - (2/3 + 0.08)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math

end)

Expand All @@ -149,35 +149,35 @@ describe("TestAttacks", function()
never deal critical strikes\n\z
Nearby enemies take 100% increased physical damage\n\z
"
build.configTab.input.enemyPhysicalReduction = 10
build.configTab.input.enemyPhysicalReduction = 8
build.configTab.input.enemyArmour = 1000 -- 50% dr for 200 damage, 66.6% dr for 100 dmg (impale stacks) .. damage taken is after armour
build.configTab:BuildModList()
runCallback("OnFrame")

-- taken * dam * (1 - (armourDR + additionalDR)
assert.are.equals(2 * 200 * (1 - (0.5 + 0.1)), build.calcsTab.mainOutput.MainHand.PhysicalHitAverage)
assert.are.equals(2 * 200 * (1 - (0.5 + 0.08)), build.calcsTab.mainOutput.MainHand.PhysicalHitAverage)
assert.are.equals(200, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg)
assert.are.equals(200, build.calcsTab.mainOutput.impaleStoredHitAvg)
-- taken * [5 impales * 10% stored damage] * 1.3 attacks * (armour mod - phys DR)
assert.are.near(2 * 100 * 1.3 * (1 - (2/3 + 0.1)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
assert.are.near(2 * 100 * 1.3 * (1 - (2/3 + 0.08)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math


-- 100% crit
build.configTab.input.customMods = "\z
+100% critical strike chance\n\z
Nearby enemies take 100% increased physical damage\n\z
"
build.configTab.input.enemyPhysicalReduction = 10
build.configTab.input.enemyPhysicalReduction = 8
build.configTab.input.enemyArmour = 1500 -- 50% dr for 300 damage, 66.6% dr for 150 dmg (impale stacks)
build.configTab:BuildModList()
runCallback("OnFrame")

-- taken * dam * (1 - (armourDR + additionalDR)
assert.are.equals(2 * 300 * (1 - (0.5 + 0.1)), build.calcsTab.mainOutput.MainHand.PhysicalCritAverage)
assert.are.equals(2 * 300 * (1 - (0.5 + 0.08)), build.calcsTab.mainOutput.MainHand.PhysicalCritAverage)
assert.are.equals(300, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg)
assert.are.equals(300, build.calcsTab.mainOutput.impaleStoredHitAvg)
-- taken * [5 impales * 10% stored damage] * 1.3 attacks * (armour mod - phys DR)
assert.are.near(2 * 150 * 1.3 * (1 - (2/3 + 0.1)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
assert.are.near(2 * 150 * 1.3 * (1 - (2/3 + 0.08)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math

end)

Expand Down
147 changes: 147 additions & 0 deletions src/Data/Misc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,153 @@ data.gameConstants = {
["GoldPlusPercentPerAffix"] = 10,
["UniqueBaseGoldCost"] = 2000,
}
-- From Metadata/Characters/Character.ot
data.characterConstants = {
["level"] = 1,
["is_player"] = 1,
["energy_shield_recharge_rate_per_minute_%"] = 2000,
["mana_regeneration_rate_per_minute_%"] = 105,
["base_maximum_all_resistances_%"] = 75,
["maximum_physical_damage_reduction_%"] = 90,
["maximum_block_%"] = 75,
["base_maximum_spell_block_%"] = 75,
["base_attack_speed_+%_per_frenzy_charge"] = 4,
["base_cast_speed_+%_per_frenzy_charge"] = 4,
["object_inherent_damage_+%_final_per_frenzy_charge"] = 4,
["physical_damage_reduction_%_per_endurance_charge"] = 4,
["elemental_damage_reduction_%_per_endurance_charge"] = 4,
["critical_strike_chance_+%_per_power_charge"] = 50,
["max_viper_strike_orbs"] = 4,
["dual_wield_inherent_attack_speed_+%_final"] = 10,
["max_fuse_arrow_orbs"] = 5,
["max_fire_beam_stacks"] = 8,
["base_evasion_rating"] = 15,
["life_per_level"] = 12,
["mana_per_level"] = 6,
["accuracy_rating_per_level"] = 2,
["inherent_block_while_dual_wielding_%"] = 20,
["base_critical_strike_multiplier"] = 150,
["critical_ailment_dot_multiplier_+"] = 50,
["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_totems_allowed"] = 1,
["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,
["maximum_life_leech_rate_%_per_minute"] = 1200,
["maximum_mana_leech_rate_%_per_minute"] = 1200,
["maximum_energy_shield_leech_rate_%_per_minute"] = 600,
["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,
["minion_global_always_hit"] = 1,
["traps_explode_on_timeout"] = 1,
["maximum_rage"] = 30,
["max_delve_degen_stacks"] = 5000,
["max_azurite_debuff_stacks"] = 10,
["melee_variation"] = 1,
["impaled_debuff_base_duration_ms"] = 8000,
["impaled_debuff_number_of_reflected_hits"] = 5,
["base_total_number_of_sigils_allowed"] = 3,
["maximum_life_leech_amount_per_leech_%_max_life"] = 10,
["maximum_mana_leech_amount_per_leech_%_max_mana"] = 10,
["maximum_energy_shield_leech_amount_per_leech_%_max_energy_shield"] = 10,
["enable_movement_skill_animation_skipping"] = 1,
["melee_hit_damage_stun_multiplier_+%"] = 25,
["non_physical_hit_damage_stun_multiplier_+%"] = -25,
["non_melee_hit_damage_stun_multiplier_+%_final"] = -25,
["object_inherent_melee_hit_stun_duration_+%_final"] = 50,
["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,
["ailment_damage_+%_final_per_affliction_charge"] = 8,
["non_damaging_ailment_effect_+%_final_per_affliction_charge"] = 8,
["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"] = 80,
["mtx_max_killcounter_stacks"] = 30000,
["soul_eater_maximum_stacks"] = 45,
["rage_loss_delay_ms"] = 2000,
["trigger_attack_graft_each_second_channeling"] = 1,
["base_speed"] = 37,
}
-- From Metadata/Monsters/Monster.ot
data.monsterConstants = {
["item_drop_slots"] = 1,
["energy_shield_recharge_rate_per_minute_%"] = 2000,
["mana_regeneration_rate_per_minute_%"] = 100,
["base_maximum_mana"] = 200,
["maximum_physical_damage_reduction_%"] = 75,
["max_viper_strike_orbs"] = 4,
["base_maximum_all_resistances_%"] = 75,
["max_fuse_arrow_orbs"] = 5,
["max_fire_beam_stacks"] = 8,
["max_charged_attack_stacks"] = 10,
["base_critical_strike_multiplier"] = 130,
["critical_ailment_dot_multiplier_+"] = 30,
["max_endurance_charges"] = 3,
["max_frenzy_charges"] = 3,
["max_power_charges"] = 3,
["base_attack_speed_+%_per_frenzy_charge"] = 4,
["base_attack_speed_+%_per_frenzy_charge_if_not_player_minion"] = 11,
["base_cast_speed_+%_per_frenzy_charge"] = 4,
["base_cast_speed_+%_per_frenzy_charge_if_not_player_minion"] = 11,
["movement_velocity_+%_per_frenzy_charge_if_not_player_minion"] = 5,
["object_inherent_damage_+%_final_per_frenzy_charge"] = 4,
["physical_damage_reduction_%_per_endurance_charge"] = 4,
["physical_damage_reduction_%_per_endurance_charge_if_not_player_minion"] = 11,
["elemental_damage_reduction_%_per_endurance_charge_if_player_minion"] = 4,
["resist_all_elements_%_per_endurance_charge_if_not_player_minion"] = 15,
["critical_strike_chance_+%_per_power_charge"] = 50,
["critical_strike_chance_+%_per_power_charge_if_not_player_minion"] = 150,
["maximum_block_%"] = 75,
["base_maximum_spell_block_%"] = 75,
["base_number_of_totems_allowed"] = 1,
["base_number_of_traps_allowed"] = 3,
["base_number_of_remote_mines_allowed"] = 5,
["movement_velocity_cap"] = 128,
["maximum_life_leech_rate_%_per_minute"] = 1200,
["maximum_mana_leech_rate_%_per_minute"] = 1200,
["maximum_energy_shield_leech_rate_%_per_minute"] = 600,
["monster_ignite_damage_+%_final"] = -72,
["monster_bleeding_damage_+%_final"] = -86,
["monster_poison_damage_+%_final"] = -50,
["bleeding_moving_damage_%_of_base_override"] = 500,
["max_azurite_debuff_stacks"] = 10,
["impaled_debuff_base_duration_ms"] = 8000,
["impaled_debuff_number_of_reflected_hits"] = 5,
["ignore_skill_weapon_restrictions"] = 1,
["base_total_number_of_sigils_allowed"] = 3,
["maximum_life_leech_amount_per_leech_%_max_life"] = 10,
["maximum_mana_leech_amount_per_leech_%_max_mana"] = 10,
["maximum_energy_shield_leech_amount_per_leech_%_max_energy_shield"] = 10,
["object_inherent_melee_hit_stun_duration_+%_final"] = 20,
["scale_melee_range_to_actor_scale"] = 1,
["use_melee_pattern_range"] = 1,
["actor_scale_+%_limit"] = 100,
["damage_taken_when_hit_+%_final_per_fortification"] = -1,
["base_max_fortification"] = 20,
["soul_eater_maximum_stacks"] = 45,
}
-- From MonsterVarieties.dat combined with SkillTotemVariations.dat
data.totemLifeMult = { [1] = 1, [2] = 1, [3] = 1, [4] = 1.2, [5] = 1, [6] = 1.2, [7] = 1.2, [8] = 1.2, [9] = 1, [10] = 1, [11] = 1, [12] = 1, [13] = 1.2, [15] = 1.2, [16] = 7.44, [17] = 1.2, [18] = 1, [19] = 1, [20] = 1.2, [21] = 1.2, }
data.monsterVarietyLifeMult = {
Expand Down
6 changes: 5 additions & 1 deletion src/Export/Classes/GGPKData.lua
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ function GGPKClass:GetNeededFiles()
"Metadata/StatDescriptions/tincture_stat_descriptions.txt",
"Metadata/StatDescriptions/graft_stat_descriptions.txt",
}
local otFiles = {
"Metadata/Characters/Character.ot",
"Metadata/Monsters/Monster.ot",
}
local itFiles = {
"Metadata/Items/Quivers/AbstractQuiver.it",
"Metadata/Items/Rings/AbstractRing.it",
Expand Down Expand Up @@ -351,5 +355,5 @@ function GGPKClass:GetNeededFiles()
"Metadata/Items/Tinctures/AbstractTincture.it",
"Metadata/Items/Jewels/AbstractAnimalCharm.it",
}
return datFiles, txtFiles, itFiles
return datFiles, txtFiles, otFiles, itFiles
end
42 changes: 42 additions & 0 deletions src/Export/Scripts/miscdata.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,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')

local totemMult = ""
local keys = { }
for var in dat("SkillTotemVariations"):Rows() do
Expand Down
8 changes: 4 additions & 4 deletions src/Modules/CalcOffence.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3198,7 +3198,7 @@ function calcs.offence(env, actor, activeSkill)
if skillModList:Flag(cfg, "IgnoreEnemyPhysicalDamageReduction") or ChanceToIgnoreEnemyPhysicalDamageReduction >= 100 then
resist = 0
else
resist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction") + skillModList:Sum("BASE", cfg, "EnemyPhysicalDamageReduction") + armourReduction), data.misc.DamageReductionCap)
resist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction") + skillModList:Sum("BASE", cfg, "EnemyPhysicalDamageReduction") + armourReduction), data.misc.EnemyPhysicalDamageReductionCap)
resist = resist > 0 and resist * (1 - (skillModList:Sum("BASE", nil, "PartialIgnoreEnemyPhysicalDamageReduction") / 100 + ChanceToIgnoreEnemyPhysicalDamageReduction / 100)) or resist
end
else
Expand Down Expand Up @@ -4204,7 +4204,7 @@ function calcs.offence(env, actor, activeSkill)
skillFlags.duration = true
local effMult = 1
if env.mode_effective then
local resist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction")), data.misc.DamageReductionCap)
local resist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction")), data.misc.EnemyPhysicalDamageReductionCap)
local takenInc = enemyDB:Sum("INC", dotCfg, "DamageTaken", "DamageTakenOverTime", "PhysicalDamageTaken", "PhysicalDamageTakenOverTime")
local takenMore = enemyDB:More(dotCfg, "DamageTaken", "DamageTakenOverTime", "PhysicalDamageTaken", "PhysicalDamageTakenOverTime")
effMult = (1 - resist / 100) * (1 + takenInc / 100) * takenMore
Expand Down Expand Up @@ -5209,7 +5209,7 @@ function calcs.offence(env, actor, activeSkill)

local enemyArmour = m_max(calcLib.val(enemyDB, "Armour"), 0)
local impaleArmourReduction = calcs.armourReductionF(enemyArmour, impaleHitDamageMod * output.impaleStoredHitAvg)
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
Expand Down Expand Up @@ -5422,7 +5422,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
Expand Down
Loading