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 wallrun;
32pub mod wield;
33
34pub use self::{
36 basic::{BasicAction, BasicActionDependency},
37 boost::BoostAnimation,
38 climb::ClimbAnimation,
39 collect::CollectAnimation,
40 consume::ConsumeAnimation,
41 crawl::CrawlAnimation,
42 dance::DanceAnimation,
43 equip::EquipAnimation,
44 glidewield::GlideWieldAnimation,
45 gliding::GlidingAnimation,
46 idle::IdleAnimation,
47 jump::JumpAnimation,
48 mount::MountAnimation,
49 multi::{MultiAction, MultiActionDependency},
50 music::MusicAnimation,
51 pet::PetAnimation,
52 roll::RollAnimation,
53 run::RunAnimation,
54 sit::SitAnimation,
55 sleep::SleepAnimation,
56 sneak::SneakAnimation,
57 sneakequip::SneakEquipAnimation,
58 sneakwield::SneakWieldAnimation,
59 staggered::StaggeredAnimation,
60 stand::StandAnimation,
61 steer::SteerAnimation,
62 stunned::StunnedAnimation,
63 swim::SwimAnimation,
64 swimwield::SwimWieldAnimation,
65 talk::TalkAnimation,
66 wallrun::WallrunAnimation,
67 wield::WieldAnimation,
68};
69use super::{FigureBoneData, Offsets, Skeleton, TrailSource, make_bone, vek::*};
70use common::comp::{
71 self,
72 tool::{Hands, ToolKind},
73};
74use core::{convert::TryFrom, f32::consts::PI};
75
76pub type Body = comp::humanoid::Body;
77
78skeleton_impls!(struct CharacterSkeleton {
79 + head,
80 + chest,
81 + belt,
82 + back,
83 + shorts,
84 + hand_l,
85 + hand_r,
86 + foot_l,
87 + foot_r,
88 + shoulder_l,
89 + shoulder_r,
90 + glider,
91 + main,
92 + second,
93 + lantern,
94 + hold,
95 torso,
96 control,
97 control_l,
98 control_r,
99 :: holding_lantern: bool,
101 back_carry_offset: f32,
103 main_weapon_trail: bool,
104 off_weapon_trail: bool,
105 glider_trails: bool,
107});
108
109impl CharacterSkeleton {
110 pub fn new(holding_lantern: bool, back_carry_offset: f32) -> Self {
111 Self {
112 holding_lantern,
113 back_carry_offset,
114 ..Self::default()
115 }
116 }
117}
118
119impl Skeleton for CharacterSkeleton {
120 type Attr = SkeletonAttr;
121 type Body = Body;
122
123 const BONE_COUNT: usize = 16;
124 #[cfg(feature = "use-dyn-lib")]
125 const COMPUTE_FN: &'static [u8] = b"character_compute_mats\0";
126
127 #[cfg_attr(feature = "be-dyn-lib", export_name = "character_compute_mats")]
128 fn compute_matrices_inner(
129 &self,
130 base_mat: Mat4<f32>,
131 buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
132 body: Self::Body,
133 ) -> Offsets {
134 let base_mat = base_mat * Mat4::scaling_3d(SkeletonAttr::from(&body).scaler / 11.0);
138
139 let torso_mat = base_mat * Mat4::<f32>::from(self.torso);
140 let chest_mat = torso_mat * Mat4::<f32>::from(self.chest);
141 let head_mat = chest_mat * Mat4::<f32>::from(self.head);
142 let shorts_mat = chest_mat * Mat4::<f32>::from(self.shorts);
143 let control_mat = chest_mat * Mat4::<f32>::from(self.control);
144 let control_l_mat = control_mat * Mat4::<f32>::from(self.control_l);
145 let control_r_mat = control_mat * Mat4::<f32>::from(self.control_r);
146 let hand_r_mat = control_r_mat * Mat4::<f32>::from(self.hand_r);
147
148 let hand_l_mat = Mat4::<f32>::from(self.hand_l);
149 let lantern_mat = if self.holding_lantern {
150 hand_r_mat
151 } else {
152 shorts_mat
153 } * Mat4::<f32>::from(self.lantern);
154 let main_mat = control_l_mat * Mat4::<f32>::from(self.main);
155 let second_mat = control_r_mat * Mat4::<f32>::from(self.second);
156 let glider_mat = chest_mat * Mat4::<f32>::from(self.glider);
157
158 *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
159 make_bone(head_mat),
160 make_bone(chest_mat),
161 make_bone(chest_mat * Mat4::<f32>::from(self.belt)),
162 make_bone(chest_mat * Mat4::<f32>::from(self.back)),
163 make_bone(shorts_mat),
164 make_bone(control_l_mat * hand_l_mat),
165 make_bone(hand_r_mat),
166 make_bone(torso_mat * Mat4::<f32>::from(self.foot_l)),
167 make_bone(torso_mat * Mat4::<f32>::from(self.foot_r)),
168 make_bone(chest_mat * Mat4::<f32>::from(self.shoulder_l)),
169 make_bone(chest_mat * Mat4::<f32>::from(self.shoulder_r)),
170 make_bone(glider_mat),
171 make_bone(main_mat),
172 make_bone(second_mat),
173 make_bone(lantern_mat),
174 make_bone(control_mat * hand_l_mat * Mat4::<f32>::from(self.hold)),
176 ];
177
178 let mount_position = (chest_mat * Vec4::from_point(Vec3::new(5.5, 0.0, 6.5)))
181 .homogenized()
182 .xyz();
183 let mount_orientation =
186 self.torso.orientation * self.chest.orientation * Quaternion::rotation_y(0.4);
187
188 let weapon_trails = self.main_weapon_trail || self.off_weapon_trail;
189 Offsets {
190 lantern: Some((lantern_mat * Vec4::new(0.0, 0.5, -6.0, 1.0)).xyz()),
191 viewpoint: Some((head_mat * Vec4::new(0.0, 0.0, 4.0, 1.0)).xyz()),
192 mount_bone: Transform {
193 position: mount_position,
194 orientation: mount_orientation,
195 scale: Vec3::one(),
196 },
197 primary_trail_mat: if weapon_trails {
198 self.main_weapon_trail
199 .then_some((main_mat, TrailSource::Weapon))
200 } else {
201 self.glider_trails
202 .then_some((glider_mat, TrailSource::GliderLeft))
203 },
204 secondary_trail_mat: if weapon_trails {
205 self.off_weapon_trail
206 .then_some((second_mat, TrailSource::Weapon))
207 } else {
208 self.glider_trails
209 .then_some((glider_mat, TrailSource::GliderRight))
210 },
211 ..Default::default()
212 }
213 }
214}
215
216pub struct SkeletonAttr {
217 scaler: f32,
218 head_scale: f32,
219 head: (f32, f32),
220 chest: (f32, f32),
221 belt: (f32, f32),
222 back: (f32, f32),
223 shorts: (f32, f32),
224 hand: (f32, f32, f32),
225 foot: (f32, f32, f32),
226 shoulder: (f32, f32, f32),
227 lantern: (f32, f32, f32),
228 shl: (f32, f32, f32, f32, f32, f32),
229 shr: (f32, f32, f32, f32, f32, f32),
230 sc: (f32, f32, f32, f32, f32, f32),
231 hhl: (f32, f32, f32, f32, f32, f32),
232 hhr: (f32, f32, f32, f32, f32, f32),
233 hc: (f32, f32, f32, f32, f32, f32),
234 sthl: (f32, f32, f32, f32, f32, f32),
235 sthr: (f32, f32, f32, f32, f32, f32),
236 stc: (f32, f32, f32, f32, f32, f32),
237 ahl: (f32, f32, f32, f32, f32, f32),
238 ahr: (f32, f32, f32, f32, f32, f32),
239 ac: (f32, f32, f32, f32, f32, f32),
240 bhl: (f32, f32, f32, f32, f32, f32),
241 bhr: (f32, f32, f32, f32, f32, f32),
242 bc: (f32, f32, f32, f32, f32, f32),
243}
244
245impl Default for SkeletonAttr {
246 fn default() -> Self {
247 Self {
248 scaler: 0.0,
249 head_scale: 0.0,
250 head: (0.0, 0.0),
251 chest: (0.0, 0.0),
252 belt: (0.0, 0.0),
253 back: (0.0, 0.0),
254 shorts: (0.0, 0.0),
255 hand: (0.0, 0.0, 0.0),
256 foot: (0.0, 0.0, 0.0),
257 shoulder: (0.0, 0.0, 0.0),
258 lantern: (0.0, 0.0, 0.0),
259 shl: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
260 shr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
261 sc: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
262 hhl: (0.0, 0.0, 10.0, 0.0, 0.0, 0.0),
263 hhr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
264 hc: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
265 sthl: (0.0, 0.0, 10.0, 0.0, 0.0, 0.0),
266 sthr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
267 stc: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
268 ahl: (0.0, 0.0, 10.0, 0.0, 0.0, 0.0),
269 ahr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
270 ac: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
271 bhl: (0.0, 0.0, 10.0, 0.0, 0.0, 0.0),
272 bhr: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
273 bc: (0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
274 }
275 }
276}
277
278impl<'a> TryFrom<&'a comp::Body> for SkeletonAttr {
279 type Error = ();
280
281 fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
282 match body {
283 comp::Body::Humanoid(body) => Ok(SkeletonAttr::from(body)),
284 _ => Err(()),
285 }
286 }
287}
288
289impl<'a> From<&'a Body> for SkeletonAttr {
290 fn from(body: &'a Body) -> Self {
291 use comp::humanoid::{BodyType::*, Species::*};
292 Self {
293 scaler: body.scaler(),
294 head_scale: match (body.species, body.body_type) {
295 (Orc, Male) => 0.9,
296 (Orc, Female) => 0.9,
297 (Human, Male) => 0.9,
298 (Human, Female) => 0.9,
299 (Elf, Male) => 0.9,
300 (Elf, Female) => 0.9,
301 (Dwarf, Male) => 1.0,
302 (Dwarf, Female) => 1.0,
303 (Draugr, Male) => 0.9,
304 (Draugr, Female) => 0.9,
305 (Danari, Male) => 1.15,
306 (Danari, Female) => 1.15,
307 },
308 head: match (body.species, body.body_type) {
309 (Orc, Male) => (-2.0, 9.0),
310 (Orc, Female) => (-2.0, 9.5),
311 (Human, Male) => (-2.3, 9.5),
312 (Human, Female) => (-2.0, 9.5),
313 (Elf, Male) => (-2.5, 9.5),
314 (Elf, Female) => (-1.0, 9.5),
315 (Dwarf, Male) => (-2.0, 10.0),
316 (Dwarf, Female) => (-2.0, 9.5),
317 (Draugr, Male) => (-1.5, 8.5),
318 (Draugr, Female) => (-1.5, 9.5),
319 (Danari, Male) => (-1.5, 7.0),
320 (Danari, Female) => (-1.5, 7.0),
321 },
322 chest: (0.0, 8.0),
323 belt: (0.0, -2.0),
324 back: (-3.1, 7.25),
325 shorts: (0.0, -5.0),
326 hand: (7.0, -0.25, 0.5),
327 foot: (3.4, 0.5, 2.0),
328 shoulder: (5.0, 0.0, 5.0),
329 lantern: (5.0, 2.5, 5.5),
330 shl: (-0.75, -1.0, 0.5, 1.47, -0.2, 0.0),
331 shr: (0.75, -1.5, -2.5, 1.47, 0.3, 0.0),
332 sc: (-6.0, 6.0, 0.0, -0.5, 0.0, 0.0),
333 hhl: (0.1, 0.0, 11.0, 4.71, 0.0, PI),
334 hhr: (0.0, 0.0, 0.0, 4.71, 0.0, PI),
335 hc: (6.0, 7.0, 1.0, -0.3, -PI / 2.0, 3.64),
336 sthl: (0.0, 0.0, 6.0, 1.97, 0.0, 0.0),
337 sthr: (0.0, 0.0, 0.0, 1.27, 0.2, 0.0),
338 stc: (-5.0, 7.0, -2.0, -0.3, 0.15, 0.0),
339 ahl: (-0.5, -1.0, 7.0, 1.17, PI, 0.0),
340 ahr: (0.0, -1.0, 1.0, -2.0, 0.0, PI),
341 ac: (-8.0, 11.0, 3.0, 2.0, 0.0, 0.0),
342 bhl: (0.0, -4.0, 1.0, PI / 2.0, 0.0, 0.0),
343 bhr: (1.0, 2.0, -2.0, PI / 2.0, 0.0, 0.0),
344 bc: (-5.0, 9.0, 1.0, 0.0, 1.2, -0.6),
345 }
346 }
347}
348
349impl CharacterSkeleton {
350 pub fn do_tools_on_back(
353 &mut self,
354 hands: (Option<Hands>, Option<Hands>),
355 active_tool_kind: Option<ToolKind>,
356 second_tool_kind: Option<ToolKind>,
357 ) {
358 match (hands, active_tool_kind, second_tool_kind) {
359 ((Some(Hands::Two), _), tool, _) | ((None, Some(Hands::Two)), _, tool) => match tool {
360 Some(ToolKind::Bow) => {
361 self.main.position = Vec3::new(0.0, -5.0 - self.back_carry_offset, 6.0);
362 self.main.orientation =
363 Quaternion::rotation_y(2.5) * Quaternion::rotation_z(PI / 2.0);
364 },
365 Some(ToolKind::Staff) | Some(ToolKind::Sceptre) => {
366 self.main.position = Vec3::new(2.0, -5.0 - self.back_carry_offset, -1.0);
367 self.main.orientation =
368 Quaternion::rotation_y(-0.5) * Quaternion::rotation_z(PI / 2.0);
369 },
370 Some(ToolKind::Shield) => {
371 self.main.position = Vec3::new(-2.0, -3.0 - self.back_carry_offset, 1.0);
372 self.main.orientation =
373 Quaternion::rotation_y(-0.75) * Quaternion::rotation_z(PI / 2.0);
374 },
375 _ => {
376 self.main.position = Vec3::new(-7.0, -5.0 - self.back_carry_offset, 15.0);
377 self.main.orientation =
378 Quaternion::rotation_y(2.5) * Quaternion::rotation_z(PI / 2.0);
379 },
380 },
381 ((_, _), _, _) => {},
382 }
383
384 match hands {
385 (Some(Hands::One), _) => match active_tool_kind {
386 Some(ToolKind::Dagger) => {
387 self.main.position = Vec3::new(5.0, 1.0 - self.back_carry_offset, 2.0);
388 self.main.orientation =
389 Quaternion::rotation_x(-1.35 * PI) * Quaternion::rotation_z(2.0 * PI);
390 },
391 Some(ToolKind::Axe) | Some(ToolKind::Hammer) | Some(ToolKind::Sword) => {
392 self.main.position = Vec3::new(-4.0, -4.5 - self.back_carry_offset, 10.0);
393 self.main.orientation =
394 Quaternion::rotation_y(2.5) * Quaternion::rotation_z(PI / 2.0);
395 },
396 Some(ToolKind::Shield) => {
397 self.main.position = Vec3::new(-2.0, -4.0 - self.back_carry_offset, 3.0);
398 self.main.orientation =
399 Quaternion::rotation_y(0.25 * PI) * Quaternion::rotation_z(-1.5 * PI);
400 },
401 _ => {},
402 },
403 (_, _) => {},
404 }
405 match hands {
406 (None | Some(Hands::One), Some(Hands::One)) => match second_tool_kind {
407 Some(ToolKind::Dagger) => {
408 self.second.position = Vec3::new(-5.0, 1.0 - self.back_carry_offset, 2.0);
409 self.second.orientation =
410 Quaternion::rotation_x(-1.35 * PI) * Quaternion::rotation_z(-2.0 * PI);
411 },
412 Some(ToolKind::Axe) | Some(ToolKind::Hammer) | Some(ToolKind::Sword) => {
413 self.second.position = Vec3::new(4.0, -5.0 - self.back_carry_offset, 10.0);
414 self.second.orientation =
415 Quaternion::rotation_y(-2.5) * Quaternion::rotation_z(-PI / 2.0);
416 },
417 Some(ToolKind::Shield) => {
418 self.second.position = Vec3::new(1.5, -4.0 - self.back_carry_offset, 3.0);
419 self.second.orientation =
420 Quaternion::rotation_y(-0.25 * PI) * Quaternion::rotation_z(1.5 * PI);
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}