1use super::{
2 super::{Animation, vek::*},
3 BipedLargeSkeleton, SkeletonAttr,
4};
5use common::{
6 comp::item::{AbilitySpec, ToolKind},
7 states::utils::StageSection,
8};
9use core::f32::consts::PI;
10
11pub struct ShockwaveAnimation;
12
13type ShockwaveAnimationDependency<'a> = (
14 Option<ToolKind>,
15 (Option<ToolKind>, Option<&'a AbilitySpec>),
16 f32,
17 f32,
18 Option<StageSection>,
19 Option<&'a str>,
20);
21impl Animation for ShockwaveAnimation {
22 type Dependency<'a> = ShockwaveAnimationDependency<'a>;
23 type Skeleton = BipedLargeSkeleton;
24
25 #[cfg(feature = "use-dyn-lib")]
26 const UPDATE_FN: &'static [u8] = b"biped_large_shockwave\0";
27
28 #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_large_shockwave")]
29 #[expect(clippy::single_match)] fn update_skeleton_inner(
31 skeleton: &Self::Skeleton,
32 (
33 active_tool_kind,
34 _second_tool_kind,
35 _global_time,
36 velocity,
37 stage_section,
38 ability_id,
39 ): Self::Dependency<'_>,
40 anim_time: f32,
41 rate: &mut f32,
42 s_a: &SkeletonAttr,
43 ) -> Self::Skeleton {
44 *rate = 1.0;
45 let mut next = (*skeleton).clone();
46
47 let (move1, move1pow, move2, move3) = match stage_section {
48 Some(StageSection::Buildup) => (anim_time, anim_time.powf(0.25), 0.0, 0.0),
49 Some(StageSection::Action) => (1.0, 1.0, anim_time, 0.0),
50 Some(StageSection::Recover) => (1.0, 1.0, 1.0, anim_time),
51 _ => (0.0, 0.0, 0.0, 0.0),
52 };
53
54 let pullback = 1.0 - move3;
55 let move1pow = move1pow * pullback;
56 let move2 = move2 * pullback;
57
58 next.main.position = Vec3::new(0.0, 0.0, 0.0);
59 next.main.orientation = Quaternion::rotation_x(0.0);
60
61 next.hand_l.position = Vec3::new(0.0, 0.0, s_a.grip.0);
62 next.hand_r.position = Vec3::new(0.0, 0.0, s_a.grip.0);
63
64 next.hand_l.orientation = Quaternion::rotation_x(0.0);
65 next.hand_r.orientation = Quaternion::rotation_x(0.0);
66
67 match active_tool_kind {
68 Some(ToolKind::Sceptre | ToolKind::Staff) => {
69 next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
70
71 next.hand_l.position = Vec3::new(s_a.sthl.0, s_a.sthl.1, s_a.sthl.2);
72 next.hand_l.orientation =
73 Quaternion::rotation_x(s_a.sthl.3) * Quaternion::rotation_y(s_a.sthl.4);
74 next.hand_r.position = Vec3::new(s_a.sthr.0, s_a.sthr.1, s_a.sthr.2);
75 next.hand_r.orientation =
76 Quaternion::rotation_x(s_a.sthr.3) * Quaternion::rotation_y(s_a.sthr.4);
77 next.main.position = Vec3::new(0.0, 0.0, 0.0);
78 next.main.orientation = Quaternion::rotation_y(0.0);
79
80 next.control.position = Vec3::new(s_a.stc.0, s_a.stc.1, s_a.stc.2);
81 next.control.orientation =
82 Quaternion::rotation_x(s_a.stc.3) * Quaternion::rotation_y(s_a.stc.4);
83
84 let twist = move1 * 0.8;
85
86 next.control.position = Vec3::new(
87 s_a.stc.0 + move1 * 5.0 + move3 * -5.0,
88 s_a.stc.1 + move1 * 13.0 + move3 * -3.0,
89 s_a.stc.2 + move1 * 10.0 + move2 * -2.0 + move3 * -8.0,
90 );
91 next.control.orientation =
92 Quaternion::rotation_x(s_a.stc.3 + move1 * 0.8 + move2 * 0.3 + move3 * -1.1)
93 * Quaternion::rotation_y(
94 s_a.stc.4 + move1 * -0.15 + move2 * 0.3 + move3 * -0.45,
95 )
96 * Quaternion::rotation_z(move1 * 0.8 + move2 * -0.8);
97
98 next.head.orientation = Quaternion::rotation_x(move1 * 0.4 + move3 * -0.4)
99 * Quaternion::rotation_z(twist * 0.2 + move2 * -0.8 + move3 * 0.6);
100
101 next.upper_torso.position = Vec3::new(
102 0.0,
103 s_a.upper_torso.0,
104 s_a.upper_torso.1 + move1 * 2.0 + move2 * -4.0 + move3 * 2.0,
105 );
106 next.upper_torso.orientation = Quaternion::rotation_x(move2 * -0.8 + move3 * 0.8)
107 * Quaternion::rotation_z(twist * -0.2 + move2 * -0.1 + move3 * 0.3);
108
109 next.lower_torso.orientation = Quaternion::rotation_x(move2 * 0.3 + move3 * -0.3)
110 * Quaternion::rotation_z(twist + move2 * -0.8);
111
112 if velocity < 0.5 {
113 next.foot_l.position = Vec3::new(
114 -s_a.foot.0,
115 s_a.foot.1 + move1 * -7.0 + move2 * 7.0,
116 s_a.foot.2,
117 );
118 next.foot_l.orientation = Quaternion::rotation_x(move1 * -0.8 + move2 * 0.8)
119 * Quaternion::rotation_z(move1 * 0.3 + move2 * -0.3);
120
121 next.foot_r.position = Vec3::new(
122 s_a.foot.0,
123 s_a.foot.1 + move1 * 5.0 + move2 * -5.0,
124 s_a.foot.2,
125 );
126 next.foot_r.orientation = Quaternion::rotation_y(move1 * -0.3 + move2 * 0.3)
127 * Quaternion::rotation_z(move1 * 0.4 + move2 * -0.4);
128 }
129 },
130 Some(ToolKind::Natural) => match ability_id {
131 Some("common.abilities.custom.yeti.icespikes") => {
132 next.second.scale = Vec3::one() * 0.0;
133
134 next.head.orientation = Quaternion::rotation_x(move1pow * 0.8 + move2 * -1.2);
135 next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
136 next.jaw.orientation = Quaternion::rotation_x(move2 * -0.3);
137 next.control_l.position = Vec3::new(-0.5, 4.0, 1.0);
138 next.control_r.position = Vec3::new(-0.5, 4.0, 1.0);
139 next.control_l.orientation = Quaternion::rotation_x(PI / 2.0);
140 next.control_r.orientation = Quaternion::rotation_x(PI / 2.0);
141 next.weapon_l.position =
142 Vec3::new(-12.0 + (move1pow * 20.0).min(10.0), -1.0, -15.0);
143 next.weapon_r.position =
144 Vec3::new(12.0 + (move1pow * -20.0).max(-10.0), -1.0, -15.0);
145
146 next.weapon_l.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1)
147 * Quaternion::rotation_z(move1pow * -1.0);
148 next.weapon_r.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1)
149 * Quaternion::rotation_z(move1pow * 1.0);
150
151 next.shoulder_l.orientation =
152 Quaternion::rotation_x(-0.3 + move1pow * 2.8 + move2 * -2.8);
153
154 next.shoulder_r.orientation =
155 Quaternion::rotation_x(-0.3 + move1pow * 2.8 + move2 * -2.8);
156
157 next.control.orientation =
158 Quaternion::rotation_x(move1pow * 2.5 + move2 * -2.0);
159
160 let twist = move1 * 0.6 + move3 * -0.6;
161 next.upper_torso.position =
162 Vec3::new(0.0, s_a.upper_torso.0, s_a.upper_torso.1);
163 next.upper_torso.orientation =
164 Quaternion::rotation_x(move1pow * 0.8 + move2 * -1.1)
165 * Quaternion::rotation_z(twist * -0.2 + move1 * -0.1 + move2 * 0.3);
166
167 next.lower_torso.orientation =
168 Quaternion::rotation_x(move1pow * -0.8 + move2 * 1.1)
169 * Quaternion::rotation_z(twist);
170
171 next.foot_l.position = Vec3::new(
172 -s_a.foot.0,
173 s_a.foot.1 + move1pow * -7.0 + move2 * 7.0,
174 s_a.foot.2,
175 );
176 next.foot_l.orientation = Quaternion::rotation_x(move1pow * -0.8 + move2 * 0.8)
177 * Quaternion::rotation_z(move1pow * 0.3 + move2 * -0.3);
178
179 next.foot_r.position = Vec3::new(
180 s_a.foot.0,
181 s_a.foot.1 + move1pow * 5.0 + move2 * -5.0,
182 s_a.foot.2,
183 );
184 next.foot_r.orientation = Quaternion::rotation_y(move1pow * -0.3 + move2 * 0.3)
185 * Quaternion::rotation_z(move1pow * 0.4 + move2 * -0.4);
186
187 next.main.orientation = Quaternion::rotation_y(move1 * 0.4 + move2 * -0.6)
188 * Quaternion::rotation_x(move2 * -0.4);
189 },
190 _ => {},
191 },
192 Some(ToolKind::Axe) => match ability_id {
193 Some("common.abilities.custom.gigas_frost.flashfreeze") => {
194 next.second.scale = Vec3::one() * 0.0;
195
196 next.head.orientation = Quaternion::rotation_x(move1pow * 0.8 + move2 * -1.2);
197 next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
198 next.jaw.orientation = Quaternion::rotation_x(move2 * -0.3);
199 next.control_l.position = Vec3::new(-0.5, 4.0, 1.0);
200 next.control_r.position = Vec3::new(-0.5, 4.0, 1.0);
201 next.control_l.orientation = Quaternion::rotation_x(PI / 2.0);
202 next.control_r.orientation = Quaternion::rotation_x(PI / 2.0);
203 next.weapon_l.position =
204 Vec3::new(-12.0 + (move1pow * 20.0).min(10.0), -1.0, -15.0);
205 next.weapon_r.position =
206 Vec3::new(12.0 + (move1pow * -20.0).max(-10.0), -1.0, -15.0);
207
208 next.weapon_l.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1)
209 * Quaternion::rotation_z(move1pow * -1.0);
210 next.weapon_r.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1)
211 * Quaternion::rotation_z(move1pow * 1.0);
212
213 next.shoulder_l.orientation =
214 Quaternion::rotation_x(-0.3 + move1pow * 2.8 + move2 * -2.8);
215
216 next.shoulder_r.orientation =
217 Quaternion::rotation_x(-0.3 + move1pow * 2.8 + move2 * -2.8);
218
219 next.control.orientation = Quaternion::rotation_x(move1pow * 1.5 + move2 * 0.6);
220
221 let twist = move1 * 0.6 + move3 * -0.6;
222 next.upper_torso.position =
223 Vec3::new(0.0, s_a.upper_torso.0, s_a.upper_torso.1);
224 next.upper_torso.orientation =
225 Quaternion::rotation_x(move1pow * 0.4 + move2 * -1.1)
226 * Quaternion::rotation_z(twist * -0.2 + move1 * -0.1 + move2 * 0.3);
227
228 next.lower_torso.orientation =
229 Quaternion::rotation_x(move1pow * -0.4 + move2 * 1.1)
230 * Quaternion::rotation_z(twist);
231
232 next.foot_l.position = Vec3::new(
233 -s_a.foot.0,
234 s_a.foot.1 + move1pow * -7.0 + move2 * 7.0,
235 s_a.foot.2,
236 );
237 next.foot_l.orientation = Quaternion::rotation_x(move1pow * -0.8 + move2 * 0.8)
238 * Quaternion::rotation_z(move1pow * 0.3 + move2 * -0.3);
239
240 next.foot_r.position = Vec3::new(
241 s_a.foot.0,
242 s_a.foot.1 + move1pow * 5.0 + move2 * -5.0,
243 s_a.foot.2,
244 );
245 next.foot_r.orientation = Quaternion::rotation_y(move1pow * -0.3 + move2 * 0.3)
246 * Quaternion::rotation_z(move1pow * 0.4 + move2 * -0.4);
247 next.main.position = Vec3::new(-5.0 + (move1pow * 20.0).min(10.0), 4.0, 12.0);
248 next.main.orientation = Quaternion::rotation_y(move1 * 0.4 + move2 * -0.1)
249 * Quaternion::rotation_x(PI);
250 },
251 _ => {},
252 },
253 Some(ToolKind::Hammer) => match ability_id {
254 Some("common.abilities.custom.cyclops.hammer_shockwave") => {
255 next.second.scale = Vec3::one() * 0.0;
256
257 next.head.orientation = Quaternion::rotation_x(move1pow * 0.8 + move2 * -1.2);
258 next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
259 next.jaw.orientation = Quaternion::rotation_x(move2 * -0.3);
260 next.control_l.position = Vec3::new(-0.5, 4.0, 1.0);
261 next.control_r.position = Vec3::new(-0.5, 4.0, 1.0);
262 next.control_l.orientation = Quaternion::rotation_x(PI / 2.0);
263 next.control_r.orientation = Quaternion::rotation_x(PI / 2.0);
264 next.weapon_l.position =
265 Vec3::new(-12.0 + (move1pow * 20.0).min(10.0), -1.0, -15.0);
266 next.weapon_r.position =
267 Vec3::new(12.0 + (move1pow * -20.0).max(-10.0), -1.0, -15.0);
268
269 next.weapon_l.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1)
270 * Quaternion::rotation_z(move1pow * -1.0);
271 next.weapon_r.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1)
272 * Quaternion::rotation_z(move1pow * 1.0);
273
274 next.shoulder_l.orientation =
275 Quaternion::rotation_x(-0.3 + move1pow * 2.8 + move2 * -2.8);
276
277 next.shoulder_r.orientation =
278 Quaternion::rotation_x(-0.3 + move1pow * 2.8 + move2 * -2.8);
279
280 next.control.orientation =
281 Quaternion::rotation_x(move1pow * 2.5 + move2 * -2.0);
282
283 let twist = move1 * 0.6 + move3 * -0.6;
284 next.upper_torso.position =
285 Vec3::new(0.0, s_a.upper_torso.0, s_a.upper_torso.1);
286 next.upper_torso.orientation =
287 Quaternion::rotation_x(move1pow * 0.8 + move2 * -1.1)
288 * Quaternion::rotation_z(twist * -0.2 + move1 * -0.1 + move2 * 0.3);
289
290 next.lower_torso.orientation =
291 Quaternion::rotation_x(move1pow * -0.8 + move2 * 1.1)
292 * Quaternion::rotation_z(twist);
293
294 next.foot_l.position = Vec3::new(
295 -s_a.foot.0,
296 s_a.foot.1 + move1pow * -7.0 + move2 * 7.0,
297 s_a.foot.2,
298 );
299 next.foot_l.orientation = Quaternion::rotation_x(move1pow * -0.8 + move2 * 0.8)
300 * Quaternion::rotation_z(move1pow * 0.3 + move2 * -0.3);
301
302 next.foot_r.position = Vec3::new(
303 s_a.foot.0,
304 s_a.foot.1 + move1pow * 5.0 + move2 * -5.0,
305 s_a.foot.2,
306 );
307 next.foot_r.orientation = Quaternion::rotation_y(move1pow * -0.3 + move2 * 0.3)
308 * Quaternion::rotation_z(move1pow * 0.4 + move2 * -0.4);
309
310 next.main.orientation = Quaternion::rotation_y(move1 * 0.4 + move2 * -0.6)
311 * Quaternion::rotation_x(move2 * -0.4);
312 },
313 Some("common.abilities.custom.dwarves.forgemaster.lavawave") => {
314 next.head.orientation = Quaternion::rotation_x(move1pow * 0.8 + move2 * -1.2);
315 next.control_l.position = Vec3::new(-0.5, 8.0, 1.0);
316 next.control_r.position = Vec3::new(-0.5, 8.0, 1.0);
317 next.control_l.orientation = Quaternion::rotation_x(PI / 2.0);
318 next.control_r.orientation = Quaternion::rotation_x(PI / 2.0);
319 next.weapon_l.position =
320 Vec3::new(-12.0 + (move1pow * 20.0).min(10.0), 3.0, -25.0);
321 next.weapon_r.position =
322 Vec3::new(12.0 + (move1pow * -20.0).max(-10.0), 3.0, -25.0);
323
324 next.weapon_l.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1)
325 * Quaternion::rotation_z(move1pow * -1.0);
326 next.weapon_r.orientation = Quaternion::rotation_x(-PI / 2.0 - 0.1)
327 * Quaternion::rotation_z(move1pow * 1.0);
328
329 next.shoulder_l.orientation =
330 Quaternion::rotation_x(-0.3 + move1pow * 2.8 + move2 * -2.8);
331
332 next.shoulder_r.orientation =
333 Quaternion::rotation_x(-0.3 + move1pow * 2.8 + move2 * -2.8);
334
335 next.control.orientation =
336 Quaternion::rotation_x(move1pow * 2.5 + move2 * -2.0);
337
338 let twist = move1 * 0.6 + move3 * -0.6;
339 next.upper_torso.position =
340 Vec3::new(0.0, s_a.upper_torso.0, s_a.upper_torso.1);
341 next.upper_torso.orientation =
342 Quaternion::rotation_x(move1pow * 0.8 + move2 * -1.1)
343 * Quaternion::rotation_z(twist * -0.2 + move1 * -0.1 + move2 * 0.3);
344
345 next.lower_torso.orientation =
346 Quaternion::rotation_x(move1pow * -0.8 + move2 * 1.1)
347 * Quaternion::rotation_z(twist);
348
349 next.foot_l.position = Vec3::new(
350 -s_a.foot.0,
351 s_a.foot.1 + move1pow * -7.0 + move2 * 7.0,
352 s_a.foot.2,
353 );
354 next.foot_l.orientation = Quaternion::rotation_x(move1pow * -0.8 + move2 * 0.8)
355 * Quaternion::rotation_z(move1pow * 0.3 + move2 * -0.3);
356
357 next.foot_r.position = Vec3::new(
358 s_a.foot.0,
359 s_a.foot.1 + move1pow * 5.0 + move2 * -5.0,
360 s_a.foot.2,
361 );
362 next.foot_r.orientation = Quaternion::rotation_y(move1pow * -0.3 + move2 * 0.3)
363 * Quaternion::rotation_z(move1pow * 0.4 + move2 * -0.4);
364
365 next.main.orientation = Quaternion::rotation_y(move1 * 0.4 + move2 * -0.6)
366 * Quaternion::rotation_x(move2 * -0.4)
367 * Quaternion::rotation_z(0.8);
368 },
369 _ => {},
370 },
371 _ => {},
372 }
373 next
374 }
375}