Skip to main content

rpfm_lib/files/group_formations/versions/
rome_2.rs

1//---------------------------------------------------------------------------//
2// Copyright (c) 2017-2026 Ismael Gutiérrez González. All rights reserved.
3//
4// This file is part of the Rusted PackFile Manager (RPFM) project,
5// which can be found here: https://github.com/Frodo45127/rpfm.
6//
7// This file is licensed under the MIT license, which can be found here:
8// https://github.com/Frodo45127/rpfm/blob/master/LICENSE.
9//---------------------------------------------------------------------------//
10
11use crate::binary::{ReadBytes, WriteBytes};
12use crate::error::Result;
13
14use super::*;
15use super::versions::v2;
16
17impl GroupFormations {
18
19    pub(crate) fn decode_rom_2<R: ReadBytes>(&mut self, data: &mut R) -> Result<()> {
20
21        //GroupFormation
22        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
28            // MinUnitCategoryPercentage
29            for _ in 0..data.read_u32()? {
30                let mut min_unit_category_percentage = MinUnitCategoryPercentage::default();
31                min_unit_category_percentage.category = UnitCategory::try_from(data.read_u32()?)?;
32                min_unit_category_percentage.percentage = data.read_u32()?;
33                formation.min_unit_category_percentage.push(min_unit_category_percentage);
34            }
35
36            for _ in 0..data.read_u32()? {
37                formation.ai_supported_subcultures.push(data.read_sized_string_u8()?);
38            }
39
40            for _ in 0..data.read_u32()? {
41                formation.ai_supported_factions.push(data.read_sized_string_u8()?);
42            }
43
44            // GroupFormationBlock
45            for _ in 0..data.read_u32()? {
46                let mut block = GroupFormationBlock::default();
47                block.block_id = data.read_u32()?;
48
49                let block_type = data.read_u32()?;
50                match block_type {
51
52                    // ContainerAbsolute
53                    0 => {
54                        let mut container = ContainerAbsolute::default();
55                        container.block_priority = data.read_f32()?;
56                        container.entity_arrangement = EntityArrangement::try_from(data.read_u32()?)?;
57                        container.inter_entity_spacing = data.read_f32()?;
58                        container.crescent_y_offset = data.read_f32()?;
59                        container.position_x = data.read_f32()?;
60                        container.position_y = data.read_f32()?;
61                        container.minimum_entity_threshold = data.read_i32()?;
62                        container.maximum_entity_threshold = data.read_i32()?;
63
64                        for _ in 0..data.read_u32()? {
65                            let mut entity_pref = EntityPreference::default();
66                            entity_pref.priority = data.read_f32()?;
67                            entity_pref.entity = Entity::V2(v2::EntityType::try_from(data.read_u32()?)?);
68                            entity_pref.entity_weight = EntityWeight::try_from(data.read_u32()?)?;
69                            container.entity_preferences.push(entity_pref);
70                        }
71
72                        block.block = Block::ContainerAbsolute(container);
73                    },
74
75                    // ContainerRelative
76                    1 => {
77                        let mut container = ContainerRelative::default();
78                        container.block_priority = data.read_f32()?;
79                        container.relative_block_id = data.read_u32()?;
80                        container.entity_arrangement = EntityArrangement::try_from(data.read_u32()?)?;
81                        container.inter_entity_spacing = data.read_f32()?;
82                        container.crescent_y_offset = data.read_f32()?;
83                        container.position_x = data.read_f32()?;
84                        container.position_y = data.read_f32()?;
85                        container.minimum_entity_threshold = data.read_i32()?;
86                        container.maximum_entity_threshold = data.read_i32()?;
87
88                        for _ in 0..data.read_u32()? {
89                            let mut entity_pref = EntityPreference::default();
90                            entity_pref.priority = data.read_f32()?;
91                            entity_pref.entity = Entity::V2(v2::EntityType::try_from(data.read_u32()?)?);
92                            entity_pref.entity_weight = EntityWeight::try_from(data.read_u32()?)?;
93                            container.entity_preferences.push(entity_pref);
94                        }
95
96                        block.block = Block::ContainerRelative(container);
97                    },
98
99                    // Spanning
100                    3 => {
101                        let mut container = Spanning::default();
102                        for _ in 0..data.read_u32()? {
103                            container.spanned_block_ids.push(data.read_u32()?);
104                        }
105                        block.block = Block::Spanning(container);
106                    },
107                    _ => todo!("unknown block type {}.", block_type),
108                }
109
110                formation.group_formation_blocks.push(block);
111            }
112
113            self.formations.push(formation);
114        }
115
116        Ok(())
117    }
118
119    pub(crate) fn encode_rom_2<W: WriteBytes>(&mut self, buffer: &mut W) -> Result<()> {
120        buffer.write_u32(self.formations.len() as u32)?;
121        for formation in self.formations() {
122            buffer.write_sized_string_u8(formation.name())?;
123            buffer.write_f32(formation.ai_priority)?;
124
125            if let AIPurpose::V2(data) = &formation.ai_purpose {
126                buffer.write_u32(data.bits())?;
127            }
128
129            buffer.write_u32(formation.min_unit_category_percentage.len() as u32)?;
130            for mucp in formation.min_unit_category_percentage() {
131                buffer.write_u32(mucp.category.into())?;
132                buffer.write_u32(mucp.percentage)?;
133            }
134
135            buffer.write_u32(formation.ai_supported_subcultures.len() as u32)?;
136            for s in formation.ai_supported_subcultures() {
137                buffer.write_sized_string_u8(s)?;
138            }
139
140            buffer.write_u32(formation.ai_supported_factions.len() as u32)?;
141            for s in formation.ai_supported_factions() {
142                buffer.write_sized_string_u8(s)?;
143            }
144
145            buffer.write_u32(formation.group_formation_blocks.len() as u32)?;
146            for block in formation.group_formation_blocks() {
147                buffer.write_u32(block.block_id)?;
148
149                match block.block {
150                    Block::ContainerAbsolute(ref b) => {
151                        buffer.write_u32(0)?;
152                        buffer.write_f32(b.block_priority)?;
153                        buffer.write_u32(b.entity_arrangement.into())?;
154                        buffer.write_f32(b.inter_entity_spacing)?;
155                        buffer.write_f32(b.crescent_y_offset)?;
156                        buffer.write_f32(b.position_x)?;
157                        buffer.write_f32(b.position_y)?;
158                        buffer.write_i32(b.minimum_entity_threshold)?;
159                        buffer.write_i32(b.maximum_entity_threshold)?;
160
161                        buffer.write_u32(b.entity_preferences.len() as u32)?;
162                        for ep in b.entity_preferences() {
163                            buffer.write_f32(ep.priority)?;
164                            if let Entity::V2(data) = &ep.entity {
165                                buffer.write_u32((*data).into())?;
166                            }
167                            buffer.write_u32(ep.entity_weight.into())?;
168                        }
169                    },
170
171                    Block::ContainerRelative(ref b) => {
172                        buffer.write_u32(1)?;
173                        buffer.write_f32(b.block_priority)?;
174                        buffer.write_u32(b.relative_block_id)?;
175                        buffer.write_u32(b.entity_arrangement.into())?;
176                        buffer.write_f32(b.inter_entity_spacing)?;
177                        buffer.write_f32(b.crescent_y_offset)?;
178                        buffer.write_f32(b.position_x)?;
179                        buffer.write_f32(b.position_y)?;
180                        buffer.write_i32(b.minimum_entity_threshold)?;
181                        buffer.write_i32(b.maximum_entity_threshold)?;
182
183                        buffer.write_u32(b.entity_preferences.len() as u32)?;
184                        for ep in b.entity_preferences() {
185                            buffer.write_f32(ep.priority)?;
186                            if let Entity::V2(data) = &ep.entity {
187                                buffer.write_u32((*data).into())?;
188                            }
189                            buffer.write_u32(ep.entity_weight.into())?;
190                        }
191                    },
192
193                    Block::Spanning(ref b) => {
194                        buffer.write_u32(3)?;
195                        buffer.write_u32(b.spanned_block_ids.len() as u32)?;
196                        for id in b.spanned_block_ids() {
197                            buffer.write_u32(*id)?;
198                        }
199                    },
200                }
201            }
202        }
203
204        Ok(())
205    }
206}