1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use shared::{F32ModelMatrix, OwnedPtr, Subclass};
use crate::{
DLVector,
cs::{CSPairAnimNode, ChrIns},
dltx::{DLString, DLUTF8StringKind},
position::{HavokPosition, PositionDelta},
rotation::{EulerAngles, Quaternion},
};
use std::ptr::NonNull;
#[repr(C)]
/// Source of name: RTTI
pub struct CSChrRideModule {
vftable: usize,
pub owner: NonNull<ChrIns>,
pub ride_node: OwnedPtr<CSRideNode>,
/// Gets populated when mounting another `ChrIns`.
/// Note: This will be null if you load into the world and you've already mounted a `ChrIns`
/// during the previous session. This is not populated on the receiving `ChrIns`.
pub last_mounted: Option<NonNull<ChrIns>>,
unk20: i32,
unk24: i32,
unk28: i32,
unk2c: i32,
unk30: bool,
/// True when a RideParam entry was found matching both entries.
pub has_ride_param: bool,
unk32: bool,
/// True when this `ChrIns` is the ridden character.
pub is_ride_character: bool,
unk34: i32,
unk38: i32,
unk3c: i32,
/// Some additional details describing the mount. This is only updated on the rider's end.
/// For example the player will have data in here, but Torrent's `ChrIns` will not.
pub mount_data: CSChrRideModuleMountData,
unk140: DLVector<()>,
unk160: bool,
unk161: bool,
/// Is in the mounting animation?
pub is_mounting: bool,
/// Is done with the mounting animation?
pub is_mounted: bool,
unk164: [u8; 0x4C],
unk1b0: DLString<DLUTF8StringKind>,
}
#[repr(C)]
pub struct CSChrRideModuleMountData {
unk0: F32ModelMatrix,
unk40: F32ModelMatrix,
/// Rotation in euler angles.
pub rotation: EulerAngles,
/// Position of the ride's `ChrIns`.
pub mount_position: HavokPosition,
/// Seems to be the position of the ride dmypoly (where the two `ChrIns`es snap together).
pub dummy_poly_position: HavokPosition,
// I believe this to be a quaternion but in the wrong order? Other quats appear to be xyzw.
// This quanternion seemingly only encodes rotations along the y (up)/yaw but the order seems
// to be wxyz with this one?
unkb0: Quaternion,
/// Speed of the mount as a directional vector.
pub velocity: PositionDelta,
unkd0: u64,
pub attack_direction: u8,
unkdc: u32,
unke0: u32,
pub received_damage_type: u32,
unke8: u32,
pub mount_health: u32,
pub fall_height: f32,
/// Is the the mount `ChrIns` touching solid ground?
pub is_touching_solid_ground: bool,
// Seems to be related to landing?
unkf5: bool,
/// Is the mount `ChrIns` in the falling loop?
pub is_falling: bool,
/// Is the mount `ChrIns` sliding?
pub is_sliding: bool,
}
#[repr(C)]
#[derive(Subclass)]
#[subclass(base = CSPairAnimNode)]
/// Source of name: RTTI
pub struct CSRideNode {
pub pair_anim_node: CSPairAnimNode,
/// 0 = none, 3 = getting on, 5 = riding, 7 = dismounting
pub ride_state: u32,
unk54: f32,
unk58: f32,
unk5c: f32,
pub ride_param_id: i32,
unk64: i32,
unk68: i32,
unk6c: i32,
unk70: bool,
pub camera_mount_control: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_size_of() {
assert_eq!(std::mem::size_of::<CSChrRideModule>(), 0x1e0);
assert_eq!(std::mem::size_of::<CSRideNode>(), 0x80);
}
}