diff --git a/CHANGELOG.md b/CHANGELOG.md index cb8df52d77..745624b452 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Weapon trails - Hostile agent will now abort pursuing their target based on multiple metrics - Admin command to reload all chunks on the server +- Furniture and waypoints in site2 towns ### Changed diff --git a/world/src/site2/plot/house.rs b/world/src/site2/plot/house.rs index 0a2dc707b6..6bf1a3a33f 100644 --- a/world/src/site2/plot/house.rs +++ b/world/src/site2/plot/house.rs @@ -1,5 +1,9 @@ use super::*; -use crate::{site2::util::Dir, Land}; +use crate::{ + site2::util::Dir, + util::{RandomField, Sampler, DIRS}, + Land, +}; use common::terrain::{Block, BlockKind, SpriteKind}; use rand::prelude::*; use vek::*; @@ -1532,6 +1536,100 @@ impl Structure for House { ); } + // interior furniture sprites + let base = alt + (storey * (i as i32 - 1)).max(0); + if i % 2 == 0 { + // bedroom on even-leveled floors + let bed_pos = match self.front { + 1 => Vec2::new(half_x, quarter_y), + 2 => Vec2::new(three_quarter_x, half_y), + _ => Vec2::new(half_x, half_y), + }; + let nightstand_pos = Vec2::new(bed_pos.x + 2, bed_pos.y + 1); + painter.sprite(bed_pos.with_z(base), SpriteKind::Bed); + // drawer next to bed + painter.sprite(nightstand_pos.with_z(base), SpriteKind::DrawerSmall); + // collectible on top of drawer + let rng = RandomField::new(0).get(nightstand_pos.with_z(base + 1)); + painter.sprite(nightstand_pos.with_z(base + 1), match rng % 5 { + 0 => SpriteKind::Lantern, + 1 => SpriteKind::PotionMinor, + 2 => SpriteKind::VialEmpty, + 3 => SpriteKind::Bowl, + _ => SpriteKind::Empty, + }); + // wardrobe along wall in corner of the room + let (wardrobe_pos, drawer_ori) = match self.front { + 0 => (Vec2::new(self.bounds.max.x - 2, self.bounds.min.y + 1), 4), + 1 => (Vec2::new(self.bounds.min.x + 6, self.bounds.max.y - 1), 0), + 2 => (Vec2::new(self.bounds.min.x + 2, self.bounds.max.y - 1), 0), + _ => (Vec2::new(self.bounds.max.x - 6, self.bounds.max.y - 1), 0), + }; + painter.rotated_sprite( + wardrobe_pos.with_z(base), + SpriteKind::WardrobeDouble, + drawer_ori, + ); + } else { + // living room with table + chairs + random + for dir in DIRS { + // random accent pieces and loot + let sprite_pos = self.bounds.center() + dir * 5; + let rng = RandomField::new(0).get(sprite_pos.with_z(base)); + painter.sprite(sprite_pos.with_z(base), match rng % 32 { + 0..=2 => SpriteKind::Crate, + 3..=4 => SpriteKind::CoatRack, + 5..=7 => SpriteKind::Pot, + 8..=9 => SpriteKind::Lantern, + _ => SpriteKind::Empty, + }); + } + + if self.bounds.max.x - self.bounds.min.x < 16 + || self.bounds.max.y - self.bounds.min.y < 16 + { + let table_pos = Vec2::new(half_x, half_y); + // room is smaller, so use small table + painter.sprite(table_pos.with_z(base), SpriteKind::TableDining); + for (idx, dir) in CARDINALS.iter().enumerate() { + let chair_pos = table_pos + dir; + painter.rotated_sprite( + chair_pos.with_z(base), + SpriteKind::ChairSingle, + (idx * 2 + ((idx % 2) * 4)) as u8, + ); + } + } else { + // room is bigger, so use large table + chair positions + let table_pos = match self.front { + 0 => Vec2::new(half_x, three_quarter_y), + 1 => Vec2::new(half_x, half_y), + _ => Vec2::new(quarter_x, half_y), + }; + painter.sprite(table_pos.with_z(base), SpriteKind::TableDouble); + for (idx, dir) in CARDINALS.iter().enumerate() { + let chair_pos = table_pos + dir * (1 + idx % 2) as i32; + painter.rotated_sprite( + chair_pos.with_z(base), + SpriteKind::ChairSingle, + (idx * 2 + ((idx % 2) * 4)) as u8, + ); + } + } + // drawer along a wall + let (drawer_pos, drawer_ori) = match self.front { + 0 => (Vec2::new(self.bounds.max.x - 1, self.bounds.max.y - 2), 6), + 1 => (Vec2::new(self.bounds.max.x - 2, self.bounds.max.y - 1), 0), + 2 => (Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 2), 6), + _ => (Vec2::new(self.bounds.min.x + 2, self.bounds.max.y - 1), 0), + }; + painter.rotated_sprite( + drawer_pos.with_z(base), + SpriteKind::DrawerLarge, + drawer_ori, + ); + } + // Stairs if i > 1 { let stair_width = 3; diff --git a/world/src/site2/plot/workshop.rs b/world/src/site2/plot/workshop.rs index 51939356bb..d8416b1379 100644 --- a/world/src/site2/plot/workshop.rs +++ b/world/src/site2/plot/workshop.rs @@ -3,7 +3,10 @@ use crate::{ util::{RandomField, Sampler}, Land, }; -use common::terrain::{Block, BlockKind, SpriteKind}; +use common::{ + generation::EntityInfo, + terrain::{Block, BlockKind, SpriteKind}, +}; use rand::prelude::*; use vek::*; @@ -134,5 +137,10 @@ impl Structure for Workshop { painter.sprite(position.with_z(base), cr_station); } } + + painter.spawn( + EntityInfo::at(self.bounds.center().with_z(base).map(|e| e as f32 + 0.5)) + .into_waypoint(), + ); } }