1use super::*;
2use crate::{
3 Land,
4 site2::gen::wall_staircase,
5 util::{CARDINALS, DIAGONALS, NEIGHBORS, RandomField, sampler::Sampler},
6};
7use common::{generation::EntityInfo, terrain::SpriteKind};
8use rand::prelude::*;
9use std::{f32::consts::TAU, sync::Arc};
10use vek::*;
11
12pub struct CastleData {
13 plot_base: i32,
14 center: Vec2<i32>,
15 side_bldg_pos_1: Vec2<i32>,
16 side_bldg_pos_2: Vec2<i32>,
17 side_bldg_positions: Vec<Vec2<i32>>,
18 tower_positions: Vec<Vec2<i32>>,
19}
20
21pub struct VampireCastle {
22 bounds: Aabr<i32>,
23 pub(crate) alt: i32,
24 pub(crate) castle_data: CastleData,
25}
26impl VampireCastle {
27 pub fn generate(land: &Land, _rng: &mut impl Rng, site: &Site, tile_aabr: Aabr<i32>) -> Self {
28 let bounds = Aabr {
29 min: site.tile_wpos(tile_aabr.min),
30 max: site.tile_wpos(tile_aabr.max),
31 };
32 let center = bounds.center();
33 let plot_base = land.get_alt_approx(center) as i32;
34 let castle_length = 24;
35 let castle_width = 18;
36 let tower_base = plot_base + 1;
37 let mut tower_positions = vec![];
38 let mut side_bldg_positions = vec![];
39 let towers = 12.0;
40 let tower_radius_raw = 105;
41 let tower_phi = TAU / towers;
42 let side_bldg_var = (RandomField::new(0).get(center.with_z(plot_base)) % 2) as i32;
43 let side_bldg_pos_1 = Vec2::new(
44 center.x,
45 center.y - (2 * (castle_length + 4)) + side_bldg_var * (4 * (castle_length + 4)),
46 );
47 let side_bldg_pos_2 = Vec2::new(
48 center.x,
49 center.y + (2 * (castle_length + 4)) - side_bldg_var * (4 * (castle_length + 4)),
50 );
51 side_bldg_positions.push(side_bldg_pos_1);
52 side_bldg_positions.push(side_bldg_pos_2);
53
54 for dir in DIAGONALS {
56 let tower_pos = Vec2::new(
57 center.x + dir.x * (castle_length + 10),
58 center.y + dir.y * (castle_width + 10),
59 );
60 tower_positions.push(tower_pos);
61 }
62 for n in 1..=towers as i32 {
64 let tower_pos_var = RandomField::new(0).get((center + n).with_z(tower_base)) % 10;
65 let tower_radius = tower_radius_raw + tower_pos_var as i32;
66 let tower_pos = Vec2::new(
67 center.x + (tower_radius as f32 * ((n as f32 * tower_phi).cos())) as i32,
68 center.y + (tower_radius as f32 * ((n as f32 * tower_phi).sin())) as i32,
69 );
70
71 if RandomField::new(0).get((center + n).with_z(tower_base)) % 8 < 3 {
72 tower_positions.push(tower_pos)
73 } else {
74 side_bldg_positions.push(tower_pos);
75 }
76 }
77 let castle_data = CastleData {
78 plot_base,
79 center,
80 side_bldg_pos_1,
81 side_bldg_pos_2,
82 side_bldg_positions,
83 tower_positions,
84 };
85
86 Self {
87 bounds,
88 alt: land.get_alt_approx(site.tile_center_wpos((tile_aabr.max - tile_aabr.min) / 2))
89 as i32,
90 castle_data,
91 }
92 }
93
94 pub fn spawn_rules(&self, wpos: Vec2<i32>) -> SpawnRules {
95 SpawnRules {
96 waypoints: false,
97 trees: wpos.distance_squared(self.bounds.center()) > (75_i32).pow(2),
98 ..SpawnRules::default()
99 }
100 }
101}
102
103impl Structure for VampireCastle {
104 #[cfg(feature = "use-dyn-lib")]
105 const UPDATE_FN: &'static [u8] = b"render_vampire_castle\0";
106
107 #[cfg_attr(feature = "be-dyn-lib", export_name = "render_vampire_castle")]
108 fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
109 let mut thread_rng = thread_rng();
110 let brick = Fill::Brick(BlockKind::Rock, Rgb::new(80, 75, 85), 24);
111 let roof_color = Fill::Block(Block::new(BlockKind::GlowingRock, Rgb::new(30, 37, 55)));
112 let wood = Fill::Brick(BlockKind::Rock, Rgb::new(71, 33, 11), 12);
113 let chain = Fill::Block(Block::air(SpriteKind::MetalChain));
114 let window_ver = Fill::Block(Block::air(SpriteKind::WitchWindow));
115 let window_ver2 = Fill::Block(Block::air(SpriteKind::WitchWindow));
116 let key_door = Fill::Block(Block::air(SpriteKind::VampireKeyDoor));
117 let key_hole = Fill::Block(Block::air(SpriteKind::VampireKeyhole));
118 let onewaydoor = Fill::Block(Block::air(SpriteKind::OneWayWall).with_ori(2).unwrap());
119 let candles = Fill::Sampling(Arc::new(|wpos| {
120 Some(match (RandomField::new(0).get(wpos)) % 4 {
121 0 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
122 _ => Block::air(SpriteKind::Candle),
123 })
124 }));
125 let candles_lite = Fill::Sampling(Arc::new(|wpos| {
126 Some(match (RandomField::new(0).get(wpos)) % 30 {
127 0 => Block::air(SpriteKind::Candle),
128 _ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
129 })
130 }));
131 let center = self.castle_data.center;
133 let plot_base = self.castle_data.plot_base;
134 let side_bldg_pos_1 = self.castle_data.side_bldg_pos_1;
135 let side_bldg_pos_2 = self.castle_data.side_bldg_pos_2;
136 let side_bldg_positions = &self.castle_data.side_bldg_positions;
137 let tower_positions = &self.castle_data.tower_positions;
138
139 let castle_base = plot_base + 1;
140 let castle_length = 24;
141 let castle_width = 18;
142 let castle_height = castle_length;
143 let entry_length = 12;
145 let entry_width = 9;
146 let entry_height = entry_length;
147 let entry_base = castle_base - 2;
148 let tower_base = plot_base + 1;
150 let tower_width = 16;
151 let tower_height_raw = 70;
152 let roof_width = tower_width + 2;
153 let roof_height = 3 * (tower_width / 2);
154 let top_height = 20;
155 let side_bldg_length = 12;
157 let side_bldg_width = 9;
158 let side_bldg_height = 12;
159 let side_bldg_roof_height_raw = 32;
160 let side_bldg_base_raw = castle_base;
161 let side_bldg_var = (RandomField::new(0).get(center.with_z(plot_base)) % 2) as i32;
162 let side_bldg_stairs_pos = side_bldg_pos_1;
163 let mut bat_positions = vec![];
164 let mut harlequin_positions = vec![];
165 let mut random_npc_positions = vec![];
166 let entry_pos = Vec2::new(center.x - castle_length - 20, center.y);
168 let entry_pillar_pos = Vec2::new(center.x - castle_length - 24, center.y);
169 painter
170 .aabb(Aabb {
171 min: Vec2::new(
172 entry_pos.x - entry_length - 10,
173 entry_pos.y - entry_width - 10,
174 )
175 .with_z(entry_base + (entry_height / 2) + (2 * entry_height)),
176 max: Vec2::new(
177 entry_pos.x + entry_length + 10,
178 entry_pos.y + entry_width + 10,
179 )
180 .with_z(entry_base + (entry_height / 2) + (3 * entry_height)),
181 })
182 .fill(brick.clone());
183 painter
184 .aabb(Aabb {
185 min: Vec2::new(
186 entry_pos.x - entry_length - 9,
187 entry_pos.y - entry_width - 9,
188 )
189 .with_z(entry_base + (entry_height / 2) + (2 * entry_height)),
190 max: Vec2::new(
191 entry_pos.x + entry_length + 9,
192 entry_pos.y + entry_width + 9,
193 )
194 .with_z(entry_base + (entry_height / 2) + (3 * entry_height)),
195 })
196 .fill(roof_color.clone());
197 painter
198 .aabb(Aabb {
199 min: Vec2::new(
200 entry_pos.x - entry_length - 5,
201 entry_pos.y - entry_width - 5,
202 )
203 .with_z(entry_base + (entry_height / 2) + (2 * entry_height) - 3),
204 max: Vec2::new(
205 entry_pos.x + entry_length + 5,
206 entry_pos.y + entry_width + 5,
207 )
208 .with_z(entry_base + (entry_height / 2) + (2 * entry_height)),
209 })
210 .fill(brick.clone());
211 let entry_decor_limiter = painter.aabb(Aabb {
213 min: Vec2::new(
214 entry_pos.x - entry_length - 9,
215 entry_pos.y - entry_width - 9,
216 )
217 .with_z(entry_base + (entry_height / 2) + (2 * entry_height) - 1),
218 max: Vec2::new(
219 entry_pos.x + entry_length + 9,
220 entry_pos.y + entry_width + 9,
221 )
222 .with_z(entry_base + (entry_height / 2) + (2 * entry_height)),
223 });
224 let entry_decor_var = RandomField::new(0).get(center.with_z(tower_base)) % 12;
225 let entry_decors = 12.0 + entry_decor_var as f32;
226 let entry_phi = TAU / entry_decors;
227 let entry_decor_radius = entry_length + 10;
228 for d in 1..=entry_decors as i32 {
229 let entry_decors_pos = Vec2::new(
230 entry_pos.x + (entry_decor_radius as f32 * ((d as f32 * entry_phi).cos())) as i32,
231 entry_pos.y + (entry_decor_radius as f32 * ((d as f32 * entry_phi).sin())) as i32,
232 );
233 painter
234 .line(
235 entry_pos.with_z(entry_base + (entry_height / 2) + (2 * entry_height) - 1),
236 entry_decors_pos
237 .with_z(entry_base + (entry_height / 2) + (2 * entry_height) - 1),
238 1.0,
239 )
240 .intersect(entry_decor_limiter)
241 .fill(brick.clone());
242 }
243 for c in 0..2 {
245 let w_carve_pos = Vec2::new(
246 entry_pos.x,
247 entry_pos.y - (2 * entry_width) + (c * (4 * entry_width)),
248 );
249 let l_carve_pos = Vec2::new(
250 entry_pos.x - (4 * (entry_length / 2)) + (c * (8 * (entry_length / 2))),
251 entry_pos.y,
252 );
253 painter
254 .superquadric(
255 Aabb {
256 min: Vec2::new(
257 w_carve_pos.x - entry_length - 20,
258 w_carve_pos.y - entry_width - 10,
259 )
260 .with_z(entry_base + (entry_height / 2) + (2 * entry_height)),
261 max: Vec2::new(
262 w_carve_pos.x + entry_length + 20,
263 w_carve_pos.y + entry_width + 10,
264 )
265 .with_z(entry_base + (6 * entry_height)),
266 },
267 2.0,
268 )
269 .clear();
270
271 painter
272 .superquadric(
273 Aabb {
274 min: Vec2::new(
275 l_carve_pos.x - entry_length - 10,
276 l_carve_pos.y - entry_width - 20,
277 )
278 .with_z(entry_base + (entry_height / 2) + (2 * entry_height)),
279 max: Vec2::new(
280 l_carve_pos.x + entry_length + 10,
281 l_carve_pos.y + entry_width + 20,
282 )
283 .with_z(entry_base + (6 * entry_height)),
284 },
285 2.0,
286 )
287 .clear();
288 }
289 for p in 0..2 {
290 let entry_pyramid_pos = Vec2::new(
291 entry_pos.x - (entry_length - 4) + (p * (2 * (entry_length - 4))),
292 entry_pos.y,
293 );
294 painter
295 .pyramid(Aabb {
296 min: (entry_pyramid_pos - entry_length)
297 .with_z(entry_base + (entry_height / 2) + (2 * entry_height)),
298 max: (entry_pyramid_pos + entry_length).with_z(
299 entry_base
300 + (entry_height / 2)
301 + (2 * entry_height)
302 + (2 * entry_length)
303 + 1,
304 ),
305 })
306 .fill(roof_color.clone());
307 }
308
309 for dir in DIAGONALS {
311 let pillar_pos = entry_pillar_pos + dir * (entry_length - 4);
312 painter
313 .cylinder(Aabb {
314 min: (pillar_pos - 4).with_z(entry_base - 2),
315 max: (pillar_pos + 4)
316 .with_z(entry_base + (entry_height / 2) + (2 * entry_height) - 2),
317 })
318 .fill(brick.clone());
319 }
320
321 painter
323 .aabb(Aabb {
324 min: Vec2::new(center.x - castle_length - 10, center.y - castle_width - 10)
325 .with_z(castle_base + (castle_height / 2) + (2 * castle_height)),
326 max: Vec2::new(center.x + castle_length + 10, center.y + castle_width + 10)
327 .with_z(castle_base + (castle_height / 2) + (3 * castle_height)),
328 })
329 .fill(brick.clone());
330 painter
331 .aabb(Aabb {
332 min: Vec2::new(center.x - castle_length - 9, center.y - castle_width - 9)
333 .with_z(castle_base + (castle_height / 2) + (2 * castle_height)),
334 max: Vec2::new(center.x + castle_length + 9, center.y + castle_width + 9)
335 .with_z(castle_base + (castle_height / 2) + (3 * castle_height)),
336 })
337 .fill(roof_color.clone());
338 for c in 0..2 {
340 let w_carve_pos = Vec2::new(
341 center.x,
342 center.y - (2 * castle_width) + (c * (4 * castle_width)),
343 );
344 let l_carve_pos = Vec2::new(
345 center.x - (4 * (castle_length / 2)) + (c * (8 * (castle_length / 2))),
346 center.y,
347 );
348 painter
349 .superquadric(
350 Aabb {
351 min: Vec2::new(
352 w_carve_pos.x - castle_length - 40,
353 w_carve_pos.y - castle_width - 20,
354 )
355 .with_z(castle_base + (castle_height / 2) + (2 * castle_height)),
356 max: Vec2::new(
357 w_carve_pos.x + castle_length + 40,
358 w_carve_pos.y + castle_width + 20,
359 )
360 .with_z(castle_base + (6 * castle_height)),
361 },
362 2.0,
363 )
364 .clear();
365
366 painter
367 .superquadric(
368 Aabb {
369 min: Vec2::new(
370 l_carve_pos.x - castle_length - 20,
371 l_carve_pos.y - castle_width - 40,
372 )
373 .with_z(castle_base + (castle_height / 2) + (2 * castle_height)),
374 max: Vec2::new(
375 l_carve_pos.x + castle_length + 20,
376 l_carve_pos.y + castle_width + 40,
377 )
378 .with_z(castle_base + (6 * castle_height)),
379 },
380 2.0,
381 )
382 .clear();
383 }
384 let tower_access = RandomField::new(0).get(center.with_z(plot_base)) % 4;
386 let harlequin_0 = (RandomField::new(0).get(center.with_z(tower_base)) % 4) as usize;
387 let harlequin_1 = (RandomField::new(0).get(center.with_z(tower_base + 1)) % 4) as usize;
388 for (t, tower_center) in tower_positions.iter().enumerate() {
389 let height_var = RandomField::new(0).get(tower_center.with_z(tower_base)) % 30;
390 let tower_height = tower_height_raw + height_var as i32;
391 let top_base = tower_base + tower_height;
392 let cone_height = 20;
393 let tower_radius = (tower_width - 6) as f32;
394 let access = t == tower_access as usize;
395 let tower_top_var = if access {
396 0
397 } else if t < 4 {
398 1
399 } else {
400 RandomField::new(0).get((tower_center).with_z(tower_base)) % 3
401 };
402 if t < 4 && access {
403 painter
405 .line(
406 (tower_center + ((center - tower_center) / 2))
407 .with_z(castle_base + (3 * castle_height) + 5),
408 (tower_center + ((center - tower_center) / 2))
409 .with_z(top_base + top_height - 1),
410 1.0,
411 )
412 .fill(chain.clone());
413 painter
414 .line(
415 tower_center.with_z(top_base + top_height),
416 (tower_center + ((center - tower_center) / 2))
417 .with_z(top_base + top_height),
418 1.0,
419 )
420 .fill(wood.clone());
421 };
422 painter
424 .cylinder(Aabb {
425 min: (tower_center - tower_width + 6).with_z(tower_base - castle_height - 30),
426 max: (tower_center + 1 + tower_width - 6).with_z(tower_base + tower_height),
427 })
428 .fill(brick.clone());
429 painter
431 .cylinder(Aabb {
432 min: (tower_center - tower_width + 1).with_z(top_base),
433 max: (tower_center + 1 + tower_width - 1).with_z(top_base + top_height),
434 })
435 .fill(brick.clone());
436
437 let carve_limiter = painter.aabb(Aabb {
439 min: (tower_center - (tower_width / 2) - 3).with_z(top_base),
440 max: (tower_center + 1 + (tower_width / 2) + 3).with_z(top_base + top_height),
441 });
442 for dir in CARDINALS {
443 let carve_pos = tower_center + dir * (tower_width + (tower_width / 4));
444 painter
445 .superquadric(
446 Aabb {
447 min: (carve_pos - tower_width + 3).with_z(top_base + 1),
448 max: (carve_pos + tower_width - 3).with_z(top_base + top_height - 1),
449 },
450 2.5,
451 )
452 .intersect(carve_limiter)
453 .clear()
454 }
455 let decor_var = RandomField::new(0).get(tower_center.with_z(tower_base)) % 6;
457 let decor_radius = (tower_width / 3) * 2;
458 let decors = 4.0 + decor_var as f32;
459 let decor_phi = TAU / decors;
460 for n in 1..=decors as i32 {
461 let pos = Vec2::new(
462 tower_center.x + (decor_radius as f32 * ((n as f32 * decor_phi).cos())) as i32,
463 tower_center.y + (decor_radius as f32 * ((n as f32 * decor_phi).sin())) as i32,
464 );
465 painter
466 .cubic_bezier(
467 pos.with_z(tower_base + (tower_height / 2) + (tower_height / 6)),
468 (pos - ((tower_center - pos) / 4))
469 .with_z(tower_base + (tower_height / 2) + (tower_height / 3)),
470 (pos - ((tower_center - pos) / 2)).with_z(
471 tower_base
472 + (tower_height / 2)
473 + (tower_height / 3)
474 + (tower_height / 6),
475 ),
476 pos.with_z(top_base + 1),
477 1.5,
478 )
479 .fill(brick.clone());
480 }
481 painter
483 .cylinder(Aabb {
484 min: (tower_center - (3 * (tower_width / 2)) + 11).with_z(top_base - 5),
485 max: (tower_center + 1 + (3 * (tower_width / 2)) - 11).with_z(top_base - 4),
486 })
487 .fill(brick.clone());
488 painter
489 .cylinder(Aabb {
490 min: (tower_center - (3 * (tower_width / 2)) + 10).with_z(top_base - 4),
491 max: (tower_center + 1 + (3 * (tower_width / 2)) - 10).with_z(top_base - 2),
492 })
493 .fill(brick.clone());
494 painter
495 .cylinder(Aabb {
496 min: (tower_center - (3 * (tower_width / 2)) + 8).with_z(top_base - 2),
497 max: (tower_center + 1 + (3 * (tower_width / 2)) - 8).with_z(top_base),
498 })
499 .fill(brick.clone());
500 painter
501 .cylinder(Aabb {
502 min: (tower_center - (3 * (tower_width / 2)) + 6).with_z(top_base),
503 max: (tower_center + 1 + (3 * (tower_width / 2)) - 6).with_z(top_base + 2),
504 })
505 .fill(brick.clone());
506 painter
508 .cylinder(Aabb {
509 min: (tower_center - (3 * (tower_width / 2)) + 5).with_z(top_base + top_height),
510 max: (tower_center + 1 + (3 * (tower_width / 2)) - 5)
511 .with_z(top_base + top_height + 2),
512 })
513 .fill(brick.clone());
514 painter
516 .cylinder(Aabb {
517 min: (tower_center - tower_width + 2).with_z(top_base),
518 max: (tower_center + 1 + tower_width - 2).with_z(top_base + top_height),
519 })
520 .fill(brick.clone());
521 for h in 0..2 {
523 painter
525 .line(
526 Vec2::new(tower_center.x - tower_width, tower_center.y)
527 .with_z(top_base + (top_height / 2) - 3 + (4 * h)),
528 Vec2::new(tower_center.x + 1 + tower_width, tower_center.y)
529 .with_z(top_base + (top_height / 2) - 3 + (4 * h)),
530 2.5,
531 )
532 .clear();
533 painter
534 .line(
535 Vec2::new(tower_center.x, tower_center.y - tower_width)
536 .with_z(top_base + (top_height / 2) - 3 + (4 * h)),
537 Vec2::new(tower_center.x, tower_center.y + 1 + tower_width)
538 .with_z(top_base + (top_height / 2) - 3 + (4 * h)),
539 2.5,
540 )
541 .clear();
542 }
543 let top_window_limiter = painter.aabb(Aabb {
545 min: (tower_center - tower_width + 2).with_z(top_base + 1),
546 max: (tower_center + 1 + tower_width - 2).with_z(top_base + tower_height - 1),
547 });
548 for h in 0..2 {
549 painter
550 .line(
551 Vec2::new(tower_center.x - tower_width, tower_center.y)
552 .with_z(top_base + (top_height / 2) - 3 + (4 * h)),
553 Vec2::new(tower_center.x + 1 + tower_width, tower_center.y)
554 .with_z(top_base + (top_height / 2) - 3 + (4 * h)),
555 2.5,
556 )
557 .intersect(top_window_limiter)
558 .fill(window_ver2.clone());
559 painter
560 .line(
561 Vec2::new(tower_center.x, tower_center.y - tower_width)
562 .with_z(top_base + (top_height / 2) - 3 + (4 * h)),
563 Vec2::new(tower_center.x, tower_center.y + 1 + tower_width)
564 .with_z(top_base + (top_height / 2) - 3 + (4 * h)),
565 2.5,
566 )
567 .intersect(top_window_limiter)
568 .fill(window_ver.clone());
569 }
570 painter
572 .aabb(Aabb {
573 min: Vec2::new(tower_center.x - 1, tower_center.y - tower_width)
574 .with_z(top_base + (top_height / 2) - 5),
575 max: Vec2::new(tower_center.x + 2, tower_center.y + tower_width + 1)
576 .with_z(top_base + (top_height / 2) - 4),
577 })
578 .fill(wood.clone());
579
580 painter
581 .aabb(Aabb {
582 min: Vec2::new(tower_center.x - tower_width, tower_center.y - 1)
583 .with_z(top_base + (top_height / 2) - 5),
584 max: Vec2::new(tower_center.x + tower_width + 1, tower_center.y + 2)
585 .with_z(top_base + (top_height / 2) - 4),
586 })
587 .fill(wood.clone());
588 painter
590 .cylinder(Aabb {
591 min: (tower_center - tower_width + 3).with_z(top_base + 1),
592 max: (tower_center + 1 + tower_width - 3).with_z(top_base + top_height),
593 })
594 .clear();
595 painter
597 .cylinder(Aabb {
598 min: (tower_center - tower_width + 3).with_z(top_base + 1),
599 max: (tower_center + 1 + tower_width - 3).with_z(top_base + 2),
600 })
601 .fill(candles_lite.clone());
602 painter
603 .cylinder(Aabb {
604 min: (tower_center - tower_width + 3).with_z(top_base + top_height - 1),
605 max: (tower_center + 1 + tower_width - 3).with_z(top_base + top_height),
606 })
607 .fill(wood.clone());
608 painter
609 .cylinder(Aabb {
610 min: (tower_center - tower_width + 8).with_z(top_base + 1),
611 max: (tower_center + 1 + tower_width - 8).with_z(top_base + top_height),
612 })
613 .clear();
614 let tower_window_limiter = painter.aabb(Aabb {
616 min: (tower_center + 1 - tower_radius as i32).with_z(tower_base),
617 max: (tower_center + tower_radius as i32).with_z(tower_base + tower_height + 1),
618 });
619 let decor_var = RandomField::new(0).get(tower_center.with_z(tower_base)) % 10;
620 let decors = 10.0 + decor_var as f32;
621 let tower_decor_phi = TAU / decors;
622 let decor_radius = (tower_width / 2) + 4;
623 for h in 0..2 {
624 for n in 0..2 {
625 for d in 1..=decors as i32 {
627 let decor_pos = Vec2::new(
628 tower_center.x
629 + (decor_radius as f32 * ((d as f32 * tower_decor_phi).cos()))
630 as i32,
631 tower_center.y
632 + (decor_radius as f32 * ((d as f32 * tower_decor_phi).sin()))
633 as i32,
634 );
635 painter
636 .line(
637 tower_center.with_z(
638 tower_base + (tower_height / 3) + ((tower_height / 3) * n),
639 ),
640 decor_pos.with_z(
641 tower_base + (tower_height / 3) + ((tower_height / 3) * n),
642 ),
643 1.0,
644 )
645 .fill(brick.clone());
646 }
647 painter
649 .line(
650 Vec2::new(tower_center.x - tower_width + 5, tower_center.y).with_z(
651 tower_base
652 + (tower_height / 4)
653 + (4 * h)
654 + ((tower_height / 4) * n),
655 ),
656 Vec2::new(tower_center.x + 1 + tower_width - 5, tower_center.y).with_z(
657 tower_base
658 + (tower_height / 4)
659 + (4 * h)
660 + ((tower_height / 4) * n),
661 ),
662 2.5,
663 )
664 .clear();
665 painter
666 .line(
667 Vec2::new(tower_center.x, tower_center.y - tower_width + 5).with_z(
668 tower_base
669 + (tower_height / 4)
670 + (4 * h)
671 + ((tower_height / 4) * n),
672 ),
673 Vec2::new(tower_center.x, tower_center.y + 1 + tower_width - 5).with_z(
674 tower_base
675 + (tower_height / 4)
676 + (4 * h)
677 + ((tower_height / 4) * n),
678 ),
679 2.5,
680 )
681 .clear();
682 painter
684 .line(
685 Vec2::new(tower_center.x - tower_width + 4, tower_center.y).with_z(
686 tower_base
687 + (tower_height / 4)
688 + (4 * h)
689 + ((tower_height / 4) * n),
690 ),
691 Vec2::new(tower_center.x + 1 + tower_width - 4, tower_center.y).with_z(
692 tower_base
693 + (tower_height / 4)
694 + (4 * h)
695 + ((tower_height / 4) * n),
696 ),
697 2.5,
698 )
699 .intersect(tower_window_limiter)
700 .fill(window_ver2.clone());
701 painter
702 .line(
703 Vec2::new(tower_center.x, tower_center.y - tower_width + 4).with_z(
704 tower_base
705 + (tower_height / 4)
706 + (4 * h)
707 + ((tower_height / 4) * n),
708 ),
709 Vec2::new(tower_center.x, tower_center.y + 1 + tower_width - 4).with_z(
710 tower_base
711 + (tower_height / 4)
712 + (4 * h)
713 + ((tower_height / 4) * n),
714 ),
715 2.5,
716 )
717 .intersect(tower_window_limiter)
718 .fill(window_ver.clone());
719 painter
721 .aabb(Aabb {
722 min: Vec2::new(
723 tower_center.x - 1,
724 tower_center.y - (tower_width / 2) - 3,
725 )
726 .with_z(tower_base + (tower_height / 4) - 3 + ((tower_height / 4) * n)),
727 max: Vec2::new(
728 tower_center.x + 2,
729 tower_center.y + (tower_width / 2) + 4,
730 )
731 .with_z(tower_base + (tower_height / 4) - 2 + ((tower_height / 4) * n)),
732 })
733 .fill(wood.clone());
734
735 painter
736 .aabb(Aabb {
737 min: Vec2::new(
738 tower_center.x - (tower_width / 2) - 3,
739 tower_center.y - 1,
740 )
741 .with_z(tower_base + (tower_height / 4) - 3 + ((tower_height / 4) * n)),
742 max: Vec2::new(
743 tower_center.x + (tower_width / 2) + 4,
744 tower_center.y + 2,
745 )
746 .with_z(tower_base + (tower_height / 4) - 2 + ((tower_height / 4) * n)),
747 })
748 .fill(wood.clone());
749 }
750 }
751 painter
753 .cylinder(Aabb {
754 min: (tower_center - roof_width).with_z(top_base + top_height),
755 max: (tower_center + 1 + roof_width)
756 .with_z(top_base + top_height + roof_height),
757 })
758 .fill(brick.clone());
759 let tower_roof_filling = painter.cylinder(Aabb {
760 min: (tower_center - roof_width + 1).with_z(top_base + top_height),
761 max: (tower_center + 1 + roof_width - 1)
762 .with_z(top_base + top_height + roof_height),
763 });
764 if tower_top_var > 0 {
765 tower_roof_filling.fill(roof_color.clone());
766 } else {
767 tower_roof_filling.clear();
768 }
769 for dir in NEIGHBORS {
771 let carve_pos = tower_center + dir * roof_width;
772 let carve_z_offset = roof_height / 20;
773
774 painter
775 .superquadric(
776 Aabb {
777 min: (carve_pos - 3 * (tower_width / 4))
778 .with_z(top_base + top_height + carve_z_offset),
779 max: (carve_pos + 3 * (tower_width / 4))
780 .with_z(top_base + top_height + (2 * roof_height) + carve_z_offset),
781 },
782 2.5,
783 )
784 .clear();
785 }
786 if tower_top_var > 0 {
787 painter
789 .cone(Aabb {
790 min: (tower_center - (roof_width / 3) - 2).with_z(top_base + top_height),
791 max: (tower_center + (roof_width / 3) + 2)
792 .with_z(top_base + cone_height + (4 * roof_height) - 4),
793 })
794 .fill(roof_color.clone());
795
796 for dir in DIAGONALS {
797 let cone_center = tower_center + dir * 6;
798 let cone_var = RandomField::new(0).get(cone_center.with_z(tower_base)) % 60;
799 painter
800 .cone(Aabb {
801 min: (cone_center - 4).with_z(top_base + top_height + 2),
802 max: (cone_center + 4)
803 .with_z(top_base + top_height + 30 + cone_var as i32),
804 })
805 .fill(roof_color.clone());
806 }
807 } else {
808 painter
810 .cylinder(Aabb {
811 min: (tower_center - (3 * (tower_width / 2)) + 6)
812 .with_z(top_base + top_height),
813 max: (tower_center + 1 + (3 * (tower_width / 2)) - 6)
814 .with_z(top_base + top_height + 2),
815 })
816 .fill(brick.clone());
817 }
818
819 let tower_radius = (tower_width - 7) as f32;
821 let add_on = if tower_top_var > 0 { 0 } else { top_height + 1 };
822 painter
823 .cylinder(Aabb {
824 min: (tower_center + 1 - tower_radius as i32)
825 .with_z(tower_base - castle_height + 1),
826 max: (tower_center + tower_radius as i32)
827 .with_z(tower_base + tower_height + 1 + add_on),
828 })
829 .clear();
830 if t > 3 {
832 for dir in DIAGONALS {
833 let entry_pos = tower_center + (dir * ((tower_width / 3) + 3));
834 painter
835 .line(
836 tower_center.with_z(tower_base + (top_height / 3) + 5),
837 entry_pos.with_z(tower_base + (top_height / 3)),
838 4.5,
839 )
840 .clear();
841 painter
842 .cylinder(Aabb {
843 min: (tower_center - tower_width + 7)
844 .with_z(tower_base - castle_height + 1),
845 max: (tower_center + 1 + tower_width - 7)
846 .with_z(tower_base + (top_height / 3)),
847 })
848 .fill(brick.clone());
849 }
850 painter
852 .cylinder(Aabb {
853 min: (tower_center - tower_width + 8).with_z(tower_base + (top_height / 3)),
854 max: (tower_center + 1 + tower_width - 8)
855 .with_z(tower_base + (top_height / 3) + 1),
856 })
857 .fill(candles_lite.clone());
858 }
859 if tower_top_var < 1 {
860 let ground_floor = if t < 4 {
862 -castle_height - 1
863 } else {
864 top_height / 3
865 };
866 painter
867 .cylinder(Aabb {
868 min: (tower_center - 2).with_z(tower_base + ground_floor),
869 max: (tower_center + 3).with_z(tower_base + tower_height + 1 + add_on),
870 })
871 .clear();
872 if t < 4 && access {
873 painter
875 .cylinder(Aabb {
876 min: (tower_center + 1 - tower_radius as i32)
877 .with_z(tower_base + tower_height + add_on),
878 max: (tower_center + tower_radius as i32)
879 .with_z(tower_base + tower_height + 1 + add_on),
880 })
881 .fill(key_door.clone());
882 painter
883 .cylinder(Aabb {
884 min: (tower_center).with_z(tower_base + tower_height + add_on),
885 max: (tower_center + 1).with_z(tower_base + tower_height + 1 + add_on),
886 })
887 .fill(key_hole.clone());
888 painter
889 .cylinder(Aabb {
890 min: (tower_center + 1 - tower_radius as i32)
891 .with_z(tower_base + tower_height + 1 + add_on),
892 max: (tower_center + tower_radius as i32)
893 .with_z(tower_base + tower_height + 2 + add_on),
894 })
895 .fill(onewaydoor.clone());
896 painter
897 .cylinder(Aabb {
898 min: (tower_center + 2 - tower_radius as i32)
899 .with_z(tower_base + tower_height + 1 + add_on),
900 max: (tower_center - 1 + tower_radius as i32)
901 .with_z(tower_base + tower_height + 2 + add_on),
902 })
903 .clear();
904 let top_bat_pos = tower_center.with_z(tower_base + tower_height + 2 + add_on);
905 bat_positions.push(top_bat_pos);
906 }
907 }
908 let bat_z = if t > 3 {
909 tower_base + (top_height / 3)
910 } else {
911 castle_base - castle_height + 1
912 };
913 let bat_pos_bottom = tower_center.with_z(bat_z);
914 bat_positions.push(bat_pos_bottom);
915 for p in 0..4 {
917 painter
918 .cylinder(Aabb {
919 min: (tower_center - (tower_width / 4) - 3)
920 .with_z(tower_base + (p * (tower_height / 3))),
921 max: (tower_center - (tower_width / 4) + 3)
922 .with_z(tower_base + (p * (tower_height / 3)) + 1),
923 })
924 .fill(roof_color.clone());
925 painter.sprite(
926 (tower_center - (tower_width / 4) + 1)
927 .with_z(tower_base + 1 + (p * (tower_height / 3))),
928 SpriteKind::Candle,
929 );
930 }
931 let chest_pos =
932 (tower_center + (tower_width / 2)).with_z(tower_base + tower_height + 1);
933 let rand_npc_pos =
934 (tower_center + (tower_width / 2) + 1).with_z(tower_base + tower_height + 1);
935 let chest_var = RandomField::new(0).get(chest_pos) % 2;
936 if chest_var > 0 {
937 painter.sprite(chest_pos, SpriteKind::DungeonChest3);
938 random_npc_positions.push(rand_npc_pos);
939 }
940 if t == harlequin_0 {
941 let harlequin_pos_0 =
942 (tower_center - (tower_width / 2)).with_z(tower_base + tower_height + 1);
943 harlequin_positions.push(harlequin_pos_0);
944 }
945 if t == harlequin_1 {
946 let harlequin_pos_1 =
947 (tower_center - (tower_width / 2) + 1).with_z(tower_base + tower_height + 1);
948 harlequin_positions.push(harlequin_pos_1);
949 }
950 }
951 let mut harlequin_2_positions = vec![];
952 for pos in side_bldg_positions.iter().skip(2) {
953 harlequin_2_positions.push(*pos)
954 }
955 for pos in tower_positions.iter().skip(4) {
956 harlequin_2_positions.push(*pos)
957 }
958 let harlequin_2 = (RandomField::new(0).get(center.with_z(tower_base))
959 % harlequin_2_positions.len() as u32) as usize;
960 let harlequin_pos_2 = harlequin_2_positions[harlequin_2].with_z(tower_base + 8);
961 harlequin_positions.push(harlequin_pos_2);
962 painter
964 .aabb(Aabb {
965 min: Vec2::new(center.x - castle_length - 3, center.y - castle_width - 3)
966 .with_z(castle_base),
967 max: Vec2::new(center.x + castle_length + 3, center.y + castle_width + 3)
968 .with_z(castle_base + (castle_height / 2)),
969 })
970 .fill(brick.clone());
971 painter
973 .aabb(Aabb {
974 min: Vec2::new(center.x - castle_length - 5, center.y - castle_width - 5)
975 .with_z(castle_base + (castle_height / 2)),
976 max: Vec2::new(center.x + castle_length + 5, center.y + castle_width + 5)
977 .with_z(castle_base + (castle_height / 2) + (2 * castle_height)),
978 })
979 .fill(brick.clone());
980 let castle_limiter = painter.aabb(Aabb {
982 min: Vec2::new(center.x - castle_length - 6, center.y - castle_width - 6)
983 .with_z(castle_base),
984 max: Vec2::new(center.x + castle_length + 6, center.y + castle_width + 6)
985 .with_z(castle_base + (castle_height / 2) + (2 * castle_height)),
986 });
987 let castle_window_limiter = painter.aabb(Aabb {
988 min: Vec2::new(center.x - castle_length - 4, center.y - castle_width - 4)
989 .with_z(castle_base + (castle_height / 2) + 1),
990 max: Vec2::new(center.x + castle_length + 4, center.y + castle_width + 4)
991 .with_z(castle_base + (castle_height / 2) + (2 * castle_height) - 1),
992 });
993 let castle_decor_var = RandomField::new(0).get(center.with_z(tower_base)) % 25;
995 let castle_decors = 25.0 + castle_decor_var as f32;
996 let castle_decor_phi = TAU / castle_decors;
997 let castle_decor_radius = castle_length + 10;
998 for d in 1..=castle_decors as i32 {
1000 let castle_decor_pos = Vec2::new(
1001 center.x
1002 + (castle_decor_radius as f32 * ((d as f32 * castle_decor_phi).cos())) as i32,
1003 center.y
1004 + (castle_decor_radius as f32 * ((d as f32 * castle_decor_phi).sin())) as i32,
1005 );
1006 for l in 0..2 {
1007 painter
1008 .line(
1009 center.with_z(
1010 castle_base + (castle_height / 2) + ((2 * l) * castle_height) - 1,
1011 ),
1012 castle_decor_pos.with_z(
1013 castle_base + (castle_height / 2) + ((2 * l) * castle_height) - 1,
1014 ),
1015 1.0,
1016 )
1017 .intersect(castle_limiter)
1018 .fill(brick.clone());
1019 painter
1020 .line(
1021 center.with_z(
1022 castle_base + 3 + castle_height + (l * ((castle_height / 2) + 5)),
1023 ),
1024 castle_decor_pos.with_z(
1025 castle_base + 3 + castle_height + (l * ((castle_height / 2) + 5)),
1026 ),
1027 1.0,
1028 )
1029 .intersect(castle_limiter)
1030 .fill(brick.clone());
1031 }
1032 }
1033 for h in 0..2 {
1035 for s in 1..=2 {
1036 for r in 0..=2 {
1037 painter
1039 .line(
1040 Vec2::new(
1041 center.x - castle_length - 5,
1042 center.y - (castle_width / 2) + (r * (castle_width / 2)),
1043 )
1044 .with_z(castle_base + (s * ((castle_height / 2) + 5)) + (4 * h)),
1045 Vec2::new(
1046 center.x + 1 + castle_length + 5,
1047 center.y - (castle_width / 2) + (r * (castle_width / 2)),
1048 )
1049 .with_z(castle_base + (s * ((castle_height / 2) + 5)) + (4 * h)),
1050 2.5,
1051 )
1052 .clear();
1053 painter
1054 .line(
1055 Vec2::new(
1056 center.x - (castle_length / 2) + (r * (castle_length / 2)),
1057 center.y - castle_width - 5,
1058 )
1059 .with_z(castle_base + (s * ((castle_height / 2) + 5)) + (4 * h)),
1060 Vec2::new(
1061 center.x - (castle_length / 2) + (r * (castle_length / 2)),
1062 center.y + 1 + castle_width + 5,
1063 )
1064 .with_z(castle_base + (s * ((castle_height / 2) + 5)) + (4 * h)),
1065 2.5,
1066 )
1067 .clear();
1068
1069 painter
1071 .aabb(Aabb {
1072 min: Vec2::new(
1073 center.x - 1 - (castle_length / 2) + (r * (castle_length / 2)),
1074 center.y - castle_width - 6,
1075 )
1076 .with_z(castle_base + (s * ((castle_height / 2) + 2)) + (3 * (s - 1))),
1077 max: Vec2::new(
1078 center.x + 2 - (castle_length / 2) + (r * (castle_length / 2)),
1079 center.y + castle_width + 6,
1080 )
1081 .with_z(
1082 castle_base + 1 + (s * ((castle_height / 2) + 2)) + (3 * (s - 1)),
1083 ),
1084 })
1085 .fill(wood.clone());
1086
1087 painter
1088 .aabb(Aabb {
1089 min: Vec2::new(
1090 center.x - castle_length - 6,
1091 center.y - 1 - (castle_width / 2) + (r * (castle_width / 2)),
1092 )
1093 .with_z(castle_base + (s * ((castle_height / 2) + 2)) + (3 * (s - 1))),
1094 max: Vec2::new(
1095 center.x + castle_length + 6,
1096 center.y + 2 - (castle_width / 2) + (r * (castle_width / 2)),
1097 )
1098 .with_z(
1099 castle_base + 1 + (s * ((castle_height / 2) + 2)) + (3 * (s - 1)),
1100 ),
1101 })
1102 .fill(wood.clone());
1103 painter
1105 .line(
1106 Vec2::new(
1107 center.x - castle_length - 5,
1108 center.y - (castle_width / 2) + (r * (castle_width / 2)),
1109 )
1110 .with_z(castle_base + (s * ((castle_height / 2) + 5)) + (4 * h)),
1111 Vec2::new(
1112 center.x + 1 + castle_length + 5,
1113 center.y - (castle_width / 2) + (r * (castle_width / 2)),
1114 )
1115 .with_z(castle_base + (s * ((castle_height / 2) + 5)) + (4 * h)),
1116 2.5,
1117 )
1118 .intersect(castle_window_limiter)
1119 .fill(window_ver2.clone());
1120 painter
1121 .line(
1122 Vec2::new(
1123 center.x - (castle_length / 2) + (r * (castle_length / 2)),
1124 center.y - castle_width - 5,
1125 )
1126 .with_z(castle_base + (s * ((castle_height / 2) + 5)) + (4 * h)),
1127 Vec2::new(
1128 center.x - (castle_length / 2) + (r * (castle_length / 2)),
1129 center.y + 1 + castle_width + 5,
1130 )
1131 .with_z(castle_base + (s * ((castle_height / 2) + 5)) + (4 * h)),
1132 2.5,
1133 )
1134 .intersect(castle_window_limiter)
1135 .fill(window_ver.clone());
1136 }
1137 }
1138 }
1139 painter
1141 .line(
1142 entry_pos.with_z(castle_base - 2),
1143 center.with_z(castle_base + castle_height - 5),
1144 5.0,
1145 )
1146 .fill(brick.clone());
1147 painter
1148 .line(
1149 entry_pos.with_z(castle_base),
1150 center.with_z(castle_base + castle_height - 3),
1151 5.0,
1152 )
1153 .clear();
1154 painter
1155 .aabb(Aabb {
1156 min: (entry_pos - 10).with_z(castle_base - 5),
1157 max: (entry_pos + 10).with_z(castle_base),
1158 })
1159 .fill(brick.clone());
1160 painter
1162 .horizontal_cylinder(
1163 Aabb {
1164 min: Vec2::new(center.x - castle_length - 3, center.y - 4)
1165 .with_z(entry_base + 6),
1166 max: Vec2::new(center.x - castle_length - 2, center.y + 5)
1167 .with_z(entry_base + 15),
1168 },
1169 Dir::NegX,
1170 )
1171 .fill(onewaydoor.clone());
1172 painter
1174 .aabb(Aabb {
1175 min: Vec2::new(center.x - castle_length - 2, center.y - castle_width - 2)
1176 .with_z(castle_base - castle_height),
1177 max: Vec2::new(center.x + castle_length + 2, center.y + castle_width + 2)
1178 .with_z(castle_base + (castle_height / 8)),
1179 })
1180 .fill(brick.clone());
1181 painter
1183 .line(
1184 center.with_z(castle_base - castle_height - 3),
1185 side_bldg_stairs_pos.with_z(side_bldg_base_raw),
1186 6.0,
1187 )
1188 .fill(brick.clone());
1189 painter
1190 .line(
1191 center.with_z(castle_base - castle_height - 3),
1192 side_bldg_stairs_pos.with_z(side_bldg_base_raw),
1193 5.0,
1194 )
1195 .clear();
1196 painter
1198 .aabb(Aabb {
1199 min: Vec2::new(center.x - castle_length - 1, center.y - castle_width - 1)
1200 .with_z(castle_base - castle_height + 1),
1201 max: Vec2::new(center.x + castle_length + 1, center.y + castle_width + 1)
1202 .with_z(castle_base + (castle_height / 8) - 1),
1203 })
1204 .clear();
1205
1206 random_npc_positions.push(center.with_z(castle_base - castle_height + 1));
1207
1208 for dir in DIAGONALS {
1210 let entry_pos = Vec2::new(
1211 center.x + dir.x * (castle_length + 2),
1212 center.y + dir.y * (castle_width + 2),
1213 );
1214 painter
1215 .line(
1216 entry_pos.with_z(castle_base - castle_height),
1217 entry_pos.with_z(castle_base - castle_height + 6),
1218 8.0,
1219 )
1220 .clear();
1221 painter
1222 .cylinder(Aabb {
1223 min: (entry_pos - 8).with_z(castle_base - castle_height - 5),
1224 max: (entry_pos + 8).with_z(castle_base - castle_height + 1),
1225 })
1226 .fill(brick.clone());
1227 }
1228 painter
1230 .aabb(Aabb {
1231 min: Vec2::new(center.x - castle_length - 20, center.y - castle_width - 20)
1232 .with_z(castle_base - castle_height - 8),
1233 max: Vec2::new(center.x + castle_length + 20, center.y + castle_width + 20)
1234 .with_z(castle_base - castle_height + 1),
1235 })
1236 .fill(brick.clone());
1237 painter
1239 .aabb(Aabb {
1240 min: Vec2::new(center.x - castle_length - 1, center.y - castle_width - 1)
1241 .with_z(castle_base + (castle_height / 8) - 6),
1242 max: Vec2::new(center.x + castle_length + 1, center.y + castle_width + 1)
1243 .with_z(castle_base + (castle_height / 8) - 1),
1244 })
1245 .fill(wood.clone());
1246 painter
1247 .aabb(Aabb {
1248 min: Vec2::new(center.x - castle_length + 1, center.y - castle_width + 1)
1249 .with_z(castle_base + (castle_height / 8) - 6),
1250 max: Vec2::new(center.x + castle_length - 1, center.y + castle_width - 1)
1251 .with_z(castle_base + (castle_height / 8) - 1),
1252 })
1253 .clear();
1254 let cellar_podium_limiter = painter.aabb(Aabb {
1255 min: Vec2::new(center.x - castle_length - 1, center.y - castle_width - 1)
1256 .with_z(castle_base - castle_height + 1),
1257 max: Vec2::new(center.x + castle_length + 1, center.y + castle_width + 1)
1258 .with_z(castle_base - castle_height + 4),
1259 });
1260 let mut cellar_beam_postions = vec![];
1261 for dir in DIAGONALS {
1262 let beam_pos = Vec2::new(
1263 center.x + (dir.x * (castle_length / 3)),
1264 center.y + (dir.y * (castle_width + 1)),
1265 );
1266 cellar_beam_postions.push(beam_pos);
1267 }
1268 for b in 0..2 {
1269 let beam_pos = Vec2::new(
1270 center.x - castle_length - 2 + (b * ((2 * castle_length) + 3)),
1271 center.y,
1272 );
1273 cellar_beam_postions.push(beam_pos);
1274 }
1275 for beam_pos in cellar_beam_postions {
1276 for n in 0..3 {
1277 painter
1278 .cylinder_with_radius(
1279 beam_pos.with_z(castle_base - castle_height + 1 + n),
1280 (5 - n) as f32,
1281 1.0,
1282 )
1283 .intersect(cellar_podium_limiter)
1284 .fill(match n {
1285 2 => candles.clone(),
1286 _ => wood.clone(),
1287 });
1288 }
1289 painter
1290 .line(
1291 beam_pos.with_z(castle_base - castle_height + 1),
1292 beam_pos.with_z(castle_base + (castle_height / 8) - 5),
1293 2.0,
1294 )
1295 .fill(wood.clone());
1296 }
1297 for (b, side_bldg_pos) in side_bldg_positions.iter().enumerate() {
1299 let side_bldg_roof_height = side_bldg_roof_height_raw
1300 + (RandomField::new(0).get(side_bldg_pos.with_z(tower_base)) % 12) as i32;
1301 let side_bldg_base = if b > 1 {
1302 side_bldg_base_raw - (side_bldg_height / 2) - side_bldg_roof_height
1303 } else {
1304 side_bldg_base_raw
1305 };
1306 let side_bldg_roof = painter.aabb(Aabb {
1308 min: Vec2::new(
1309 side_bldg_pos.x - side_bldg_length - 10,
1310 side_bldg_pos.y - side_bldg_width - 10,
1311 )
1312 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height)),
1313 max: Vec2::new(
1314 side_bldg_pos.x + side_bldg_length + 10,
1315 side_bldg_pos.y + side_bldg_width + 10,
1316 )
1317 .with_z(side_bldg_base + side_bldg_roof_height + (3 * side_bldg_height)),
1318 });
1319 side_bldg_roof.fill(brick.clone());
1320 painter
1321 .aabb(Aabb {
1322 min: Vec2::new(
1323 side_bldg_pos.x - side_bldg_length - 9,
1324 side_bldg_pos.y - side_bldg_width - 9,
1325 )
1326 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height)),
1327 max: Vec2::new(
1328 side_bldg_pos.x + side_bldg_length + 9,
1329 side_bldg_pos.y + side_bldg_width + 9,
1330 )
1331 .with_z(side_bldg_base + side_bldg_roof_height + (3 * side_bldg_height)),
1332 })
1333 .fill(roof_color.clone());
1334 painter
1336 .aabb(Aabb {
1337 min: Vec2::new(
1338 side_bldg_pos.x - side_bldg_length - 5,
1339 side_bldg_pos.y - side_bldg_width - 5,
1340 )
1341 .with_z(side_bldg_base - 2),
1342 max: Vec2::new(
1343 side_bldg_pos.x + side_bldg_length + 5,
1344 side_bldg_pos.y + side_bldg_width + 5,
1345 )
1346 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height)),
1347 })
1348 .fill(brick.clone());
1349 for c in 0..2 {
1351 let w_carve_pos = Vec2::new(
1352 side_bldg_pos.x,
1353 side_bldg_pos.y - (2 * side_bldg_width) + (c * (4 * side_bldg_width)),
1354 );
1355 let l_carve_pos = Vec2::new(
1356 side_bldg_pos.x - (4 * (side_bldg_length / 2))
1357 + (c * (8 * (side_bldg_length / 2))),
1358 side_bldg_pos.y,
1359 );
1360 painter
1361 .superquadric(
1362 Aabb {
1363 min: Vec2::new(
1364 w_carve_pos.x - side_bldg_length - 20,
1365 w_carve_pos.y - side_bldg_width - 10,
1366 )
1367 .with_z(
1368 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height),
1369 ),
1370 max: Vec2::new(
1371 w_carve_pos.x + side_bldg_length + 20,
1372 w_carve_pos.y + side_bldg_width + 10,
1373 )
1374 .with_z(
1375 side_bldg_base + side_bldg_roof_height - (side_bldg_height / 2)
1376 + (6 * side_bldg_height),
1377 ),
1378 },
1379 2.0,
1380 )
1381 .intersect(side_bldg_roof)
1382 .clear();
1383
1384 painter
1385 .superquadric(
1386 Aabb {
1387 min: Vec2::new(
1388 l_carve_pos.x - side_bldg_length - 10,
1389 l_carve_pos.y - side_bldg_width - 20,
1390 )
1391 .with_z(
1392 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height),
1393 ),
1394 max: Vec2::new(
1395 l_carve_pos.x + side_bldg_length + 10,
1396 l_carve_pos.y + side_bldg_width + 20,
1397 )
1398 .with_z(
1399 side_bldg_base + side_bldg_roof_height - (side_bldg_height / 2)
1400 + (6 * side_bldg_height),
1401 ),
1402 },
1403 2.0,
1404 )
1405 .intersect(side_bldg_roof)
1406 .clear();
1407 }
1408 for p in 0..2 {
1409 let pyramid_pos = Vec2::new(
1410 side_bldg_pos.x - (side_bldg_length - 4) + (p * (2 * (side_bldg_length - 4))),
1411 side_bldg_pos.y,
1412 );
1413 painter
1414 .pyramid(Aabb {
1415 min: (pyramid_pos - side_bldg_length).with_z(
1416 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height),
1417 ),
1418 max: (pyramid_pos + side_bldg_length).with_z(
1419 side_bldg_base
1420 + side_bldg_roof_height
1421 + (2 * side_bldg_height)
1422 + (2 * side_bldg_length)
1423 + 1,
1424 ),
1425 })
1426 .fill(roof_color.clone());
1427 }
1428
1429 let side_bldg_decor_limiter_1 = painter.aabb(Aabb {
1431 min: Vec2::new(
1432 side_bldg_pos.x - side_bldg_length - 9,
1433 side_bldg_pos.y - side_bldg_width - 9,
1434 )
1435 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 1),
1436 max: Vec2::new(
1437 side_bldg_pos.x + side_bldg_length + 9,
1438 side_bldg_pos.y + side_bldg_width + 9,
1439 )
1440 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height)),
1441 });
1442 let side_bldg_decor_limiter_2 = painter.aabb(Aabb {
1443 min: Vec2::new(
1444 side_bldg_pos.x - side_bldg_length - 6,
1445 side_bldg_pos.y - side_bldg_width - 6,
1446 )
1447 .with_z(side_bldg_base + 8),
1448 max: Vec2::new(
1449 side_bldg_pos.x + side_bldg_length + 6,
1450 side_bldg_pos.y + side_bldg_width + 6,
1451 )
1452 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 2),
1453 });
1454 let side_bldg_window_limiter = painter.aabb(Aabb {
1455 min: Vec2::new(
1456 side_bldg_pos.x - side_bldg_length - 4,
1457 side_bldg_pos.y - side_bldg_width - 4,
1458 )
1459 .with_z(side_bldg_base),
1460 max: Vec2::new(
1461 side_bldg_pos.x + side_bldg_length + 4,
1462 side_bldg_pos.y + side_bldg_width + 4,
1463 )
1464 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 2),
1465 });
1466 let side_bldg_decor_rows = (side_bldg_roof_height + (2 * side_bldg_height)) / 6;
1467 for r in 0..=6 {
1468 let side_bldg_decor_limiter = if r == 0 {
1469 side_bldg_decor_limiter_1
1470 } else {
1471 side_bldg_decor_limiter_2
1472 };
1473 let side_bldg_decor_var =
1474 RandomField::new(0).get((side_bldg_pos + r).with_z(tower_base)) % 12;
1475 let side_bldg_decors = 12.0 + side_bldg_decor_var as f32;
1476 let side_bldg_phi = TAU / side_bldg_decors;
1477 let side_bldg_decor_radius = side_bldg_length + 10;
1478 for d in 1..=side_bldg_decors as i32 {
1479 let side_bldg_decors_pos = Vec2::new(
1480 side_bldg_pos.x
1481 + (side_bldg_decor_radius as f32 * ((d as f32 * side_bldg_phi).cos()))
1482 as i32,
1483 side_bldg_pos.y
1484 + (side_bldg_decor_radius as f32 * ((d as f32 * side_bldg_phi).sin()))
1485 as i32,
1486 );
1487 painter
1488 .line(
1489 side_bldg_pos.with_z(
1490 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height)
1491 - 1
1492 - (r * side_bldg_decor_rows),
1493 ),
1494 side_bldg_decors_pos.with_z(
1495 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height)
1496 - 1
1497 - (r * side_bldg_decor_rows),
1498 ),
1499 1.0,
1500 )
1501 .intersect(side_bldg_decor_limiter)
1502 .fill(brick.clone());
1503 }
1504 }
1505 if b < 2 {
1507 for r in 0..2 {
1509 for t in 0..=2 {
1510 for h in 0..2 {
1511 painter
1513 .line(
1514 Vec2::new(
1515 side_bldg_pos.x - side_bldg_length - 7,
1516 side_bldg_pos.y - 1 - (side_bldg_width / 2)
1517 + (r * ((side_bldg_length) - 2)),
1518 )
1519 .with_z(
1520 side_bldg_base
1521 + (side_bldg_roof_height / 4)
1522 + (t * (side_bldg_roof_height / 3))
1523 + (4 * h),
1524 ),
1525 Vec2::new(
1526 side_bldg_pos.x + 1 + side_bldg_length + 7,
1527 side_bldg_pos.y - 1 - (side_bldg_width / 2)
1528 + (r * ((side_bldg_length) - 2)),
1529 )
1530 .with_z(
1531 side_bldg_base
1532 + (side_bldg_roof_height / 4)
1533 + (t * (side_bldg_roof_height / 3))
1534 + (4 * h),
1535 ),
1536 2.5,
1537 )
1538 .clear();
1539 painter
1540 .line(
1541 Vec2::new(
1542 side_bldg_pos.x - (side_bldg_length / 2)
1543 + (r * side_bldg_width),
1544 side_bldg_pos.y - side_bldg_width - 7,
1545 )
1546 .with_z(
1547 side_bldg_base
1548 + (side_bldg_roof_height / 4)
1549 + (t * (side_bldg_roof_height / 3))
1550 + (4 * h),
1551 ),
1552 Vec2::new(
1553 side_bldg_pos.x - (side_bldg_length / 2)
1554 + (r * side_bldg_width),
1555 side_bldg_pos.y + 1 + side_bldg_width + 7,
1556 )
1557 .with_z(
1558 side_bldg_base
1559 + (side_bldg_roof_height / 4)
1560 + (t * (side_bldg_roof_height / 3))
1561 + (4 * h),
1562 ),
1563 2.5,
1564 )
1565 .clear();
1566
1567 painter
1569 .line(
1570 Vec2::new(
1571 side_bldg_pos.x - side_bldg_length - 7,
1572 side_bldg_pos.y - 1 - (side_bldg_width / 2)
1573 + (r * ((side_bldg_length) - 2)),
1574 )
1575 .with_z(
1576 side_bldg_base
1577 + (side_bldg_roof_height / 4)
1578 + (t * (side_bldg_roof_height / 3))
1579 + (4 * h),
1580 ),
1581 Vec2::new(
1582 side_bldg_pos.x + 1 + side_bldg_length + 7,
1583 side_bldg_pos.y - 1 - (side_bldg_width / 2)
1584 + (r * ((side_bldg_length) - 2)),
1585 )
1586 .with_z(
1587 side_bldg_base
1588 + (side_bldg_roof_height / 4)
1589 + (t * (side_bldg_roof_height / 3))
1590 + (4 * h),
1591 ),
1592 2.5,
1593 )
1594 .intersect(side_bldg_window_limiter)
1595 .fill(window_ver2.clone());
1596 painter
1597 .line(
1598 Vec2::new(
1599 side_bldg_pos.x - (side_bldg_length / 2)
1600 + (r * side_bldg_width),
1601 side_bldg_pos.y - side_bldg_width - 7,
1602 )
1603 .with_z(
1604 side_bldg_base
1605 + (side_bldg_roof_height / 4)
1606 + (t * (side_bldg_roof_height / 3))
1607 + (4 * h),
1608 ),
1609 Vec2::new(
1610 side_bldg_pos.x - (side_bldg_length / 2)
1611 + (r * side_bldg_width),
1612 side_bldg_pos.y + 1 + side_bldg_width + 7,
1613 )
1614 .with_z(
1615 side_bldg_base
1616 + (side_bldg_roof_height / 4)
1617 + (t * (side_bldg_roof_height / 3))
1618 + (4 * h),
1619 ),
1620 2.5,
1621 )
1622 .intersect(side_bldg_window_limiter)
1623 .fill(window_ver.clone());
1624 }
1625 painter
1627 .aabb(Aabb {
1628 min: Vec2::new(
1629 side_bldg_pos.x - 1 - (side_bldg_length / 2)
1630 + (r * ((side_bldg_length) - 3)),
1631 side_bldg_pos.y - side_bldg_width - 6,
1632 )
1633 .with_z(
1634 side_bldg_base - 2
1635 + (side_bldg_roof_height / 4)
1636 + (t * (side_bldg_roof_height / 3)),
1637 ),
1638 max: Vec2::new(
1639 side_bldg_pos.x + 2 - (side_bldg_length / 2)
1640 + (r * (side_bldg_length - 3)),
1641 side_bldg_pos.y + side_bldg_width + 6,
1642 )
1643 .with_z(
1644 side_bldg_base - 1
1645 + (side_bldg_roof_height / 4)
1646 + (t * (side_bldg_roof_height / 3)),
1647 ),
1648 })
1649 .fill(wood.clone());
1650
1651 painter
1652 .aabb(Aabb {
1653 min: Vec2::new(
1654 side_bldg_pos.x - side_bldg_length - 6,
1655 side_bldg_pos.y - 2 - (side_bldg_width / 2)
1656 + (r * (side_bldg_width + 1)),
1657 )
1658 .with_z(
1659 side_bldg_base - 2
1660 + (side_bldg_roof_height / 4)
1661 + (t * (side_bldg_roof_height / 3)),
1662 ),
1663 max: Vec2::new(
1664 side_bldg_pos.x + side_bldg_length + 6,
1665 side_bldg_pos.y + 1 - (side_bldg_width / 2)
1666 + (r * (side_bldg_width + 1)),
1667 )
1668 .with_z(
1669 side_bldg_base - 1
1670 + (side_bldg_roof_height / 4)
1671 + (t * (side_bldg_roof_height / 3)),
1672 ),
1673 })
1674 .fill(wood.clone());
1675 }
1676 }
1677 let gangway_handle = 2;
1679 painter
1681 .line(
1682 center.with_z(side_bldg_base + (2 * castle_height) + gangway_handle),
1683 side_bldg_pos_2
1684 .with_z(side_bldg_base + (2 * castle_height) + gangway_handle),
1685 6.0,
1686 )
1687 .fill(roof_color.clone());
1688 painter
1689 .line(
1690 center.with_z(side_bldg_base + (2 * castle_height) + gangway_handle),
1691 side_bldg_pos.with_z(side_bldg_base + (2 * castle_height) + gangway_handle),
1692 5.0,
1693 )
1694 .fill(wood.clone());
1695 painter
1696 .line(
1697 center.with_z(side_bldg_base + (2 * castle_height) + gangway_handle),
1698 side_bldg_pos.with_z(side_bldg_base + (2 * castle_height) + gangway_handle),
1699 4.0,
1700 )
1701 .clear();
1702 }
1703 painter
1705 .aabb(Aabb {
1706 min: Vec2::new(
1707 side_bldg_pos.x - side_bldg_length - 3,
1708 side_bldg_pos.y - side_bldg_width - 3,
1709 )
1710 .with_z(side_bldg_base),
1711 max: Vec2::new(
1712 side_bldg_pos.x + side_bldg_length + 3,
1713 side_bldg_pos.y + side_bldg_width + 3,
1714 )
1715 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 1),
1716 })
1717 .clear();
1718 for r in 0..2 {
1720 let row = r * (side_bldg_roof_height + (2 * side_bldg_height) - 2);
1721 painter
1722 .aabb(Aabb {
1723 min: Vec2::new(
1724 side_bldg_pos.x - side_bldg_length - 3,
1725 side_bldg_pos.y - side_bldg_width - 3,
1726 )
1727 .with_z(side_bldg_base + row),
1728 max: Vec2::new(
1729 side_bldg_pos.x + side_bldg_length + 3,
1730 side_bldg_pos.y + side_bldg_width + 3,
1731 )
1732 .with_z(side_bldg_base + row + 1),
1733 })
1734 .fill(wood.clone());
1735 painter
1736 .aabb(Aabb {
1737 min: Vec2::new(
1738 side_bldg_pos.x - side_bldg_length - 1,
1739 side_bldg_pos.y - side_bldg_width - 1,
1740 )
1741 .with_z(side_bldg_base + row),
1742 max: Vec2::new(
1743 side_bldg_pos.x + side_bldg_length + 1,
1744 side_bldg_pos.y + side_bldg_width + 1,
1745 )
1746 .with_z(side_bldg_base + row + 1),
1747 })
1748 .clear();
1749 }
1750 let podium_limiter_1 = painter.aabb(Aabb {
1752 min: Vec2::new(
1753 side_bldg_pos.x - side_bldg_length - 3,
1754 side_bldg_pos.y - side_bldg_width - 3,
1755 )
1756 .with_z(side_bldg_base),
1757 max: Vec2::new(
1758 side_bldg_pos.x + side_bldg_length + 3,
1759 side_bldg_pos.y + side_bldg_width + 3,
1760 )
1761 .with_z(side_bldg_base + 3),
1762 });
1763 let podium_limiter_2 = painter.aabb(Aabb {
1764 min: Vec2::new(
1765 side_bldg_pos.x - side_bldg_length - 3,
1766 side_bldg_pos.y - side_bldg_width - 3,
1767 )
1768 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 10),
1769 max: Vec2::new(
1770 side_bldg_pos.x + side_bldg_length + 3,
1771 side_bldg_pos.y + side_bldg_width + 3,
1772 )
1773 .with_z(side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 6),
1774 });
1775 let mut side_bldg_beam_pos = vec![];
1776 for dir in DIAGONALS {
1777 let corner_pos = Vec2::new(
1778 side_bldg_pos.x + (dir.x * (side_bldg_length + 2)),
1779 side_bldg_pos.y + (dir.y * (side_bldg_width + 2)),
1780 );
1781 side_bldg_beam_pos.push(corner_pos);
1782 }
1783 for corner_pos in &side_bldg_beam_pos {
1784 for n in 0..3 {
1785 painter
1786 .cylinder_with_radius(
1787 corner_pos.with_z(side_bldg_base + n),
1788 (5 - n) as f32,
1789 1.0,
1790 )
1791 .intersect(podium_limiter_1)
1792 .fill(match n {
1793 2 => candles.clone(),
1794 _ => wood.clone(),
1795 });
1796 painter
1797 .cylinder_with_radius(
1798 corner_pos.with_z(
1799 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height)
1800 - 10
1801 + n,
1802 ),
1803 (2 + n) as f32,
1804 1.0,
1805 )
1806 .intersect(podium_limiter_2)
1807 .fill(wood.clone());
1808 }
1809 painter
1810 .cylinder_with_radius(
1811 corner_pos.with_z(
1812 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 7,
1813 ),
1814 4.0,
1815 1.0,
1816 )
1817 .intersect(podium_limiter_2)
1818 .fill(candles.clone());
1819 }
1820 if b < 2 {
1821 let side_bldg_room_stairs = painter.aabb(Aabb {
1823 min: Vec2::new(
1824 side_bldg_pos.x - side_bldg_length - 3,
1825 side_bldg_pos.y - side_bldg_width - 3,
1826 )
1827 .with_z(side_bldg_base),
1828 max: Vec2::new(
1829 side_bldg_pos.x + side_bldg_length + 3,
1830 side_bldg_pos.y + side_bldg_width + 3,
1831 )
1832 .with_z(side_bldg_base + (2 * castle_height) + 2),
1833 });
1834 side_bldg_room_stairs
1835 .sample(wall_staircase(
1836 side_bldg_pos.with_z(side_bldg_base + 1),
1837 (side_bldg_width + 3) as f32,
1838 side_bldg_roof_height as f32,
1839 ))
1840 .fill(candles_lite.clone());
1841 side_bldg_room_stairs
1842 .sample(wall_staircase(
1843 side_bldg_pos.with_z(side_bldg_base),
1844 (side_bldg_width + 3) as f32,
1845 side_bldg_roof_height as f32,
1846 ))
1847 .fill(wood.clone());
1848 for dir in DIAGONALS {
1850 let chain_pos = Vec2::new(
1851 side_bldg_pos.x + dir.x * (side_bldg_length - 4),
1852 side_bldg_pos.y + dir.y * (side_bldg_width - 4),
1853 );
1854 painter
1855 .aabb(Aabb {
1856 min: chain_pos.with_z(castle_base + side_bldg_height - 1),
1857 max: (chain_pos + 1).with_z(
1858 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 1,
1859 ),
1860 })
1861 .fill(chain.clone());
1862 }
1863 for p in 1..=4 {
1864 let npc_var =
1865 RandomField::new(0).get(side_bldg_pos.with_z(castle_base + p)) % 5;
1866
1867 painter
1868 .aabb(Aabb {
1869 min: Vec2::new(
1870 side_bldg_pos.x - side_bldg_length + 4,
1871 side_bldg_pos.y - side_bldg_width + 4,
1872 )
1873 .with_z(castle_base + (side_bldg_height * p) - 2),
1874 max: Vec2::new(
1875 side_bldg_pos.x + side_bldg_length - 3,
1876 side_bldg_pos.y + side_bldg_width - 3,
1877 )
1878 .with_z(castle_base + (side_bldg_height * p) - 1),
1879 })
1880 .fill(wood.clone());
1881 if npc_var > 0 {
1882 random_npc_positions
1883 .push(side_bldg_pos.with_z(castle_base + (side_bldg_height * p) + 2));
1884 }
1885 }
1886 } else {
1887 let entry_limiter = painter.aabb(Aabb {
1890 min: (side_bldg_pos - (2 * side_bldg_length))
1891 .with_z(side_bldg_base + side_bldg_roof_height + (side_bldg_height / 2)),
1892 max: (side_bldg_pos + (2 * side_bldg_length)).with_z(
1893 side_bldg_base + side_bldg_roof_height + (side_bldg_height / 2) + 7,
1894 ),
1895 });
1896 for dir in CARDINALS {
1897 let entry_pos = side_bldg_pos + dir * (side_bldg_length + 4);
1898 painter
1899 .line(
1900 side_bldg_pos.with_z(
1901 side_bldg_base + side_bldg_roof_height + (side_bldg_height / 2),
1902 ),
1903 entry_pos.with_z(
1904 side_bldg_base + side_bldg_roof_height + (side_bldg_height / 2),
1905 ),
1906 6.5,
1907 )
1908 .intersect(entry_limiter)
1909 .clear();
1910 }
1911 let side_bldg_npc_pos = side_bldg_pos
1912 .with_z(side_bldg_base + side_bldg_roof_height + (side_bldg_height / 2) + 2);
1913 random_npc_positions.push(side_bldg_npc_pos);
1914
1915 painter
1917 .aabb(Aabb {
1918 min: Vec2::new(
1919 side_bldg_pos.x - side_bldg_length - 20,
1920 side_bldg_pos.y - side_bldg_width - 20,
1921 )
1922 .with_z(side_bldg_base - 40),
1923 max: Vec2::new(
1924 side_bldg_pos.x + side_bldg_length + 20,
1925 side_bldg_pos.y + side_bldg_width + 20,
1926 )
1927 .with_z(side_bldg_base + 2),
1928 })
1929 .fill(brick.clone());
1930 painter
1931 .aabb(Aabb {
1932 min: Vec2::new(
1933 side_bldg_pos.x - side_bldg_length - 8,
1934 side_bldg_pos.y - side_bldg_width - 8,
1935 )
1936 .with_z(side_bldg_base + 1),
1937 max: Vec2::new(
1938 side_bldg_pos.x + side_bldg_length + 8,
1939 side_bldg_pos.y + side_bldg_width + 8,
1940 )
1941 .with_z(side_bldg_base + side_bldg_roof_height + (side_bldg_height / 2)),
1942 })
1943 .fill(brick.clone());
1944 painter
1946 .ramp_inset(
1947 Aabb {
1948 min: Vec2::new(
1949 side_bldg_pos.x - (2 * side_bldg_length) - 4,
1950 side_bldg_pos.y - side_bldg_width - 12,
1951 )
1952 .with_z(side_bldg_base + 2),
1953 max: Vec2::new(
1954 side_bldg_pos.x + side_bldg_length + 8,
1955 side_bldg_pos.y - side_bldg_width - 8,
1956 )
1957 .with_z(
1958 side_bldg_base + side_bldg_roof_height + (side_bldg_height / 2),
1959 ),
1960 },
1961 (2 * side_bldg_length) + 20,
1962 Dir::X,
1963 )
1964 .fill(brick.clone());
1965 painter
1966 .ramp_inset(
1967 Aabb {
1968 min: Vec2::new(
1969 side_bldg_pos.x - side_bldg_length - 8,
1970 side_bldg_pos.y + side_bldg_width + 8,
1971 )
1972 .with_z(side_bldg_base + 2),
1973 max: Vec2::new(
1974 side_bldg_pos.x + (2 * side_bldg_length) + 4,
1975 side_bldg_pos.y + side_bldg_width + 12,
1976 )
1977 .with_z(
1978 side_bldg_base + side_bldg_roof_height + (side_bldg_height / 2),
1979 ),
1980 },
1981 (2 * side_bldg_length) + 20,
1982 Dir::NegX,
1983 )
1984 .fill(brick.clone());
1985 }
1986 for corner_pos in side_bldg_beam_pos {
1988 painter
1989 .line(
1990 corner_pos.with_z(side_bldg_base),
1991 corner_pos.with_z(
1992 side_bldg_base + side_bldg_roof_height + (2 * side_bldg_height) - 1,
1993 ),
1994 2.0,
1995 )
1996 .fill(wood.clone());
1997 }
1998 }
1999 painter
2001 .cylinder(Aabb {
2002 min: (side_bldg_stairs_pos - 6).with_z(side_bldg_base_raw - 2),
2003 max: (side_bldg_stairs_pos + 6).with_z(side_bldg_base_raw - 1),
2004 })
2005 .clear();
2006 painter
2008 .cylinder(Aabb {
2009 min: (side_bldg_stairs_pos - 7).with_z(side_bldg_base_raw - 1),
2010 max: (side_bldg_stairs_pos + 7).with_z(side_bldg_base_raw),
2011 })
2012 .fill(key_door.clone());
2013 painter
2014 .cylinder(Aabb {
2015 min: (side_bldg_stairs_pos - 2).with_z(side_bldg_base_raw - 1),
2016 max: (side_bldg_stairs_pos - 1).with_z(side_bldg_base_raw),
2017 })
2018 .fill(key_hole.clone());
2019 painter
2021 .aabb(Aabb {
2022 min: Vec2::new(center.x - castle_length - 3, center.y - castle_width - 3)
2023 .with_z(castle_base + (castle_height / 2) + 1),
2024 max: Vec2::new(center.x + castle_length + 3, center.y + castle_width + 3)
2025 .with_z(castle_base + (castle_height / 2) + (2 * castle_height) - 1),
2026 })
2027 .clear();
2028 let entry_side = if side_bldg_var < 1 {
2030 side_bldg_width + 3
2031 } else {
2032 -(side_bldg_width + 4)
2033 };
2034 painter
2035 .horizontal_cylinder(
2036 Aabb {
2037 min: Vec2::new(side_bldg_pos_1.x - 4, side_bldg_pos_1.y + entry_side)
2038 .with_z(side_bldg_base_raw + (2 * castle_height) - 2),
2039 max: Vec2::new(side_bldg_pos_1.x + 5, side_bldg_pos_1.y + entry_side + 1)
2040 .with_z(side_bldg_base_raw + (2 * castle_height) + 7),
2041 },
2042 Dir::NegY,
2043 )
2044 .fill(key_door.clone());
2045 painter
2046 .aabb(Aabb {
2047 min: Vec2::new(side_bldg_pos_1.x, side_bldg_pos_1.y + entry_side)
2048 .with_z(side_bldg_base_raw + (2 * castle_height)),
2049 max: Vec2::new(side_bldg_pos_1.x + 1, side_bldg_pos_1.y + entry_side + 1)
2050 .with_z(side_bldg_base_raw + (2 * castle_height) + 1),
2051 })
2052 .fill(key_hole.clone());
2053 painter
2054 .aabb(Aabb {
2055 min: Vec2::new(side_bldg_pos_1.x - 2, side_bldg_pos_1.y + entry_side - 7)
2056 .with_z(side_bldg_base_raw + (2 * castle_height) - 2),
2057 max: Vec2::new(side_bldg_pos_1.x + 3, side_bldg_pos_1.y + entry_side + 8)
2058 .with_z(side_bldg_base_raw + (2 * castle_height) - 1),
2059 })
2060 .fill(wood.clone());
2061 painter.sprite(
2062 side_bldg_pos_2.with_z(side_bldg_base_raw),
2063 SpriteKind::DungeonChest3,
2064 );
2065 painter
2067 .aabb(Aabb {
2068 min: Vec2::new(center.x - castle_length - 3, center.y - castle_width - 3)
2069 .with_z(castle_base + (2 * castle_height) - 7),
2070 max: Vec2::new(center.x + castle_length + 3, center.y + castle_width + 3)
2071 .with_z(castle_base + (2 * castle_height) - 6),
2072 })
2073 .fill(candles_lite.clone());
2074 painter
2075 .aabb(Aabb {
2076 min: Vec2::new(center.x - castle_length - 3, center.y - castle_width - 3)
2077 .with_z(castle_base + (2 * castle_height) - 8),
2078 max: Vec2::new(center.x + castle_length + 3, center.y + castle_width + 3)
2079 .with_z(castle_base + (2 * castle_height) - 7),
2080 })
2081 .fill(wood.clone());
2082 painter
2083 .aabb(Aabb {
2084 min: Vec2::new(center.x - castle_length + 3, center.y - castle_width + 3)
2085 .with_z(castle_base + (2 * castle_height) - 8),
2086 max: Vec2::new(center.x + castle_length - 3, center.y + castle_width - 3)
2087 .with_z(castle_base + (2 * castle_height) - 6),
2088 })
2089 .clear();
2090 for r in 0..2 {
2092 let row = r * ((2 * castle_height) - 3);
2093 painter
2094 .aabb(Aabb {
2095 min: Vec2::new(center.x - castle_length - 3, center.y - castle_width - 3)
2096 .with_z(castle_base + (castle_height / 2) + 1 + row),
2097 max: Vec2::new(center.x + castle_length + 3, center.y + castle_width + 3)
2098 .with_z(castle_base + (castle_height / 2) + 2 + row),
2099 })
2100 .fill(wood.clone());
2101 painter
2102 .aabb(Aabb {
2103 min: Vec2::new(center.x - castle_length - 1, center.y - castle_width - 1)
2104 .with_z(castle_base + (castle_height / 2) + 1 + row),
2105 max: Vec2::new(center.x + castle_length + 1, center.y + castle_width + 1)
2106 .with_z(castle_base + (castle_height / 2) + 2 + row),
2107 })
2108 .clear();
2109 }
2110
2111 let castle_podium_limiter_1 = painter.aabb(Aabb {
2113 min: Vec2::new(center.x - castle_length - 3, center.y - castle_width - 3)
2114 .with_z(castle_base + (castle_height / 2) + 1),
2115 max: Vec2::new(center.x + castle_length + 3, center.y + castle_width + 3)
2116 .with_z(castle_base + (castle_height / 2) + 4),
2117 });
2118 let castle_podium_limiter_2 = painter.aabb(Aabb {
2119 min: Vec2::new(center.x - castle_length - 3, center.y - castle_width - 3)
2120 .with_z(castle_base + (2 * castle_height) - 10),
2121 max: Vec2::new(center.x + castle_length + 3, center.y + castle_width + 3)
2122 .with_z(castle_base + (2 * castle_height) - 6),
2123 });
2124 let mut wood_beam_postions = vec![];
2125 let mut outer_beam_postions = vec![];
2126 for dir in DIAGONALS {
2127 let beam_pos_outer = Vec2::new(
2128 center.x + (dir.x * (castle_length + 2)),
2129 center.y + (dir.y * (castle_width + 2)),
2130 );
2131 let beam_pos_inner = Vec2::new(
2132 center.x + (dir.x * (castle_length / 4)),
2133 center.y + (dir.y * (castle_width + 2)),
2134 );
2135 wood_beam_postions.push(beam_pos_outer);
2136 outer_beam_postions.push(beam_pos_outer);
2137 wood_beam_postions.push(beam_pos_inner);
2138 }
2139 for beam_pos in wood_beam_postions {
2140 for n in 0..2 {
2141 painter
2142 .cylinder_with_radius(
2143 beam_pos.with_z(castle_base + (castle_height / 2) + 1 + n),
2144 (5 - n) as f32,
2145 1.0,
2146 )
2147 .intersect(castle_podium_limiter_1)
2148 .fill(wood.clone());
2149 }
2150 }
2151 for beam_pos in outer_beam_postions {
2152 for n in 0..3 {
2153 painter
2154 .cylinder_with_radius(
2155 beam_pos.with_z(castle_base + (2 * castle_height) - 10 + n),
2156 (2 + n) as f32,
2157 1.0,
2158 )
2159 .intersect(castle_podium_limiter_2)
2160 .fill(wood.clone());
2161 }
2162 painter
2163 .cylinder_with_radius(
2164 beam_pos.with_z(castle_base + (2 * castle_height) - 7),
2165 4.0,
2166 1.0,
2167 )
2168 .intersect(castle_podium_limiter_2)
2169 .fill(candles.clone());
2170 painter
2171 .line(
2172 beam_pos.with_z(castle_base + (castle_height / 2) + 1),
2173 beam_pos.with_z(castle_base + (castle_height / 2) + (2 * castle_height) - 1),
2174 2.0,
2175 )
2176 .fill(wood.clone());
2177 }
2178 let boss_pos = center.with_z(castle_base + (castle_height / 2) + 2);
2180 painter.spawn(EntityInfo::at(boss_pos.as_()).with_asset_expect(
2181 "common.entity.dungeon.vampire.bloodmoon_bat",
2182 &mut thread_rng,
2183 None,
2184 ));
2185 for bat_pos in bat_positions {
2187 for _ in 0..2 {
2188 painter.spawn(EntityInfo::at(bat_pos.as_()).with_asset_expect(
2189 "common.entity.dungeon.vampire.vampire_bat",
2190 &mut thread_rng,
2191 None,
2192 ))
2193 }
2194 }
2195 for harlequin_pos in harlequin_positions {
2197 painter.spawn(EntityInfo::at(harlequin_pos.as_()).with_asset_expect(
2198 "common.entity.dungeon.vampire.harlequin",
2199 &mut thread_rng,
2200 None,
2201 ))
2202 }
2203 for npc_pos in random_npc_positions {
2204 spawn_random_entity(npc_pos, painter);
2205 }
2206 }
2207}
2208
2209pub fn spawn_random_entity(pos: Vec3<i32>, painter: &Painter) {
2210 let mut rng = thread_rng();
2211 let entities = [
2212 "common.entity.dungeon.vampire.strigoi",
2213 "common.entity.dungeon.vampire.executioner",
2214 "common.entity.dungeon.vampire.bloodservant",
2215 ];
2216 let random_entity_index = rng.gen_range(0..entities.len());
2217 let random_entity = entities[random_entity_index];
2218 painter.spawn(EntityInfo::at(pos.as_()).with_asset_expect(random_entity, &mut rng, None));
2219}