banished_game/people/
cemetery.rs1use crate::scheduler::ticks;
12use crate::terrain::CellType;
13use crate::town::Sim;
14
15const PERIOD: f32 = 300.0;
17
18#[derive(Debug, Clone, Copy, PartialEq)]
22pub struct CemeteryTemplate {
23 pub tombstone: usize,
25 pub life: f32,
27 pub range: f32,
29}
30
31impl Sim<'_, '_> {
32 fn lay_graves(&self, e: usize) -> Vec<i32> {
36 let n = self.size as i32;
37 let (x0, y0) = self.placed[e].cell;
38 let (w, h) = self.placed[e].footprint;
39 let yaw = self.placed[e].yaw as i32;
40 let along = yaw == 0 || yaw == 180;
41 let gate = self.sites.get(&e).and_then(|s| s.parts.first().copied());
42 let off = gate.map_or(-10, |g| {
43 let (gx, gy) = self.placed[g].cell;
44 if along {
45 gx - x0
46 } else {
47 gy - y0
48 }
49 });
50 let (x1, y1, w2, h2) = (x0 + 1, y0 + 1, w - 2, h - 2);
51 let mut graves = Vec::new();
52 if along {
53 for row in (0..h2).step_by(2) {
54 for col in 0..w2 {
55 if col != off + 1 && col != off {
56 graves.push((row + y1) * n + col + x1);
57 }
58 }
59 }
60 } else {
61 for col in (0..w2).step_by(2) {
62 for row in 0..h2 {
63 if row != off + 1 && row != off {
64 graves.push((row + y1) * n + col + x1);
65 }
66 }
67 }
68 }
69 graves
70 }
71
72 pub(crate) fn cemetery_enter2(&mut self, e: usize) {
75 self.cemeteries.push(e);
76 if self.sites.get(&e).is_some_and(|s| s.graves.is_empty()) {
77 let graves = self.lay_graves(e);
78 self.sites.get_mut(&e).unwrap().graves = graves;
79 }
80 for cell in self.sites[&e].graves.clone() {
81 let i = cell as usize;
82 if self.cells.objects[i].is_none_or(|o| !self.tombstones.contains_key(&o)) {
83 self.cells.set_type(i, CellType(2));
84 self.cells.objects[i] = None;
85 }
86 }
87 }
88
89 pub fn place_burials(&mut self) {
94 for (cemetery, cell) in std::mem::take(self.burials) {
95 let Some(t) = self
96 .sites
97 .get(&cemetery)
98 .and_then(|s| self.site_templates[s.template].cemetery)
99 else {
100 continue;
101 };
102 let i = cell as usize;
103 self.cells.set_type(i, CellType(2));
104 self.cells.objects[i] = None;
105 let n = self.size as i32;
106 let template = &self.templates[t.tombstone];
107 let (variant, mesh) = template.model.as_ref().map_or((0, 0), |m| {
108 (m.variant.max(0) as usize, m.mesh.max(0) as usize)
109 });
110 let mut yaw = self.placed[cemetery].yaw as i32;
111 while yaw < 0 {
112 yaw += 360;
113 }
114 let id = self.placed.len();
115 self.placed.push(crate::nature::seeding::Placed {
116 template: t.tombstone,
117 bucket: template.bucket,
118 cell: (cell % n, cell / n),
119 footprint: (1, 1),
120 position: self.ground_at(cell),
121 yaw: yaw as f32,
122 variant,
123 mesh,
124 growth: 0.0,
125 growth_state: None,
126 spawn_state: None,
127 alive: true,
128 removal_requested: false,
129 animation: None,
130 scale: [1.0; 4],
131 });
132 let life = (self.rng.rand_float() * t.range + t.life) * PERIOD;
133 self.tombstones.insert(id, ticks(life));
134 self.stamp(id);
135 *self.models_dirty = true;
136 }
137 }
138}
139
140pub fn tombstone_visit(
145 tombstones: &mut std::collections::BTreeMap<usize, i64>,
146 cells: &mut crate::nature::seeding::Cells,
147 placed: &mut [crate::nature::seeding::Placed],
148 id: usize,
149 elapsed: i64,
150) -> bool {
151 let Some(left) = tombstones.get_mut(&id) else {
152 return false;
153 };
154 *left -= elapsed;
155 if 0 < *left {
156 return false;
157 }
158 tombstones.remove(&id);
159 let p = &mut placed[id];
160 p.alive = false;
161 let i = (p.cell.1 as usize) * cells.size + p.cell.0 as usize;
162 if cells.objects[i] == Some(id) {
163 cells.objects[i] = None;
164 cells.set_type(i, CellType(2));
165 }
166 true
167}