steel_core/entity/ai/goal/
water_avoiding_random_stroll.rs1use 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}