rpfm_lib/files/group_formations/versions/
warhammer_3.rs1use crate::binary::{ReadBytes, WriteBytes};
12use crate::error::Result;
13
14use super::*;
15use super::versions::v2;
16
17impl GroupFormations {
18
19 pub(crate) fn decode_wh3<R: ReadBytes>(&mut self, data: &mut R) -> Result<()> {
20
21 for _ in 0..data.read_u32()? {
23 let mut formation = GroupFormation::default();
24 formation.name = data.read_sized_string_u8()?;
25 formation.ai_priority = data.read_f32()?;
26 formation.ai_purpose = AIPurpose::V2(v2::AIPurposeFlags::from_bits_truncate(data.read_u32()?));
27 formation.uk_2 = data.read_u32()?;
28
29 for _ in 0..data.read_u32()? {
31 let mut min_unit_category_percentage = MinUnitCategoryPercentage::default();
32 min_unit_category_percentage.category = UnitCategory::try_from(data.read_u32()?)?;
33 min_unit_category_percentage.percentage = data.read_u32()?;
34 formation.min_unit_category_percentage.push(min_unit_category_percentage);
35 }
36
37 for _ in 0..data.read_u32()? {
38 formation.ai_supported_subcultures.push(data.read_sized_string_u8()?);
39 }
40
41 for _ in 0..data.read_u32()? {
42 formation.ai_supported_factions.push(data.read_sized_string_u8()?);
43 }
44
45 for _ in 0..data.read_u32()? {
47 let mut block = GroupFormationBlock::default();
48 block.block_id = data.read_u32()?;
49
50 let block_type = data.read_u32()?;
51 match block_type {
52
53 0 => {
55 let mut container = ContainerAbsolute::default();
56 container.block_priority = data.read_f32()?;
57 container.entity_arrangement = EntityArrangement::try_from(data.read_u32()?)?;
58 container.inter_entity_spacing = data.read_f32()?;
59 container.crescent_y_offset = data.read_f32()?;
60 container.position_x = data.read_f32()?;
61 container.position_y = data.read_f32()?;
62 container.minimum_entity_threshold = data.read_i32()?;
63 container.maximum_entity_threshold = data.read_i32()?;
64
65 for _ in 0..data.read_u32()? {
66 let mut entity_pref = EntityPreference::default();
67 entity_pref.priority = data.read_f32()?;
68 entity_pref.entity = Entity::V2(v2::EntityType::try_from(data.read_u32()?)?);
69 entity_pref.entity_weight = EntityWeight::try_from(data.read_u32()?)?;
70 entity_pref.uk_1 = data.read_u32()?;
71 entity_pref.entity_class = data.read_sized_string_u8()?;
72 container.entity_preferences.push(entity_pref);
73 }
74
75 block.block = Block::ContainerAbsolute(container);
76 },
77
78 1 => {
80 let mut container = ContainerRelative::default();
81 container.block_priority = data.read_f32()?;
82 container.relative_block_id = data.read_u32()?;
83 container.entity_arrangement = EntityArrangement::try_from(data.read_u32()?)?;
84 container.inter_entity_spacing = data.read_f32()?;
85 container.crescent_y_offset = data.read_f32()?;
86 container.position_x = data.read_f32()?;
87 container.position_y = data.read_f32()?;
88 container.minimum_entity_threshold = data.read_i32()?;
89 container.maximum_entity_threshold = data.read_i32()?;
90
91 for _ in 0..data.read_u32()? {
92 let mut entity_pref = EntityPreference::default();
93 entity_pref.priority = data.read_f32()?;
94 entity_pref.entity = Entity::V2(v2::EntityType::try_from(data.read_u32()?)?);
95 entity_pref.entity_weight = EntityWeight::try_from(data.read_u32()?)?;
96 entity_pref.uk_1 = data.read_u32()?;
97 entity_pref.entity_class = data.read_sized_string_u8()?;
98 container.entity_preferences.push(entity_pref);
99 }
100
101 block.block = Block::ContainerRelative(container);
102 },
103
104 3 => {
106 let mut container = Spanning::default();
107 for _ in 0..data.read_u32()? {
108 container.spanned_block_ids.push(data.read_u32()?);
109 }
110 block.block = Block::Spanning(container);
111 },
112 _ => todo!("unknown block type {}.", block_type),
113 }
114
115 formation.group_formation_blocks.push(block);
116 }
117
118 self.formations.push(formation);
119 }
120
121 Ok(())
122 }
123
124 pub(crate) fn encode_wh3<W: WriteBytes>(&mut self, buffer: &mut W) -> Result<()> {
125 buffer.write_u32(self.formations.len() as u32)?;
126 for formation in self.formations() {
127 buffer.write_sized_string_u8(formation.name())?;
128 buffer.write_f32(formation.ai_priority)?;
129
130 if let AIPurpose::V2(data) = &formation.ai_purpose {
131 buffer.write_u32(data.bits())?;
132 }
133
134 buffer.write_u32(formation.uk_2)?;
135
136 buffer.write_u32(formation.min_unit_category_percentage.len() as u32)?;
137 for mucp in formation.min_unit_category_percentage() {
138 buffer.write_u32(mucp.category.into())?;
139 buffer.write_u32(mucp.percentage)?;
140 }
141
142 buffer.write_u32(formation.ai_supported_subcultures.len() as u32)?;
143 for s in formation.ai_supported_subcultures() {
144 buffer.write_sized_string_u8(s)?;
145 }
146
147 buffer.write_u32(formation.ai_supported_factions.len() as u32)?;
148 for s in formation.ai_supported_factions() {
149 buffer.write_sized_string_u8(s)?;
150 }
151
152 buffer.write_u32(formation.group_formation_blocks.len() as u32)?;
153 for block in formation.group_formation_blocks() {
154 buffer.write_u32(block.block_id)?;
155
156 match block.block {
157 Block::ContainerAbsolute(ref b) => {
158 buffer.write_u32(0)?;
159 buffer.write_f32(b.block_priority)?;
160 buffer.write_u32(b.entity_arrangement.into())?;
161 buffer.write_f32(b.inter_entity_spacing)?;
162 buffer.write_f32(b.crescent_y_offset)?;
163 buffer.write_f32(b.position_x)?;
164 buffer.write_f32(b.position_y)?;
165 buffer.write_i32(b.minimum_entity_threshold)?;
166 buffer.write_i32(b.maximum_entity_threshold)?;
167
168 buffer.write_u32(b.entity_preferences.len() as u32)?;
169 for ep in b.entity_preferences() {
170 buffer.write_f32(ep.priority)?;
171 if let Entity::V2(data) = &ep.entity {
172 buffer.write_u32((*data).into())?;
173 }
174 buffer.write_u32(ep.entity_weight.into())?;
175 buffer.write_u32(ep.uk_1)?;
176 buffer.write_sized_string_u8(&ep.entity_class)?;
177 }
178 },
179
180 Block::ContainerRelative(ref b) => {
181 buffer.write_u32(1)?;
182 buffer.write_f32(b.block_priority)?;
183 buffer.write_u32(b.relative_block_id)?;
184 buffer.write_u32(b.entity_arrangement.into())?;
185 buffer.write_f32(b.inter_entity_spacing)?;
186 buffer.write_f32(b.crescent_y_offset)?;
187 buffer.write_f32(b.position_x)?;
188 buffer.write_f32(b.position_y)?;
189 buffer.write_i32(b.minimum_entity_threshold)?;
190 buffer.write_i32(b.maximum_entity_threshold)?;
191
192 buffer.write_u32(b.entity_preferences.len() as u32)?;
193 for ep in b.entity_preferences() {
194 buffer.write_f32(ep.priority)?;
195 if let Entity::V2(data) = &ep.entity {
196 buffer.write_u32((*data).into())?;
197 }
198 buffer.write_u32(ep.entity_weight.into())?;
199 buffer.write_u32(ep.uk_1)?;
200 buffer.write_sized_string_u8(&ep.entity_class)?;
201 }
202 },
203
204 Block::Spanning(ref b) => {
205 buffer.write_u32(3)?;
206 buffer.write_u32(b.spanned_block_ids.len() as u32)?;
207 for id in b.spanned_block_ids() {
208 buffer.write_u32(*id)?;
209 }
210 },
211 }
212 }
213 }
214
215 Ok(())
216 }
217}