veloren_voxygen/ecs/sys/
floater.rs

1use crate::ecs::comp::HpFloaterList;
2use common::{
3    comp::{Health, Pos},
4    resources::{DeltaTime, PlayerEntity},
5};
6use common_ecs::{Job, Origin, Phase, System};
7use specs::{Entities, Join, Read, ReadStorage, WriteStorage};
8
9// How long floaters last (in seconds)
10pub const HP_SHOWTIME: f32 = 3.0;
11pub const PRECISE_SHOWTIME: f32 = 0.7;
12pub const MY_HP_SHOWTIME: f32 = 2.5;
13
14#[derive(Default)]
15pub struct Sys;
16impl<'a> System<'a> for Sys {
17    type SystemData = (
18        Entities<'a>,
19        Read<'a, PlayerEntity>,
20        Read<'a, DeltaTime>,
21        ReadStorage<'a, Pos>,
22        ReadStorage<'a, Health>,
23        WriteStorage<'a, HpFloaterList>,
24    );
25
26    const NAME: &'static str = "floater";
27    const ORIGIN: Origin = Origin::Frontend("voxygen");
28    const PHASE: Phase = Phase::Create;
29
30    fn run(
31        _job: &mut Job<Self>,
32        (entities, my_entity, dt, pos, healths, mut hp_floater_lists): Self::SystemData,
33    ) {
34        // Add hp floater lists to all entities with health and a position
35        for entity in (&entities, &healths, &pos, !&hp_floater_lists)
36            .join()
37            .map(|(e, _, _, _)| e)
38            .collect::<Vec<_>>()
39        {
40            let _ = hp_floater_lists.insert(entity, HpFloaterList {
41                floaters: Vec::new(),
42                time_since_last_dmg_by_me: None,
43            });
44        }
45
46        // Remove floater lists on entities without health or without position
47        for entity in (&entities, !&healths, &hp_floater_lists)
48            .join()
49            .map(|(e, _, _)| e)
50            .collect::<Vec<_>>()
51        {
52            hp_floater_lists.remove(entity);
53        }
54        for entity in (&entities, !&pos, &hp_floater_lists)
55            .join()
56            .map(|(e, _, _)| e)
57            .collect::<Vec<_>>()
58        {
59            hp_floater_lists.remove(entity);
60        }
61
62        // Maintain existing floaters
63        for (entity, hp_floater_list) in (&entities, &mut hp_floater_lists).join() {
64            // Increment timer for time since last damaged by me
65            hp_floater_list
66                .time_since_last_dmg_by_me
67                .as_mut()
68                .map(|t| *t += dt.0);
69
70            for floater in hp_floater_list.floaters.iter_mut() {
71                // Increment timer
72                floater.timer += dt.0;
73                floater.jump_timer += dt.0;
74            }
75
76            // Clear floaters if newest floater is past show time
77            if hp_floater_list.floaters.last().is_some_and(|f| {
78                f.timer
79                    > if Some(entity) != my_entity.0 {
80                        HP_SHOWTIME
81                    } else {
82                        MY_HP_SHOWTIME
83                    }
84            }) {
85                hp_floater_list.floaters.clear();
86            }
87        }
88    }
89}