Skip to main content

steel_core/entity/
combat_rules.rs

1use 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}