steel_core/entity/
combat_rules.rs1use crate::enchantment_helper::{self, EnchantmentDamageContext};
2use crate::entity::LivingEntity;
3
4use super::damage::DamageSource;
5
6const MAX_ARMOR: f32 = 20.0;
7const ARMOR_PROTECTION_DIVIDER: f32 = 25.0;
8const BASE_ARMOR_TOUGHNESS: f32 = 2.0;
9const MIN_ARMOR_RATIO: f32 = 0.2;
10
11pub(super) fn get_damage_after_absorb(
12 victim: &(impl LivingEntity + ?Sized),
13 damage: f32,
14 source: &DamageSource,
15 total_armor: f32,
16 armor_toughness: f32,
17) -> f32 {
18 let toughness = BASE_ARMOR_TOUGHNESS + armor_toughness / 4.0;
19 let real_armor =
20 (total_armor - damage / toughness).clamp(total_armor * MIN_ARMOR_RATIO, MAX_ARMOR);
21 let armor_fraction = real_armor / ARMOR_PROTECTION_DIVIDER;
22 let mut modified_armor_fraction = armor_fraction;
23
24 if let Some(direct_entity) = source.direct_entity() {
25 let context = EnchantmentDamageContext::from_damage_source(victim.entity_type(), source);
26 direct_entity.with_weapon_item(&mut |weapon| {
27 if let Some(weapon) = weapon {
28 modified_armor_fraction = enchantment_helper::modify_armor_effectiveness(
29 weapon,
30 &context,
31 armor_fraction,
32 )
33 .clamp(0.0, 1.0);
34 }
35 });
36 }
37
38 damage * (1.0 - modified_armor_fraction)
39}
40
41pub(super) fn get_damage_after_magic_absorb(damage: f32, total_magic_armor: f32) -> f32 {
42 let real_armor = total_magic_armor.clamp(0.0, MAX_ARMOR);
43 damage * (1.0 - real_armor / ARMOR_PROTECTION_DIVIDER)
44}
45
46#[cfg(test)]
47mod tests {
48 use super::get_damage_after_magic_absorb;
49
50 #[test]
51 fn magic_absorb_clamps_protection_to_vanilla_range() {
52 assert_eq!(
53 get_damage_after_magic_absorb(10.0, -1.0).to_bits(),
54 10.0_f32.to_bits()
55 );
56 assert_eq!(
57 get_damage_after_magic_absorb(10.0, 5.0).to_bits(),
58 8.0_f32.to_bits()
59 );
60 assert_eq!(
61 get_damage_after_magic_absorb(10.0, 25.0).to_bits(),
62 (10.0_f32 * (1.0 - 20.0_f32 / 25.0)).to_bits()
63 );
64 }
65}