Skip to main content

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}