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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use super::{AtkParamLookupResult, BlockId};
use bitfield::bitfield;
use std::fmt::Display;
#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum FieldInsType {
Hit = 0,
Chr = 1,
Obj = 2,
Bullet = 3,
Geom = 4,
ReplayGhost = 5,
ReplayEnemy = 6,
Map = 7,
HitGeom = 8,
}
bitfield! {
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
/// Used to reference a specific FieldIns managed by its respective (external) domain.
pub struct FieldInsSelector(u32);
impl Debug;
/// The index within the container.
pub index, _: 19, 0;
_, set_index: 19, 0;
/// The container for this FieldIns, used to determine which ChrSet to use.
pub container, _: 27, 20;
_, set_container: 27, 20;
/// The type of FieldIns, used to determine the container type.
_field_ins_type, set_field_ins_type: 31, 28;
}
impl FieldInsSelector {
/// Create a new FieldInsSelector by its components.
pub fn from_parts(field_ins_type: FieldInsType, container: u32, index: u32) -> Self {
let mut selector = FieldInsSelector(0);
selector.set_field_ins_type(field_ins_type as u32);
selector.set_container(container);
selector.set_index(index);
selector
}
pub fn field_ins_type(&self) -> Option<FieldInsType> {
match self._field_ins_type() {
0 => Some(FieldInsType::Hit),
1 => Some(FieldInsType::Chr),
2 => Some(FieldInsType::Obj),
3 => Some(FieldInsType::Bullet),
4 => Some(FieldInsType::Geom),
5 => Some(FieldInsType::ReplayGhost),
6 => Some(FieldInsType::ReplayEnemy),
7 => Some(FieldInsType::Map),
8 => Some(FieldInsType::HitGeom),
_ => None,
}
}
}
/// Used throughout the game engine to refer to characters, geometry, bullets, hits and more.
///
/// Source of name: Destructor reveals this being a field in FieldIns and it's used as a means of
/// naming some FieldIns derivant everywhere where raw pointers cannot be shared.
#[repr(C, align(8))]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct FieldInsHandle {
pub selector: FieldInsSelector,
pub block_id: BlockId,
}
impl FieldInsHandle {
pub fn is_empty(&self) -> bool {
self.selector.0 == u32::MAX
}
}
impl Display for FieldInsHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_empty() {
write!(f, "FieldIns(None)")
} else {
write!(
f,
"FieldIns({}, {}, {})",
self.block_id,
self.selector.container(),
self.selector.index()
)
}
}
}
#[vtable_rs::vtable]
/// Describes the VMT for the FieldInsBase which ChrIns, GeomIns, BulletIns, etc derive from.
pub trait FieldInsBaseVmt {
/// Part of FieldInsBase, retrieves reflection metadata for FD4Component derivants.
fn get_runtime_metadata(&self) -> usize;
fn destructor(&mut self, param_2: u32);
/// Part of FieldInsBase, ChrIns = 1, CSBulletIns = 3, CSWorldGeomIns = 6, MapIns = 7, CSWorldGeomHitIns = 8,
fn get_field_ins_type(&self) -> u32;
fn use_npc_atk_param(&self) -> bool;
fn get_atk_param_for_behavior(&self, param_2: u32, atk_param: &mut AtkParamLookupResult)
-> u32;
/// Part of FieldInsBase. ChrIns = 0, PlayerIns = 1, EnemyIns = 0, ReplayGhostIns = 1,
/// ReplayEnemyIns = 0, CSBulletIns = 0, CSWorldGeomIns = 0, CSFieldInsBase = 0,
/// CSHamariSimulateChrIns = 0, MapIns = 0, HitIns = 0, CSWorldGeomStaticIns = 0, HitInsBase =
/// 0, CSWorldGeomHitIns = 0, CSWorldGeomDynamicIns = 0,
fn use_player_behavior_param(&self) -> bool;
/// Obfuscated beyond recognition
fn unk30(&self);
/// Obfuscated beyond recognition
fn unk38(&self);
}