1use super::*;
4
5#[derive(Debug, Clone, PartialEq)]
9pub struct Disease {
10 pub table: Option<String>,
13 pub name: String,
15 pub spread_interval: f32,
20 pub spread_chance: f32,
25 pub spread_radius: f32,
28 pub weight: f32,
33 pub recovery: f32,
39}
40
41pub fn disease(data: &[u8]) -> Result<Disease> {
43 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
44 if h.type_id != type_id("Disease") {
45 return format_err(format!("expected Disease, found {:#010x}", h.type_id));
46 }
47 r.block(|r, _| {
48 Ok(Disease {
49 table: r.external_ref()?,
50 name: r.string()?,
51 spread_interval: r.f32()?,
52 spread_chance: r.f32()?,
53 spread_radius: r.f32()?,
54 weight: r.f32()?,
55 recovery: r.f32()?,
56 })
57 })
58 })?;
59 Ok(value)
60}
61
62pub fn attendance_description(data: &[u8]) -> Result<i32> {
67 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
68 if h.type_id != type_id("AttendanceDescription") {
69 return format_err(format!(
70 "expected AttendanceDescription, found {:#010x}",
71 h.type_id
72 ));
73 }
74 r.block(|r, _| r.i32())
75 })?;
76 Ok(value)
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
83pub struct HappinessDescription {
84 pub kind: i32,
88 pub needs_workers: bool,
91 pub needs_stock: bool,
94 pub mask: u32,
97 pub pad: i32,
100}
101
102pub fn happiness_description(data: &[u8]) -> Result<HappinessDescription> {
104 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
105 if h.type_id != type_id("HappinessDescription") {
106 return format_err(format!(
107 "expected HappinessDescription, found {:#010x}",
108 h.type_id
109 ));
110 }
111 r.block(|r, _| {
112 Ok(HappinessDescription {
113 kind: r.i32()?,
114 needs_workers: r.bool()?,
115 needs_stock: r.bool()?,
116 mask: r.u32()?,
117 pad: r.i32()?,
118 })
119 })
120 })?;
121 Ok(value)
122}
123
124#[derive(Debug, Clone, PartialEq, Eq)]
128pub struct PopulationDescription {
129 pub name: String,
132 pub cell: i32,
135 pub herd_block: i32,
138 pub habitat: u32,
141 pub forbidden: u32,
144 pub no_occupants: bool,
147 pub capacity: i32,
150 pub regrowth: i32,
153 pub value_44: i32,
156 pub refresh: bool,
159 pub herd: Option<String>,
162}
163
164pub fn population_description(data: &[u8]) -> Result<PopulationDescription> {
166 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
167 if h.type_id != type_id("PopulationDescription") {
168 return format_err(format!(
169 "expected PopulationDescription, found {:#010x}",
170 h.type_id
171 ));
172 }
173 r.block(|r, _| {
174 let cell = r.i32()?;
175 let herd_block = r.i32()?;
176 let habitat = r.u32()?;
177 let forbidden = r.u32()?;
178 let no_occupants = r.bool()?;
179 let capacity = r.i32()?;
180 let regrowth = r.i32()?;
181 let value_44 = r.i32()?;
182 let refresh = r.bool()?;
183 let herd = r.external_ref()?;
184 let name = r.string()?;
185 Ok(PopulationDescription {
186 name,
187 cell,
188 herd_block,
189 habitat,
190 forbidden,
191 no_occupants,
192 capacity,
193 regrowth,
194 value_44,
195 refresh,
196 herd,
197 })
198 })
199 })?;
200 Ok(value)
201}
202
203#[derive(Debug, Clone, Copy, Default, PartialEq)]
208pub struct DiseaseDescription {
209 pub months: (i32, i32),
212 pub odds: f32,
215 pub odds_same: f32,
218 pub check: f32,
221 pub kill: f32,
224 pub spread: f32,
227 pub duration: f32,
230 pub radius: i32,
233}
234
235pub fn disease_description(data: &[u8]) -> Result<DiseaseDescription> {
237 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
238 if h.type_id != type_id("DiseaseDescription") {
239 return format_err(format!(
240 "expected DiseaseDescription, found {:#010x}",
241 h.type_id
242 ));
243 }
244 r.block(|r, _| {
245 Ok(DiseaseDescription {
246 months: (r.i32()?, r.i32()?),
247 odds: r.f32()?,
248 odds_same: r.f32()?,
249 check: r.f32()?,
250 kill: r.f32()?,
251 spread: r.f32()?,
252 duration: r.f32()?,
253 radius: r.i32()?,
254 })
255 })
256 })?;
257 Ok(value)
258}
259
260pub fn cemetery_description(data: &[u8]) -> Result<Option<String>> {
265 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
266 if h.type_id != type_id("CemeteryDescription") {
267 return format_err(format!(
268 "expected CemeteryDescription, found {:#010x}",
269 h.type_id
270 ));
271 }
272 r.block(|r, _| r.external_ref())
273 })?;
274 Ok(value)
275}
276
277#[derive(Debug, Clone, Default, PartialEq)]
282pub struct ImmigrationDescription {
283 pub nomad: Option<String>,
286 pub population: i32,
289 pub required: Vec<Option<String>>,
292 pub share: (f32, f32),
295 pub wait: (f32, f32),
298 pub months: (i32, i32),
301 pub risk: f32,
304 pub risk_months: i32,
307}
308
309pub fn immigration_description(data: &[u8]) -> Result<ImmigrationDescription> {
311 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
312 if h.type_id != type_id("ImmigrationDescription") {
313 return format_err(format!(
314 "expected ImmigrationDescription, found {:#010x}",
315 h.type_id
316 ));
317 }
318 r.block(|r, _| {
319 let nomad = r.external_ref()?;
320 let population = r.i32()?;
321 let required = (0..r.count()?)
322 .map(|_| r.external_ref())
323 .collect::<Result<_>>()?;
324 let share = (r.f32()?, r.f32()?);
325 let wait = (r.f32()?, r.f32()?);
326 let months = (r.i32()?, r.i32()?);
327 let (risk, risk_months) = (r.f32()?, r.i32()?);
328 Ok(ImmigrationDescription {
329 nomad,
330 population,
331 required,
332 share,
333 wait,
334 months,
335 risk,
336 risk_months,
337 })
338 })
339 })?;
340 Ok(value)
341}
342
343pub fn nomad_description(data: &[u8]) -> Result<(Option<String>, [Option<String>; 2])> {
349 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
350 if h.type_id != type_id("NomadDescription") {
351 return format_err(format!(
352 "expected NomadDescription, found {:#010x}",
353 h.type_id
354 ));
355 }
356 r.block(|r, _| {
357 let citizen = r.external_ref()?;
358 let men = r.external_ref()?;
359 let women = r.external_ref()?;
360 Ok((citizen, [men, women]))
361 })
362 })?;
363 Ok(value)
364}
365
366pub fn tombstone_description(data: &[u8]) -> Result<(f32, f32)> {
371 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
372 if h.type_id != type_id("TombstoneDescription") {
373 return format_err(format!(
374 "expected TombstoneDescription, found {:#010x}",
375 h.type_id
376 ));
377 }
378 r.block(|r, _| Ok((r.f32()?, r.f32()?)))
379 })?;
380 Ok(value)
381}
382
383#[derive(Debug, Clone)]
389pub struct CitizenDescription {
390 pub fields: std::collections::BTreeMap<u32, Scalar>,
392 pub list: Vec<Option<String>>,
397 pub refs: [Option<String>; 3],
400}
401
402#[derive(Debug, Clone, Copy, PartialEq)]
404pub enum Scalar {
405 F32(f32),
407 I32(i32),
409}
410
411pub fn citizen_description(data: &[u8]) -> Result<CitizenDescription> {
413 let (_, value) = crs::parse(data, |r: &mut Reader, h| {
414 if h.type_id != type_id("CitizenDescription") {
415 return format_err(format!(
416 "expected CitizenDescription, found {:#010x}",
417 h.type_id
418 ));
419 }
420 r.block(|r, _| {
421 use Scalar::*;
422 let mut fields = std::collections::BTreeMap::new();
423 let mut f = |r: &mut Reader, o: u32| -> Result<()> {
424 fields.insert(o, F32(r.f32()?));
425 Ok(())
426 };
427 for o in [
428 0x44, 0x6c, 0x70, 0x74, 0x78, 0x7c, 0x80, 0x84, 0x88, 0x8c, 0x90, 0x38, 0x3c, 0x40,
429 0xc0, 0xd8, 0xdc, 0xe0, 0xe4, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c, 0x60, 0xc4, 0xd4,
430 0xc8, 0xcc, 0xd0, 0xe8, 0xec, 0xf0, 0xf4,
431 ] {
432 f(r, o)?;
433 }
434 fields.insert(0x110, I32(r.i32()?));
435 let list = (0..r.count()?)
436 .map(|_| r.external_ref())
437 .collect::<Result<_>>()?;
438 fields.insert(0x114, F32(r.f32()?));
439 fields.insert(0x118, I32(r.i32()?));
440 for o in [0x120, 0x11c, 0x128, 0x124, 0x130, 0xa4] {
441 fields.insert(o, F32(r.f32()?));
442 }
443 fields.insert(0xa8, I32(r.i32()?));
444 fields.insert(0xac, I32(r.i32()?));
445 fields.insert(0xa0, F32(r.f32()?));
446 fields.insert(0xb0, I32(r.i32()?));
447 fields.insert(0xb4, F32(r.f32()?));
448 fields.insert(0xb8, F32(r.f32()?));
449 fields.insert(0xbc, I32(r.i32()?));
450 let refs = [r.external_ref()?, r.external_ref()?, r.external_ref()?];
451 fields.insert(0x64, F32(r.f32()?));
452 fields.insert(0x68, F32(r.f32()?));
453 for o in [0xf8, 0xfc, 0x100, 0x104, 0x108] {
454 fields.insert(o, I32(r.i32()?));
455 }
456 fields.insert(0x10c, F32(r.f32()?));
457 Ok(CitizenDescription { fields, list, refs })
458 })
459 })?;
460 Ok(value)
461}
462
463impl CitizenDescription {
464 pub fn f(&self, offset: u32) -> f32 {
466 match self.fields.get(&offset) {
467 Some(Scalar::F32(v)) => *v,
468 Some(Scalar::I32(v)) => *v as f32,
469 None => 0.0,
470 }
471 }
472 pub fn i(&self, offset: u32) -> i32 {
474 match self.fields.get(&offset) {
475 Some(Scalar::I32(v)) => *v,
476 Some(Scalar::F32(v)) => *v as i32,
477 None => 0,
478 }
479 }
480 pub fn adult_age(&self) -> f32 {
483 self.f(0x44)
484 }
485 pub fn start_age(&self) -> (f32, f32) {
490 (self.f(0x50), self.f(0x54))
491 }
492 pub fn lifespan(&self) -> (f32, f32) {
497 (self.f(0x38), self.f(0x3c))
498 }
499}