-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathfall_damage.rs
More file actions
56 lines (49 loc) · 2 KB
/
Copy pathfall_damage.rs
File metadata and controls
56 lines (49 loc) · 2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//! Handles fall damage for entities
use feather_core::util::Position;
use feather_server_types::{
BlocksFallen, BumpVec, CanTakeDamage, Dead, Game, Health, PreviousPosition,
};
use fecs::{component, Entity, IntoQuery, Read, World, Write};
use std::cell::RefCell;
/// System which updates `BlocksFallen` for all entities.
#[fecs::system]
pub fn update_blocks_fallen(game: &mut Game, world: &mut World) {
// Entities who went from !on_ground => on_ground
// (Legion for_each closures are not FnMuts; no idea why.)
let landed = RefCell::new(BumpVec::<Entity>::new_in(game.bump()));
// TODO: use parallel iterator (blocked on allocator API)
// (BumpVec isn't Send.)
<(Read<Position>, Read<PreviousPosition>, Write<BlocksFallen>)>::query()
.filter(component::<Health>())
.filter(component::<CanTakeDamage>())
.filter(!component::<Dead>())
.for_each_entities_mut(
world.inner_mut(),
|(entity, (pos, prev_pos, mut blocks_fallen))| {
match (prev_pos.0.map(|pos| pos.on_ground), pos.on_ground) {
(Some(false), false) => {
// In air: update blocks_fallen
blocks_fallen.0 += (prev_pos.0.unwrap().y - pos.y).max(0.0);
}
(Some(true), false) => {
// reset blocks_fallen
blocks_fallen.0 = 0.0;
}
(Some(false), true) => {
// landed
landed.borrow_mut().push(entity);
}
_ => (),
}
},
);
// Damage landed entities
for entity in landed.into_inner() {
let blocks_fallen = world.get::<BlocksFallen>(entity).0;
// https://minecraft.gamepedia.com/Damage#Fall_damage
let damage = (blocks_fallen - 3.0).max(0.0).round() as u32;
if damage != 0 {
game.damage(entity, damage, world);
}
}
}