commonlibsse_ng\re\p/
PlayerCharacter.rs

1pub mod crime;
2pub mod grab_data;
3pub mod player_target_loc;
4pub mod runtime_info;
5pub mod skill;
6pub mod vr_node_data;
7
8use crate::re::ActorValues::ActorValue;
9use crate::re::BGSActorCellEvent::BGSActorCellEvent;
10use crate::re::BGSAddToPlayerInventoryEvent::ACQUIRE_TYPE;
11use crate::re::BGSTextureSet::BGSTextureSet;
12use crate::re::BSCoreTypes::RefHandle;
13use crate::re::BSPointerHandle::ActorHandle;
14use crate::re::BSTEvent::{BSTEventSink, BSTEventSource};
15use crate::re::Character::{Character, CharacterVtbl};
16use crate::re::CrosshairPickData::VR_DEVICE;
17use crate::re::FormTypes::FormType;
18use crate::re::InventoryEntryData::InventoryEntryData;
19use crate::re::MagicItem::MagicItem;
20use crate::re::MenuModeChangeEvent::MenuModeChangeEvent;
21use crate::re::MenuOpenCloseEvent::MenuOpenCloseEvent;
22use crate::re::NiSmartPointer::NiPointer;
23use crate::re::PositionPlayerEvent::PositionPlayerEvent;
24use crate::re::TESBoundObject::TESBoundObject;
25use crate::re::TESForm::TESForm;
26use crate::re::TESObject::TESObject;
27use crate::re::TESObjectCELL::TESObjectCELL;
28use crate::re::TESObjectREFR::TESObjectREFR;
29use crate::re::TESObjectWEAP::TESObjectWEAP;
30use crate::re::TESTrackedStatsEvent::TESTrackedStatsEvent;
31use crate::re::offsets_rtti::RTTI_PlayerCharacter;
32use crate::re::offsets_vtable::VTABLE_PlayerCharacter;
33use crate::re::{BGSActorDeathEvent, TESFaction, TESRace};
34use crate::re::{Effect, MagicSystem, UserEventEnabledEvent};
35use crate::rel::id::VariantID;
36
37#[commonlibsse_ng_derive_internal::to_bitflags]
38#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
39#[repr(u32)]
40pub enum PLAYER_ACTION {
41    #[default]
42    None = 0,
43    SwingMeleeWeapon,
44    CastProjectileSpell,
45    ShootBow,
46    ZKeyObject,
47    Jumping,
48    KnockingOverObjects,
49    StandOnTableChair,
50    IronSights,
51    DestroyObject,
52    LockedObject,
53    Pickpocket,
54    CastSelfSpell,
55    Shout,
56    ActorCollision,
57
58    Total,
59    InvalidMarker,
60}
61
62#[repr(C)]
63pub struct FriendshipFactionsStruct {
64    friend_counts: [u16; 4], // 0
65}
66const _: () = assert!(core::mem::size_of::<FriendshipFactionsStruct>() == 0x8);
67
68#[repr(C)]
69pub struct PlayerActionObject {
70    timer: f32,          // 0
71    refObj: RefHandle,   // 4
72    next: PLAYER_ACTION, // 8
73}
74const _: () = assert!(core::mem::size_of::<PlayerActionObject>() == 0x0C);
75
76#[repr(C)]
77#[derive(Debug)]
78pub struct PlayerCharacter {
79    pub __base: Character,                            // 000
80    pub __base1: BSTEventSource<BGSActorCellEvent>,   // SE: 0x2D0, AE: 0x2D8, VR: 0x2E8
81    pub __base2: BSTEventSource<BGSActorDeathEvent>,  // SE: 0x328, AE: 0x330, VR: 0x340
82    pub __base3: BSTEventSource<PositionPlayerEvent>, // SE: 0x380, AE: 0x388, VR: 0x398
83    pub __base4: BSTEventSink<MenuOpenCloseEvent>,    // SE,VR: 0x2B0, AE: 0x2B8
84    pub __base5: BSTEventSink<MenuModeChangeEvent>,   // SE,VR: 0x2B8, AE: 0x2C0
85    pub __base6: BSTEventSink<UserEventEnabledEvent>, // SE,VR: 0x2C0, AE: 0x2C8
86    pub __base7: BSTEventSink<TESTrackedStatsEvent>,  // SE,VR: 0x2C8, AE: 0x2D0
87}
88const _: () = assert!(core::mem::size_of::<PlayerCharacter>() == 0x1A0);
89
90impl PlayerCharacter {
91    pub const RTTI: VariantID = RTTI_PlayerCharacter;
92    pub const VTABLE: [VariantID; 17] = VTABLE_PlayerCharacter;
93    pub const FORM_TYPE: FormType = FormType::ActorCharacter;
94
95    /// Returns the singleton instance of `Self`.
96    #[commonlibsse_ng_derive_internal::relocate(
97        cast_as = "*mut NiPointer<PlayerCharacter>",
98        default = "None",
99        deref_once,
100        id(se = 517014, ae = 403521)
101    )]
102    pub fn get_singleton() -> Option<&'static PlayerCharacter> {
103        |deref_type: DerefType| unsafe { deref_type.as_ptr().map(|p| p.as_ref()) }
104    }
105
106    /// Returns the singleton instance of `Self`.
107    ///
108    /// # Safety
109    /// When it is known whether this is mutable or not. (The author does not know if it is safe.)
110    #[commonlibsse_ng_derive_internal::relocate(
111        cast_as = "*mut NiPointer<PlayerCharacter>",
112        default = "None",
113        deref_once,
114        id(se = 517014, ae = 403521)
115    )]
116    pub unsafe fn get_singleton_mut() -> Option<&'static mut PlayerCharacter> {
117        |deref_type: DerefType| unsafe { deref_type.as_ptr().map(|mut p| p.as_mut()) }
118    }
119
120    #[commonlibsse_ng_derive_internal::relocate(
121        cast_as = "*mut bool",
122        default = "false",
123        deref_once,
124        id(se = 517711, ae = 404238)
125    )]
126    #[inline]
127    pub fn is_god_mode() -> bool {
128        |deref_type: DerefType| deref_type
129    }
130
131    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39471, ae_id = 40548)]
132    pub fn activate_pick_ref(&mut self) {}
133
134    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39471, ae_id = 40548)]
135    pub fn activate_pick_ref_vr(&mut self, device: VR_DEVICE) {}
136
137    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39384, ae_id = 40456)]
138    pub fn add_player_add_item_event(
139        &mut self,
140        object: TESObject,
141        owner: *mut TESForm,
142        container: *mut TESObjectREFR,
143        type_: ACQUIRE_TYPE,
144    ) {
145    }
146
147    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39568, ae_id = 40654)]
148    pub fn attempt_pickpocket(
149        &mut self,
150        container_ref: *mut TESObjectREFR,
151        entry: *mut InventoryEntryData,
152        number: i32,
153        from_container: bool,
154    ) -> bool {
155    }
156
157    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39409, ae_id = 40484)]
158    pub fn check_cast(
159        &mut self,
160        spell: MagicItem,
161        effect: Effect,
162        reason: MagicSystem::CannotCastReason,
163    ) -> bool {
164    }
165
166    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39480, ae_id = 40557)]
167    pub fn destroy_mouse_springs(&mut self) {}
168
169    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39365, ae_id = 40437)]
170    pub fn center_on_cell_impl(
171        &mut self,
172        cell_name: Option<&str>,
173        cell: Option<TESObjectCELL>,
174    ) -> bool {
175    }
176
177    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39413, ae_id = 40488)]
178    pub fn add_skill_experience(&mut self, skill: ActorValue, experience: f32) {}
179
180    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39507, ae_id = 40586)]
181    pub fn set_ai_driven(&mut self, enable: bool) {}
182
183    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39574, ae_id = 40660)]
184    pub fn set_escaping(&mut self, flag: bool, escaped: bool) {}
185
186    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39475, ae_id = 40552)]
187    pub fn start_grab_object(&mut self, device: VR_DEVICE) {}
188
189    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 39535, ae_id = 40621)]
190    pub fn update_crosshairs(&mut self) {}
191
192    // VR-specific functions (if VR is enabled)
193    // pub fn is_grabbing_with_device(&mut self, device: VR_DEVICE) -> bool {}
194}
195
196pub struct PlayerCharacterVtbl {
197    pub __base: CharacterVtbl,
198
199    // 0x12A * 8 = 4520
200    pub Unk_12A: fn(this: *mut PlayerCharacter), // 0x12A
201    pub GetViolentCrimeGoldValue: fn(this: *const PlayerCharacter, faction: *mut TESFaction) -> u32, // 0x12B
202    pub GetNonViolentCrimeGoldValue:
203        fn(this: *const PlayerCharacter, faction: *mut TESFaction) -> u32, // 0x12C
204    pub ClearAllCrimeGold: fn(this: *mut PlayerCharacter, faction: *mut TESFaction), // 0x12D
205    pub Unk_12E: fn(this: *mut PlayerCharacter),                                     // 0x12E
206}
207
208impl crate::re::NiSmartPointer::RefCountable for PlayerCharacter {
209    #[inline]
210    fn inc_ref_count(&self) {
211        self.__base.__base.__base.inc_ref_count();
212    }
213
214    #[inline]
215    fn dec_ref_count(&mut self) {
216        self.__base.__base.__base.dec_ref_count();
217    }
218}
219
220#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
221pub enum EventType {
222    Thief = 3,
223    Container = 5,
224    DeadBody = 6,
225}
226
227#[commonlibsse_ng_derive_internal::to_bitflags]
228#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
229#[repr(u8)]
230pub enum ByCharGenFlag {
231    #[default]
232    None = 0,
233    DisableSaving = 1 << 0,
234    HandsBound = 1 << 2,
235}
236
237bitflags::bitflags! {
238    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
239    #[repr(transparent)]
240    pub struct PlayerFlags: u64 {
241        const TRAVEL_USE_DOOR                = 1 << 0;      // 0:0
242        const FAST_TRAVELING                 = 1 << 1;      // 0:1
243        const OVER_AUTO_AIM_TARGET           = 1 << 2;      // 0:2
244        const SHOW_QUEST_ITEMS               = 1 << 3;      // 0:3
245        const UNK0_4                         = 1 << 4;      // 0:4
246        const HAS_QUEUED_EQUIP_ANIM          = 1 << 5;      // 0:5
247        const ESCAPING                       = 1 << 6;      // 0:6
248        const FORCE_QUEST_TARGET_REPATH      = 1 << 7;      // 0:7
249        const UNK1_0                         = 1 << 8;      // 1:0
250        const UNK1_1                         = 1 << 9;      // 1:1
251        const SLEEPING                       = 1 << 10;     // 1:2
252        const UNK1_3                         = 1 << 11;     // 1:3
253        const UNK1_4                         = 1 << 12;     // 1:4
254        const UNK1_5                         = 1 << 13;     // 1:5
255        const GREETING_PLAYER                = 1 << 14;     // 1:6
256        const UNK1_7                         = 1 << 15;     // 1:7
257        const UNK2_0                         = 1 << 16;     // 2:0
258        const AI_CONTROLLED_TO_POS           = 1 << 17;     // 2:1
259        const AI_CONTROLLED_FROM_POS         = 1 << 18;     // 2:2
260        const AI_CONTROLLED_PACKAGE          = 1 << 19;     // 2:3
261        const RETURN_TO_LAST_KNOWN_GOOD_POSITION = 1 << 20; // 2:4
262        const IS_BEING_CHASED                = 1 << 21;     // 2:5
263        const UNK2_6                         = 1 << 22;     // 2:6
264        const UNK2_7                         = 1 << 23;     // 2:7
265        const IS_IN_THIRD_PERSON_MODE        = 1 << 24;     // 3:0
266        const UNK3_1                         = 1 << 25;     // 3:1
267        const UNK3_2                         = 1 << 26;     // 3:2
268        const UNK3_3                         = 1 << 27;     // 3:3
269        const TARGET_3D_DISTANT              = 1 << 28;     // 3:4
270        const IS_IN_COMBAT                   = 1 << 29;     // 3:5
271        const ATTEMPTED_YIELD_IN_CURRENT_COMBAT = 1 << 30;  // 3:6
272        const UNK3_7                         = 1 << 31;     // 3:7
273        const IS_LOADING                     = 1 << 32;     // 4:0
274        const SHOULD_UPDATE_CROSSHAIR        = 1 << 33;     // 4:1
275        const UNK4_2                         = 1 << 34;     // 4:2
276        const HEALTH_TUTORIAL_SHOWN          = 1 << 35;     // 4:3
277        const MAGICKA_TUTORIAL_SHOWN         = 1 << 36;     // 4:4
278        const STAMINA_TUTORIAL_SHOWN         = 1 << 37;     // 4:5
279        const GO_TO_JAIL_QUEUED              = 1 << 38;     // 4:6
280        const UNK4_7                         = 1 << 39;     // 4:7
281        const IS_SPRINTING                   = 1 << 40;     // 5:0
282        const IS_SUNGAZING                   = 1 << 41;     // 5:1
283        const DRAGON_RIDE_TARGET_LOCKED      = 1 << 42;     // 5:2
284        const EVER_MODDED                    = 1 << 43;     // 5:3
285        const SERVING_JAIL_TIME              = 1 << 44;     // 5:4
286        const UNK5_5                         = 1 << 45;     // 5:5
287        const UNK5_6                         = 1 << 46;     // 5:6
288        const UNK5_7                         = 1 << 47;     // 5:7
289        const UNK6_0                         = 1 << 47;     // 6:0
290        const UNK6_1                         = 1 << 47;     // 6:1
291        const UNK6_2                         = 1 << 47;     // 6:2
292        const UNK6_3                         = 1 << 47;     // 6:3
293        const UNK6_4                         = 1 << 47;     // 6:4
294        const UNK6_5                         = 1 << 47;     // 6:5
295        const UNK6_6                         = 1 << 47;     // 6:6
296        const UNK6_7                         = 1 << 47;     // 6:7
297        const UNK7_0                         = 1 << 47;     // 7:0
298        const UNK7_1                         = 1 << 47;     // 7:1
299        const UNK7_2                         = 1 << 47;     // 7:2
300        const UNK7_3                         = 1 << 47;     // 7:3
301        const UNK7_4                         = 1 << 47;     // 7:4
302        const UNK7_5                         = 1 << 47;     // 7:5
303        const UNK7_6                         = 1 << 47;     // 7:6
304        const UNK7_7                         = 1 << 47;     // 7:7
305    }
306}
307
308#[repr(C)]
309#[derive(Debug)]
310pub struct QueuedWeapon {
311    rightHandWeapon: *mut TESObjectWEAP, // 00 - These may be main/off hand weapon for VR?
312    leftHandWeapon: *mut TESObjectWEAP,  // 08
313}
314const _: () = {
315    assert!(core::mem::offset_of!(QueuedWeapon, rightHandWeapon) == 0x0);
316    assert!(core::mem::offset_of!(QueuedWeapon, leftHandWeapon) == 0x8);
317    assert!(core::mem::size_of::<QueuedWeapon>() == 0x10);
318};
319
320#[repr(C)]
321#[derive(Debug)]
322pub struct PreTransformationData {
323    pub storedSelectedSpells: [*mut MagicItem; 4],
324    pub storedRace: *mut TESRace,
325    pub storedSelectedPower: *mut TESForm,
326    pub storedLastOneHandItems: [*mut TESBoundObject; 2],
327}
328
329#[repr(C)]
330#[derive(Debug)]
331pub struct RaceData {
332    pub complexion: *mut BGSTextureSet,
333    pub charGenRace: *mut TESRace,
334    pub race2: *mut TESRace,
335}
336
337#[repr(C)]
338#[derive(Debug)]
339pub struct GameStateData {
340    pub difficulty: i32,
341    pub assumedIdentity: ActorHandle,
342    pub murder: i8,
343    pub perkCount: i8,
344    pub byCharGenFlag: ByCharGenFlag,
345    pub padB: u8,
346}
347const _: () = assert!(core::mem::size_of::<GameStateData>() == 0xC);