1use crate::dat::common::DeString;
2use crate::dat::unit::Task;
3use crate::dat::ResourceUsage;
4
5const RESOURCE_STORAGE_SIZE: usize = 3;
6const GRAPHIC_DISPLACEMENT_SIZE: usize = 3;
7const BUILDING_ANNEXES_SIZE: usize = 4;
8
9#[derive(Protocol, Debug, Clone, PartialEq)]
10pub struct Civilizations {
11 pub size: u16,
12 #[protocol(length_prefix(elements(size)))]
13 pub civilizations: Vec<Civilization>,
14}
15
16#[derive(Protocol, Debug, Clone, PartialEq)]
17pub struct Civilization {
18 pub player_type: u8,
19 pub name: DeString,
20 pub resource_size: u16,
21 pub tech_tree_id: i16,
22 pub team_bonus_id: u16,
23 #[protocol(length_prefix(elements(resource_size)))]
24 pub resources: Vec<f32>,
25 pub icon_set: u8,
26 pub units_pointers_size: u16,
27 #[protocol(length_prefix(elements(units_pointers_size)))]
28 pub unit_pointers: Vec<u32>,
29 #[protocol(length_prefix(pointers(unit_pointers)))]
30 pub units: Vec<Unit>,
31}
32
33#[derive(Protocol, Debug, Clone, PartialEq)]
34pub struct Unit {
35 pub unit_type: UnitType,
36 pub id: i16,
37 pub language_dll_name: i32,
38 pub language_dll_creation: i32,
39 pub class: i16,
40 pub standing_graphics: (i16, i16),
41 pub dying_graphic: i16,
42 pub undead_graphic: i16,
43 pub undead_mode: u8,
44 pub hit_points: i16,
45 pub line_of_sight: f32,
46 pub garrison_capacity: u8,
47 pub collision_box: (f32, f32, f32),
48 pub train_sound: i16,
49 pub damage_sound: i16,
50 pub dead_unit_id: i16,
51 pub blood_unit_id: i16,
52 pub sort_number: u8,
53 pub can_be_built_on: u8,
54 pub icon_id: i16,
55 pub hide_in_editor: u8,
56 pub old_portrait_pict: i16,
57 pub enabled: u8,
58 pub disabled: u8,
59 pub placement_side_terrain: (i16, i16),
60 pub placement_terrain: (i16, i16),
61 pub clearance_size: (f32, f32),
62 pub hill_mode: u8,
63 pub fog_visibility: u8,
64 pub terrain_restriction: i16,
65 pub fly_mode: u8,
66 pub resource_capacity: i16,
67 pub resource_decay: f32,
68 pub blast_defense_level: u8,
69 pub combat_level: u8,
70 pub interaction_mode: u8,
71 pub minimap_mode: u8,
72 pub interface_kind: u8,
73 pub multiple_attribute_mode: f32,
74 pub minimap_color: u8,
75 pub language_dll_help: i32,
76 pub language_dll_hot_key_text: i32,
77 pub hot_key: i32,
78 pub recyclable: u8,
79 pub enable_auto_gather: u8,
80 pub create_doppelganger_on_death: u8,
81 pub resource_gather_group: u8,
82 pub occlusion_mode: u8,
83 pub obstruction_type: u8,
84 pub obstruction_class: u8,
85 pub r#trait: u8,
86 pub civilization: u8,
87 pub nothing: i16,
88 pub selection_effect: u8,
89 pub editor_selection_colour: u8,
90 pub outline_box: (f32, f32, f32),
91 pub data: u32,
92 pub data_2: u32,
93 #[protocol(fixed_length(RESOURCE_STORAGE_SIZE))]
94 pub resources_storage: Vec<ResourceStorage>,
95 pub damage_graphic_size: u8,
96 #[protocol(length_prefix(elements(damage_graphic_size)))]
97 pub damage_graphics: Vec<DamageGraphic>,
98 pub selection_sound: i16,
99 pub dying_sound: i16,
100 pub wwise_train_sound_id: u32,
101 pub wwise_damage_sound_id: u32,
102 pub wwise_selection_sound_id: u32,
103 pub wwise_dying_sound_id: u32,
104 pub old_attack_reaction: u8,
105 pub convert_terrain: u8,
106 pub name: DeString,
107 pub copy_id: i16,
108 pub base_id: i16,
109 #[protocol(skip_if("unit_type < UnitType::Flag"))]
110 pub speed: Option<f32>,
111 #[protocol(skip_if("unit_type < UnitType::DeadFish"))]
112 pub dead_fish: Option<DeadFish>,
113 #[protocol(skip_if("unit_type < UnitType::Bird"))]
114 pub bird: Option<Bird>,
115 #[protocol(skip_if("unit_type < UnitType::Combatant"))]
116 pub type_50: Option<Combatant>,
117 #[protocol(skip_if("unit_type != UnitType::Projectile"))]
118 pub projectile: Option<Projectile>,
119 #[protocol(skip_if("unit_type < UnitType::Creatable"))]
120 pub creatable: Option<Creatable>,
121 #[protocol(skip_if("unit_type != UnitType::Building"))]
122 pub building: Option<Building>,
123}
124
125#[derive(Protocol, Debug, Clone, PartialEq)]
126pub struct ResourceStorage(i16, f32, u8);
127
128#[derive(Protocol, Debug, Clone, PartialEq)]
129pub struct DamageGraphic {
130 pub graphic_id: i16,
131 pub damage_percent: i16,
132 pub apply_mode: u8,
133}
134
135#[derive(Protocol, Debug, Clone, PartialEq, PartialOrd)]
136#[protocol(discriminant = "integer")]
137#[repr(u8)]
138pub enum UnitType {
139 EyeCandy = 10,
141
142 Trees = 15,
144
145 Flag = 20,
147
148 Dopl = 25,
150
151 DeadFish = 30,
154
155 Bird = 40,
157
158 Combatant = 50,
160
161 Projectile = 60,
163
164 Creatable = 70,
166
167 Building = 80,
169
170 AoeTrees = 90,
172}
173
174#[derive(Protocol, Debug, Clone, PartialEq)]
175pub struct DeadFish {
176 pub walking_graphic: i16,
177 pub running_graphic: i16,
178 pub rotation_speed: f32,
179 pub old_size_class: u8,
180 pub tracking_unit: i16,
181 pub tracking_unit_mode: u8,
182 pub tracking_unit_density: f32,
183 pub old_move_algorithm: u8,
184 pub turn_radius: f32,
185 pub turn_radius_speed: f32,
186 pub max_yaw_per_second_moving: f32,
187 pub stationary_yaw_revolution_time: f32,
188 pub max_yaw_per_second_stationary: f32,
189 pub min_collision_size_multiplier: f32,
190}
191
192#[derive(Protocol, Debug, Clone, PartialEq)]
193pub struct Bird {
194 pub default_task_id: i16,
195 pub search_radius: f32,
196 pub work_rate: f32,
197 pub drop_sites_size: (i16, i16, i16),
198 pub task_swap_group: u8,
199 pub attack_sound: i16,
200 pub move_sound: i16,
201 pub wwise_attack_sound_id: u32,
202 pub wwise_move_sound_id: u32,
203 pub run_pattern: u8,
204 pub task_list_size_count: i16,
205 #[protocol(length_prefix(elements(task_list_size_count)))]
206 pub task_list: Vec<Task>,
207}
208
209#[derive(Protocol, Debug, Clone, PartialEq)]
210pub struct Combatant {
211 pub base_armor: i16,
212 pub attack_count_size: i16,
213 #[protocol(length_prefix(elements(attack_count_size)))]
214 pub attacks: Vec<AttackOrArmor>,
215 pub armor_count_size: i16,
216 #[protocol(length_prefix(elements(armor_count_size)))]
217 pub armor: Vec<AttackOrArmor>,
218 pub defense_terrain_bonus: i16,
219 pub bonus_damage_resistance: f32,
220 pub max_range: f32,
221 pub blast_width: f32,
222 pub reload_time: f32,
223 pub projectile_unit_id: i16,
224 pub accuracy_percent: i16,
225 pub break_off_combat: u8,
226 pub frame_delay: i16,
227 #[protocol(fixed_length(GRAPHIC_DISPLACEMENT_SIZE))]
228 pub graphic_displacement: Vec<f32>,
229 pub blast_attack_level: u8,
230 pub min_range: f32,
231 pub accuracy_dispersion: f32,
232 pub attack_graphic: i16,
233 pub displayed_melee_armour: i16,
234 pub displayed_attack: i16,
235 pub displayed_range: f32,
236 pub displayed_reload_time: f32,
237}
238
239#[derive(Protocol, Debug, Clone, PartialEq)]
240pub struct Projectile {
241 pub projectile_type: u8,
242 pub smart_mode: u8,
243 pub hit_mode: u8,
244 pub vanish_mode: u8,
245 pub area_effect_specials: u8,
246 pub projectile_arc: f32,
247}
248
249#[derive(Protocol, Debug, Clone, PartialEq)]
250pub struct Creatable {
251 #[protocol(fixed_length(RESOURCE_STORAGE_SIZE))]
252 pub resources_costs: Vec<ResourceUsage>,
253 pub train_time: i16,
254 pub train_location_id: i16,
255 pub button_id: u8,
256 pub rear_attack_modifier: f32,
257 pub flank_attack_modifier: f32,
258 pub creatable_type: u8,
259 pub hero_mode: u8,
260 pub garrison_graphic: i32,
261 pub spawning_graphic: i16,
262 pub upgrade_graphic: i16,
263 pub hero_glow_graphic: i16,
264 pub max_charge: f32,
265 pub recharge_rate: f32,
266 pub charge_event: i16,
267 pub charge_type: i16,
268 pub total_projectiles: f32,
269 pub max_total_projectiles: u8,
270 pub projectile_spawning_area: (f32, f32, f32),
271 pub secondary_projectile_unit: i32,
272 pub special_graphic: i32,
273 pub special_ability: u8,
274 pub displayed_pierce_armour: i16,
275}
276
277#[derive(Protocol, Debug, Clone, PartialEq)]
278pub struct Building {
279 pub construction_graphic_id: i16,
280 pub snow_graphic_id: i16,
281 pub destruction_graphic_id: i16,
282 pub destruction_rubble_graphic_id: i16,
283 pub researching_graphic: i16,
284 pub research_completed_graphic: i16,
285 pub adjacent_mode: u8,
286 pub graphics_angle: i16,
287 pub disappears_when_built: u8,
288 pub stack_unit_id: i16,
289 pub foundation_terrain_id: i16,
290 pub old_overlay_id: i16,
291 pub tech_id: i16,
292 pub can_burn: u8,
293 #[protocol(fixed_length(BUILDING_ANNEXES_SIZE))]
294 pub building_annexes: Vec<Annexe>,
295 pub head_unit: i16,
296 pub transform_unit: i16,
297 pub transform_sound: i16,
298 pub construction_sound: i16,
299 pub wwise_transform_sound_id: u32,
300 pub wwise_construction_sound_id: u32,
301 pub garrison_type: u8,
302 pub garrison_heal_rate: f32,
303 pub garrison_repair_rate: f32,
304 pub pile_unit: i16,
305 #[protocol(fixed_length(6))]
306 pub looting_table: Vec<u8>,
307}
308
309#[derive(Protocol, Debug, Clone, PartialEq)]
310pub struct Annexe {
311 pub unit_id: i16,
312 pub misplacement: (f32, f32),
313}
314
315#[derive(Protocol, Debug, Clone, PartialEq)]
316pub struct AttackOrArmor {
317 pub class: i16,
318 pub amount: i16,
319}