steel_core/entity/mob_effect/
heal_or_harm.rs1use std::sync::Arc;
4
5use steel_registry::vanilla_damage_types;
6
7use super::{InstantaneousMobEffect, MobEffectBehavior};
8use crate::entity::damage::DamageSource;
9use crate::entity::{LivingEntity, SharedEntity};
10use crate::world::World;
11
12pub struct HealOrHarmBehavior {
14 pub is_harm: bool,
16}
17
18const BASE_HEAL_AMOUNT: i32 = 4;
20const BASE_HARM_AMOUNT: i32 = 6;
22
23impl MobEffectBehavior for HealOrHarmBehavior {
24 fn as_instantaneous(&self) -> Option<&dyn InstantaneousMobEffect> {
25 Some(self)
26 }
27
28 fn apply_effect_tick(&self, world: &World, user: &dyn LivingEntity, amplifier: i32) -> bool {
31 if self.is_harm == user.is_inverted_heal_and_harm() {
32 let amount = BASE_HEAL_AMOUNT.wrapping_shl(amplifier as u32).max(0);
35 user.heal(amount as f32);
36 } else {
37 user.hurt(
38 world,
39 &DamageSource::environment(&vanilla_damage_types::MAGIC),
40 BASE_HARM_AMOUNT.wrapping_shl(amplifier as u32) as f32,
41 );
42 }
43 true
44 }
45}
46
47impl InstantaneousMobEffect for HealOrHarmBehavior {
48 fn apply_instantaneous(
53 &self,
54 world: &World,
55 user: &dyn LivingEntity,
56 amplifier: i32,
57 direct_entity: Option<&SharedEntity>,
58 causing_entity: Option<&SharedEntity>,
59 scale: f64,
60 ) {
61 if self.is_harm == user.is_inverted_heal_and_harm() {
62 let amount =
63 (scale * f64::from(BASE_HEAL_AMOUNT.wrapping_shl(amplifier as u32)) + 0.5) as i32;
64 user.heal(amount as f32);
65 } else {
66 let mut source = DamageSource::environment(if direct_entity.is_some() {
67 &vanilla_damage_types::INDIRECT_MAGIC
68 } else {
69 &vanilla_damage_types::MAGIC
70 });
71 if let Some(direct) = direct_entity {
72 source = source.with_direct_entity(Arc::clone(direct));
73 if let Some(cause) = causing_entity {
74 source = source.with_causing_entity(Arc::clone(cause));
75 }
76 }
77 let amount =
80 (scale * f64::from(BASE_HARM_AMOUNT.wrapping_shl(amplifier as u32)) + 0.5) as i32;
81 user.hurt(world, &source, amount as f32);
82 }
83 }
84}