Skip to main content

steel_core/entity/ai/goal/
water_avoiding_random_stroll.rs

1use glam::DVec3;
2
3use super::random_pos::{default_random_pos, land_random_pos};
4use super::random_stroll::RandomStrollGoal;
5use super::selector::{Goal, GoalControls};
6use crate::entity::PathfinderMob;
7
8const WATER_AVOIDING_RANDOM_STROLL_PROBABILITY: f32 = 0.001;
9
10pub struct WaterAvoidingRandomStrollGoal {
11    stroll: RandomStrollGoal,
12    probability: f32,
13}
14
15impl WaterAvoidingRandomStrollGoal {
16    #[must_use]
17    pub const fn new(speed_modifier: f64) -> Self {
18        Self::with_probability(speed_modifier, WATER_AVOIDING_RANDOM_STROLL_PROBABILITY)
19    }
20
21    #[must_use]
22    pub const fn with_probability(speed_modifier: f64, probability: f32) -> Self {
23        Self {
24            stroll: RandomStrollGoal::new(speed_modifier),
25            probability,
26        }
27    }
28}
29
30impl Goal for WaterAvoidingRandomStrollGoal {
31    fn controls(&self) -> GoalControls {
32        self.stroll.controls()
33    }
34
35    fn can_use(&mut self, mob: &dyn PathfinderMob) -> bool {
36        let probability = self.probability;
37        self.stroll
38            .can_use_with_position(mob, |mob| random_stroll_pos(mob, probability))
39    }
40
41    fn can_continue_to_use(&mut self, mob: &dyn PathfinderMob) -> bool {
42        self.stroll.can_continue_to_use(mob)
43    }
44
45    fn start(&mut self, mob: &dyn PathfinderMob) {
46        self.stroll.start(mob);
47    }
48
49    fn stop(&mut self, mob: &dyn PathfinderMob) {
50        self.stroll.stop(mob);
51    }
52}
53
54fn random_stroll_pos(mob: &dyn PathfinderMob, probability: f32) -> Option<DVec3> {
55    if mob.is_in_water() {
56        return land_random_pos(mob, 15, 7).or_else(|| default_random_pos(mob, 10, 7));
57    }
58
59    let use_land_random_pos = rand::random::<f32>() >= probability;
60    if use_land_random_pos {
61        land_random_pos(mob, 10, 7)
62    } else {
63        default_random_pos(mob, 10, 7)
64    }
65}