Skip to main content

banished_game/work/
control.rs

1//! The buildings' window buttons (ControlUI): a ControlUIConfig names a component (its type id) and
2//! a control; the button shows the component's slot (bit 0 enabled, bit 1 on) and a click calls its
3//! slot. See docs/BUILDING-WINDOWS.md.
4//!
5//! Original: `FUN_140060310`, `FUN_1400601d0`, `FUN_140060150`.
6// +0x24; +0x20; +0x68; +0x70
7
8use crate::town::Sim;
9use crate::work::construction::{run, Callbacks};
10use crate::work::jobs::Jobs;
11
12/// The components with controls, by type id (`CRC32` of the UTF-16 class name).
13pub mod kind {
14    /// A crop field.
15    pub const CROP_FIELD: u32 = 0xa3cc_d302;
16    /// An orchard.
17    pub const ORCHARD: u32 = 0xa981_9b71;
18    /// A pasture.
19    pub const PASTURE: u32 = 0x66ae_21ad;
20    /// A trading post.
21    pub const TRADE: u32 = 0x9292_c700;
22    /// A school, chapel or doctor.
23    pub const ATTENDANCE: u32 = 0x5146_364d;
24    /// A forester's lodge.
25    pub const FORESTER: u32 = 0xb18e_acda;
26    /// ResourceProduceComponent and the classes that keep its slots.
27    pub const CONSUME_PRODUCE: u32 = 0x1935_bdbb;
28    /// A fishing dock.
29    pub const FISHING: u32 = 0x9d9a_f271;
30    /// A hunter's lodge.
31    pub const HUNT: u32 = 0xacc2_7fa4;
32    /// A market.
33    pub const MARKET: u32 = 0x4c8f_7637;
34    /// A gatherer's shelter or a herbalist.
35    pub const HERBALIST: u32 = 0xca1a_33a3;
36}
37
38impl Sim<'_, '_> {
39    // +0x70
40    /// Slot of the `kind` component of `e`, control `index`.
41    pub fn control(&mut self, jobs: &mut Jobs, e: usize, kind: u32, index: i32) {
42        match kind {
43            kind::CROP_FIELD => self.field_action(e, index),
44            kind::ORCHARD => self.orchard_action(e, index),
45            // `FUN_14012cf30`: only when the control is available.
46            kind::PASTURE => {
47                if self.pasture_query(e, index) & 1 != 0 {
48                    self.pasture_action(jobs, e, index);
49                }
50            }
51            kind::TRADE => self.toggle_trade_work(jobs, e),
52            // `FUN_1400447e0`: the workplace on or off; switched off, everyone leaves
53            // (`FUN_1400448c0`).
54            kind::ATTENDANCE => {
55                let on = !self.workforce.workplaces.get(&e).is_some_and(|w| w.enabled);
56                self.enable_workplace(e, on);
57                if !on {
58                    self.evict(e);
59                }
60            }
61            kind::FORESTER => self.forester_toggle(jobs, e, index),
62            kind::CONSUME_PRODUCE | kind::FISHING | kind::HUNT | kind::MARKET | kind::HERBALIST => {
63                self.produce_toggle(jobs, e)
64            }
65            _ => {}
66        }
67    }
68
69    /// `FUN_140130a70`: the machine's message 0 (`FUN_1401302c0` in 0xd: go idle;
70    /// `FUN_140130180` in 0xe: produce again unless switched off, `+0x48`), then a run.
71    pub(crate) fn produce_toggle(&mut self, jobs: &mut Jobs, e: usize) {
72        let Some(site) = self.sites.get(&e) else {
73            return;
74        };
75        if site.machine.index < 0 {
76            run(self, jobs, e, false, false);
77        }
78        let site = &self.sites[&e];
79        let disabled = site.produce.as_ref().is_some_and(|p| p.disabled);
80        match site.machine.state {
81            0xd => self.machine(e).request(0xe),
82            0xe if !disabled => self.machine(e).request(0xd),
83            _ => {}
84        }
85        run(self, jobs, e, false, false);
86    }
87
88    /// `FUN_140124d60`: control 1 switches planting, 2 cutting; the first switched on or the
89    /// last switched off toggles production (`FUN_140130a70`).
90    fn forester_toggle(&mut self, jobs: &mut Jobs, e: usize, index: i32) {
91        let Some(f) = self.sites.get_mut(&e).and_then(|s| s.forester.as_mut()) else {
92            return;
93        };
94        let before = f.plant || f.cut;
95        match index {
96            1 => f.plant = !f.plant,
97            2 => f.cut = !f.cut,
98            _ => {}
99        }
100        let after = f.plant || f.cut;
101        if before != after {
102            self.produce_toggle(jobs, e);
103        }
104    }
105}