banished_formats/game/disasters.rs
1//! Fires and tornadoes.
2
3use super::*;
4
5// Template\Common.rsc:fire*.
6/// A `FireDescription`: how a fire burns, spreads and is put out.
7///
8/// Original: `FUN_14004a560`; fires that start by themselves, `FUN_1400ae760`.
9#[derive(Debug, Clone, Copy, Default, PartialEq)]
10pub struct FireDescription {
11 // +0x20
12 /// The burning time: `burn_months × 300 + burn` seconds.
13 pub burn: f32,
14 // +0x24
15 /// The burning time in months of 300 seconds (see `burn`).
16 pub burn_months: f32,
17 // +0x28
18 /// The particle slot of the flames.
19 pub particle: i32,
20 // +0x2c
21 /// The ambient emitter slot of the sound.
22 pub emitter: i32,
23 // +0x30
24 /// The time between attempts to spread, in months of 300 seconds. Each bucket of water
25 /// takes `interval × 300 / buckets` seconds off.
26 pub interval: f32,
27 // +0x34
28 /// The odds that a neighbour catches fire.
29 pub spread: f32,
30 // +0x38
31 /// The emergency radius, in cells: citizens in it come to put the fire out.
32 pub radius: i32,
33 // +0x3c
34 /// The buckets of water that put the fire out.
35 pub buckets: i32,
36 // +0x40
37 /// The most firefighters.
38 pub workers: i32,
39 // +0x44
40 /// How often a building catches fire by itself, in years (with `odds`).
41 pub years: f32,
42 // +0x48
43 /// The odds that a building catches fire by itself (with `years`).
44 pub odds: f32,
45}
46
47/// Read a [`FireDescription`] from the bytes of its resource.
48pub fn fire_description(data: &[u8]) -> Result<FireDescription> {
49 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
50 if h.type_id != type_id("FireDescription") {
51 return format_err(format!(
52 "expected FireDescription, found {:#010x}",
53 h.type_id
54 ));
55 }
56 r.block(|r, _| {
57 let mut d = FireDescription {
58 burn: r.f32()?,
59 burn_months: r.f32()?,
60 particle: r.i32()?,
61 emitter: r.i32()?,
62 interval: r.f32()?,
63 spread: r.f32()?,
64 ..Default::default()
65 };
66 d.buckets = r.i32()?;
67 d.years = r.f32()?;
68 d.odds = r.f32()?;
69 d.radius = r.i32()?;
70 d.workers = r.i32()?;
71 Ok(d)
72 })
73 })?;
74 Ok(value)
75}
76
77// +0x20; +0x24; +0x30; +0x28; +0x34
78/// `TornadoDescription`: speed, the ends' least distance, the reach of a wrecking pass, the time
79/// between passes, how far a pass throws its point.
80///
81/// Original: `FUN_1400596f0`.
82pub fn tornado_description(data: &[u8]) -> Result<(f32, i32, i32, i64, i32)> {
83 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
84 if h.type_id != type_id("TornadoDescription") {
85 return format_err(format!(
86 "expected TornadoDescription, found {:#010x}",
87 h.type_id
88 ));
89 }
90 r.block(|r, _| {
91 let speed = r.f32()?;
92 let distance = r.i32()?;
93 let reach = r.i32()?;
94 let interval = r.i64()?;
95 let throw = r.i32()?;
96 Ok((speed, distance, reach, interval, throw))
97 })
98 })?;
99 Ok(value)
100}