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