diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index a9278f8508..0a3e40d00a 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -111,6 +111,10 @@ impl BlockKind { BlockKind::Radish => true, BlockKind::Turnip => true, BlockKind::Coconut => true, + BlockKind::Window1 => true, + BlockKind::Window2 => true, + BlockKind::Window3 => true, + BlockKind::Window4 => true, BlockKind::Scarecrow => true, _ => false, } @@ -230,6 +234,7 @@ impl BlockKind { match self { BlockKind::Tomato => 1.65, BlockKind::LargeCactus => 2.5, + BlockKind::Scarecrow => 3.0, _ => 1.0, } } @@ -280,6 +285,16 @@ impl Block { } } + pub fn get_ori(&self) -> Option { + match self.kind { + BlockKind::Window1 + | BlockKind::Window2 + | BlockKind::Window3 + | BlockKind::Window4 => Some(self.color[0] & 0b111), + _ => None, + } + } + pub fn kind(&self) -> BlockKind { self.kind } } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 3b7d46a271..dfbf48f669 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -262,16 +262,19 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug>( let wpos = Vec3::from(pos * V::RECT_SIZE.map(|e: u32| e as i32)) + Vec3::new(x, y, z); - let kind = volume.get(wpos).unwrap_or(&Block::empty()).kind(); + let block = volume.get(wpos).ok().copied().unwrap_or(Block::empty()); - if let Some(cfg) = sprite_config_for(kind) { + if let Some(cfg) = sprite_config_for(block.kind()) { let seed = wpos.x as u64 * 3 + wpos.y as u64 * 7 + wpos.x as u64 * wpos.y as u64; // Awful PRNG + let ori = block + .get_ori() + .unwrap_or((seed % 8) as u8); let instance = SpriteInstance::new( Mat4::identity() - .rotated_z(f32::consts::PI * 0.5 * (seed % 4) as f32) + .rotated_z(f32::consts::PI * 0.25 * ori as f32) .translated_3d( wpos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0), ), @@ -280,7 +283,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug>( ); instances - .entry((kind, seed as usize % cfg.variations)) + .entry((block.kind(), seed as usize % cfg.variations)) .or_insert_with(|| Vec::new()) .push(instance); } @@ -340,28 +343,28 @@ impl Terrain { (BlockKind::Window1, 0), make_model( "voxygen.voxel.sprite.window.window-0", - Vec3::new(-6.0, -6.0, 0.0), + Vec3::new(-5.5, -5.5, 0.0), ), ), ( (BlockKind::Window2, 0), make_model( "voxygen.voxel.sprite.window.window-1", - Vec3::new(-6.0, -6.0, 0.0), + Vec3::new(-5.5, -5.5, 0.0), ), ), ( (BlockKind::Window3, 0), make_model( "voxygen.voxel.sprite.window.window-2", - Vec3::new(-6.0, -6.0, 0.0), + Vec3::new(-5.5, -5.5, 0.0), ), ), ( (BlockKind::Window4, 0), make_model( "voxygen.voxel.sprite.window.window-3", - Vec3::new(-6.0, -6.0, 0.0), + Vec3::new(-5.5, -5.5, 0.0), ), ), // Cacti diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index 712281800c..f25318b6e8 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -491,6 +491,7 @@ fn walk_in_dir(sim: &WorldSim, a: Vec2, dir: Vec2) -> Option { if loc_suitable_for_walking(sim, a) && loc_suitable_for_walking(sim, a + dir) { let a_alt = sim.get(a)?.alt; let b_alt = sim.get(a + dir)?.alt; + let water_cost = if sim.get(a + dir)?.river.near_water() { 25.0 } else { 0.0 }; Some((b_alt - a_alt).abs() / 2.5) } else { None diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index 96c3279bc8..d78016d66c 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -165,10 +165,18 @@ impl Archetype for House { bound_offset: Vec2, center_offset: Vec2, z: i32, + ori: Ori, branch: &Branch, ) -> BlockMask { let profile = Vec2::new(bound_offset.x, z); + let make_meta = |ori| { + Rgb::new(match ori { + Ori::East => 0, + Ori::North => 2, + }, 0, 0) + }; + let make_block = |r, g, b| { let nz = self .noise @@ -196,6 +204,7 @@ impl Archetype for House { .with_priority(facade_layer); let empty = BlockMask::nothing(); let internal = BlockMask::new(Block::empty(), structural_layer); + let end_window = BlockMask::new(Block::new(BlockKind::Window1, make_meta(ori.flip())), facade_layer); let fire = BlockMask::new(Block::new(BlockKind::Ember, Rgb::white()), foundation_layer); let ceil_height = 6; @@ -301,21 +310,21 @@ impl Archetype for House { } else if !branch.attr.storey_fill.has_upper() { return Some(empty); } else { - let frame_bounds = if profile.y >= ceil_height { - Aabr { + let (frame_bounds, frame_borders) = if profile.y >= ceil_height { + (Aabr { min: Vec2::new(-1, ceil_height + 2), max: Vec2::new(1, ceil_height + 5), - } + }, Vec2::new(1, 1)) } else { - Aabr { + (Aabr { min: Vec2::new(2, foundation_height + 2), max: Vec2::new(width - 2, ceil_height - 2), - } + }, Vec2::new(1, 0)) }; let window_bounds = Aabr { - min: (frame_bounds.min + 1) + min: (frame_bounds.min + frame_borders) .map2(frame_bounds.center(), |a, b| a.min(b)), - max: (frame_bounds.max - 1) + max: (frame_bounds.max - frame_borders) .map2(frame_bounds.center(), |a, b| a.max(b)), }; @@ -324,9 +333,9 @@ impl Archetype for House { // Window frame is large enough for a window let surface_pos = Vec2::new(bound_offset.x, profile.y); if window_bounds.contains_point(surface_pos) { - return Some(internal); + return Some(end_window); } else if frame_bounds.contains_point(surface_pos) { - return Some(log.with_priority(3)); + return Some(log.with_priority(facade_layer)); }; } diff --git a/world/src/site/settlement/building/archetype/keep.rs b/world/src/site/settlement/building/archetype/keep.rs index 8758c67bae..9810ec5e48 100644 --- a/world/src/site/settlement/building/archetype/keep.rs +++ b/world/src/site/settlement/building/archetype/keep.rs @@ -48,6 +48,7 @@ impl Archetype for Keep { bound_offset: Vec2, center_offset: Vec2, z: i32, + ori: Ori, branch: &Branch, ) -> BlockMask { let profile = Vec2::new(bound_offset.x, z); diff --git a/world/src/site/settlement/building/archetype/mod.rs b/world/src/site/settlement/building/archetype/mod.rs index a40b87035c..89ca5dca24 100644 --- a/world/src/site/settlement/building/archetype/mod.rs +++ b/world/src/site/settlement/building/archetype/mod.rs @@ -18,6 +18,7 @@ pub trait Archetype { bound_offset: Vec2, center_offset: Vec2, z: i32, + ori: Ori, branch: &Branch, ) -> BlockMask; } diff --git a/world/src/site/settlement/building/mod.rs b/world/src/site/settlement/building/mod.rs index 9b44c5316a..cc37d4acc5 100644 --- a/world/src/site/settlement/building/mod.rs +++ b/world/src/site/settlement/building/mod.rs @@ -50,9 +50,9 @@ impl Building { pub fn sample(&self, pos: Vec3) -> Option { let rpos = pos - self.origin; self.skel - .sample_closest(rpos.into(), |dist, bound_offset, center_offset, branch| { + .sample_closest(rpos.into(), |dist, bound_offset, center_offset, ori, branch| { self.archetype - .draw(dist, bound_offset, center_offset, rpos.z, branch) + .draw(dist, bound_offset, center_offset, rpos.z, ori, branch) }) .finish() } diff --git a/world/src/site/settlement/building/skeleton.rs b/world/src/site/settlement/building/skeleton.rs index ac2cc0404b..4387a9e590 100644 --- a/world/src/site/settlement/building/skeleton.rs +++ b/world/src/site/settlement/building/skeleton.rs @@ -75,7 +75,7 @@ impl Skeleton { pub fn sample_closest( &self, pos: Vec2, - mut f: impl FnMut(i32, Vec2, Vec2, &Branch) -> BlockMask, + mut f: impl FnMut(i32, Vec2, Vec2, Ori, &Branch) -> BlockMask, ) -> BlockMask { let mut min = None::<(_, BlockMask)>; self.for_each(|node, ori, branch, is_child, parent_locus| { @@ -115,7 +115,7 @@ impl Skeleton { } || true { - let new_bm = f(dist, bound_offset, center_offset, branch); + let new_bm = f(dist, bound_offset, center_offset, ori, branch); min = min .map(|(_, bm)| (dist_locus, bm.resolve_with(new_bm))) .or(Some((dist_locus, new_bm))); diff --git a/world/src/site/settlement/mod.rs b/world/src/site/settlement/mod.rs index fba588ca17..5e0ebbe689 100644 --- a/world/src/site/settlement/mod.rs +++ b/world/src/site/settlement/mod.rs @@ -611,6 +611,11 @@ impl Settlement { Crop::Sunflower => Some(BlockKind::Sunflower), _ => None, } + .or_else(|| if roll(9, 256) == 0 { + Some(BlockKind::Scarecrow) + } else { + None + }) .map(|kind| Block::new(kind, Rgb::white())); } } else {