veloren_voxygen_anim/character/
wallrun.rs

1use super::{
2    super::{Animation, vek::*},
3    CharacterSkeleton, SkeletonAttr,
4};
5use common::comp::item::{AbilitySpec, Hands, ToolKind};
6use core::f32::consts::PI;
7
8pub struct WallrunAnimation;
9
10impl Animation for WallrunAnimation {
11    type Dependency<'a> = (
12        (Option<ToolKind>, Option<&'a AbilitySpec>),
13        Option<ToolKind>,
14        (Option<Hands>, Option<Hands>),
15        Vec3<f32>,
16        f32,
17        Option<Vec3<f32>>,
18        bool,
19    );
20    type Skeleton = CharacterSkeleton;
21
22    #[cfg(feature = "use-dyn-lib")]
23    const UPDATE_FN: &'static [u8] = b"character_wallrun\0";
24
25    #[cfg_attr(feature = "be-dyn-lib", unsafe(export_name = "character_wallrun"))]
26    fn update_skeleton_inner(
27        skeleton: &Self::Skeleton,
28        (
29            (active_tool_kind, active_tool_spec),
30            second_tool_kind,
31            hands,
32            orientation,
33            acc_vel,
34            wall,
35            was_wielded,
36        ): Self::Dependency<'_>,
37        _anim_time: f32,
38        rate: &mut f32,
39        s_a: &SkeletonAttr,
40    ) -> Self::Skeleton {
41        let mut next = (*skeleton).clone();
42
43        *rate = 1.0;
44
45        let lab: f32 = 0.8;
46
47        let footrotl = ((1.0 / (0.5 + (0.5) * ((acc_vel * 1.6 * lab + PI * 1.4).sin()).powi(2)))
48            .sqrt())
49            * ((acc_vel * 1.6 * lab + PI * 1.4).sin());
50        let footrotr = ((1.0 / (0.5 + (0.5) * ((acc_vel * 1.6 * lab + PI * 0.4).sin()).powi(2)))
51            .sqrt())
52            * ((acc_vel * 1.6 * lab + PI * 0.4).sin());
53
54        let foothoril = (acc_vel * 2.2 * lab + PI * 1.45).sin();
55        let foothorir = (acc_vel * 2.2 * lab + PI * (0.45)).sin();
56
57        let shortalt = (acc_vel * lab * 2.2 + PI / 1.0).sin();
58
59        let short = ((5.0 / (1.5 + 3.5 * ((acc_vel * lab * 1.6).sin()).powi(2))).sqrt())
60            * ((acc_vel * lab * 1.6).sin());
61
62        next.shorts.position = Vec3::new(0.0, s_a.shorts.0 + 2.0, s_a.shorts.1 + 1.0);
63        next.belt.position = Vec3::new(0.0, s_a.belt.0 + 1.0, s_a.belt.1);
64
65        next.foot_l.position = Vec3::new(
66            -s_a.foot.0,
67            s_a.foot.1 + foothorir * 6.0,
68            s_a.foot.2 + shortalt * 2.0 + 2.0,
69        );
70        next.foot_l.orientation = Quaternion::rotation_x(0.6 + shortalt * 0.8);
71
72        next.foot_r.position = Vec3::new(
73            s_a.foot.0,
74            s_a.foot.1 + foothoril * 6.0,
75            s_a.foot.2 + shortalt * -2.0 + 2.0,
76        );
77        next.foot_r.orientation = Quaternion::rotation_x(0.6 - shortalt * 0.8);
78        next.belt.orientation = Quaternion::rotation_x(0.3);
79        next.shorts.orientation = Quaternion::rotation_x(0.5);
80
81        next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + shortalt * 0.0);
82
83        next.shoulder_l.orientation = Quaternion::rotation_x(short * 0.15);
84
85        next.shoulder_r.orientation = Quaternion::rotation_x(short * -0.15);
86
87        if wall.is_some_and(|e| e.y > 0.5) {
88            let push = (1.0 - orientation.x.abs()).powi(2);
89            let right_sub = -(orientation.x).min(0.0);
90            let left_sub = (orientation.x).max(0.0);
91            next.hand_l.position = Vec3::new(
92                -s_a.hand.0,
93                s_a.hand.1,
94                s_a.hand.2 + push * 5.0 + 2.0 * left_sub,
95            );
96            next.hand_r.position = Vec3::new(
97                s_a.hand.0,
98                s_a.hand.1,
99                s_a.hand.2 + push * 5.0 + 2.0 * right_sub,
100            );
101            next.hand_l.orientation =
102                Quaternion::rotation_x(push * 2.0 + footrotr * -0.2 * right_sub)
103                    * Quaternion::rotation_y(1.0 * left_sub)
104                    * Quaternion::rotation_z(2.5 * left_sub + 1.0 * right_sub);
105            next.hand_r.orientation =
106                Quaternion::rotation_x(push * 2.0 + footrotl * -0.2 * left_sub)
107                    * Quaternion::rotation_y(-1.0 * right_sub)
108                    * Quaternion::rotation_z(-2.5 * right_sub - 1.0 * left_sub);
109            next.torso.orientation = Quaternion::rotation_y(orientation.x / 1.5);
110            next.chest.orientation = Quaternion::rotation_y(orientation.x / -3.0)
111                * Quaternion::rotation_z(shortalt * -0.2);
112            next.head.orientation = Quaternion::rotation_z(shortalt * 0.25)
113                * Quaternion::rotation_z(orientation.x / -2.0)
114                * Quaternion::rotation_x(-0.1);
115        } else if wall.is_some_and(|e| e.y < -0.5) {
116            let push = (1.0 - orientation.x.abs()).powi(2);
117            let right_sub = (orientation.x).max(0.0);
118            let left_sub = -(orientation.x).min(0.0);
119            next.hand_l.position = Vec3::new(
120                -s_a.hand.0,
121                s_a.hand.1,
122                s_a.hand.2 + push * 5.0 + 2.0 * left_sub,
123            );
124            next.hand_r.position = Vec3::new(
125                s_a.hand.0,
126                s_a.hand.1,
127                s_a.hand.2 + push * 5.0 + 2.0 * right_sub,
128            );
129            next.hand_l.orientation =
130                Quaternion::rotation_x(push * 2.0 + footrotr * -0.2 * right_sub)
131                    * Quaternion::rotation_y(1.0 * left_sub)
132                    * Quaternion::rotation_z(2.5 * left_sub + 1.0 * right_sub);
133            next.hand_r.orientation =
134                Quaternion::rotation_x(push * 2.0 + footrotl * -0.2 * left_sub)
135                    * Quaternion::rotation_y(-1.0 * right_sub)
136                    * Quaternion::rotation_z(-2.5 * right_sub - 1.0 * left_sub);
137            next.chest.orientation = Quaternion::rotation_y(orientation.x);
138            next.torso.orientation = Quaternion::rotation_y(orientation.x / -1.5);
139            next.chest.orientation = Quaternion::rotation_y(orientation.x / 3.0)
140                * Quaternion::rotation_z(shortalt * -0.2);
141            next.head.orientation = Quaternion::rotation_z(shortalt * 0.25)
142                * Quaternion::rotation_z(orientation.x / 2.0)
143                * Quaternion::rotation_x(-0.1);
144        } else if wall.is_some_and(|e| e.x < -0.5) {
145            let push = (1.0 - orientation.y.abs()).powi(2);
146            let right_sub = -(orientation.y).min(0.0);
147            let left_sub = (orientation.y).max(0.0);
148            next.hand_l.position = Vec3::new(
149                -s_a.hand.0,
150                s_a.hand.1,
151                s_a.hand.2 + push * 5.0 + 2.0 * left_sub,
152            );
153            next.hand_r.position = Vec3::new(
154                s_a.hand.0,
155                s_a.hand.1,
156                s_a.hand.2 + push * 5.0 + 2.0 * right_sub,
157            );
158            next.hand_l.orientation =
159                Quaternion::rotation_x(push * 2.0 + footrotr * -0.2 * right_sub)
160                    * Quaternion::rotation_y(1.0 * left_sub)
161                    * Quaternion::rotation_z(2.5 * left_sub + 1.0 * right_sub);
162            next.hand_r.orientation =
163                Quaternion::rotation_x(push * 2.0 + footrotl * -0.2 * left_sub)
164                    * Quaternion::rotation_y(-1.0 * right_sub)
165                    * Quaternion::rotation_z(-2.5 * right_sub - 1.0 * left_sub);
166            next.torso.orientation = Quaternion::rotation_y(orientation.y / 1.5);
167            next.chest.orientation = Quaternion::rotation_y(orientation.y / -3.0)
168                * Quaternion::rotation_z(shortalt * -0.2);
169            next.head.orientation = Quaternion::rotation_z(shortalt * 0.25)
170                * Quaternion::rotation_z(orientation.y / -2.0)
171                * Quaternion::rotation_x(-0.1);
172        } else if wall.is_some_and(|e| e.x > 0.5) {
173            let push = (1.0 - orientation.y.abs()).powi(2);
174            let right_sub = (orientation.y).max(0.0);
175            let left_sub = -(orientation.y).min(0.0);
176            next.hand_l.position = Vec3::new(
177                -s_a.hand.0,
178                s_a.hand.1,
179                s_a.hand.2 + push * 5.0 + 2.0 * left_sub,
180            );
181            next.hand_r.position = Vec3::new(
182                s_a.hand.0,
183                s_a.hand.1,
184                s_a.hand.2 + push * 5.0 + 2.0 * right_sub,
185            );
186            next.hand_l.orientation =
187                Quaternion::rotation_x(push * 2.0 + footrotr * -0.2 * right_sub)
188                    * Quaternion::rotation_y(1.0 * left_sub)
189                    * Quaternion::rotation_z(2.5 * left_sub + 1.0 * right_sub);
190            next.hand_r.orientation =
191                Quaternion::rotation_x(push * 2.0 + footrotl * -0.2 * left_sub)
192                    * Quaternion::rotation_y(-1.0 * right_sub)
193                    * Quaternion::rotation_z(-2.5 * right_sub - 1.0 * left_sub);
194            next.torso.orientation = Quaternion::rotation_y(orientation.y / -1.5);
195            next.chest.orientation = Quaternion::rotation_y(orientation.y / 3.0)
196                * Quaternion::rotation_z(shortalt * -0.2);
197            next.head.orientation = Quaternion::rotation_z(shortalt * 0.25)
198                * Quaternion::rotation_z(orientation.y / 2.0)
199                * Quaternion::rotation_x(-0.1);
200        };
201
202        if was_wielded {
203            next.main.position = Vec3::new(0.0, 0.0, 0.0);
204            next.main.orientation = Quaternion::rotation_x(0.0);
205            next.second.position = Vec3::new(0.0, 0.0, 0.0);
206            next.second.orientation = Quaternion::rotation_x(0.0);
207            next.hold.scale = Vec3::one() * 0.0;
208
209            match (hands, active_tool_kind, second_tool_kind) {
210                ((Some(Hands::Two), _), tool, _) | ((None, Some(Hands::Two)), _, tool) => {
211                    match tool {
212                        Some(ToolKind::Sword) => {
213                            next.hand_l.position = Vec3::new(s_a.shl.0, s_a.shl.1, s_a.shl.2);
214                            next.hand_l.orientation = Quaternion::rotation_x(s_a.shl.3)
215                                * Quaternion::rotation_y(s_a.shl.4);
216                            next.hand_r.position = Vec3::new(s_a.shr.0, s_a.shr.1, s_a.shr.2);
217                            next.hand_r.orientation = Quaternion::rotation_x(s_a.shr.3)
218                                * Quaternion::rotation_y(s_a.shr.4);
219
220                            next.control.position = Vec3::new(s_a.sc.0, s_a.sc.1 - 3.0, s_a.sc.2);
221                            next.control.orientation =
222                                Quaternion::rotation_x(s_a.sc.3) * Quaternion::rotation_z(0.0);
223                        },
224                        Some(ToolKind::Axe) => {
225                            next.main.position = Vec3::new(0.0, 0.0, 0.0);
226                            next.main.orientation = Quaternion::rotation_x(0.0);
227
228                            next.hand_l.position = Vec3::new(s_a.ahl.0, s_a.ahl.1, s_a.ahl.2);
229                            next.hand_l.orientation = Quaternion::rotation_x(s_a.ahl.3)
230                                * Quaternion::rotation_y(s_a.ahl.4);
231                            next.hand_r.position = Vec3::new(s_a.ahr.0, s_a.ahr.1, s_a.ahr.2);
232                            next.hand_r.orientation = Quaternion::rotation_x(s_a.ahr.3)
233                                * Quaternion::rotation_z(s_a.ahr.5);
234
235                            next.control.position = Vec3::new(s_a.ac.0, s_a.ac.1, s_a.ac.2);
236                            next.control.orientation = Quaternion::rotation_x(s_a.ac.3)
237                                * Quaternion::rotation_y(s_a.ac.4)
238                                * Quaternion::rotation_z(s_a.ac.5);
239                        },
240                        Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => {
241                            next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1, s_a.hhl.2);
242                            next.hand_l.orientation = Quaternion::rotation_x(s_a.hhl.3)
243                                * Quaternion::rotation_y(s_a.hhl.4)
244                                * Quaternion::rotation_z(s_a.hhl.5);
245                            next.hand_r.position = Vec3::new(s_a.hhr.0, s_a.hhr.1, s_a.hhr.2);
246                            next.hand_r.orientation = Quaternion::rotation_x(s_a.hhr.3)
247                                * Quaternion::rotation_y(s_a.hhr.4)
248                                * Quaternion::rotation_z(s_a.hhr.5);
249
250                            next.control.position = Vec3::new(s_a.hc.0, s_a.hc.1, s_a.hc.2 + 6.0);
251                            next.control.orientation = Quaternion::rotation_x(s_a.hc.3)
252                                * Quaternion::rotation_y(s_a.hc.4)
253                                * Quaternion::rotation_z(s_a.hc.5);
254                        },
255                        Some(ToolKind::Staff) | Some(ToolKind::Sceptre) => {
256                            next.hand_r.position = Vec3::new(s_a.sthr.0, s_a.sthr.1, s_a.sthr.2);
257                            next.hand_r.orientation = Quaternion::rotation_x(s_a.sthr.3)
258                                * Quaternion::rotation_y(s_a.sthr.4);
259
260                            next.control.position =
261                                Vec3::new(s_a.stc.0, s_a.stc.1 - 2.0, s_a.stc.2 + 4.0);
262
263                            next.hand_l.position = Vec3::new(s_a.sthl.0, s_a.sthl.1, s_a.sthl.2);
264                            next.hand_l.orientation = Quaternion::rotation_x(s_a.sthl.3);
265
266                            next.control.orientation = Quaternion::rotation_x(s_a.stc.3)
267                                * Quaternion::rotation_y(s_a.stc.4)
268                                * Quaternion::rotation_z(s_a.stc.5);
269                        },
270                        Some(ToolKind::Bow) => {
271                            next.main.position = Vec3::new(0.0, 0.0, 0.0);
272                            next.main.orientation = Quaternion::rotation_x(0.0);
273                            next.hand_l.position = Vec3::new(s_a.bhl.0, s_a.bhl.1, s_a.bhl.2);
274                            next.hand_l.orientation = Quaternion::rotation_x(s_a.bhl.3);
275                            next.hand_r.position = Vec3::new(s_a.bhr.0, s_a.bhr.1, s_a.bhr.2);
276                            next.hand_r.orientation = Quaternion::rotation_x(s_a.bhr.3);
277
278                            next.hold.position = Vec3::new(0.0, -1.0, -5.2);
279                            next.hold.orientation = Quaternion::rotation_x(-PI / 2.0);
280                            next.hold.scale = Vec3::one() * 1.0;
281
282                            next.control.position =
283                                Vec3::new(s_a.bc.0 + 2.0, s_a.bc.1, s_a.bc.2 + 5.0);
284                            next.control.orientation = Quaternion::rotation_x(0.8)
285                                * Quaternion::rotation_y(s_a.bc.4)
286                                * Quaternion::rotation_z(s_a.bc.5);
287                        },
288                        Some(ToolKind::Instrument) => {
289                            if let Some(AbilitySpec::Custom(spec)) = active_tool_spec {
290                                match spec.as_str() {
291                                    "Washboard" => {
292                                        next.hand_l.position = Vec3::new(-7.0, 0.0, 3.0);
293                                        next.hand_l.orientation = Quaternion::rotation_x(1.27);
294                                        next.main.position = Vec3::new(-5.0, -4.5, -5.0);
295                                        next.main.orientation = Quaternion::rotation_x(5.5);
296                                    },
297                                    _ => {
298                                        next.hand_l.position = Vec3::new(-7.0, 4.0, 3.0);
299                                        next.hand_l.orientation = Quaternion::rotation_x(1.27);
300                                        next.main.position = Vec3::new(-5.0, 5.0, 23.0);
301                                        next.main.orientation = Quaternion::rotation_x(PI);
302                                    },
303                                }
304                            }
305                        },
306                        Some(ToolKind::Debug) => {
307                            next.hand_l.position = Vec3::new(-7.0, 4.0, 3.0);
308                            next.hand_l.orientation = Quaternion::rotation_x(1.27);
309                            next.main.position = Vec3::new(-5.0, 5.0, 23.0);
310                            next.main.orientation = Quaternion::rotation_x(PI);
311                        },
312                        Some(ToolKind::Farming) => {
313                            next.head.orientation = Quaternion::rotation_x(-0.2);
314                            next.hand_l.position = Vec3::new(9.0, 1.0, 1.0);
315                            next.hand_l.orientation = Quaternion::rotation_x(PI / 2.0);
316                            next.hand_r.position = Vec3::new(9.0, 1.0, 11.0);
317                            next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0);
318                            next.main.position = Vec3::new(7.5, 7.5, 13.2);
319                            next.main.orientation = Quaternion::rotation_y(PI);
320
321                            next.control.position = Vec3::new(-11.0, 1.8, 4.0);
322                            next.control.orientation = Quaternion::rotation_x(0.0)
323                                * Quaternion::rotation_y(0.6)
324                                * Quaternion::rotation_z(0.0);
325                        },
326                        _ => {},
327                    }
328                },
329                ((_, _), _, _) => {},
330            };
331            match hands {
332                (Some(Hands::One), _) => {
333                    next.control_l.position = Vec3::new(-7.0, 6.0, 5.0);
334                    next.control_l.orientation =
335                        Quaternion::rotation_x(-0.3) * Quaternion::rotation_y(0.2);
336                    next.hand_l.position = Vec3::new(-1.0, -0.5, 0.0);
337                    next.hand_l.orientation = Quaternion::rotation_x(PI / 2.0)
338                },
339                (_, _) => {},
340            };
341            match hands {
342                (None | Some(Hands::One), Some(Hands::One)) => {
343                    next.control_r.position = Vec3::new(7.0, 6.0, 5.0);
344                    next.control_r.orientation =
345                        Quaternion::rotation_x(-0.3) * Quaternion::rotation_y(-0.2);
346                    next.hand_r.position = Vec3::new(1.0, -0.5, 0.0);
347                    next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0)
348                },
349                (_, _) => {},
350            };
351            match hands {
352                (None, None) | (None, Some(Hands::One)) => {
353                    next.hand_l.position = Vec3::new(-8.0, 2.0, 1.0);
354                    next.hand_l.orientation =
355                        Quaternion::rotation_x(0.5) * Quaternion::rotation_y(0.25);
356                },
357                (_, _) => {},
358            };
359            match hands {
360                (None, None) | (Some(Hands::One), None) => {
361                    next.hand_r.position = Vec3::new(8.0, 2.0, 1.0);
362                    next.hand_r.orientation =
363                        Quaternion::rotation_x(0.5) * Quaternion::rotation_y(-0.25);
364                },
365                (_, _) => {},
366            };
367        }
368
369        next
370    }
371}