veloren_voxygen_anim/quadruped_low/
mod.rs

1pub mod beta;
2pub mod breathe;
3pub mod combomelee;
4pub mod dash;
5pub mod idle;
6pub mod jump;
7pub mod leapshockwave;
8pub mod run;
9pub mod shockwave;
10pub mod shoot;
11pub mod spritesummon;
12pub mod stunned;
13pub mod tailwhip;
14
15// Reexports
16pub use self::{
17    beta::BetaAnimation, breathe::BreatheAnimation, combomelee::ComboAnimation,
18    dash::DashAnimation, idle::IdleAnimation, jump::JumpAnimation,
19    leapshockwave::LeapShockAnimation, run::RunAnimation, shockwave::ShockwaveAnimation,
20    shoot::ShootAnimation, spritesummon::SpriteSummonAnimation, stunned::StunnedAnimation,
21    tailwhip::TailwhipAnimation,
22};
23
24use super::{FigureBoneData, Offsets, Skeleton, make_bone, vek::*};
25use common::{
26    comp::{self},
27    states::utils::StageSection,
28};
29use core::convert::TryFrom;
30
31pub type Body = comp::quadruped_low::Body;
32
33skeleton_impls!(struct QuadrupedLowSkeleton {
34    + head_c_upper,
35    + pub head_c_lower,
36    + jaw_c,
37    + head_l_upper,
38    + pub head_l_lower,
39    + jaw_l,
40    + head_r_upper,
41    + pub head_r_lower,
42    + jaw_r,
43    + chest,
44    + tail_front,
45    + tail_rear,
46    + foot_fl,
47    + foot_fr,
48    + foot_bl,
49    + foot_br,
50    mount,
51});
52
53impl Skeleton for QuadrupedLowSkeleton {
54    type Attr = SkeletonAttr;
55    type Body = Body;
56
57    const BONE_COUNT: usize = 16;
58    #[cfg(feature = "use-dyn-lib")]
59    const COMPUTE_FN: &'static [u8] = b"quadruped_low_compute_mats\0";
60
61    #[cfg_attr(feature = "be-dyn-lib", export_name = "quadruped_low_compute_mats")]
62    fn compute_matrices_inner(
63        &self,
64        base_mat: Mat4<f32>,
65        buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
66        body: Self::Body,
67    ) -> Offsets {
68        let attr = SkeletonAttr::from(&body);
69        let base_mat = base_mat * Mat4::scaling_3d(attr.scaler / 11.0);
70
71        let chest_mat = base_mat * Mat4::<f32>::from(self.chest);
72        let tail_front = chest_mat * Mat4::<f32>::from(self.tail_front);
73        let tail_rear = tail_front * Mat4::<f32>::from(self.tail_rear);
74        let head_c_lower_mat = chest_mat * Mat4::<f32>::from(self.head_c_lower);
75        let head_c_upper_mat = head_c_lower_mat * Mat4::<f32>::from(self.head_c_upper);
76        let head_l_lower_mat = chest_mat * Mat4::<f32>::from(self.head_l_lower);
77        let head_l_upper_mat = head_l_lower_mat * Mat4::<f32>::from(self.head_l_upper);
78        let head_r_lower_mat = chest_mat * Mat4::<f32>::from(self.head_r_lower);
79        let head_r_upper_mat = head_r_lower_mat * Mat4::<f32>::from(self.head_r_upper);
80
81        *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
82            make_bone(head_c_upper_mat),
83            make_bone(head_c_lower_mat),
84            make_bone(head_c_upper_mat * Mat4::<f32>::from(self.jaw_c)),
85            make_bone(head_l_upper_mat),
86            make_bone(head_l_lower_mat),
87            make_bone(head_l_upper_mat * Mat4::<f32>::from(self.jaw_l)),
88            make_bone(head_r_upper_mat),
89            make_bone(head_r_lower_mat),
90            make_bone(head_r_upper_mat * Mat4::<f32>::from(self.jaw_r)),
91            make_bone(chest_mat),
92            make_bone(tail_front),
93            make_bone(tail_rear),
94            make_bone(chest_mat * Mat4::<f32>::from(self.foot_fl)),
95            make_bone(chest_mat * Mat4::<f32>::from(self.foot_fr)),
96            make_bone(chest_mat * Mat4::<f32>::from(self.foot_bl)),
97            make_bone(chest_mat * Mat4::<f32>::from(self.foot_br)),
98        ];
99        //let (mount_bone_mat, mount_bone_ori) = (chest_mat, self.chest.orientation);
100        // Offset from the mounted bone's origin.
101        // Note: This could be its own bone if we need to animate it independently.
102
103        // NOTE: We apply the ori from base_mat externally so we don't need to worry
104        // about it here for now.
105
106        use comp::quadruped_low::Species::*;
107        let (mount_bone_mat, mount_bone_ori) = match (body.species, body.body_type) {
108            (Maneater, _) => (
109                head_c_upper_mat,
110                self.chest.orientation
111                    * self.head_c_lower.orientation
112                    * self.head_c_upper.orientation,
113            ),
114            _ => (chest_mat, self.chest.orientation),
115        };
116        let mount_position = (mount_bone_mat * Vec4::from_point(mount_point(&body)))
117            .homogenized()
118            .xyz();
119        let mount_orientation = mount_bone_ori;
120
121        Offsets {
122            viewpoint: Some((head_c_upper_mat * Vec4::new(0.0, 4.0, 1.0, 1.0)).xyz()),
123            mount_bone: Transform {
124                position: mount_position,
125                orientation: mount_orientation,
126                scale: Vec3::one(),
127            },
128            heads: vec![
129                (head_l_upper_mat * Vec4::unit_w()).xyz(),
130                (head_c_upper_mat * Vec4::unit_w()).xyz(),
131                (head_r_upper_mat * Vec4::unit_w()).xyz(),
132            ],
133            tail: Some((
134                (tail_front * Vec4::unit_w()).xyz(),
135                (tail_rear * Vec4::new(0.0, -attr.tail_rear_length, 0.0, 1.0)).xyz(),
136            )),
137            ..Default::default()
138        }
139    }
140}
141
142pub struct SkeletonAttr {
143    head_upper: (f32, f32),
144    head_lower: (f32, f32),
145    jaw: (f32, f32),
146    side_head_lower: (f32, f32, f32),
147    side_head_upper: (f32, f32, f32),
148    chest: (f32, f32),
149    tail_front: (f32, f32),
150    tail_rear: (f32, f32),
151    tail_rear_length: f32,
152    feet_f: (f32, f32, f32),
153    feet_b: (f32, f32, f32),
154    lean: (f32, f32),
155    scaler: f32,
156    tempo: f32,
157    tongue_for_tail: bool,
158}
159
160impl<'a> TryFrom<&'a comp::Body> for SkeletonAttr {
161    type Error = ();
162
163    fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
164        match body {
165            comp::Body::QuadrupedLow(body) => Ok(SkeletonAttr::from(body)),
166            _ => Err(()),
167        }
168    }
169}
170
171impl Default for SkeletonAttr {
172    fn default() -> Self {
173        Self {
174            head_upper: (0.0, 0.0),
175            head_lower: (0.0, 0.0),
176            jaw: (0.0, 0.0),
177            side_head_lower: (0.0, 0.0, 0.0),
178            side_head_upper: (0.0, 0.0, 0.0),
179            chest: (0.0, 0.0),
180            tail_front: (0.0, 0.0),
181            tail_rear: (0.0, 0.0),
182            tail_rear_length: 0.0,
183            feet_f: (0.0, 0.0, 0.0),
184            feet_b: (0.0, 0.0, 0.0),
185            lean: (0.0, 0.0),
186            scaler: 0.0,
187            tempo: 0.0,
188            tongue_for_tail: false,
189        }
190    }
191}
192
193impl<'a> From<&'a Body> for SkeletonAttr {
194    fn from(body: &'a Body) -> Self {
195        use comp::quadruped_low::Species::*;
196        Self {
197            head_upper: match (body.species, body.body_type) {
198                (Crocodile, _) => (1.5, 2.0),
199                (SeaCrocodile, _) => (1.5, 2.0),
200                (Alligator, _) => (0.5, 2.0),
201                (Salamander, _) => (0.5, 1.0),
202                (Elbst, _) => (0.5, 1.0),
203                (Monitor, _) => (5.5, 3.0),
204                (Asp, _) => (4.5, 10.5),
205                (Tortoise, _) => (5.0, 1.0),
206                (Rocksnapper, _) => (6.0, 0.5),
207                (Rootsnapper, _) => (6.0, 0.5),
208                (Reefsnapper, _) => (6.0, 0.5),
209                (Pangolin, _) => (-0.5, 8.0),
210                (Maneater, _) => (7.0, 11.5),
211                (Sandshark, _) => (8.5, 0.5),
212                (Hakulaq, _) => (8.0, 10.0),
213                (Dagon, _) => (8.0, 10.0),
214                (Lavadrake, _) => (7.0, 8.0),
215                (Icedrake, _) => (7.0, 8.0),
216                (Basilisk, _) => (5.0, 2.5),
217                (Deadwood, _) => (2.0, -3.0),
218                (Mossdrake, _) => (7.0, 8.0),
219                (Driggle, _) => (3.0, 4.0),
220                (Snaretongue, _) => (7.0, 5.5),
221                (Hydra, _) => (12.0, 19.0),
222            },
223            head_lower: match (body.species, body.body_type) {
224                (Crocodile, _) => (8.0, 0.0),
225                (SeaCrocodile, _) => (8.0, 0.0),
226                (Alligator, _) => (9.0, 0.25),
227                (Salamander, _) => (9.0, 0.0),
228                (Elbst, _) => (9.0, 0.0),
229                (Monitor, _) => (7.0, 0.0),
230                (Asp, _) => (6.0, -2.5),
231                (Tortoise, _) => (12.0, -3.5),
232                (Rocksnapper, _) => (12.0, -9.0),
233                (Rootsnapper, _) => (12.0, -9.0),
234                (Reefsnapper, _) => (12.0, -9.0),
235                (Pangolin, _) => (8.0, -9.0),
236                (Maneater, _) => (1.0, 4.5),
237                (Sandshark, _) => (13.5, -10.5),
238                (Hakulaq, _) => (10.5, 1.0),
239                (Dagon, _) => (12.0, -6.0),
240                (Lavadrake, _) => (9.0, -6.0),
241                (Icedrake, _) => (11.5, -6.0),
242                (Basilisk, _) => (12.5, -5.5),
243                (Deadwood, _) => (0.0, 0.0),
244                (Mossdrake, _) => (9.0, -6.0),
245                (Driggle, _) => (6.0, -3.0),
246                (Snaretongue, _) => (8.5, 0.0),
247                (Hydra, _) => (8.0, -6.5),
248            },
249            side_head_lower: match (body.species, body.body_type) {
250                (Hydra, _) => (9.0, 10.0, -6.5),
251                _ => (0.0, 0.0, 0.0),
252            },
253            side_head_upper: match (body.species, body.body_type) {
254                (Hydra, _) => ((1.0), (7.0), (17.0)),
255                _ => (0.0, 0.0, 0.0),
256            },
257            jaw: match (body.species, body.body_type) {
258                (Crocodile, _) => (2.5, -3.0),
259                (SeaCrocodile, _) => (2.5, -3.0),
260                (Alligator, _) => (2.5, -2.0),
261                (Salamander, _) => (0.5, -1.0),
262                (Elbst, _) => (0.5, -1.0),
263                (Monitor, _) => (3.0, -1.0),
264                (Asp, _) => (2.0, -2.0),
265                (Tortoise, _) => (-3.5, -2.0),
266                (Rocksnapper, _) => (-5.0, -1.5),
267                (Rootsnapper, _) => (-5.0, -1.5),
268                (Reefsnapper, _) => (-5.0, -1.5),
269                (Pangolin, _) => (0.0, 0.0),
270                (Maneater, _) => (-1.0, 4.0),
271                (Sandshark, _) => (-8.0, -5.5),
272                (Hakulaq, _) => (-6.5, -4.0),
273                (Dagon, _) => (2.0, -2.0),
274                (Lavadrake, _) => (3.0, -5.0),
275                (Icedrake, _) => (-0.5, -8.0),
276                (Basilisk, _) => (0.5, -3.0),
277                (Deadwood, _) => (-1.0, 4.0),
278                (Mossdrake, _) => (3.0, -5.0),
279                (Driggle, _) => (-2.0, -5.0),
280                (Snaretongue, _) => (-7.0, -7.0),
281                (Hydra, _) => (1.0, -2.0),
282            },
283            chest: match (body.species, body.body_type) {
284                (Crocodile, _) => (0.0, 5.0),
285                (SeaCrocodile, _) => (0.0, 5.0),
286                (Alligator, _) => (0.0, 5.0),
287                (Salamander, _) => (0.0, 5.0),
288                (Elbst, _) => (0.0, 5.0),
289                (Monitor, _) => (0.0, 5.0),
290                (Asp, _) => (0.0, 8.0),
291                (Tortoise, _) => (0.0, 11.0),
292                (Rocksnapper, _) => (0.0, 18.5),
293                (Rootsnapper, _) => (0.0, 18.5),
294                (Reefsnapper, _) => (0.0, 18.5),
295                (Pangolin, _) => (0.0, 7.0),
296                (Maneater, _) => (0.0, 12.0),
297                (Sandshark, _) => (0.0, 20.0),
298                (Hakulaq, _) => (0.0, 13.5),
299                (Dagon, _) => (0.0, 13.5),
300                (Lavadrake, _) => (0.0, 16.5),
301                (Icedrake, _) => (0.0, 16.5),
302                (Basilisk, _) => (0.0, 15.0),
303                (Deadwood, _) => (0.0, 12.0),
304                (Mossdrake, _) => (0.0, 16.5),
305                (Driggle, _) => (0.0, 8.0),
306                (Snaretongue, _) => (-8.0, 9.0),
307                (Hydra, _) => (0.0, 16.0),
308            },
309            tail_rear: match (body.species, body.body_type) {
310                (Crocodile, _) => (-12.5, -1.0),
311                (SeaCrocodile, _) => (-12.5, -1.0),
312                (Alligator, _) => (-13.0, -1.0),
313                (Salamander, _) => (-6.5, 0.0),
314                (Elbst, _) => (-6.5, 0.0),
315                (Monitor, _) => (-12.0, 0.0),
316                (Asp, _) => (-14.0, -2.0),
317                (Tortoise, _) => (-10.0, -1.5),
318                (Rocksnapper, _) => (-14.5, -2.0),
319                (Rootsnapper, _) => (-14.5, -2.0),
320                (Reefsnapper, _) => (-14.5, -2.0),
321                (Pangolin, _) => (-7.0, -3.0),
322                (Maneater, _) => (-15.0, 4.0),
323                (Sandshark, _) => (-10.0, 0.5),
324                (Hakulaq, _) => (-9.0, -2.0),
325                (Dagon, _) => (-9.0, -2.0),
326                (Lavadrake, _) => (-12.0, -2.0),
327                (Icedrake, _) => (-12.0, 1.0),
328                (Basilisk, _) => (-10.0, -4.0),
329                (Deadwood, _) => (-15.0, 4.0),
330                (Mossdrake, _) => (-12.0, -2.0),
331                (Driggle, _) => (-4.0, 0.0),
332                (Snaretongue, _) => (5.0, 0.0),
333                (Hydra, _) => (-16.0, -1.0),
334            },
335            tail_rear_length: match (body.species, body.body_type) {
336                // TODO: Tweak tails as needed
337                (Crocodile, _) => 1.0,
338                (SeaCrocodile, _) => 1.0,
339                (Alligator, _) => 1.0,
340                (Salamander, _) => 1.0,
341                (Elbst, _) => 1.0,
342                (Monitor, _) => 1.0,
343                (Asp, _) => 1.0,
344                (Tortoise, _) => 1.0,
345                (Rocksnapper, _) => 1.0,
346                (Rootsnapper, _) => 1.0,
347                (Reefsnapper, _) => 1.0,
348                (Pangolin, _) => 1.0,
349                (Maneater, _) => 1.0,
350                (Sandshark, _) => 1.0,
351                (Hakulaq, _) => 1.0,
352                (Dagon, _) => 1.0,
353                (Lavadrake, _) => 1.0,
354                (Icedrake, _) => 1.0,
355                (Basilisk, _) => 1.0,
356                (Deadwood, _) => 1.0,
357                (Mossdrake, _) => 1.0,
358                (Driggle, _) => 1.0,
359                (Snaretongue, _) => 1.0,
360                (Hydra, _) => 10.0,
361            },
362            tail_front: match (body.species, body.body_type) {
363                (Crocodile, _) => (-6.0, 0.0),
364                (SeaCrocodile, _) => (-6.0, 0.0),
365                (Alligator, _) => (-5.0, 0.0),
366                (Salamander, _) => (-7.5, 0.0),
367                (Elbst, _) => (-7.0, 0.0),
368                (Monitor, _) => (-6.5, 0.0),
369                (Asp, _) => (-6.0, -2.0),
370                (Tortoise, _) => (-13.0, -3.5),
371                (Rocksnapper, _) => (-13.5, -6.5),
372                (Rootsnapper, _) => (-13.5, -6.5),
373                (Reefsnapper, _) => (-13.5, -6.5),
374                (Pangolin, _) => (-7.5, -0.5),
375                (Maneater, _) => (-1.0, 4.0),
376                (Sandshark, _) => (-13.0, -8.0),
377                (Hakulaq, _) => (-6.0, -5.5),
378                (Dagon, _) => (-9.0, -2.0),
379                (Lavadrake, _) => (-7.0, -4.5),
380                (Icedrake, _) => (-7.0, -4.5),
381                (Basilisk, _) => (-6.5, -5.5),
382                (Deadwood, _) => (-1.0, 4.0),
383                (Mossdrake, _) => (-7.0, -4.5),
384                (Driggle, _) => (-5.5, -4.0),
385                (Snaretongue, _) => (5.0, -2.0),
386                (Hydra, _) => (-14.0, -7.5),
387            },
388            feet_f: match (body.species, body.body_type) {
389                (Crocodile, _) => (3.5, 6.0, -1.0),
390                (SeaCrocodile, _) => (3.5, 6.0, -1.0),
391                (Alligator, _) => (4.5, 4.25, -1.0),
392                (Salamander, _) => (5.0, 4.5, -2.0),
393                (Elbst, _) => (5.0, 4.5, -2.0),
394                (Monitor, _) => (3.0, 5.0, 0.0),
395                (Asp, _) => (1.5, 4.0, -1.0),
396                (Tortoise, _) => (5.5, 6.5, -3.0),
397                (Rocksnapper, _) => (7.5, 5.0, -8.5),
398                (Rootsnapper, _) => (7.5, 5.0, -8.5),
399                (Reefsnapper, _) => (7.5, 5.0, -8.5),
400                (Pangolin, _) => (5.5, 5.5, -1.0),
401                (Maneater, _) => (4.5, 4.0, -5.5),
402                (Sandshark, _) => (5.5, 2.0, -8.0),
403                (Hakulaq, _) => (4.5, 2.0, -4.5),
404                (Dagon, _) => (4.5, 2.0, -4.5),
405                (Lavadrake, _) => (4.5, 4.0, -6.5),
406                (Icedrake, _) => (4.5, 4.0, -6.5),
407                (Basilisk, _) => (6.5, 4.0, -2.0),
408                (Deadwood, _) => (3.5, 4.0, -5.0),
409                (Mossdrake, _) => (4.5, 4.0, -6.5),
410                (Driggle, _) => (4.5, 2.5, -4.0),
411                (Snaretongue, _) => (6.5, 6.5, 1.0),
412                (Hydra, _) => (13.0, 7.0, -3.0),
413            },
414            feet_b: match (body.species, body.body_type) {
415                (Crocodile, _) => (3.5, -6.0, -1.0),
416                (SeaCrocodile, _) => (3.5, -6.0, -1.0),
417                (Alligator, _) => (4.5, -5.5, -1.0),
418                (Salamander, _) => (3.0, -6.0, -2.0),
419                (Elbst, _) => (3.0, -6.0, -2.0),
420                (Monitor, _) => (2.5, -6.5, 0.0),
421                (Asp, _) => (2.5, -5.5, -1.0),
422                (Tortoise, _) => (5.5, -11.5, -3.0),
423                (Rocksnapper, _) => (8.0, -12.0, -9.5),
424                (Rootsnapper, _) => (8.0, -12.0, -9.5),
425                (Reefsnapper, _) => (8.0, -12.0, -9.5),
426                (Pangolin, _) => (6.5, -3.5, -1.0),
427                (Maneater, _) => (4.5, -2.5, -3.0),
428                (Sandshark, _) => (3.5, -15.0, -14.0),
429                (Hakulaq, _) => (3.5, -8.0, -4.5),
430                (Dagon, _) => (3.5, -8.0, -4.5),
431                (Lavadrake, _) => (3.5, -8.0, -6.5),
432                (Icedrake, _) => (3.5, -8.0, -6.5),
433                (Basilisk, _) => (5.5, -6.5, -2.0),
434                (Deadwood, _) => (3.5, -6.0, -5.0),
435                (Mossdrake, _) => (3.5, -8.0, -6.5),
436                (Driggle, _) => (3.5, -3.5, -5.0),
437                (Snaretongue, _) => (1.5, 1.5, 2.0),
438                (Hydra, _) => (5.0, -6.5, -5.0),
439            },
440            lean: match (body.species, body.body_type) {
441                (Pangolin, _) => (0.4, 0.0),
442                _ => (0.0, 1.0),
443            },
444            scaler: match (body.species, body.body_type) {
445                (Crocodile, _) => 1.05,
446                (SeaCrocodile, _) => 1.05,
447                (Alligator, _) => 1.12,
448                (Salamander, _) => 1.12,
449                (Elbst, _) => 1.12,
450                (Monitor, _) => 0.9,
451                (Asp, _) => 1.12,
452                (Rocksnapper, _) => 1.12,
453                (Rootsnapper, _) => 1.12,
454                (Reefsnapper, _) => 1.12,
455                (Hakulaq, _) => 1.05,
456                (Dagon, _) => 1.05,
457                (Pangolin, _) => 1.05,
458                (Maneater, _) => 1.12,
459                (Lavadrake, _) => 1.12,
460                (Icedrake, _) => 1.12,
461                (Basilisk, _) => 1.3,
462                (Mossdrake, _) => 1.12,
463                (Snaretongue, _) => 1.0,
464                (Hydra, _) => 1.5,
465                _ => 0.9,
466            },
467            tempo: match (body.species, body.body_type) {
468                (Crocodile, _) => 0.7,
469                (SeaCrocodile, _) => 0.7,
470                (Alligator, _) => 0.7,
471                (Salamander, _) => 0.85,
472                (Elbst, _) => 0.85,
473                (Monitor, _) => 1.4,
474                (Tortoise, _) => 0.7,
475                (Rocksnapper, _) => 0.7,
476                (Rootsnapper, _) => 0.7,
477                (Reefsnapper, _) => 0.7,
478                (Hakulaq, _) => 1.2,
479                (Dagon, _) => 1.2,
480                (Pangolin, _) => 1.15,
481                (Maneater, _) => 0.9,
482                (Lavadrake, _) => 1.1,
483                (Icedrake, _) => 1.1,
484                (Basilisk, _) => 0.8,
485                (Mossdrake, _) => 1.1,
486                (Snaretongue, _) => 0.7,
487                (Hydra, _) => 0.6,
488                _ => 1.0,
489            },
490            // bool to special case Snaretongue
491            tongue_for_tail: matches!(body.species, Snaretongue),
492        }
493    }
494}
495fn mount_point(body: &Body) -> Vec3<f32> {
496    use comp::quadruped_low::Species::*;
497    match (body.species, body.body_type) {
498        (Crocodile, _) => (0.0, 3.5, 3.5),
499        (Alligator, _) => (0.0, 2.5, 3.0),
500        (Salamander, _) => (0.0, 2.0, 4.0),
501        (Monitor, _) => (0.0, 0.0, 3.0),
502        (Asp, _) => (0.0, 2.0, 4.0),
503        (Tortoise, _) => (0.0, 0.0, 6.0),
504        (Pangolin, _) => (0.0, -1.0, 4.5),
505        (Maneater, _) => (0.0, 4.0, -7.5),
506        (Sandshark, _) => (0.0, -6.0, 0.0),
507        (Hakulaq, _) => (0.0, 5.0, 2.5),
508        (Lavadrake, _) => (0.0, 2.0, -0.5),
509        (Basilisk, _) => (0.0, -1.5, 8.0),
510        (Deadwood, _) => (0.0, -2.0, 3.0),
511        (Icedrake, _) => (0.0, -7.0, 6.0),
512        (SeaCrocodile, _) => (1.0, 3.5, 6.0),
513        (Dagon, _) => (1.0, 9.5, 0.5),
514        (Rocksnapper, _) => (0.0, 7.0, 8.5),
515        (Rootsnapper, _) => (0.0, -2.0, 12.5),
516        (Reefsnapper, _) => (0.0, 2.0, 4.5),
517        (Elbst, _) => (0.0, 2.0, 3.0),
518        (Mossdrake, _) => (0.0, 2.0, 3.5),
519        (Driggle, _) => (0.0, 6.0, 2.0),
520        (Snaretongue, _) => (0.0, 2.0, 6.0),
521        (Hydra, _) => (0.0, 2.0, 4.0),
522    }
523    .into()
524}
525
526pub fn quadruped_low_alpha(
527    next: &mut QuadrupedLowSkeleton,
528    _s_a: &SkeletonAttr,
529    stage_section: StageSection,
530    anim_time: f32,
531    global_time: f32,
532    timer: f32,
533) {
534    let (movement1base, movement2base, movement3) = match stage_section {
535        StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0),
536        StageSection::Action => (1.0, anim_time.powi(4), 0.0),
537        StageSection::Recover => (1.0, 1.0, anim_time),
538        _ => (0.0, 0.0, 0.0),
539    };
540    let pullback = 1.0 - movement3;
541    let subtract = global_time - timer;
542    let check = subtract - subtract.trunc();
543    let mirror = (check - 0.5).signum();
544    let twitch3 = (mirror * movement3 * 9.0).sin();
545    let movement1 = mirror * movement1base * pullback;
546    let movement2 = mirror * movement2base * pullback;
547    let movement1abs = movement1base * pullback;
548    let movement2abs = movement2base * pullback;
549
550    // Center head
551    next.head_c_upper.orientation = Quaternion::rotation_z(twitch3 * -0.7);
552
553    next.head_c_lower.orientation =
554        Quaternion::rotation_x(movement1abs * 0.35 + movement2abs * -0.9)
555            * Quaternion::rotation_y(movement1 * 0.7 + movement2 * -1.0);
556
557    next.jaw_c.orientation = Quaternion::rotation_x(movement1abs * -0.5 + movement2abs * 0.5);
558
559    // Left head
560    next.head_l_upper.orientation = Quaternion::rotation_z(twitch3 * -0.7);
561
562    next.head_l_lower.orientation =
563        Quaternion::rotation_x(movement1abs * 0.35 + movement2abs * -0.9)
564            * Quaternion::rotation_y(movement1 * 0.7 + movement2 * -1.0);
565
566    next.jaw_l.orientation = Quaternion::rotation_x(movement1abs * -0.5 + movement2abs * 0.5);
567
568    // Right head
569    next.head_r_upper.orientation = Quaternion::rotation_z(twitch3 * -0.7);
570
571    next.head_r_lower.orientation =
572        Quaternion::rotation_x(movement1abs * 0.35 + movement2abs * -0.9)
573            * Quaternion::rotation_y(movement1 * 0.7 + movement2 * -1.0);
574
575    next.jaw_r.orientation = Quaternion::rotation_x(movement1abs * -0.5 + movement2abs * 0.5);
576
577    next.chest.orientation = Quaternion::rotation_y(movement1 * -0.08 + movement2 * 0.15)
578        * Quaternion::rotation_z(movement1 * -0.2 + movement2 * 0.6);
579
580    next.tail_front.orientation =
581        Quaternion::rotation_x(0.15) * Quaternion::rotation_z(movement1 * -0.4 + movement2 * -0.2);
582
583    next.tail_rear.orientation =
584        Quaternion::rotation_x(-0.12) * Quaternion::rotation_z(movement1 * -0.4 + movement2 * -0.2);
585}
586
587pub fn quadruped_low_beta(
588    next: &mut QuadrupedLowSkeleton,
589    _s_a: &SkeletonAttr,
590    stage_section: StageSection,
591    anim_time: f32,
592    global_time: f32,
593    timer: f32,
594) {
595    let (movement1base, movement2base, movement3) = match stage_section {
596        StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0),
597        StageSection::Action => (1.0, anim_time.powi(4), 0.0),
598        StageSection::Recover => (1.0, 1.0, anim_time),
599        _ => (0.0, 0.0, 0.0),
600    };
601    let pullback = 1.0 - movement3;
602    let subtract = global_time - timer;
603    let check = subtract - subtract.trunc();
604    let mirror = (check - 0.5).signum();
605    let twitch3 = (mirror * movement3 * 9.0).sin();
606    let movement1 = mirror * movement1base * pullback;
607    let movement2 = mirror * movement2base * pullback;
608    let movement1abs = movement1base * pullback;
609    let movement2abs = movement2base * pullback;
610
611    // Center head
612    next.head_c_upper.orientation = Quaternion::rotation_z(twitch3 * 0.2);
613
614    next.head_c_lower.orientation =
615        Quaternion::rotation_x(movement1abs * 0.15 + movement2abs * -0.6)
616            * Quaternion::rotation_y(movement1 * -0.1 + movement2 * 0.15);
617
618    next.jaw_c.orientation = Quaternion::rotation_x(movement1abs * -0.9 + movement2abs * 0.9);
619
620    // Left head
621    next.head_l_upper.orientation = Quaternion::rotation_z(twitch3 * 0.2);
622
623    next.head_l_lower.orientation =
624        Quaternion::rotation_x(movement1abs * 0.15 + movement2abs * -0.6)
625            * Quaternion::rotation_y(movement1 * -0.1 + movement2 * 0.15);
626
627    next.jaw_l.orientation = Quaternion::rotation_x(movement1abs * -0.9 + movement2abs * 0.9);
628
629    // Right head
630    next.head_r_upper.orientation = Quaternion::rotation_z(twitch3 * 0.2);
631
632    next.head_r_lower.orientation =
633        Quaternion::rotation_x(movement1abs * 0.15 + movement2abs * -0.6)
634            * Quaternion::rotation_y(movement1 * -0.1 + movement2 * 0.15);
635
636    next.jaw_r.orientation = Quaternion::rotation_x(movement1abs * -0.9 + movement2abs * 0.9);
637
638    next.chest.orientation = Quaternion::rotation_y(movement1 * 0.08 + movement2 * -0.15)
639        * Quaternion::rotation_z(movement1 * 0.2 + movement2 * -0.3);
640
641    next.tail_front.orientation =
642        Quaternion::rotation_x(0.15) * Quaternion::rotation_z(movement1 * 0.4 + movement2 * 0.2);
643
644    next.tail_rear.orientation =
645        Quaternion::rotation_x(-0.12) * Quaternion::rotation_z(movement1 * 0.4 + movement2 * 0.2);
646}