1use super::{
2 super::{Animation, vek::*},
3 BipedSmallSkeleton, SkeletonAttr,
4};
5use common::{comp::item::ToolKind, states::utils::StageSection};
6use std::f32::consts::PI;
7
8pub struct ShootAnimation;
9
10type ShootAnimationDependency<'a> = (
11 Option<ToolKind>,
12 Vec3<f32>,
13 Vec3<f32>,
14 Vec3<f32>,
15 f32,
16 Vec3<f32>,
17 f32,
18 Option<StageSection>,
19 f32,
20 Option<&'a str>,
21);
22
23impl Animation for ShootAnimation {
24 type Dependency<'a> = ShootAnimationDependency<'a>;
25 type Skeleton = BipedSmallSkeleton;
26
27 #[cfg(feature = "use-dyn-lib")]
28 const UPDATE_FN: &'static [u8] = b"biped_small_shoot\0";
29
30 #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_small_shoot")]
31
32 fn update_skeleton_inner(
33 skeleton: &Self::Skeleton,
34 (
35 active_tool_kind,
36 velocity,
37 _orientation,
38 _last_ori,
39 _global_time,
40 _avg_vel,
41 _acc_vel,
42 stage_section,
43 _timer,
44 ability_id,
45 ): Self::Dependency<'_>,
46 anim_time: f32,
47 _rate: &mut f32,
48 s_a: &SkeletonAttr,
49 ) -> Self::Skeleton {
50 let mut next = (*skeleton).clone();
51 let speed = Vec2::<f32>::from(velocity).magnitude();
52
53 let fast = (anim_time * 10.0).sin();
54 let fastalt = (anim_time * 10.0 + PI / 2.0).sin();
55
56 let speednorm = speed / 9.4;
57 let speednormcancel = 1.0 - speednorm;
58
59 next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1 + fast * -0.1 * speednormcancel);
60 next.head.orientation = Quaternion::rotation_x(0.45 * speednorm)
61 * Quaternion::rotation_y(fast * 0.07 * speednormcancel);
62 next.chest.position = Vec3::new(
63 0.0,
64 s_a.chest.0,
65 s_a.chest.1 + fastalt * 0.4 * speednormcancel + speednormcancel * -0.5,
66 );
67
68 next.pants.position = Vec3::new(0.0, s_a.pants.0, s_a.pants.1);
69
70 next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
71 next.tail.orientation = Quaternion::rotation_x(0.05 * fastalt * speednormcancel)
72 * Quaternion::rotation_z(fast * 0.15 * speednormcancel);
73
74 match ability_id {
75 Some("common.abilities.adlet.hunter.throw") => {
76 next.main.position = Vec3::new(8.0, -7.0, 2.0);
77 next.main.orientation = Quaternion::rotation_x(PI / -2.0);
78
79 next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
80 next.hand_r.position = Vec3::new(5.0, -2.0, s_a.grip.2);
81
82 next.hand_l.orientation = Quaternion::rotation_x(0.0);
83 next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0);
84 },
85 Some("common.abilities.adlet.tracker.trap") => {
86 next.main.position = Vec3::new(10.0, 0.0, 9.0);
87
88 next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
89 next.hand_r.position = Vec3::new(5.0, -2.0, s_a.grip.2);
90
91 next.hand_l.orientation = Quaternion::rotation_x(0.0);
92 next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0);
93 },
94 _ => {
95 next.main.position = Vec3::new(0.0, 0.0, 0.0);
96 next.main.orientation = Quaternion::rotation_x(0.0);
97
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
101 next.hand_l.orientation = Quaternion::rotation_x(0.0);
102 next.hand_r.orientation = Quaternion::rotation_x(0.0);
103 },
104 };
105
106 match active_tool_kind {
107 Some(ToolKind::Bow) => match ability_id {
108 Some("common.abilities.adlet.tracker.trap") => {
109 let (move1base, move2base, move3) = match stage_section {
110 Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
111 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
112 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
113 _ => (0.0, 0.0, 0.0),
114 };
115 let pullback = 1.0 - move3;
116 let move1abs = move1base * pullback;
117 let move2abs = move2base * pullback;
118 next.main.position = Vec3::new(2.0, -3.0, -3.0);
119
120 next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2 - 2.0);
121 next.hand_r.position = Vec3::new(
122 s_a.hand.0,
123 s_a.hand.1 + move2abs * 1.5,
124 s_a.hand.2 - 2.5 + move1abs * 2.5,
125 );
126
127 next.hand_r.orientation =
128 Quaternion::rotation_x(move1abs * 4.0 + move2abs * -0.7)
129 * Quaternion::rotation_y(0.0 + move1abs * -0.7);
130
131 next.hand_l.orientation = Quaternion::rotation_x(PI / 3.0 * move1abs)
132 * Quaternion::rotation_y(-0.7 * move1abs + move2abs * 0.1);
133 },
134 _ => {
135 let (move1base, move2base, move3) = match stage_section {
136 Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
137 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
138 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
139 _ => (0.0, 0.0, 0.0),
140 };
141 let pullback = 1.0 - move3;
142 let move1abs = move1base * pullback;
143 let move2abs = move2base * pullback;
144 next.control_l.position = Vec3::new(
145 -1.0 - s_a.grip.0 * 2.0 + move2abs * -4.0,
146 move2abs * -8.0,
147 0.0,
148 );
149 next.control_r.position = Vec3::new(1.0 + s_a.grip.0 * 2.0, 3.0, -2.0);
150
151 next.control.position = Vec3::new(
152 -1.0,
153 2.0 + move1abs * 3.0 + s_a.grip.2,
154 3.0 + move1abs * 7.0 - s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0,
155 );
156
157 next.control_l.orientation =
158 Quaternion::rotation_x(PI / 2.0) * Quaternion::rotation_y(-0.3);
159 next.control_r.orientation =
160 Quaternion::rotation_x(PI / 2.0 + s_a.grip.0 * 0.2)
161 * Quaternion::rotation_y(0.5 + s_a.grip.0 * 0.2);
162
163 next.control.orientation = Quaternion::rotation_x(-0.3 + move1abs * 0.4)
164 * Quaternion::rotation_y(0.5 * speednorm);
165 },
166 },
167 Some(ToolKind::Natural) => match ability_id {
168 Some("common.abilities.custom.irrwurz.magicball") => {
169 let (move1base, move2base, move3) = match stage_section {
170 Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
171 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
172 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
173 _ => (0.0, 0.0, 0.0),
174 };
175 let pullback = 1.0 - move3;
176 let move1abs = move1base * pullback;
177 let move2abs = move2base * pullback;
178 next.main.position = Vec3::new(2.0, -3.0, -3.0);
179
180 next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2 - 2.0);
181 next.hand_r.position = Vec3::new(
182 s_a.hand.0,
183 s_a.hand.1 + move2abs * 1.5,
184 s_a.hand.2 - 2.5 + move1abs * 2.5,
185 );
186
187 next.hand_r.orientation =
188 Quaternion::rotation_x(move1abs * 4.0 + move2abs * -0.7);
189
190 next.hand_l.orientation = Quaternion::rotation_x(PI / 3.0 * move1abs)
191 * Quaternion::rotation_y(-0.7 * move1abs + move2abs * 0.1);
192 },
193 Some("common.abilities.custom.goblin_chucker.throw") => {
194 let (move1base, move2base, move3) = match stage_section {
195 Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
196 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
197 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
198 _ => (0.0, 0.0, 0.0),
199 };
200 let pullback = 1.0 - move3;
201 let move1abs = move1base * pullback;
202 let move2abs = move2base * pullback;
203
204 next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2 - 2.0);
205 next.hand_r.position = Vec3::new(
206 s_a.hand.0,
207 s_a.hand.1 + move2abs * 1.5,
208 s_a.hand.2 - 2.5 + move1abs * 2.5,
209 );
210
211 next.hand_r.orientation =
212 Quaternion::rotation_x(move1abs * 4.0 + move2abs * -0.7)
213 * Quaternion::rotation_y(0.0 + move1abs * -0.7);
214
215 next.hand_l.orientation = Quaternion::rotation_x(PI / 3.0 * move1abs)
216 * Quaternion::rotation_y(-0.7 * move1abs + move2abs * 0.1);
217 },
218 _ => {
219 let (move1base, move2base, move3) = match stage_section {
220 Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
221 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
222 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
223 _ => (0.0, 0.0, 0.0),
224 };
225 let pullback = 1.0 - move3;
226 let move1abs = move1base * pullback;
227 let move2abs = move2base * pullback;
228 next.control_l.position = Vec3::new(
229 1.0 - s_a.grip.0 * 2.0 + move2abs * -4.0,
230 move2abs * -8.0,
231 0.0,
232 );
233 next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 6.0, -2.0);
234
235 next.control.position = Vec3::new(
236 -1.0,
237 2.0 + move1abs * 3.0 + s_a.grip.2,
238 3.0 + move1abs * 7.0 - s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0,
239 );
240
241 next.control_l.orientation =
242 Quaternion::rotation_x(PI / 2.0) * Quaternion::rotation_y(-0.3);
243 next.control_r.orientation =
244 Quaternion::rotation_x(PI / 2.0 + s_a.grip.0 * 0.2)
245 * Quaternion::rotation_y(0.5 + s_a.grip.0 * 0.2);
246
247 next.control.orientation = Quaternion::rotation_x(-0.3 + move1abs * 0.4)
248 * Quaternion::rotation_y(0.5 * speednorm);
249 },
250 },
251 Some(ToolKind::Blowgun) => {
252 let (move1base, move2base, move3) = match stage_section {
253 Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
254 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
255 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
256 _ => (0.0, 0.0, 0.0),
257 };
258 let pullback = 1.0 - move3;
259 let move1abs = move1base * pullback;
260 let move2abs = move2base * pullback;
261 next.head.orientation = Quaternion::rotation_x(move1abs * 0.5 + move2abs * -0.7);
262 next.control_l.position = Vec3::new(1.0 - s_a.grip.0 * 2.0, 0.0, 3.0);
263 next.control_r.position = Vec3::new(-1.0 + s_a.grip.0 * 2.0, 0.0, 4.0);
264
265 next.control.position = Vec3::new(
266 0.0,
267 move1abs * -2.0 + move2abs * 1.0 + s_a.grip.2,
268 move1abs * 3.5 + move2abs * -2.0 + 4.0 - s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0,
269 );
270
271 next.control_l.orientation =
272 Quaternion::rotation_x(3.8 + move1abs * 0.4 + move2abs * -0.5)
273 * Quaternion::rotation_y(-0.3);
274 next.control_r.orientation = Quaternion::rotation_x(
275 3.5 + move1abs * 0.4 + move2abs * -0.5 + s_a.grip.0 * 0.2,
276 ) * Quaternion::rotation_y(0.5 + s_a.grip.0 * 0.2);
277
278 next.control.orientation = Quaternion::rotation_x(
279 -2.2 + move1abs * 0.7 + move2abs * -0.2 + 0.5 * speednorm,
280 );
281 },
282 Some(ToolKind::Staff) => match ability_id {
283 Some(
284 "common.abilities.custom.dwarves.flamekeeper.mines"
285 | "common.abilities.custom.dwarves.flamekeeper.lava_mortar",
286 ) => {
287 let (move1base, _move2base, move3) = match stage_section {
288 Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0),
289 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
290 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
291 _ => (0.0, 0.0, 0.0),
292 };
293 let pullback = 1.0 - move3;
294 let move1abs = move1base * pullback;
295 next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0);
296 next.control_r.position = Vec3::new(
297 7.0 + s_a.grip.0 * 2.0 + move1abs * -8.0,
298 -4.0 + move1abs * 4.0,
299 3.0,
300 );
301
302 next.control.position = Vec3::new(
303 -5.0,
304 -1.0 + s_a.grip.2,
305 -2.0 + -s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0 + move1abs * 5.0,
306 );
307
308 next.control_l.orientation = Quaternion::rotation_x(PI / 2.0 + move1abs * 0.8)
309 * Quaternion::rotation_y(-0.3)
310 * Quaternion::rotation_z(-0.3);
311 next.control_r.orientation =
312 Quaternion::rotation_x(PI / 2.0 + s_a.grip.0 * 0.2 + move1abs * 0.8)
313 * Quaternion::rotation_y(-0.4 + s_a.grip.0 * 0.2 + move1abs * 0.8)
314 * Quaternion::rotation_z(-0.0);
315
316 next.control.orientation = Quaternion::rotation_x(-0.3 + move1abs * -0.3)
317 * Quaternion::rotation_y(-0.2 * speednorm + move1abs * 0.3)
318 * Quaternion::rotation_z(0.5 + move1abs * 0.6);
319 },
320 _ => {
321 let (move1base, _move2base, move3) = match stage_section {
322 Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0),
323 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
324 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
325 _ => (0.0, 0.0, 0.0),
326 };
327 let pullback = 1.0 - move3;
328 let move1abs = move1base * pullback;
329 next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0);
330 next.control_r.position = Vec3::new(
331 7.0 + s_a.grip.0 * 2.0 + move1abs * -8.0,
332 -4.0 + move1abs * 4.0,
333 3.0,
334 );
335
336 next.control.position = Vec3::new(
337 -5.0,
338 -1.0 + s_a.grip.2,
339 -2.0 + -s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0 + move1abs * 5.0,
340 );
341
342 next.control_l.orientation = Quaternion::rotation_x(PI / 2.0 + move1abs * 0.8)
343 * Quaternion::rotation_y(-0.3)
344 * Quaternion::rotation_z(-0.3);
345 next.control_r.orientation =
346 Quaternion::rotation_x(PI / 2.0 + s_a.grip.0 * 0.2 + move1abs * 0.8)
347 * Quaternion::rotation_y(-0.4 + s_a.grip.0 * 0.2 + move1abs * 0.8)
348 * Quaternion::rotation_z(-0.0);
349
350 next.control.orientation = Quaternion::rotation_x(-0.3 + move1abs * -0.6)
351 * Quaternion::rotation_y(-0.2 * speednorm)
352 * Quaternion::rotation_z(0.5 + move1abs * 0.6);
353 },
354 },
355 Some(ToolKind::Spear) => {
356 let (move1base, move2base, move3) = match stage_section {
357 Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
358 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
359 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
360 _ => (0.0, 0.0, 0.0),
361 };
362 let pullback = 1.0 - move3;
363 let move1abs = move1base * pullback;
364 let move2abs = move2base * pullback;
365 next.control_l.position = Vec3::new(
366 0.0,
367 0.0 + move1abs * 4.0 + move2abs * -4.0,
368 -2.0 + move1abs * -8.0,
369 );
370 next.control_r.position = Vec3::new(
371 -1.0 + s_a.grip.0 * 2.0,
372 2.0 + move3 * -4.0,
373 -2.0 + move3 * -4.0,
374 );
375
376 next.control.position = Vec3::new(
377 -1.0,
378 0.0 + move1abs * -8.0 + move2abs * 8.0 + s_a.grip.2,
379 3.0 + move1abs * 7.0 - s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0,
380 );
381
382 next.control_l.orientation =
383 Quaternion::rotation_x(PI / 2.0) * Quaternion::rotation_y(-0.3);
384 next.control_r.orientation = Quaternion::rotation_x(PI / 2.0 + s_a.grip.0 * 0.2)
385 * Quaternion::rotation_y(0.5 + s_a.grip.0 * 0.2 + move3 * -1.5);
386
387 next.control.orientation =
388 Quaternion::rotation_x(-0.3 + move1abs * 0.5 + move2abs * -0.5 + move3 * 0.5)
389 * Quaternion::rotation_y(0.5 * speednorm);
390
391 if matches!(stage_section, Some(StageSection::Recover)) {
392 if move3 < 0.05 {
393 next.main.position += Vec3::new(0.0, 100000.0, -10000000.0);
394 }
395 if move3 < 0.3 {
396 next.main.scale = Vec3::zero();
397 }
398 }
399 },
400 Some(ToolKind::Dagger) => {
401 let (move1base, move2base, move3) = match stage_section {
402 Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
403 Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0),
404 Some(StageSection::Recover) => (1.0, 1.0, anim_time),
405 _ => (0.0, 0.0, 0.0),
406 };
407 let pullback = 1.0 - move3;
408 let move1abs = move1base * pullback;
409 let move2abs = move2base * pullback;
410 next.main.position = Vec3::new(0.0, 2.0, -5.0);
411 next.control_l.position = Vec3::new(
412 0.0,
413 0.0 + move1abs * 1.0 + move2abs * -1.0,
414 -2.0 + move1abs * -2.0,
415 );
416 next.control_r.position = Vec3::new(
417 -1.0 + s_a.grip.0 * 2.0,
418 2.0 + move3 * -4.0,
419 -2.0 + move3 * -4.0,
420 );
421
422 next.control.position = Vec3::new(
423 -1.0,
424 0.0 + move1abs * -3.0 + move2abs * 3.0 + s_a.grip.2,
425 3.0 + move1abs * 3.0 - s_a.grip.2 / 2.5 + s_a.grip.0 * -2.0,
426 );
427
428 next.control_l.orientation =
429 Quaternion::rotation_x(PI / 2.0) * Quaternion::rotation_y(-0.3);
430 next.control_r.orientation = Quaternion::rotation_x(PI / 2.0 + s_a.grip.0 * 0.2)
431 * Quaternion::rotation_y(0.5 + s_a.grip.0 * 0.2 + move3 * -1.5);
432
433 next.control.orientation =
434 Quaternion::rotation_x(-0.3 + move1abs * 0.5 + move2abs * -0.5 + move3 * 0.5)
435 * Quaternion::rotation_y(0.5 * speednorm);
436
437 if matches!(stage_section, Some(StageSection::Recover)) {
438 next.main.scale = Vec3::zero();
439 }
440 },
441 _ => {},
442 }
443
444 next
445 }
446}