Skip to main content

banished_game/town/
orders.rs

1//! Giving citizens their orders: workers of a building, queued actions and the think hook.
2
3use super::*;
4
5impl Sim<'_, '_> {
6    /// Each citizen's worker state.
7    pub fn workers(&self) -> Vec<Worker> {
8        self.states
9            .iter()
10            .zip(self.adult)
11            .map(|(s, &adult)| Worker {
12                adult,
13                profession: s.profession,
14                workplace: s.workplace,
15                home: s.home,
16            })
17            .collect()
18    }
19
20    /// Set each citizen's worker state.
21    pub fn set_workers(&mut self, workers: &[Worker]) {
22        for (s, w) in self.states.iter_mut().zip(workers) {
23            s.profession = w.profession;
24            s.workplace = w.workplace;
25        }
26    }
27
28    /// `FUN_1400ca8d0` on a citizen: abort everything; aborted CompleteTasks of `current` go
29    /// straight to its fail slot, the others to the manager's queue.
30    pub(crate) fn clear_citizen(&mut self, c: usize, mut current: Option<&mut Work>) {
31        let groups = self.groups;
32        let Some(group) = groups.get(c).copied().flatten() else {
33            return;
34        };
35        let ch = &mut self.characters[c];
36        let mut stack = std::mem::take(&mut ch.stack);
37        stack.clear(ch, group, self.storages);
38        let outbox = std::mem::take(&mut stack.outbox);
39        ch.stack = stack;
40        for m in outbox {
41            let e = JobEvent {
42                work: m.a,
43                citizen: c,
44                param: m.b,
45                complete: m.message == 0,
46            };
47            match current.as_deref_mut() {
48                Some(w) if w.id == e.work => self.fail(w, c, e.param),
49                _ => self.events.push(e),
50            }
51        }
52    }
53
54    pub(crate) fn push(&mut self, c: usize, action: Action) {
55        let groups = self.groups;
56        let Some(group) = groups.get(c).copied().flatten() else {
57            return;
58        };
59        let ch = &mut self.characters[c];
60        let mut stack = std::mem::take(&mut ch.stack);
61        stack.push(ch, group, action);
62        ch.stack = stack;
63    }
64
65    pub(crate) fn on_empty_think(&mut self, c: usize) {
66        self.characters[c]
67            .stack
68            .set_on_empty(vec![Action::SendMessage(Message {
69                component: Component::CitizenAi,
70                message: 0,
71                entity: None,
72                a: 0,
73                b: 0,
74            })]);
75    }
76
77    /// `FUN_1400cebf0`: PerformWork, slower without a tool when it uses one.
78    pub(crate) fn perform(
79        &self,
80        c: usize,
81        facing: f32,
82        anim: usize,
83        secs: f32,
84        tool: bool,
85    ) -> Action {
86        let mut duration = ticks(secs);
87        if tool && self.states[c].tool_uses < 1 {
88            duration = ticks(seconds(duration) * self.rules.no_tool_factor);
89        }
90        Action::PerformWork {
91            facing,
92            anim,
93            duration,
94            elapsed: 0,
95            consume: tool,
96        }
97    }
98
99    /// The writes every successful assignment makes on the citizen.
100    pub(crate) fn took_job(&mut self, c: usize, work: &Work) {
101        let s = &mut self.states[c];
102        s.health_events |= 4;
103        s.job = work.id;
104        s.supply_activity = 0;
105        if work.profession == s.profession && work.id >= 0 {
106            s.flags |= 0x20000;
107        }
108    }
109}