Skip to main content

banished_game/
town.rs

1//! The simulation context jobs and construction run in: [`Sim`] implements the job manager's
2//! work slots ([`WorkHost`]) and the building state callbacks ([`Callbacks`]), over the
3//! citizens, the map, the storages and the construction state. See docs/JOBS.md.
4//!
5//! This file holds the context's state and a few free helpers; its methods are split by topic:
6//! - `geometry`: cells, ground heights, reachability and work points;
7//! - `orders`: a building's workers and the actions given to citizens;
8//! - `sites`: building sites and buildings, marking them on the map, destroying them;
9//! - `building`: carrying materials to a site and building it;
10//! - `clearing`: clearing an area before building;
11//! - `piles`: loose piles of goods on the ground;
12//! - `storage`: picking up goods, finding a storage, dropping off, emptying a storage;
13//! - `callbacks` and `work_host`: the two trait implementations.
14
15mod building;
16mod callbacks;
17mod clearing;
18mod geometry;
19mod orders;
20mod piles;
21mod sites;
22mod storage;
23mod work_host;
24
25use std::collections::{BTreeMap, BTreeSet};
26
27use banished_formats::types::AnimationGroup;
28
29use crate::behaviour::activities::{EntityView, StorageGeometry, TownView};
30use crate::behaviour::agents::{CitizenRulesAi, CitizenState};
31use crate::behaviour::character::{Action, Character, Component, Message, MoveTo};
32use crate::nature::seeding::{Cells, Placed, Template};
33use crate::pathfind::nearest_neighbour;
34use crate::pathfind::WALKABLE;
35use crate::random::Random;
36use crate::scheduler::{seconds, ticks};
37use crate::sectors::SectorGraph;
38use crate::terrain::HeightGrid;
39use crate::work::construction::{
40    run, BuildWork, Callback, Callbacks, ClearWork, Gather, Machine, PickupWork, Pile, Site,
41    SiteTemplate,
42};
43use crate::work::jobs::{JobEvent, Jobs, Work, WorkHost, WorkKind, NESTED};
44use crate::work::professions::{Professions, Worker, Workforce};
45use crate::work::stock::{find_material_storage, RawMaterial, Storage, StorageSite};
46use crate::world::placement::{PlacementRules, Rect};
47
48/// `0x2001`: the construction works' registration mask (category 13).
49pub const CONSTRUCTION_MASK: u32 = 0x2001;
50
51/// [`Sim::haul`]'s endpoints and flags.
52#[derive(Default)]
53pub(crate) struct Haul {
54    pub target_entity: usize,
55    pub target_storage: usize,
56    pub target: [f32; 3],
57    pub source_storage: usize,
58    pub source_entity: usize,
59    pub source: [f32; 3],
60    pub material: usize,
61    pub amount: i32,
62    pub param: i32,
63    pub partial: bool,
64    pub complete_on_pickup: bool,
65    /// `param_14`: the hauler uses a tool (its work steps spend one, its loaded walk is
66    /// clip 5).
67    pub tool: bool,
68    /// Several materials at once (when `material` is null): the delivery drops everything
69    /// carried.
70    ///
71    /// Original: `FUN_1400cf700` adds each one to the pickup.
72    pub items: Vec<(usize, i32)>,
73}
74
75/// The world the citizens' update borrows (everything but the citizens themselves).
76pub struct Env<'a, 't> {
77    /// Wild animals (hunting).
78    pub wildlife: &'a mut crate::nature::wildlife::Wildlife,
79    /// The gameplay map.
80    pub cells: &'a mut Cells,
81    /// The placed objects.
82    pub placed: &'a mut Vec<Placed>,
83    /// The object templates.
84    pub templates: &'a [Template],
85    /// The ground's heights.
86    pub terrain: &'a HeightGrid<'t>,
87    /// The raw materials.
88    pub materials: &'a [RawMaterial],
89    /// The town's storages.
90    pub storages: &'a mut [Storage],
91    /// The storage sites.
92    pub sites: &'a [StorageSite],
93    /// The game's random numbers.
94    pub rng: &'a mut Random,
95    /// The construction manager.
96    pub construction: &'a mut crate::work::construction::Construction,
97    /// The stock manager's `(count, limit)` per slot from the last recount.
98    pub stock: [(i32, i32); 21],
99    // Game +0x130 → +0x18
100    /// The environment's temperature.
101    pub temperature: f32,
102    /// This iteration's bucket visits (`EntityScheduler::take_visits`): placed entities by
103    /// index, citizens from `scheduler::EXTRA`, each with the time since its last visit.
104    pub visits: &'a [(usize, i64)],
105}
106
107/// Everything a work slot or a state callback touches.
108pub struct Sim<'s, 't> {
109    /// The citizens' characters.
110    pub characters: &'s mut [Character],
111    /// The citizens' states.
112    pub states: &'s mut [CitizenState],
113    /// Each citizen's animation group.
114    pub groups: &'s [Option<&'s AnimationGroup>],
115    /// Adult and not at school (the citizens assignment counts).
116    pub adult: &'s [bool],
117    /// The citizens' AI rules.
118    pub rules: CitizenRulesAi,
119    /// The map's size in cells.
120    pub size: usize,
121    /// The gameplay map.
122    pub cells: &'s mut Cells,
123    /// The walkable region of each cell.
124    pub regions: &'s [u16],
125    /// The sector graph.
126    pub sectors: &'s mut SectorGraph,
127    /// The ground's heights.
128    pub terrain: &'s HeightGrid<'t>,
129    /// The placed objects.
130    pub placed: &'s mut Vec<Placed>,
131    /// The object templates.
132    pub templates: &'s [Template],
133    /// A view of each entity.
134    pub entities: &'s [EntityView],
135    /// The town's storages.
136    pub storages: &'s mut [Storage],
137    /// The storage sites.
138    pub storage_sites: &'s [StorageSite],
139    /// The raw materials.
140    pub materials: &'s [RawMaterial],
141    /// The game's random numbers.
142    pub rng: &'s mut Random,
143    /// The stock manager's `(count, limit)` per slot from the last recount.
144    pub stock: [(i32, i32); 21],
145    /// The environment's temperature.
146    pub temperature: f32,
147    /// The professions.
148    pub professions: &'s Professions,
149    /// The workers assigned to each workplace.
150    pub workforce: &'s mut Workforce,
151    /// The building templates.
152    pub site_templates: &'s [SiteTemplate],
153    /// The buildings, by entity.
154    pub sites: &'s mut BTreeMap<usize, Site>,
155    /// The homes, by entity.
156    pub homes: &'s mut BTreeMap<usize, crate::people::life::Home>,
157    /// Who attends each service building, by entity.
158    pub attendance: &'s mut BTreeMap<usize, crate::work::construction::Attendance>,
159    /// The service buildings that people attend.
160    pub attendance_list: &'s mut Vec<usize>,
161    /// The herbalists and hospitals.
162    pub healers: &'s mut Vec<usize>,
163    /// The buildings that raise happiness nearby.
164    pub happiness: &'s mut Vec<usize>,
165    /// The calendar's seconds into the year.
166    pub calendar: f32,
167    /// The current year.
168    pub year: u32,
169    /// The orchards' fruit, by entity.
170    pub fruits: &'s mut BTreeMap<usize, crate::production::orchard::Fruit>,
171    /// The animals (livestock and their pastures).
172    pub wildlife: &'s mut crate::nature::wildlife::Wildlife,
173    /// Whether removing a resource leaves its piles behind, by resource.
174    pub keep_piles: &'s mut BTreeMap<usize, bool>,
175    /// Building events for the event log: `(kind, argument, entity)`.
176    pub site_events: &'s mut Vec<(i32, i32, usize)>,
177    /// Storages that opened or closed: `(entity, opened)`.
178    pub storage_changes: &'s mut Vec<(usize, bool)>,
179    /// The buildings to build again after they were destroyed.
180    pub rebuilds: &'s mut Vec<crate::work::destroy::Rebuild>,
181    /// The town's water sources (wells and shore points).
182    pub water: &'s mut crate::disasters::fire::Water,
183    // Game +0xd0
184    /// The game's debug flags (all four disaster bits are set when disasters are off).
185    pub game_flags: u32,
186    // +0x10
187    /// The sky's state is precipitation (environment = 0).
188    pub precipitation: bool,
189    // +0xa8
190    /// The town's population.
191    pub population: i32,
192    // +0x1a8; +0x1a0
193    /// The visitors' timer and the time of the last visitor.
194    pub visitors: &'s mut (f32, i64),
195    // +0xe8
196    /// The planned road cells, each with its road-building work.
197    pub pending_roads: &'s mut BTreeMap<i32, i32>,
198    /// The pending changes to the ground.
199    pub terraform_requests: &'s mut Vec<crate::world::terraform::Terraform>,
200    /// The rectangles to flatten: `[x0, y0, x1, y1]`.
201    pub flatten_requests: &'s mut Vec<[i32; 4]>,
202    /// The tornadoes, by entity.
203    pub tornadoes: &'s mut BTreeMap<usize, crate::disasters::tornado::Tornado>,
204    /// The citizens a tornado killed.
205    pub tornado_kills: &'s mut Vec<usize>,
206    /// The production trackers, by entity.
207    pub trackers: &'s mut BTreeMap<usize, crate::work::tracker::Tracker>,
208    /// The ground decals of building sites, by entity.
209    pub decals: &'s mut BTreeMap<usize, crate::work::construction::Decal>,
210    /// The counts of goods made and used.
211    pub counters: &'s mut crate::work::tracker::StockCounters,
212    // +0x30; +0x1ac
213    /// The town's trading posts.
214    pub trading_posts: &'s mut Vec<usize>,
215    /// The total value traded.
216    pub trade_value: &'s mut i32,
217    // +0x110; +0x120
218    /// The raw materials the town knows; `known` holds the crops, orchard trees and livestock it
219    /// knows.
220    ///
221    /// Original: `FUN_140097330`, `FUN_140096ef0`.
222    pub known_materials: &'s mut Vec<usize>,
223    /// The crops, orchard trees and livestock the town knows.
224    pub known: &'s mut Vec<usize>,
225    /// The goods traders can bring.
226    pub trade_goods: &'s [crate::commerce::trade::TradeGood],
227    /// The river's path.
228    pub river: &'s [[f32; 2]],
229    /// The path manager (the trader boats' water paths).
230    pub pathfinder: &'s mut crate::pathfind::Pathfinder,
231    /// The citizens' name databases (the merchants' names).
232    pub names: Option<&'s (
233        banished_formats::names::NameDatabase,
234        banished_formats::names::NameDatabase,
235    )>,
236    /// The scheduled update's elapsed time (ticks) for the site callbacks.
237    pub site_dt: i64,
238    /// The cemeteries.
239    pub cemeteries: &'s mut Vec<usize>,
240    /// The tombstones, with the time each one stays.
241    pub tombstones: &'s mut BTreeMap<usize, i64>,
242    /// The burials waiting: `(cemetery, cell)`.
243    pub burials: &'s mut Vec<(usize, i32)>,
244    /// The buildings that have a site record.
245    pub site_list: &'s mut Vec<usize>,
246    /// The job events from this update.
247    pub events: Vec<JobEvent>,
248    /// The piles, by entity.
249    pub piles: &'s mut BTreeMap<usize, Pile>,
250    /// The resources a work has claimed.
251    pub claimed: &'s mut std::collections::BTreeSet<usize>,
252    /// The piles made in this update.
253    pub new_piles: &'s mut Vec<usize>,
254    /// Set when a model changed and must be drawn again.
255    pub models_dirty: &'s mut bool,
256    /// Works a ClearArea try asked the manager to offer ([`WorkHost::take_offers`]).
257    pub offers: Vec<i32>,
258    /// Scratch for `Sim::seeder` (planting removes nothing and plays no sounds).
259    pub removed: Vec<usize>,
260    /// The animation events to play: `(entity, effect)`.
261    pub animation_events: Vec<(usize, String)>,
262    /// Whether the offers get a second try (as an auto-pickup's do).
263    ///
264    /// Original: `FUN_1400fdaf0(.., 1)`.
265    pub offers_again: bool,
266    /// A ConsumeProduce try waiting on its pile offers ([`WorkHost::resume`]).
267    pub(crate) produce_resume: Option<crate::work::produce::ProduceResume>,
268    /// A pasture try waiting on its product pickups' offers ([`Sim::pasture_try`]).
269    pub(crate) pasture_stage: bool,
270}
271
272/// A pile's work category mask from its material's flags.
273///
274/// Original: `FUN_14012e950`.
275pub fn pile_mask(flags: u32) -> u32 {
276    for (bit, mask) in [
277        (5, 2),
278        (6, 4),
279        (10, 0x10),
280        (12, 0x40),
281        (11, 0x20),
282        (13, 0x100),
283        (16, 0x200),
284        (9, 8),
285    ] {
286        if flags >> bit & 1 != 0 {
287            return mask;
288        }
289    }
290    if flags >> 14 & 1 != 0 {
291        0x80
292    } else {
293        1
294    }
295}
296
297/// `FUN_14011ce30`'s clearing mask bit for a resource's raw material: logs `0x400`, iron
298/// `0x1000`, stone `0x800`, else 1.
299fn clear_mask(flags: u32) -> u32 {
300    if flags >> 10 & 1 != 0 {
301        0x400
302    } else if flags >> 12 & 1 != 0 {
303        0x1000
304    } else if flags >> 11 & 1 != 0 {
305        0x800
306    } else {
307        1
308    }
309}
310
311/// `MapComponent::IsAnimating` per placed entity.
312pub fn animating(placed: &[Placed], templates: &[Template]) -> Vec<bool> {
313    placed
314        .iter()
315        .map(|p| {
316            p.alive
317                && p.animation.as_ref().is_some_and(|pb| {
318                    templates[p.template]
319                        .animations
320                        .get(p.variant)
321                        .and_then(Option::as_ref)
322                        .and_then(|g| g.clips.get(pb.clip))
323                        .is_some_and(|clip| pb.is_animating(clip))
324                })
325        })
326        .collect()
327}
328
329/// The ground at a cell's centre, on the terrain only (bridge floors are skipped).
330///
331/// Original: `FUN_1400a48b0` with `param_4` 1.
332pub fn cell_ground(size: usize, terrain: &HeightGrid, cell: i32) -> [f32; 3] {
333    let n = size as i32;
334    let h = (n >> 1) as f32 - 0.5;
335    let (x, y) = ((cell % n) as f32 - h, (cell / n) as f32 - h);
336    let mut normal = [0.0; 3];
337    [x, y, terrain.ground(x, y, &mut normal)]
338}
339
340/// The ground at a cell's centre: on a bridge's floor where one covers the cell above the
341/// terrain, else on the terrain.
342///
343/// Original: `FUN_1400a48b0` with `param_4` 0, as nearly every caller passes.
344pub fn floor_ground(
345    floors: &crate::world::floor::Floors,
346    size: usize,
347    terrain: &HeightGrid,
348    cell: i32,
349) -> [f32; 3] {
350    let n = size as i32;
351    let h = (n >> 1) as f32 - 0.5;
352    let (x, y) = ((cell % n) as f32 - h, (cell / n) as f32 - h);
353    [x, y, floors.ground(size, terrain, x, y)]
354}
355
356/// The amount still to clear in an entity's area, over a grid of `n × n` cells that maps each
357/// cell to its object.
358///
359/// Original: `FUN_14011d800`.
360pub fn clear_remaining(objects: &[Option<usize>], n: i32, placed: &Placed, e: usize) -> i32 {
361    let (x, y) = placed.cell;
362    let (w, h) = placed.footprint;
363    let mut count = 0;
364    for cy in y..y + h {
365        for cx in x..x + w {
366            if objects[(cy * n + cx) as usize].is_some_and(|o| o != e) {
367                count += 1;
368            }
369        }
370    }
371    count
372}