veloren_voxygen_anim/biped_small/
combomelee.rs

1use std::f32::consts::PI;
2
3use super::{
4    super::{Animation, vek::*},
5    BipedSmallSkeleton, SkeletonAttr, biped_small_alpha_axe, biped_small_alpha_dagger,
6    biped_small_alpha_spear, biped_small_wield_spear, init_biped_small_alpha,
7};
8use common::states::utils::StageSection;
9
10pub struct ComboAnimation;
11impl Animation for ComboAnimation {
12    type Dependency<'a> = (Option<&'a str>, StageSection, usize, Vec3<f32>, f32, f32);
13    type Skeleton = BipedSmallSkeleton;
14
15    #[cfg(feature = "use-dyn-lib")]
16    const UPDATE_FN: &'static [u8] = b"biped_small_combo\0";
17
18    #[cfg_attr(feature = "be-dyn-lib", unsafe(export_name = "biped_small_combo"))]
19    fn update_skeleton_inner(
20        skeleton: &Self::Skeleton,
21        (ability_id, stage_section, current_strike, velocity, _global_time, _timer): Self::Dependency<'_>,
22        anim_time: f32,
23        rate: &mut f32,
24        s_a: &SkeletonAttr,
25    ) -> Self::Skeleton {
26        *rate = 1.0;
27        let mut next = (*skeleton).clone();
28
29        next.main.position = Vec3::new(0.0, 0.0, 0.0);
30        next.main.orientation = Quaternion::rotation_z(0.0);
31        next.second.position = Vec3::new(0.0, 0.0, 0.0);
32        next.second.orientation = Quaternion::rotation_z(0.0);
33        let multi_strike_pullback = 1.0
34            - if matches!(stage_section, StageSection::Recover) {
35                anim_time.powi(4)
36            } else {
37                0.0
38            };
39
40        for strike in 0..=current_strike {
41            match ability_id {
42                Some(
43                    "common.abilities.custom.bushly.singlestrike"
44                    | "common.abilities.custom.irrwurz.singlestrike"
45                    | "common.abilities.custom.husk.singlestrike"
46                    | "common.abilities.custom.husk.triplestrike"
47                    | "common.abilities.custom.dwarves.iron_dwarf.singlestrike"
48                    | "common.abilities.custom.dwarves.iron_dwarf.triplestrike",
49                ) => {
50                    let (move1, move2) = if strike == current_strike {
51                        match stage_section {
52                            StageSection::Buildup => {
53                                (((anim_time.max(0.4) - 0.4) * 1.5).powf(0.5), 0.0)
54                            },
55                            StageSection::Action => (1.0, (anim_time.min(0.4) * 2.5).powi(2)),
56                            StageSection::Recover => (1.0, 1.0),
57                            _ => (0.0, 0.0),
58                        }
59                    } else {
60                        (1.0, 1.0)
61                    };
62                    let move1 = move1 * multi_strike_pullback;
63                    let move2 = move2 * multi_strike_pullback;
64                    next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
65                    next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
66                    next.main.position = Vec3::new(0.0, 0.0, 0.0);
67                    next.main.orientation = Quaternion::rotation_x(0.0);
68                    next.hand_l.orientation = Quaternion::rotation_x(0.0);
69                    next.hand_r.orientation = Quaternion::rotation_x(0.0);
70
71                    match strike {
72                        0..=2 => {
73                            next.chest.orientation = Quaternion::rotation_x(move2 * -1.0)
74                                * Quaternion::rotation_z(move1 * 1.2 + move2 * -1.8);
75                            next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2);
76                            next.hand_l.orientation = Quaternion::rotation_x(1.2);
77                            next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2);
78                            next.hand_r.orientation = Quaternion::rotation_x(1.2);
79                        },
80                        _ => {},
81                    }
82                },
83                Some("common.abilities.custom.cactid.singlestrike") => {
84                    let (move1, move2) = if strike == current_strike {
85                        match stage_section {
86                            StageSection::Buildup => {
87                                (((anim_time.max(0.4) - 0.4) * 1.5).powf(0.5), 0.0)
88                            },
89                            StageSection::Action => (1.0, (anim_time.min(0.4) * 2.5).powi(2)),
90                            StageSection::Recover => (1.0, 1.0),
91                            _ => (0.0, 0.0),
92                        }
93                    } else {
94                        (1.0, 1.0)
95                    };
96                    let move1 = move1 * multi_strike_pullback;
97                    let move2 = move2 * multi_strike_pullback;
98                    next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
99                    next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
100                    next.main.position = Vec3::new(0.0, 0.0, 0.0);
101                    next.main.orientation = Quaternion::rotation_x(0.0);
102                    next.hand_l.orientation = Quaternion::rotation_x(0.0);
103                    next.hand_r.orientation = Quaternion::rotation_x(0.0);
104                    next.head.orientation = Quaternion::rotation_z(move2 * 1.0);
105
106                    next.chest.orientation = Quaternion::rotation_x(move2 * -1.0)
107                        * Quaternion::rotation_z(move1 * -1.2 + move2 * 1.8);
108                    next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2);
109                    next.hand_l.orientation = Quaternion::rotation_x(1.2);
110                    next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2);
111                    next.hand_r.orientation = Quaternion::rotation_x(1.2);
112                },
113                Some(
114                    "common.abilities.axesimple.doublestrike"
115                    | "common.abilities.custom.goblin_thug.doublestrike"
116                    | "common.abilities.custom.green_legoom.doublestrike"
117                    | "common.abilities.custom.red_legoom.doublestrike"
118                    | "common.abilities.vampire.bloodservant.doublestrike"
119                    | "common.abilities.custom.boreal_warrior.hammer.singlestrike",
120                ) => {
121                    let anim_time = anim_time.min(1.0);
122                    let (move1base, move2base, move3) = match stage_section {
123                        StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0),
124                        StageSection::Action => (1.0, anim_time.powi(4), 0.0),
125                        StageSection::Recover => (1.0, 1.0, anim_time),
126                        _ => (0.0, 0.0, 0.0),
127                    };
128                    let pullback = 1.0 - move3;
129                    let move1abs = move1base * pullback;
130                    let move2abs = move2base * pullback;
131
132                    init_biped_small_alpha(&mut next, s_a);
133                    biped_small_alpha_axe(&mut next, s_a, move1abs, move2abs);
134                },
135                Some("common.abilities.custom.ashen_warrior.axe.doublestrike") => {
136                    let anim_time = anim_time.min(1.0);
137                    let (move1base, move2base) = if strike == current_strike {
138                        match stage_section {
139                            StageSection::Buildup => (anim_time.sqrt(), 0.0),
140                            StageSection::Action => (1.0, anim_time.powi(4)),
141                            StageSection::Recover => (1.0, 1.0),
142                            _ => (0.0, 0.0),
143                        }
144                    } else {
145                        (1.0, 1.0)
146                    };
147                    let move1 = move1base * multi_strike_pullback;
148                    let move2 = move2base * multi_strike_pullback;
149
150                    match strike {
151                        0 => {
152                            next.main.position = Vec3::new(-8.0, 2.0, 0.0);
153                            next.main.orientation = Quaternion::rotation_x(0.0);
154                            next.second.position = Vec3::new(8.0, 2.0, 0.0);
155                            next.second.orientation = Quaternion::rotation_x(0.0);
156                            next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, 2.0);
157                            next.hand_l.orientation = Quaternion::rotation_x(PI / 2.0);
158                            next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, 2.0);
159                            next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0);
160
161                            next.chest.orientation.rotate_z(PI / 4.0 * move1);
162                            next.pants.orientation.rotate_z(-PI / 8.0 * move1);
163                            next.hand_l.position += Vec3::new(0.0, 0.0, 2.0) * move1;
164                            next.hand_l.orientation.rotate_y(-PI / 8.0 * move1);
165                            next.main.orientation.rotate_y(-PI / 8.0 * move1);
166                            next.control_r.orientation.rotate_y(-PI / 8.0 * move1);
167
168                            next.chest.orientation.rotate_z(-PI / 2.5 * move2);
169                            next.pants.orientation.rotate_z(PI / 8.0 * move2);
170                            next.hand_l.position += Vec3::new(0.0, 5.0, -3.0) * move2;
171                            next.hand_l.orientation.rotate_x(-PI / 3.0 * move2);
172                            next.hand_l.orientation.rotate_y(-PI / 4.0 * move2);
173                            next.hand_l.orientation.rotate_z(-PI / 4.0 * move2);
174                            next.main.position += Vec3::new(0.0, 5.0, -3.0) * move2;
175                            next.main.orientation.rotate_x(-PI / 3.0 * move2);
176                            next.main.orientation.rotate_y(-PI / 4.0 * move2);
177                            next.main.orientation.rotate_z(-PI / 4.0 * move2);
178                        },
179                        1 => {
180                            next.chest.orientation.rotate_z(-PI / 5.0 * move1);
181                            next.control_r.orientation.rotate_y(PI / 4.0 * move1);
182
183                            next.chest.orientation.rotate_z(PI / 2.0 * move2);
184                            next.hand_l.position += Vec3::new(0.0, -4.0, 0.0) * move2;
185                            next.hand_l.orientation.rotate_x(PI / 6.0 * move2);
186                            next.hand_l.orientation.rotate_y(PI / 8.0 * move2);
187                            next.hand_l.orientation.rotate_z(PI / 8.0 * move2);
188                            next.main.position += Vec3::new(0.0, -4.0, 0.0) * move2;
189                            next.main.orientation.rotate_x(PI / 6.0 * move2);
190                            next.main.orientation.rotate_y(PI / 8.0 * move2);
191                            next.main.orientation.rotate_z(PI / 8.0 * move2);
192                            next.control_r.orientation.rotate_x(-PI / 4.0 * move2);
193                            next.control_r.orientation.rotate_y(PI / 8.0 * move2);
194                            next.control_r.orientation.rotate_z(PI / 8.0 * move2);
195                        },
196                        _ => {},
197                    }
198                },
199                Some("common.abilities.custom.ashen_warrior.axe.knockback_combo") => {
200                    let anim_time = anim_time.min(1.0);
201                    let (move1base, move2base, move3base) = if strike == current_strike {
202                        match stage_section {
203                            StageSection::Buildup => (anim_time, 0.0, 0.0),
204                            StageSection::Action => (1.0, anim_time, 0.0),
205                            StageSection::Recover => (1.0, 1.0, anim_time),
206                            _ => (0.0, 0.0, 0.0),
207                        }
208                    } else {
209                        (1.0, 1.0, 1.0)
210                    };
211                    let multi_strike_pullback = 1.0 - move3base;
212                    let move1 = move1base * multi_strike_pullback;
213                    let move2 = move2base * multi_strike_pullback;
214
215                    match strike {
216                        0 => {
217                            next.main.position = Vec3::new(-8.0, 2.0, 0.0);
218                            next.main.orientation = Quaternion::rotation_x(0.0);
219                            next.second.position = Vec3::new(8.0, 2.0, 0.0);
220                            next.second.orientation = Quaternion::rotation_x(0.0);
221                            next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, 2.0);
222                            next.hand_l.orientation = Quaternion::rotation_x(PI / 2.0);
223                            next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, 2.0);
224                            next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0);
225
226                            next.hand_l.position += Vec3::new(-6.0, 0.0, -4.0) * move1;
227                            next.hand_l.orientation.rotate_y(PI / 1.3 * move1);
228                            next.main.position += Vec3::new(0.0, 0.0, 4.0) * move1;
229                            next.main.orientation.rotate_y(PI / 1.3 * move1);
230                            next.control_r.position += Vec3::new(15.0, 0.0, -5.0) * move1;
231                            next.control_r.orientation.rotate_y(-PI / 1.3 * move1);
232                            next.chest.orientation.rotate_x(-PI / 12.0 * move1);
233                            next.pants.orientation.rotate_x(PI / 12.0 * move1);
234
235                            next.control_r.orientation.rotate_x(PI / 2.0 * move2);
236                            next.control_r.orientation.rotate_y(PI / 2.0 * move2);
237                            next.control_r.orientation.rotate_z(-PI / 4.0 * move2);
238                            next.hand_l.orientation.rotate_x(PI / 2.0 * move2);
239                            next.hand_l.orientation.rotate_y(-PI / 2.0 * move2);
240                            next.hand_l.orientation.rotate_z(PI / 4.0 * move2);
241                            next.main.orientation.rotate_x(PI / 2.0 * move2);
242                            next.main.orientation.rotate_y(-PI / 2.0 * move2);
243                            next.main.orientation.rotate_z(PI / 4.0 * move2);
244                            next.chest.orientation.rotate_x(PI / 8.0 * move2);
245                            next.pants.orientation.rotate_x(-PI / 8.0 * move2);
246                        },
247                        1 => {
248                            let rotate_about =
249                                |bone: &mut Transform<f32, f32, f32>,
250                                 pivot: Vec3<f32>,
251                                 rotation: Quaternion<f32>| {
252                                    bone.orientation = bone.orientation * rotation;
253                                    bone.position = rotation * (bone.position - pivot) + pivot;
254                                };
255
256                            next.chest.orientation.rotate_x(PI * move1base);
257                            rotate_about(
258                                &mut next.foot_l,
259                                next.chest.position,
260                                Quaternion::rotation_x(PI * move1base),
261                            );
262                            rotate_about(
263                                &mut next.foot_r,
264                                next.chest.position,
265                                Quaternion::rotation_x(PI * move1base),
266                            );
267                            next.pants.orientation.rotate_x(PI / 4.0 * move1);
268                            next.foot_l.orientation.rotate_x(PI / 4.0 * move1);
269                            next.foot_r.orientation.rotate_x(PI / 4.0 * move1);
270                            next.control_r.orientation.rotate_y(-PI / 2.0 * move1);
271                            next.hand_l.orientation.rotate_y(-PI / 2.0 * move1);
272                            next.main.orientation.rotate_y(-PI / 2.0 * move1);
273
274                            next.chest.orientation.rotate_z(2.0 * PI * move2base);
275                            next.foot_l.orientation.rotate_z(2.0 * PI * move2base);
276                            next.foot_r.orientation.rotate_z(2.0 * PI * move2base);
277                            next.pants.orientation.rotate_x(-PI / 4.0 * move2);
278                            next.foot_l.orientation.rotate_x(-PI / 4.0 * move2);
279                            next.foot_r.orientation.rotate_x(-PI / 4.0 * move2);
280
281                            next.chest.orientation.rotate_x(PI * move3base);
282                            rotate_about(
283                                &mut next.foot_l,
284                                next.chest.position,
285                                Quaternion::rotation_x(PI * move3base),
286                            );
287                            rotate_about(
288                                &mut next.foot_r,
289                                next.chest.position,
290                                Quaternion::rotation_x(PI * move3base),
291                            );
292                        },
293                        _ => {},
294                    }
295                },
296                Some("common.abilities.custom.boreal_warrior.bow.doublestrike") => {
297                    let anim_time = anim_time.min(1.0);
298                    let (move1base, move2base) = if strike == current_strike {
299                        match stage_section {
300                            StageSection::Buildup => (anim_time.sqrt(), 0.0),
301                            StageSection::Action => (1.0, anim_time.powi(4)),
302                            StageSection::Recover => (1.0, 1.0),
303                            _ => (0.0, 0.0),
304                        }
305                    } else {
306                        (1.0, 1.0)
307                    };
308                    let move1 = move1base * multi_strike_pullback;
309                    let move2 = move2base * multi_strike_pullback;
310
311                    match strike {
312                        0 => {
313                            init_biped_small_alpha(&mut next, s_a);
314
315                            next.control.position += Vec3::new(0.0, 8.0, 0.0);
316                            next.control.orientation.rotate_x(-PI / 8.0);
317                            next.hand_l.position += Vec3::new(-6.0, -4.0, -4.0);
318                            next.hand_l.orientation.rotate_x(PI / 2.0);
319                            next.hand_l.orientation.rotate_z(-PI / 8.0);
320                            next.hand_r.position += Vec3::new(4.0, -4.0, -6.0);
321                            next.hand_r.orientation.rotate_x(PI / 2.0);
322                            next.hand_r.orientation.rotate_z(PI / 9.0);
323
324                            next.chest.orientation.rotate_z(PI / 4.0 * move1);
325                            next.control.position += Vec3::new(0.0, (PI * move1).cos(), 0.0);
326                            next.control.orientation.rotate_y(-PI / 8.0 * move1);
327                            next.control.orientation.rotate_x(-PI / 8.0 * move1.powi(2));
328
329                            next.control
330                                .orientation
331                                .rotate_y(-PI / 3.0 * f32::from(move2 != 0.0));
332                            next.chest.orientation.rotate_z(-PI / 2.5 * move2);
333                        },
334                        1 => {
335                            next.chest.orientation.rotate_z(-PI / 5.0 * move1);
336                            next.control.position += Vec3::new(0.0, (PI * move1).cos(), 0.0);
337                            next.control.orientation.rotate_y(PI / 2.0 * move1);
338
339                            next.control
340                                .orientation
341                                .rotate_y(PI / 3.0 * f32::from(move2 != 0.0));
342                            next.chest.orientation.rotate_z(PI / 2.0 * move2);
343                        },
344                        _ => {},
345                    }
346                },
347                Some(
348                    "common.abilities.daggersimple.singlestrike"
349                    | "common.abilities.vampire.bloodmoon_heiress.singlestrike",
350                ) => {
351                    let anim_time = anim_time.min(1.0);
352                    let (move1base, move2base, move3) = match stage_section {
353                        StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0),
354                        StageSection::Action => (1.0, anim_time.powi(4), 0.0),
355                        StageSection::Recover => (1.0, 1.0, anim_time),
356                        _ => (0.0, 0.0, 0.0),
357                    };
358                    let pullback = 1.0 - move3;
359                    let move1abs = move1base * pullback;
360                    let move2abs = move2base * pullback;
361
362                    init_biped_small_alpha(&mut next, s_a);
363                    biped_small_alpha_dagger(&mut next, s_a, move1abs, move2abs);
364                },
365                Some(
366                    "common.abilities.spear.doublestrike"
367                    | "common.abilities.custom.purple_legoom.doublestrike",
368                ) => {
369                    let anim_time = anim_time.min(1.0);
370                    let speed = Vec2::<f32>::from(velocity).magnitude();
371                    let speednorm = speed / 9.4;
372                    let speednormcancel = 1.0 - speednorm;
373
374                    let (move1base, move2base, move3) = match stage_section {
375                        StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0),
376                        StageSection::Action => (1.0, anim_time.powi(4), 0.0),
377                        StageSection::Recover => (1.0, 1.0, anim_time),
378                        _ => (0.0, 0.0, 0.0),
379                    };
380                    let pullback = 1.0 - move3;
381                    let move1abs = move1base * pullback;
382                    let move2abs = move2base * pullback;
383
384                    init_biped_small_alpha(&mut next, s_a);
385                    biped_small_alpha_spear(
386                        &mut next,
387                        s_a,
388                        move1abs,
389                        move2abs,
390                        anim_time,
391                        speednormcancel,
392                    );
393                },
394                Some("common.abilities.haniwa.guard.backpedal") => {
395                    init_biped_small_alpha(&mut next, s_a);
396                    biped_small_wield_spear(&mut next, s_a, anim_time, 0.0, 0.0);
397
398                    let (move1, move2, move3) = match stage_section {
399                        StageSection::Buildup => (anim_time.powf(0.25), 0.0, 0.0),
400                        StageSection::Action => (1.0, anim_time, 0.0),
401                        StageSection::Recover => (1.0, 1.0, anim_time.powf(0.25)),
402                        _ => (0.0, 0.0, 0.0),
403                    };
404                    let pullback = 1.0 - move3;
405                    let move1 = move1 * pullback;
406                    let move2 = move2 * pullback;
407
408                    biped_small_alpha_spear(&mut next, s_a, move1, move2, anim_time, 0.0);
409                },
410                _ => {},
411            }
412        }
413        next
414    }
415}