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", 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 let multi_strike_pullback = 1.0
32 - if matches!(stage_section, StageSection::Recover) {
33 anim_time.powi(4)
34 } else {
35 0.0
36 };
37
38 for strike in 0..=current_strike {
39 match ability_id {
40 Some(
41 "common.abilities.custom.bushly.singlestrike"
42 | "common.abilities.custom.irrwurz.singlestrike"
43 | "common.abilities.custom.husk.singlestrike"
44 | "common.abilities.custom.husk.triplestrike"
45 | "common.abilities.custom.dwarves.iron_dwarf.singlestrike"
46 | "common.abilities.custom.dwarves.iron_dwarf.triplestrike",
47 ) => {
48 let (move1, move2) = if strike == current_strike {
49 match stage_section {
50 StageSection::Buildup => {
51 (((anim_time.max(0.4) - 0.4) * 1.5).powf(0.5), 0.0)
52 },
53 StageSection::Action => (1.0, (anim_time.min(0.4) * 2.5).powi(2)),
54 StageSection::Recover => (1.0, 1.0),
55 _ => (0.0, 0.0),
56 }
57 } else {
58 (1.0, 1.0)
59 };
60 let move1 = move1 * multi_strike_pullback;
61 let move2 = move2 * multi_strike_pullback;
62 next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
63 next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
64 next.main.position = Vec3::new(0.0, 0.0, 0.0);
65 next.main.orientation = Quaternion::rotation_x(0.0);
66 next.hand_l.orientation = Quaternion::rotation_x(0.0);
67 next.hand_r.orientation = Quaternion::rotation_x(0.0);
68
69 match strike {
70 0..=2 => {
71 next.chest.orientation = Quaternion::rotation_x(move2 * -1.0)
72 * Quaternion::rotation_z(move1 * 1.2 + move2 * -1.8);
73 next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2);
74 next.hand_l.orientation = Quaternion::rotation_x(1.2);
75 next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2);
76 next.hand_r.orientation = Quaternion::rotation_x(1.2);
77 },
78 _ => {},
79 }
80 },
81 Some("common.abilities.custom.cactid.singlestrike") => {
82 let (move1, move2) = if strike == current_strike {
83 match stage_section {
84 StageSection::Buildup => {
85 (((anim_time.max(0.4) - 0.4) * 1.5).powf(0.5), 0.0)
86 },
87 StageSection::Action => (1.0, (anim_time.min(0.4) * 2.5).powi(2)),
88 StageSection::Recover => (1.0, 1.0),
89 _ => (0.0, 0.0),
90 }
91 } else {
92 (1.0, 1.0)
93 };
94 let move1 = move1 * multi_strike_pullback;
95 let move2 = move2 * multi_strike_pullback;
96 next.hand_l.position = Vec3::new(s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
97 next.hand_r.position = Vec3::new(-s_a.grip.0 * 4.0, 0.0, s_a.grip.2);
98 next.main.position = Vec3::new(0.0, 0.0, 0.0);
99 next.main.orientation = Quaternion::rotation_x(0.0);
100 next.hand_l.orientation = Quaternion::rotation_x(0.0);
101 next.hand_r.orientation = Quaternion::rotation_x(0.0);
102 next.head.orientation = Quaternion::rotation_z(move2 * 1.0);
103
104 next.chest.orientation = Quaternion::rotation_x(move2 * -1.0)
105 * Quaternion::rotation_z(move1 * -1.2 + move2 * 1.8);
106 next.hand_l.position = Vec3::new(-s_a.hand.0, s_a.hand.1, s_a.hand.2);
107 next.hand_l.orientation = Quaternion::rotation_x(1.2);
108 next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2);
109 next.hand_r.orientation = Quaternion::rotation_x(1.2);
110 },
111 Some(
112 "common.abilities.axesimple.doublestrike"
113 | "common.abilities.custom.goblin_thug.doublestrike"
114 | "common.abilities.custom.green_legoom.doublestrike"
115 | "common.abilities.custom.red_legoom.doublestrike"
116 | "common.abilities.vampire.bloodservant.doublestrike"
117 | "common.abilities.custom.boreal_warrior.hammer.singlestrike",
118 ) => {
119 let anim_time = anim_time.min(1.0);
120 let (move1base, move2base, move3) = match stage_section {
121 StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0),
122 StageSection::Action => (1.0, anim_time.powi(4), 0.0),
123 StageSection::Recover => (1.0, 1.0, anim_time),
124 _ => (0.0, 0.0, 0.0),
125 };
126 let pullback = 1.0 - move3;
127 let move1abs = move1base * pullback;
128 let move2abs = move2base * pullback;
129
130 init_biped_small_alpha(&mut next, s_a);
131 biped_small_alpha_axe(&mut next, s_a, move1abs, move2abs);
132 },
133 Some("common.abilities.custom.boreal_warrior.bow.doublestrike") => {
134 let anim_time = anim_time.min(1.0);
135 let (move1base, move2base) = if strike == current_strike {
136 match stage_section {
137 StageSection::Buildup => (anim_time.sqrt(), 0.0),
138 StageSection::Action => (1.0, anim_time.powi(4)),
139 StageSection::Recover => (1.0, 1.0),
140 _ => (0.0, 0.0),
141 }
142 } else {
143 (1.0, 1.0)
144 };
145 let move1 = move1base * multi_strike_pullback;
146 let move2 = move2base * multi_strike_pullback;
147
148 match strike {
149 0 => {
150 init_biped_small_alpha(&mut next, s_a);
151 next.control.position += Vec3::new(0.0, 8.0, 0.0);
152 next.control.orientation.rotate_x(-PI / 8.0);
153 next.hand_l.position += Vec3::new(-6.0, -4.0, -4.0);
154 next.hand_l.orientation.rotate_x(PI / 2.0);
155 next.hand_l.orientation.rotate_z(-PI / 8.0);
156 next.hand_r.position += Vec3::new(4.0, -4.0, -6.0);
157 next.hand_r.orientation.rotate_x(PI / 2.0);
158 next.hand_r.orientation.rotate_z(PI / 9.0);
159
160 next.chest.orientation.rotate_z(PI / 4.0 * move1);
161 next.control.position += Vec3::new(0.0, (PI * move1).cos(), 0.0);
162 next.control.orientation.rotate_y(-PI / 8.0 * move1);
163 next.control.orientation.rotate_x(-PI / 8.0 * move1.powi(2));
164
165 next.control
166 .orientation
167 .rotate_y(-PI / 3.0 * f32::from(move2 != 0.0));
168 next.chest.orientation.rotate_z(-PI / 2.5 * move2);
169 },
170 1 => {
171 next.chest.orientation.rotate_z(-PI / 5.0 * move1);
172 next.control.position += Vec3::new(0.0, (PI * move1).cos(), 0.0);
173 next.control.orientation.rotate_y(PI / 2.0 * move1);
174
175 next.control
176 .orientation
177 .rotate_y(PI / 3.0 * f32::from(move2 != 0.0));
178 next.chest.orientation.rotate_z(PI / 2.0 * move2);
179 },
180 _ => {},
181 }
182 },
183 Some(
184 "common.abilities.daggersimple.singlestrike"
185 | "common.abilities.vampire.bloodmoon_heiress.singlestrike",
186 ) => {
187 let anim_time = anim_time.min(1.0);
188 let (move1base, move2base, move3) = match stage_section {
189 StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0),
190 StageSection::Action => (1.0, anim_time.powi(4), 0.0),
191 StageSection::Recover => (1.0, 1.0, anim_time),
192 _ => (0.0, 0.0, 0.0),
193 };
194 let pullback = 1.0 - move3;
195 let move1abs = move1base * pullback;
196 let move2abs = move2base * pullback;
197
198 init_biped_small_alpha(&mut next, s_a);
199 biped_small_alpha_dagger(&mut next, s_a, move1abs, move2abs);
200 },
201 Some(
202 "common.abilities.spear.doublestrike"
203 | "common.abilities.custom.purple_legoom.doublestrike",
204 ) => {
205 let anim_time = anim_time.min(1.0);
206 let speed = Vec2::<f32>::from(velocity).magnitude();
207 let speednorm = speed / 9.4;
208 let speednormcancel = 1.0 - speednorm;
209
210 let (move1base, move2base, move3) = match stage_section {
211 StageSection::Buildup => (anim_time.sqrt(), 0.0, 0.0),
212 StageSection::Action => (1.0, anim_time.powi(4), 0.0),
213 StageSection::Recover => (1.0, 1.0, anim_time),
214 _ => (0.0, 0.0, 0.0),
215 };
216 let pullback = 1.0 - move3;
217 let move1abs = move1base * pullback;
218 let move2abs = move2base * pullback;
219
220 init_biped_small_alpha(&mut next, s_a);
221 biped_small_alpha_spear(
222 &mut next,
223 s_a,
224 move1abs,
225 move2abs,
226 anim_time,
227 speednormcancel,
228 );
229 },
230 Some("common.abilities.haniwa.guard.backpedal") => {
231 init_biped_small_alpha(&mut next, s_a);
232 biped_small_wield_spear(&mut next, s_a, anim_time, 0.0, 0.0);
233
234 let (move1, move2, move3) = match stage_section {
235 StageSection::Buildup => (anim_time.powf(0.25), 0.0, 0.0),
236 StageSection::Action => (1.0, anim_time, 0.0),
237 StageSection::Recover => (1.0, 1.0, anim_time.powf(0.25)),
238 _ => (0.0, 0.0, 0.0),
239 };
240 let pullback = 1.0 - move3;
241 let move1 = move1 * pullback;
242 let move2 = move2 * pullback;
243
244 biped_small_alpha_spear(&mut next, s_a, move1, move2, anim_time, 0.0);
245 },
246 _ => {},
247 }
248 }
249 next
250 }
251}