From a966841c5a8e16606d26334bc655371871aa68de Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 30 Jul 2020 16:46:17 +0100 Subject: [PATCH] Castle and cave tweaks --- world/src/civ/mod.rs | 14 ++- world/src/site/castle/mod.rs | 41 ++++++--- .../settlement/building/archetype/keep.rs | 89 ++++++++++++------- 3 files changed, 96 insertions(+), 48 deletions(-) diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index f443373a5c..f569b8b054 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -258,15 +258,23 @@ impl Civs { ctx.sim.get_mut(locs[0].0).unwrap().cave.0.neighbors |= 1 << ((to_prev_idx as u8 + 4) % 8); + ctx.sim.get_mut(locs[1].0).unwrap().cave.0.neighbors |= + (1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8)); ctx.sim.get_mut(locs[2].0).unwrap().cave.0.neighbors |= 1 << ((to_next_idx as u8 + 4) % 8); - let mut chunk = ctx.sim.get_mut(locs[1].0).unwrap(); - chunk.cave.0.neighbors |= (1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8)); - let depth = locs[1].1 * 250.0 - 20.0; + } + + for (i, loc) in path.iter().enumerate() { + let mut chunk = ctx.sim.get_mut(loc.0).unwrap(); + let depth = loc.1 * 250.0 - 20.0; chunk.cave.1.alt = chunk.alt - depth + ctx.rng.gen_range(-4.0, 4.0) * (depth > 10.0) as i32 as f32; chunk.cave.1.width = ctx.rng.gen_range(6.0, 32.0); chunk.cave.0.offset = Vec2::new(ctx.rng.gen_range(-16, 17), ctx.rng.gen_range(-16, 17)); + + if chunk.cave.1.alt + chunk.cave.1.width + 5.0 > chunk.alt { + chunk.spawn_rate = 0.0; + } } } diff --git a/world/src/site/castle/mod.rs b/world/src/site/castle/mod.rs index 60b570bb99..afd2404442 100644 --- a/world/src/site/castle/mod.rs +++ b/world/src/site/castle/mod.rs @@ -51,6 +51,7 @@ pub struct Castle { towers: Vec, keeps: Vec, rounded_towers: bool, + ridged: bool, } pub struct GenCtx<'a, R: Rng> { @@ -114,6 +115,7 @@ impl Castle { }) .collect(), rounded_towers: ctx.rng.gen(), + ridged: ctx.rng.gen(), keeps: (0..keep_count) .map(|i| { let angle = (i as f32 / keep_count as f32) * f32::consts::PI * 2.0; @@ -123,7 +125,7 @@ impl Castle { let locus = ctx.rng.gen_range(20, 26); let offset = (dir * dist).map(|e| e as i32); - let storeys = ctx.rng.gen_range(1, 5).clamped(2, 3); + let storeys = ctx.rng.gen_range(1, 8).clamped(3, 5); Keep { offset, @@ -244,9 +246,9 @@ impl Castle { let wall_ori = if (tower0.offset.x - tower1.offset.x).abs() < (tower0.offset.y - tower1.offset.y).abs() { - Ori::East - } else { Ori::North + } else { + Ori::East }; ( @@ -271,13 +273,15 @@ impl Castle { .map(|(dist, _, path, _)| path.head_space(dist)) .unwrap_or(0); - // Apply the dungeon entrance let wall_sample = if let Some(col) = get_column(offs + wall_pos - rpos) { col } else { col_sample }; + // Make sure particularly weird terrain doesn't give us underground walls + let wall_alt = wall_alt + (wall_sample.alt as i32 - wall_alt - 10).max(0); + let keep_archetype = KeepArchetype { flag_color: Rgb::new(200, 80, 40), }; @@ -294,17 +298,18 @@ impl Castle { let mut mask = keep_archetype.draw( Vec3::from(wall_rpos) + Vec3::unit_z() * wpos.z - wall_alt, wall_dist, - Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()), + border_pos, rpos - wall_pos, wall_z, wall_ori, 4, 0, &Attr { - storeys: 1, + storeys: 2, is_tower: false, ridged: false, rounded: true, + has_doors: false, }, ); @@ -329,17 +334,22 @@ impl Castle { ) }, border_pos.reduce_max() - tower_locus, - Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()), + Vec2::new(border_pos.reduce_min(), border_pos.reduce_max()), (wpos - tower_wpos).xy(), wpos.z - tower.alt, - Ori::East, + if border_pos.x > border_pos.y { + Ori::East + } else { + Ori::North + }, tower_locus, 0, &Attr { - storeys: 2, + storeys: 3, is_tower: true, - ridged: false, + ridged: self.ridged, rounded: self.rounded_towers, + has_doors: false, }, )); } @@ -364,17 +374,22 @@ impl Castle { ) }, border_pos.reduce_max() - keep.locus, - Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()), + Vec2::new(border_pos.reduce_min(), border_pos.reduce_max()), (wpos - keep_wpos).xy(), wpos.z - keep.alt, - Ori::East, + if border_pos.x > border_pos.y { + Ori::East + } else { + Ori::North + }, keep.locus, 0, &Attr { storeys: keep.storeys, is_tower: keep.is_tower, - ridged: true, + ridged: self.ridged, rounded: self.rounded_towers, + has_doors: true, }, )); } diff --git a/world/src/site/settlement/building/archetype/keep.rs b/world/src/site/settlement/building/archetype/keep.rs index ee197e3848..476ab57f8d 100644 --- a/world/src/site/settlement/building/archetype/keep.rs +++ b/world/src/site/settlement/building/archetype/keep.rs @@ -19,6 +19,7 @@ pub struct Attr { pub is_tower: bool, pub ridged: bool, pub rounded: bool, + pub has_doors: bool, } impl Archetype for Keep { @@ -26,16 +27,18 @@ impl Archetype for Keep { fn generate(rng: &mut R) -> (Self, Skeleton) { let len = rng.gen_range(-8, 24).max(0); + let storeys = rng.gen_range(1, 3); let skel = Skeleton { offset: -rng.gen_range(0, len + 7).clamped(0, len), ori: if rng.gen() { Ori::East } else { Ori::North }, root: Branch { len, attr: Attr { - storeys: 1, + storeys, is_tower: false, ridged: false, rounded: true, + has_doors: true, }, locus: 10 + rng.gen_range(0, 5), border: 3, @@ -46,10 +49,11 @@ impl Archetype for Keep { Branch { len: 0, attr: Attr { - storeys: 2, + storeys: storeys + rng.gen_range(1, 3), is_tower: true, ridged: false, rounded: true, + has_doors: false, }, locus: 6 + rng.gen_range(0, 3), border: 3, @@ -89,6 +93,17 @@ impl Archetype for Keep { let important_layer = normal_layer + 1; let internal_layer = important_layer + 1; + let make_meta = |ori| { + Rgb::new( + match ori { + Ori::East => 0, + Ori::North => 2, + }, + 0, + 0, + ) + }; + let make_block = |r, g, b| { BlockMask::new( Block::new(BlockKind::Normal, Rgb::new(r, g, b)), @@ -100,6 +115,10 @@ impl Archetype for Keep { let brick_tex = RandomField::new(0).get(brick_tex_pos) as u8 % 24; let foundation = make_block(80 + brick_tex, 80 + brick_tex, 80 + brick_tex); let wall = make_block(100 + brick_tex, 100 + brick_tex, 110 + brick_tex); + let window = BlockMask::new( + Block::new(BlockKind::Window1, make_meta(ori.flip())), + normal_layer, + ); let floor = make_block( 80 + (pos.y.abs() % 2) as u8 * 15, 60 + (pos.y.abs() % 2) as u8 * 15, @@ -132,23 +151,19 @@ impl Archetype for Keep { } }; - let edge_pos = if (bound_offset.x.abs() > bound_offset.y.abs()) ^ (ori == Ori::East) { - pos.y - } else { - pos.x - }; - + let ridge_x = (center_offset.map(|e| e.abs()).reduce_min() + 2) % 8; let width = locus - + if (edge_pos + 1000) % 8 < 4 && attr.ridged && !attr.rounded { + + if ridge_x < 4 && attr.ridged && !attr.rounded { 1 } else { 0 }; let rampart_width = 2 + width; - let storey_height = 16; + let storey_height = 9; let roof_height = attr.storeys * storey_height; + let storey_y = profile.y % storey_height; let door_height = 6; - let rampart_height = roof_height + if edge_pos % 2 == 0 { 3 } else { 4 }; + let rampart_height = roof_height + if ridge_x % 2 == 0 { 3 } else { 4 }; let min_dist = if attr.rounded { bound_offset.map(|e| e.pow(2) as f32).sum().powf(0.5) as i32 } else { @@ -158,24 +173,32 @@ impl Archetype for Keep { if profile.y <= 0 - (min_dist - width - 1).max(0) && min_dist < width + 3 { // Foundations foundation - } else if (0..=roof_height).contains(&profile.y) && profile.y % storey_height == 0 && min_dist < rampart_width { + } else if (0..=roof_height).contains(&profile.y) && storey_y == 0 && min_dist <= width + 1 { if min_dist < width { floor } else { wall } - } else if !attr.is_tower - && bound_offset.x.abs() == 4 - && min_dist == width + 1 - && profile.y < roof_height - { - wall } else if bound_offset.x.abs() < 3 && profile.y < door_height - bound_offset.x.abs() && profile.y > 0 && min_dist >= width - 2 + && min_dist <= width + 1 + && attr.has_doors { internal - } else if min_dist == width && profile.y <= roof_height { - wall + } else if (min_dist == width || (!attr.is_tower && min_dist == width + 1)) + && profile.y <= roof_height + { + if attr.is_tower + && (3..7).contains(&storey_y) + && bound_offset.x.abs() < width - 2 + && (5..7).contains(&ridge_x) + { + window + } else { + wall + } } else if profile.y >= roof_height { - if profile.y > roof_height && min_dist < rampart_width { + if profile.y > roof_height + && (min_dist < rampart_width - 1 || (attr.is_tower && min_dist < rampart_width)) + { if attr.is_tower && center_offset == Vec2::zero() && profile.y < roof_height + 16 { pole } else if attr.is_tower @@ -189,7 +212,7 @@ impl Archetype for Keep { } else { empty } - } else if min_dist == rampart_width { + } else if min_dist <= rampart_width { if profile.y < rampart_height { wall } else { @@ -203,15 +226,17 @@ impl Archetype for Keep { } else { empty } - .resolve_with(if attr.is_tower && profile.y > 0 && profile.y <= roof_height { - make_staircase( - Vec3::new(center_offset.x, center_offset.y, pos.z), - 7.0f32.min(width as f32 - 1.0), - 0.5, - 9.0, - ) - } else { - BlockMask::nothing() - }) + .resolve_with( + if attr.is_tower && profile.y > 0 && profile.y <= roof_height { + make_staircase( + Vec3::new(center_offset.x, center_offset.y, pos.z), + 7.0f32.min(width as f32 - 1.0), + 0.5, + 9.0, + ) + } else { + BlockMask::nothing() + }, + ) } }