rpfm_lib/files/group_formations/versions/
troy.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_troy<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
33 min_unit_category_percentage.category = UnitCategory::try_from(data.read_u32()?)?;
34 min_unit_category_percentage.percentage = data.read_u32()?;
35
36 formation.min_unit_category_percentage.push(min_unit_category_percentage);
37 }
38
39 for _ in 0..data.read_u32()? {
40 formation.ai_supported_subcultures.push(data.read_sized_string_u8()?);
41 }
42
43 for _ in 0..data.read_u32()? {
49 let mut block = GroupFormationBlock::default();
50 block.block_id = data.read_u32()?;
51
52 let block_type = data.read_u32()?;
54 match block_type {
55
56 0 => {
58 let mut container = ContainerAbsolute::default();
59 container.block_priority = data.read_f32()?;
60 container.entity_arrangement = EntityArrangement::try_from(data.read_u32()?)?;
61 container.inter_entity_spacing = data.read_f32()?;
62 container.crescent_y_offset = data.read_f32()?;
63 container.position_x = data.read_f32()?;
64 container.position_y = data.read_f32()?;
65 container.minimum_entity_threshold = data.read_i32()?;
66 container.maximum_entity_threshold = data.read_i32()?;
67
68 for _ in 0..data.read_u32()? {
70 let mut entity_pref = EntityPreference::default();
71 entity_pref.priority = data.read_f32()?;
72 entity_pref.entity = Entity::V2(v2::EntityType::try_from(data.read_u32()?)?);
73 entity_pref.entity_weight = EntityWeight::try_from(data.read_u32()?)?;
74 entity_pref.uk_1 = data.read_u32()?;
75 entity_pref.entity_class = data.read_sized_string_u8()?;
76 container.entity_preferences.push(entity_pref);
77 }
78
79 block.block = Block::ContainerAbsolute(container);
80 },
81
82 1 => {
84 let mut container = ContainerRelative::default();
85 container.block_priority = data.read_f32()?;
86 container.relative_block_id = data.read_u32()?;
87 container.entity_arrangement = EntityArrangement::try_from(data.read_u32()?)?;
88 container.inter_entity_spacing = data.read_f32()?;
89 container.crescent_y_offset = data.read_f32()?;
90 container.position_x = data.read_f32()?;
91 container.position_y = data.read_f32()?;
92 container.minimum_entity_threshold = data.read_i32()?;
93 container.maximum_entity_threshold = data.read_i32()?;
94
95 for _ in 0..data.read_u32()? {
97 let mut entity_pref = EntityPreference::default();
98 entity_pref.priority = data.read_f32()?;
99 entity_pref.entity = Entity::V2(v2::EntityType::try_from(data.read_u32()?)?);
100 entity_pref.entity_weight = EntityWeight::try_from(data.read_u32()?)?;
101 entity_pref.uk_1 = data.read_u32()?;
102 entity_pref.entity_class = data.read_sized_string_u8()?;
103 container.entity_preferences.push(entity_pref);
104 }
105
106 block.block = Block::ContainerRelative(container);
107 },
108
109 3 => {
111 let mut container = Spanning::default();
112 for _ in 0..data.read_u32()? {
113 container.spanned_block_ids.push(data.read_u32()?);
114 }
115 block.block = Block::Spanning(container);
116 },
117 _ => todo!("unknown block type {}.", block_type),
118 }
119
120 formation.group_formation_blocks.push(block);
121 }
122
123 self.formations.push(formation);
124 }
125
126 Ok(())
127 }
128
129 pub(crate) fn encode_troy<W: WriteBytes>(&mut self, buffer: &mut W) -> Result<()> {
130 buffer.write_u32(self.formations.len() as u32)?;
131 for formation in self.formations() {
132 buffer.write_sized_string_u8(formation.name())?;
133
134 buffer.write_f32(formation.ai_priority)?;
135 if let AIPurpose::V2(data) = &formation.ai_purpose {
136 buffer.write_u32(data.bits())?;
137 }
138
139 buffer.write_u32(formation.uk_2)?;
140 buffer.write_u32(formation.min_unit_category_percentage.len() as u32)?;
141 for mucp in formation.min_unit_category_percentage() {
142 buffer.write_u32(mucp.category.into())?;
143 buffer.write_u32(mucp.percentage)?;
144 }
145
146 buffer.write_u32(formation.ai_supported_subcultures.len() as u32)?;
147 for ai_supported_subculture in formation.ai_supported_subcultures() {
148 buffer.write_sized_string_u8(ai_supported_subculture)?;
149 }
150
151 buffer.write_u32(formation.group_formation_blocks.len() as u32)?;
157 for block in formation.group_formation_blocks() {
158 buffer.write_u32(block.block_id)?;
159
160 match block.block {
161 Block::ContainerAbsolute(ref b) => {
162 buffer.write_u32(0)?;
163
164 buffer.write_f32(b.block_priority)?;
165 buffer.write_u32(b.entity_arrangement.into())?;
166 buffer.write_f32(b.inter_entity_spacing)?;
167 buffer.write_f32(b.crescent_y_offset)?;
168 buffer.write_f32(b.position_x)?;
169 buffer.write_f32(b.position_y)?;
170 buffer.write_i32(b.minimum_entity_threshold)?;
171 buffer.write_i32(b.maximum_entity_threshold)?;
172
173 buffer.write_u32(b.entity_preferences.len() as u32)?;
174 for ep in b.entity_preferences() {
175 buffer.write_f32(ep.priority)?;
176 if let Entity::V2(data) = &ep.entity {
177 buffer.write_u32((*data).into())?;
178 }
179 buffer.write_u32(ep.entity_weight.into())?;
180 buffer.write_u32(ep.uk_1)?;
181 buffer.write_sized_string_u8(&ep.entity_class)?;
182 }
183 },
184
185 Block::ContainerRelative(ref b) => {
186 buffer.write_u32(1)?;
187
188 buffer.write_f32(b.block_priority)?;
189 buffer.write_u32(b.relative_block_id)?;
190 buffer.write_u32(b.entity_arrangement.into())?;
191 buffer.write_f32(b.inter_entity_spacing)?;
192 buffer.write_f32(b.crescent_y_offset)?;
193 buffer.write_f32(b.position_x)?;
194 buffer.write_f32(b.position_y)?;
195 buffer.write_i32(b.minimum_entity_threshold)?;
196 buffer.write_i32(b.maximum_entity_threshold)?;
197
198 buffer.write_u32(b.entity_preferences.len() as u32)?;
199 for ep in b.entity_preferences() {
200 buffer.write_f32(ep.priority)?;
201 if let Entity::V2(data) = &ep.entity {
202 buffer.write_u32((*data).into())?;
203 }
204 buffer.write_u32(ep.entity_weight.into())?;
205
206 buffer.write_u32(ep.uk_1)?;
207 buffer.write_sized_string_u8(&ep.entity_class)?;
208 }
209 },
210
211 Block::Spanning(ref block) => {
212 buffer.write_u32(3)?;
213 buffer.write_u32(block.spanned_block_ids.len() as u32)?;
214 for id in block.spanned_block_ids() {
215 buffer.write_u32(*id)?;
216 }
217 },
218 }
219 }
220 }
221
222 Ok(())
223 }
224}