banished_formats/weather.rs
1//! `Weather`: a precipitation effect description (`Environment/Rain.rsc`, `Environment/Snow.rsc`),
2//! referenced from the EnvironmentDescription's weather list.
3//!
4//! Original: `FUN_1400d9160`.
5
6use crate::crc::type_id;
7use crate::crs::{self, Reader};
8use crate::error::{format_err, Result};
9
10/// A weather effect: rain or snow particles and how they fall.
11#[derive(Debug, Clone)]
12pub struct Weather {
13 // +0x20
14 /// Particle material.
15 pub material: Option<String>,
16 // +0x28
17 /// Particle count.
18 pub count: i32,
19 // +0x2c; normalised by FUN_1400d9450.
20 /// The direction the particles fall in (the game normalises it).
21 pub direction: [f32; 3],
22 // +0x38, +0x3c
23 /// Particle speed base and random range.
24 pub speed: [f32; 2],
25 // +0x40
26 /// Not identified yet.
27 pub flag: bool,
28 // +0x44..+0x58; +0x48
29 /// is the particle volume's size.
30 pub floats_44: [f32; 6],
31 // +0x5c; geometry +0xc0
32 /// Seconds to fade the intensity (`geometry`) from 0 to 1.
33 ///
34 /// Original: `FUN_1400d8330`.
35 pub fade_time: f32,
36 // +0x60..+0x68
37 /// Not identified yet.
38 pub colors: [u32; 3],
39 // +0x6c..+0x7c
40 /// Not identified yet.
41 pub floats_6c: [f32; 5],
42}
43
44/// Read a [`Weather`] from the bytes of its resource.
45pub fn weather(data: &[u8]) -> Result<Weather> {
46 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
47 if h.type_id != type_id("Weather") {
48 return format_err(format!("expected Weather, found {:#010x}", h.type_id));
49 }
50 r.block(|r, _| {
51 Ok(Weather {
52 material: r.external_ref()?,
53 count: r.u32()? as i32,
54 direction: r.f32s()?,
55 speed: r.f32s()?,
56 flag: r.bool()?,
57 floats_44: r.f32s()?,
58 fade_time: r.f32()?,
59 colors: [r.u32()?, r.u32()?, r.u32()?],
60 floats_6c: r.f32s()?,
61 })
62 })
63 })?;
64 Ok(value)
65}