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}