1pub mod basic;
2pub mod boost;
3pub mod climb;
4pub mod collect;
5pub mod consume;
6pub mod crawl;
7pub mod dance;
8pub mod equip;
9pub mod glidewield;
10pub mod gliding;
11pub mod idle;
12pub mod jump;
13pub mod mount;
14pub mod multi;
15pub mod music;
16pub mod pet;
17pub mod roll;
18pub mod run;
19pub mod sit;
20pub mod sleep;
21pub mod sneak;
22pub mod sneakequip;
23pub mod sneakwield;
24pub mod staggered;
25pub mod stand;
26pub mod steer;
27pub mod stunned;
28pub mod swim;
29pub mod swimwield;
30pub mod talk;
31pub mod throw;
32pub mod wallrun;
33pub mod wield;
34
35pub use self::{
37 basic::{BasicAction, BasicActionDependency},
38 boost::BoostAnimation,
39 climb::ClimbAnimation,
40 collect::CollectAnimation,
41 consume::ConsumeAnimation,
42 crawl::CrawlAnimation,
43 dance::DanceAnimation,
44 equip::EquipAnimation,
45 glidewield::GlideWieldAnimation,
46 gliding::GlidingAnimation,
47 idle::IdleAnimation,
48 jump::JumpAnimation,
49 mount::MountAnimation,
50 multi::{MultiAction, MultiActionDependency},
51 music::MusicAnimation,
52 pet::PetAnimation,
53 roll::RollAnimation,
54 run::RunAnimation,
55 sit::SitAnimation,
56 sleep::SleepAnimation,
57 sneak::SneakAnimation,
58 sneakequip::SneakEquipAnimation,
59 sneakwield::SneakWieldAnimation,
60 staggered::StaggeredAnimation,
61 stand::StandAnimation,
62 steer::SteerAnimation,
63 stunned::StunnedAnimation,
64 swim::SwimAnimation,
65 swimwield::SwimWieldAnimation,
66 talk::TalkAnimation,
67 throw::ThrowAnimation,
68 wallrun::WallrunAnimation,
69 wield::WieldAnimation,
70};
71use super::{FigureBoneData, Skeleton, vek::*};
72use common::comp::{
73 self,
74 tool::{Hands, ToolKind},
75};
76use core::{convert::TryFrom, f32::consts::PI};
77
78pub type Body = comp::humanoid::Body;
79
80skeleton_impls!(struct CharacterSkeleton ComputedCharacterSkeleton {
81 + head
82 + chest
83 + belt
84 + back
85 + shorts
86 + hand_l
87 + hand_r
88 + foot_l
89 + foot_r
90 + shoulder_l
91 + shoulder_r
92 + glider
93 + main
94 + second
95 + lantern
96 + hold
97 torso
98 control
99 control_l
100 control_r
101 :: holding_lantern: bool,
103 back_carry_offset: f32,
105 main_weapon_trail: bool,
106 off_weapon_trail: bool,
107 glider_trails: bool,
109});
110
111impl CharacterSkeleton {
112 pub fn new(holding_lantern: bool, back_carry_offset: f32) -> Self {
113 Self {
114 holding_lantern,
115 back_carry_offset,
116 ..Self::default()
117 }
118 }
119}
120
121impl Skeleton for CharacterSkeleton {
122 type Attr = SkeletonAttr;
123 type Body = Body;
124 type ComputedSkeleton = ComputedCharacterSkeleton;
125
126 const BONE_COUNT: usize = ComputedCharacterSkeleton::BONE_COUNT;
127 #[cfg(feature = "use-dyn-lib")]
128 const COMPUTE_FN: &'static [u8] = b"character_compute_mats\0";
129
130 #[cfg_attr(feature = "be-dyn-lib", unsafe(export_name = "character_compute_mats"))]
131 fn compute_matrices_inner(
132 &self,
133 base_mat: Mat4<f32>,
134 buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
135 body: Self::Body,
136 ) -> Self::ComputedSkeleton {
137 let base_mat = base_mat * Mat4::scaling_3d(SkeletonAttr::from(&body).scaler / 11.0);
141
142 let torso_mat = base_mat * Mat4::<f32>::from(self.torso);
143 let chest_mat = torso_mat * Mat4::<f32>::from(self.chest);
144 let head_mat = chest_mat * Mat4::<f32>::from(self.head);
145 let shorts_mat = chest_mat * Mat4::<f32>::from(self.shorts);
146 let control_mat = chest_mat * Mat4::<f32>::from(self.control);
147 let control_l_mat = control_mat * Mat4::<f32>::from(self.control_l);
148 let control_r_mat = control_mat * Mat4::<f32>::from(self.control_r);
149 let hand_r_mat = control_r_mat * Mat4::<f32>::from(self.hand_r);
150
151 let hand_l_mat = Mat4::<f32>::from(self.hand_l);
152 let lantern_mat = if self.holding_lantern {
153 hand_r_mat
154 } else {
155 shorts_mat
156 } * Mat4::<f32>::from(self.lantern);
157 let main_mat = control_l_mat * Mat4::<f32>::from(self.main);
158 let second_mat = control_r_mat * Mat4::<f32>::from(self.second);
159 let glider_mat = chest_mat * Mat4::<f32>::from(self.glider);
160
161 let computed_skeleton = ComputedCharacterSkeleton {
162 head: head_mat,
163 chest: chest_mat,
164 belt: chest_mat * Mat4::<f32>::from(self.belt),
165 back: chest_mat * Mat4::<f32>::from(self.back),
166 shorts: shorts_mat,
167 hand_l: control_l_mat * hand_l_mat,
168 hand_r: hand_r_mat,
169 foot_l: torso_mat * Mat4::<f32>::from(self.foot_l),
170 foot_r: torso_mat * Mat4::<f32>::from(self.foot_r),
171 shoulder_l: chest_mat * Mat4::<f32>::from(self.shoulder_l),
172 shoulder_r: chest_mat * Mat4::<f32>::from(self.shoulder_r),
173 glider: glider_mat,
174 main: main_mat,
175 second: second_mat,
176 lantern: lantern_mat,
177 hold: control_mat * hand_l_mat * Mat4::<f32>::from(self.hold),
179 };
180
181 computed_skeleton.set_figure_bone_data(buf);
182 computed_skeleton
183 }
184}
185
186pub struct SkeletonAttr {
187 scaler: f32,
188 head_scale: f32,
189 head: (f32, f32),
190 chest: (f32, f32),
191 belt: (f32, f32),
192 back: (f32, f32),
193 shorts: (f32, f32),
194 hand: (f32, f32, f32),
195 foot: (f32, f32, f32),
196 shoulder: (f32, f32, f32),
197 lantern: (f32, f32, f32),
198 shl: (f32, f32, f32, f32, f32, f32),
199 shr: (f32, f32, f32, f32, f32, f32),
200 sc: (f32, f32, f32, f32, f32, f32),
201 hhl: (f32, f32, f32, f32, f32, f32),
202 hhr: (f32, f32, f32, f32, f32, f32),
203 hc: (f32, f32, f32, f32, f32, f32),
204 sthl: (f32, f32, f32, f32, f32, f32),
205 sthr: (f32, f32, f32, f32, f32, f32),
206 stc: (f32, f32, f32, f32, f32, f32),
207 ahl: (f32, f32, f32, f32, f32, f32),
208 ahr: (f32, f32, f32, f32, f32, f32),
209 ac: (f32, f32, f32, f32, f32, f32),
210 bhl: (f32, f32, f32, f32, f32, f32),
211 bhr: (f32, f32, f32, f32, f32, f32),
212 bc: (f32, f32, f32, f32, f32, f32),
213}
214
215impl Default for SkeletonAttr {
216 fn default() -> Self {
217 Self {
218 scaler: 0.0,
219 head_scale: 0.0,
220 head: (0.0, 0.0),
221 chest: (0.0, 0.0),
222 belt: (0.0, 0.0),
223 back: (0.0, 0.0),
224 shorts: (0.0, 0.0),
225 hand: (0.0, 0.0, 0.0),
226 foot: (0.0, 0.0, 0.0),
227 shoulder: (0.0, 0.0, 0.0),
228 lantern: (0.0, 0.0, 0.0),
229 shl: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
230 shr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
231 sc: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
232 hhl: (0.0, 0.0, 10.0, 0.0, 0.0, 0.0),
233 hhr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
234 hc: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
235 sthl: (0.0, 0.0, 10.0, 0.0, 0.0, 0.0),
236 sthr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
237 stc: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
238 ahl: (0.0, 0.0, 10.0, 0.0, 0.0, 0.0),
239 ahr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
240 ac: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
241 bhl: (0.0, 0.0, 10.0, 0.0, 0.0, 0.0),
242 bhr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
243 bc: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
244 }
245 }
246}
247
248impl<'a> TryFrom<&'a comp::Body> for SkeletonAttr {
249 type Error = ();
250
251 fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
252 match body {
253 comp::Body::Humanoid(body) => Ok(SkeletonAttr::from(body)),
254 _ => Err(()),
255 }
256 }
257}
258
259impl<'a> From<&'a Body> for SkeletonAttr {
260 fn from(body: &'a Body) -> Self {
261 use comp::humanoid::{BodyType::*, Species::*};
262 Self {
263 scaler: body.scaler(),
264 head_scale: match (body.species, body.body_type) {
265 (Orc, Male) => 0.9,
266 (Orc, Female) => 0.9,
267 (Human, Male) => 0.9,
268 (Human, Female) => 0.9,
269 (Elf, Male) => 0.9,
270 (Elf, Female) => 0.9,
271 (Dwarf, Male) => 1.0,
272 (Dwarf, Female) => 1.0,
273 (Draugr, Male) => 0.9,
274 (Draugr, Female) => 0.9,
275 (Danari, Male) => 1.15,
276 (Danari, Female) => 1.15,
277 },
278 head: match (body.species, body.body_type) {
279 (Orc, Male) => (-2.0, 9.0),
280 (Orc, Female) => (-2.0, 9.5),
281 (Human, Male) => (-2.3, 9.5),
282 (Human, Female) => (-2.0, 9.5),
283 (Elf, Male) => (-2.5, 9.5),
284 (Elf, Female) => (-1.0, 9.5),
285 (Dwarf, Male) => (-2.0, 10.0),
286 (Dwarf, Female) => (-2.0, 9.5),
287 (Draugr, Male) => (-1.5, 8.5),
288 (Draugr, Female) => (-1.5, 9.5),
289 (Danari, Male) => (-1.5, 7.0),
290 (Danari, Female) => (-1.5, 7.0),
291 },
292 chest: (0.0, 8.0),
293 belt: (0.0, -2.0),
294 back: (-3.1, 7.25),
295 shorts: (0.0, -5.0),
296 hand: (7.0, -0.25, 0.5),
297 foot: (3.4, 0.5, 2.0),
298 shoulder: (5.0, 0.0, 5.0),
299 lantern: (5.0, 2.5, 5.5),
300 shl: (-0.75, -1.0, 0.5, 1.47, -0.2, 0.0),
301 shr: (0.75, -1.5, -2.5, 1.47, 0.3, 0.0),
302 sc: (-6.0, 6.0, 0.0, -0.5, 0.0, 0.0),
303 hhl: (0.1, 0.0, 11.0, 4.71, 0.0, PI),
304 hhr: (0.0, 0.0, 0.0, 4.71, 0.0, PI),
305 hc: (6.0, 7.0, 1.0, -0.3, -PI / 2.0, 3.64),
306 sthl: (0.0, 0.0, 6.0, 1.97, 0.0, 0.0),
307 sthr: (0.0, 0.0, 0.0, 1.27, 0.2, 0.0),
308 stc: (-5.0, 7.0, -2.0, -0.3, 0.15, 0.0),
309 ahl: (-0.5, -1.5, 5.25, 1.5, PI, 0.0),
310 ahr: (0.0, -2.0, 1.0, 1.5, 0.0, PI),
311 ac: (-8.5, 2.0, 0.5, 4.25, PI, 0.2),
312 bhl: (0.0, -4.0, 1.0, PI / 2.0, 0.0, 0.0),
313 bhr: (1.0, 2.0, -2.0, PI / 2.0, 0.0, 0.0),
314 bc: (-5.0, 9.0, 1.0, 0.0, 1.2, -0.6),
315 }
316 }
317}
318
319pub fn mount_mat(
320 computed_skeleton: &ComputedCharacterSkeleton,
321 skeleton: &CharacterSkeleton,
322) -> (Mat4<f32>, Quaternion<f32>) {
323 (
324 computed_skeleton.chest,
325 skeleton.torso.orientation * skeleton.chest.orientation * Quaternion::rotation_y(0.4),
326 )
327}
328
329pub fn mount_transform(
330 computed_skeleton: &ComputedCharacterSkeleton,
331 skeleton: &CharacterSkeleton,
332) -> Transform<f32, f32, f32> {
333 let (mount_mat, orientation) = mount_mat(computed_skeleton, skeleton);
334 Transform {
335 position: mount_mat.mul_point(Vec3::new(5.5, 0.0, 6.5)),
336 orientation,
337 scale: Vec3::one(),
338 }
339}
340
341impl CharacterSkeleton {
342 pub fn do_tools_on_back(
345 &mut self,
346 hands: (Option<Hands>, Option<Hands>),
347 active_tool_kind: Option<ToolKind>,
348 second_tool_kind: Option<ToolKind>,
349 ) {
350 match (hands, active_tool_kind, second_tool_kind) {
351 ((Some(Hands::Two), _), tool, _) | ((None, Some(Hands::Two)), _, tool) => match tool {
352 Some(ToolKind::Bow) => {
353 self.main.position = Vec3::new(0.0, -5.0 - self.back_carry_offset, 6.0);
354 self.main.orientation =
355 Quaternion::rotation_y(2.5) * Quaternion::rotation_z(PI / 2.0);
356 },
357 Some(ToolKind::Staff) | Some(ToolKind::Sceptre) => {
358 self.main.position = Vec3::new(2.0, -5.0 - self.back_carry_offset, -1.0);
359 self.main.orientation =
360 Quaternion::rotation_y(-0.5) * Quaternion::rotation_z(PI / 2.0);
361 },
362 Some(ToolKind::Shield) => {
363 self.main.position = Vec3::new(-2.0, -3.0 - self.back_carry_offset, 1.0);
364 self.main.orientation =
365 Quaternion::rotation_y(-0.75) * Quaternion::rotation_z(PI / 2.0);
366 },
367 _ => {
368 self.main.position = Vec3::new(-7.0, -5.0 - self.back_carry_offset, 15.0);
369 self.main.orientation =
370 Quaternion::rotation_y(2.5) * Quaternion::rotation_z(PI / 2.0);
371 },
372 },
373 ((_, _), _, _) => {},
374 }
375
376 match hands {
377 (Some(Hands::One), _) => match active_tool_kind {
378 Some(ToolKind::Dagger) => {
379 self.main.position = Vec3::new(5.0, 1.0 - self.back_carry_offset, 2.0);
380 self.main.orientation =
381 Quaternion::rotation_x(-1.35 * PI) * Quaternion::rotation_z(2.0 * PI);
382 },
383 Some(ToolKind::Axe) | Some(ToolKind::Hammer) | Some(ToolKind::Sword) => {
384 self.main.position = Vec3::new(-4.0, -4.5 - self.back_carry_offset, 10.0);
385 self.main.orientation =
386 Quaternion::rotation_y(2.5) * Quaternion::rotation_z(PI / 2.0);
387 },
388 Some(ToolKind::Shield) => {
389 self.main.position = Vec3::new(-2.0, -4.0 - self.back_carry_offset, 3.0);
390 self.main.orientation =
391 Quaternion::rotation_y(0.25 * PI) * Quaternion::rotation_z(-1.5 * PI);
392 },
393 Some(ToolKind::Throwable) => {
394 self.main.position = Vec3::new(-6.0, 0.0, -4.0);
395 self.main.scale = Vec3::zero();
396 },
397 _ => {},
398 },
399 (_, _) => {},
400 }
401 match hands {
402 (None | Some(Hands::One), Some(Hands::One)) => match second_tool_kind {
403 Some(ToolKind::Dagger) => {
404 self.second.position = Vec3::new(-5.0, 1.0 - self.back_carry_offset, 2.0);
405 self.second.orientation =
406 Quaternion::rotation_x(-1.35 * PI) * Quaternion::rotation_z(-2.0 * PI);
407 },
408 Some(ToolKind::Axe) | Some(ToolKind::Hammer) | Some(ToolKind::Sword) => {
409 self.second.position = Vec3::new(4.0, -5.0 - self.back_carry_offset, 10.0);
410 self.second.orientation =
411 Quaternion::rotation_y(-2.5) * Quaternion::rotation_z(-PI / 2.0);
412 },
413 Some(ToolKind::Shield) => {
414 self.second.position = Vec3::new(1.5, -4.0 - self.back_carry_offset, 3.0);
415 self.second.orientation =
416 Quaternion::rotation_y(-0.25 * PI) * Quaternion::rotation_z(1.5 * PI);
417 },
418 Some(ToolKind::Throwable) => {
419 self.second.position = Vec3::new(6.0, 0.0, -4.0);
420 self.second.scale = Vec3::zero();
421 },
422 _ => {},
423 },
424 (_, _) => {},
425 }
426 }
427
428 pub fn do_hold_lantern(
431 &mut self,
432 s_a: &SkeletonAttr,
433 anim_time: f32,
434 acc_vel: f32,
435 speednorm: f32,
436 impact: f32,
437 tilt: f32,
438 ) {
439 let lab = 2.0 / s_a.scaler;
440
441 let short = ((5.0 / (1.5 + 3.5 * ((acc_vel * lab * 1.6 + PI * 0.5).sin()).powi(2))).sqrt())
442 * ((acc_vel * lab * 1.6 + PI * 0.5).sin());
443
444 let shorte = ((1.0 / (0.8 + 0.2 * ((acc_vel * lab * 1.6).sin()).powi(2))).sqrt())
445 * ((acc_vel * lab * 1.6).sin());
446
447 self.lantern.position = Vec3::new(s_a.lantern.0, s_a.lantern.1, s_a.lantern.2);
448 self.lantern.orientation = Quaternion::rotation_x(shorte * 0.7 * speednorm.powi(2) + 0.4)
449 * Quaternion::rotation_y(shorte * 0.4 * speednorm.powi(2));
450 self.lantern.scale = Vec3::one() * 0.65;
451 self.hold.scale = Vec3::one() * 0.0;
452
453 if self.holding_lantern {
454 self.hand_r.position = Vec3::new(
455 s_a.hand.0 + 1.0,
456 s_a.hand.1 + 2.0 - impact * 0.2,
457 s_a.hand.2 + 12.0 + impact * -0.1,
458 );
459 self.hand_r.orientation = Quaternion::rotation_x(2.25) * Quaternion::rotation_z(0.9);
460 self.shoulder_r.orientation = Quaternion::rotation_x(short * -0.15 + 2.0);
461
462 let fast = (anim_time * 8.0).sin();
463 let fast2 = (anim_time * 6.0 + 8.0).sin();
464
465 self.lantern.position = Vec3::new(-0.5, -0.5, -2.5);
466 self.lantern.orientation = self.hand_r.orientation.inverse()
467 * Quaternion::rotation_x(
468 (fast + 0.5) * 1.0 * speednorm + (tilt.abs() * 2.0).min(PI * 0.5),
469 )
470 * Quaternion::rotation_y(tilt * 1.0 * fast + tilt * 1.0 + fast2 * speednorm * 0.25);
471 }
472 }
473}
474
475pub fn hammer_start(next: &mut CharacterSkeleton, s_a: &SkeletonAttr) {
476 next.main.position = Vec3::new(0.0, 0.0, 0.0);
477 next.main.orientation = Quaternion::rotation_z(0.0);
478 next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1 + 3.0, s_a.hhl.2 - 1.0);
479 next.hand_l.orientation = Quaternion::rotation_x(s_a.hhl.3)
480 * Quaternion::rotation_y(s_a.hhl.4)
481 * Quaternion::rotation_z(s_a.hhl.5);
482 next.hand_r.position = Vec3::new(s_a.hhr.0, s_a.hhr.1 + 3.0, s_a.hhr.2 + 1.0);
483 next.hand_r.orientation = Quaternion::rotation_x(s_a.hhr.3)
484 * Quaternion::rotation_y(s_a.hhr.4)
485 * Quaternion::rotation_z(s_a.hhr.5);
486
487 next.control.position = Vec3::new(s_a.hc.0 - 1.0, s_a.hc.1, s_a.hc.2 - 3.0);
488 next.control.orientation = Quaternion::rotation_x(s_a.hc.3)
489 * Quaternion::rotation_y(s_a.hc.4)
490 * Quaternion::rotation_z(s_a.hc.5);
491}
492
493pub fn twist_back(next: &mut CharacterSkeleton, move1: f32, c: f32, h: f32, b: f32, s: f32) {
494 next.chest.orientation.rotate_z(move1 * c);
495 next.head.orientation.rotate_z(move1 * -h);
496 next.belt.orientation.rotate_z(move1 * -b);
497 next.shorts.orientation.rotate_z(move1 * -s);
498}
499
500pub fn twist_forward(next: &mut CharacterSkeleton, move2: f32, c: f32, h: f32, b: f32, s: f32) {
501 next.chest.orientation.rotate_z(move2 * -c);
502 next.head.orientation.rotate_z(move2 * h);
503 next.belt.orientation.rotate_z(move2 * b);
504 next.shorts.orientation.rotate_z(move2 * s);
505}
506
507pub fn dual_wield_start(next: &mut CharacterSkeleton) {
508 next.main.position = Vec3::new(0.0, 0.0, 0.0);
509 next.main.orientation = Quaternion::rotation_z(0.0);
510 next.second.position = Vec3::new(0.0, 0.0, 0.0);
511 next.second.orientation = Quaternion::rotation_z(0.0);
512
513 next.control_l.position =
514 next.hand_l.position * Vec3::new(0.5, 0.5, 0.3) + Vec3::new(-4.0, 0.0, 0.0);
515 next.control_l.orientation = Quaternion::lerp(
516 next.hand_l.orientation,
517 Quaternion::rotation_x(PI * -0.5),
518 0.65,
519 );
520 next.hand_l.position = Vec3::new(0.0, -2.0, 0.0);
521 next.hand_l.orientation = Quaternion::rotation_x(PI * 0.5);
522
523 next.control_r.position =
524 next.hand_r.position * Vec3::new(0.5, 0.5, 0.3) + Vec3::new(4.0, 0.0, 0.0);
525 next.control_r.orientation = Quaternion::lerp(
526 next.hand_r.orientation,
527 Quaternion::rotation_x(PI * -0.5),
528 0.65,
529 );
530 next.hand_r.position = Vec3::new(0.0, -2.0, 0.0);
531 next.hand_r.orientation = Quaternion::rotation_x(PI * 0.5);
532}