1use common::{
2 comp::{
3 Body, CharacterActivity, Collider, ControlAction, Controller, InputKind, Ori, PhysicsState,
4 Pos, Scale, Vel,
5 },
6 link::Is,
7 mounting::{Mount, Rider, VolumeRider},
8 terrain::TerrainGrid,
9 uid::IdMaps,
10};
11use common_ecs::{Job, Origin, Phase, System};
12use specs::{Entities, Join, LendJoin, Read, ReadExpect, ReadStorage, WriteStorage};
13use vek::*;
14
15#[derive(Default)]
17pub struct Sys;
18impl<'a> System<'a> for Sys {
19 type SystemData = (
20 Read<'a, IdMaps>,
21 ReadExpect<'a, TerrainGrid>,
22 Entities<'a>,
23 WriteStorage<'a, Controller>,
24 ReadStorage<'a, Is<Rider>>,
25 ReadStorage<'a, Is<Mount>>,
26 ReadStorage<'a, Is<VolumeRider>>,
27 WriteStorage<'a, Pos>,
28 WriteStorage<'a, Vel>,
29 WriteStorage<'a, Ori>,
30 WriteStorage<'a, CharacterActivity>,
31 WriteStorage<'a, PhysicsState>,
32 ReadStorage<'a, Body>,
33 ReadStorage<'a, Scale>,
34 ReadStorage<'a, Collider>,
35 );
36
37 const NAME: &'static str = "mount";
38 const ORIGIN: Origin = Origin::Common;
39 const PHASE: Phase = Phase::Create;
40
41 fn run(
42 _job: &mut Job<Self>,
43 (
44 id_maps,
45 terrain,
46 entities,
47 mut controllers,
48 is_riders,
49 is_mounts,
50 is_volume_riders,
51 mut positions,
52 mut velocities,
53 mut orientations,
54 mut character_activities,
55 mut physics_states,
56 bodies,
57 scales,
58 colliders,
59 ): Self::SystemData,
60 ) {
61 for (entity, is_mount, body) in (&entities, &is_mounts, bodies.maybe()).join() {
63 let Some((inputs_and_actions, rider)) =
65 id_maps.uid_entity(is_mount.rider).and_then(|rider| {
66 controllers.get_mut(rider).map(|c| {
67 (
68 if !matches!(body, Some(Body::Humanoid(_))) {
71 let actions = c
72 .actions
73 .extract_if(.., |action| match action {
74 ControlAction::StartInput { input: i, .. }
75 | ControlAction::CancelInput(i) => matches!(
76 i,
77 InputKind::Jump | InputKind::Fly | InputKind::Roll
78 ),
79 _ => false,
80 })
81 .collect();
82 Some((c.inputs.clone(), actions))
83 } else {
84 None
85 },
86 rider,
87 )
88 })
89 })
90 else {
91 continue;
92 };
93
94 let pos = positions.get(entity).copied();
96 let ori = orientations.get(entity).copied();
97 let vel = velocities.get(entity).copied();
98 if let (Some(pos), Some(ori), Some(vel)) = (pos, ori, vel) {
99 let mounter_body = bodies.get(rider);
100 let mounting_offset = body.map_or(Vec3::unit_z(), Body::mount_offset)
101 * scales.get(entity).map_or(1.0, |s| s.0)
102 + mounter_body.map_or(Vec3::zero(), Body::rider_offset)
103 * scales.get(rider).map_or(1.0, |s| s.0);
104 let _ = positions.insert(rider, Pos(pos.0 + ori.to_quat() * mounting_offset));
105 let _ = orientations.insert(rider, ori);
106 let _ = velocities.insert(rider, vel);
107 }
108 if let Some((inputs, actions)) = inputs_and_actions
110 && let Some(controller) = controllers.get_mut(entity)
111 {
112 controller.inputs = inputs;
113 controller.actions = actions;
114 }
115 }
116
117 for (physics_state, _) in (
121 &mut physics_states,
122 is_riders.mask() | is_volume_riders.mask(),
123 )
124 .join()
125 {
126 *physics_state = PhysicsState::default();
127 }
128
129 for (entity, is_volume_rider) in (&entities, &is_volume_riders).join() {
131 if let Some((mat, _)) = is_volume_rider.pos.get_mount_mat(
132 &terrain,
133 &id_maps,
134 |e| positions.get(e).copied().zip(orientations.get(e).copied()),
135 &colliders,
136 ) {
137 if let Some(pos) = positions.get_mut(entity) {
138 pos.0 = mat.mul_point(Vec3::zero());
139 }
140 if let Some(ori) = orientations.get_mut(entity) {
141 *ori = Ori::from_unnormalized_vec(mat.mul_direction(Vec3::unit_y()))
142 .unwrap_or_default();
143 }
144 }
145 let v = match is_volume_rider.pos.kind {
146 common::mounting::Volume::Terrain => Vec3::zero(),
147 common::mounting::Volume::Entity(uid) => {
148 if let Some(v) = id_maps.uid_entity(uid).and_then(|e| velocities.get(e)) {
149 v.0
150 } else {
151 Vec3::zero()
152 }
153 },
154 };
155 if let Some(vel) = velocities.get_mut(entity) {
156 vel.0 = v;
157 }
158
159 let inputs = controllers.get_mut(entity).map(|c| {
160 let actions: Vec<_> = c
161 .actions
162 .extract_if(.., |action| match action {
163 ControlAction::StartInput { input: i, .. }
164 | ControlAction::CancelInput(i) => {
165 matches!(i, InputKind::Jump | InputKind::Fly | InputKind::Roll)
166 },
167 _ => false,
168 })
169 .collect();
170 let inputs = c.inputs.clone();
171
172 (actions, inputs)
173 });
174
175 if is_volume_rider.block.is_controller() {
176 if let Some((actions, inputs)) = inputs {
177 if let Some(mut character_activity) = character_activities
178 .get_mut(entity)
179 .filter(|c| c.steer_dir != inputs.move_dir.y)
180 {
181 character_activity.steer_dir = inputs.move_dir.y;
182 }
183 match is_volume_rider.pos.kind {
184 common::mounting::Volume::Entity(uid) => {
185 if let Some(controller) =
186 id_maps.uid_entity(uid).and_then(|e| controllers.get_mut(e))
187 {
188 controller.inputs = inputs;
189 controller.actions = actions;
190 }
191 },
192 common::mounting::Volume::Terrain => {},
193 }
194 }
195 }
196 }
197 }
198}