mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Progress on converting dungeons to site2. Adds Sampling and Translate primitives.
This commit is contained in:
parent
46e93ba563
commit
df4f536523
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2492,6 +2492,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inline_tweak"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7033e97b20277cc0d043226d1940fa7719ff08d2305d1fc7421e53066d00eb4b"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.7.1"
|
||||
@ -6154,6 +6163,7 @@ dependencies = [
|
||||
"fxhash",
|
||||
"hashbrown 0.11.2",
|
||||
"image",
|
||||
"inline_tweak",
|
||||
"itertools 0.10.0",
|
||||
"lazy_static",
|
||||
"lz-fear",
|
||||
|
@ -35,7 +35,7 @@ rayon = "1.5"
|
||||
serde = { version = "1.0.110", features = ["derive"] }
|
||||
ron = { version = "0.6", default-features = false }
|
||||
assets_manager = {version = "0.4.3", features = ["ron"]}
|
||||
#inline_tweak = "1.0.2"
|
||||
inline_tweak = "1.0.2"
|
||||
|
||||
# compression benchmarks
|
||||
lz-fear = { version = "0.1.1", optional = true }
|
||||
|
@ -5,7 +5,7 @@ mod econ;
|
||||
use crate::{
|
||||
config::CONFIG,
|
||||
sim::{RiverKind, WorldSim},
|
||||
site::{namegen::NameGen, Castle, Dungeon, Settlement, Site as WorldSite, Tree},
|
||||
site::{namegen::NameGen, Castle, Settlement, Site as WorldSite, Tree},
|
||||
site2,
|
||||
util::{attempt, seed_expan, CARDINALS, NEIGHBORS},
|
||||
Index, Land,
|
||||
@ -193,13 +193,15 @@ impl Civs {
|
||||
SiteKind::Settlement => {
|
||||
WorldSite::settlement(Settlement::generate(wpos, Some(ctx.sim), &mut rng))
|
||||
},
|
||||
SiteKind::Dungeon => {
|
||||
WorldSite::dungeon(Dungeon::generate(wpos, Some(ctx.sim), &mut rng))
|
||||
},
|
||||
SiteKind::Dungeon => WorldSite::dungeon(site2::Site::generate_dungeon(
|
||||
&Land::from_sim(&ctx.sim),
|
||||
&mut rng,
|
||||
wpos,
|
||||
)),
|
||||
SiteKind::Castle => {
|
||||
WorldSite::castle(Castle::generate(wpos, Some(ctx.sim), &mut rng))
|
||||
},
|
||||
SiteKind::Refactor => WorldSite::refactor(site2::Site::generate(
|
||||
SiteKind::Refactor => WorldSite::refactor(site2::Site::generate_city(
|
||||
&Land::from_sim(&ctx.sim),
|
||||
&mut rng,
|
||||
wpos,
|
||||
|
@ -144,7 +144,7 @@ impl World {
|
||||
civ::SiteKind::Settlement => world_msg::SiteKind::Town,
|
||||
civ::SiteKind::Dungeon => world_msg::SiteKind::Dungeon {
|
||||
difficulty: match site.site_tmp.map(|id| &index.sites[id].kind) {
|
||||
Some(site::SiteKind::Dungeon(d)) => d.difficulty(),
|
||||
Some(site::SiteKind::Dungeon(d)) => d.difficulty().unwrap_or(0),
|
||||
_ => 0,
|
||||
},
|
||||
},
|
||||
|
@ -1,6 +1,5 @@
|
||||
mod block_mask;
|
||||
mod castle;
|
||||
mod dungeon;
|
||||
pub mod economy;
|
||||
pub mod namegen;
|
||||
mod settlement;
|
||||
@ -8,7 +7,7 @@ mod tree;
|
||||
|
||||
// Reexports
|
||||
pub use self::{
|
||||
block_mask::BlockMask, castle::Castle, dungeon::Dungeon, economy::Economy,
|
||||
block_mask::BlockMask, castle::Castle, economy::Economy,
|
||||
settlement::Settlement, tree::Tree,
|
||||
};
|
||||
|
||||
@ -21,7 +20,7 @@ use vek::*;
|
||||
#[derive(Deserialize)]
|
||||
pub struct Colors {
|
||||
pub castle: castle::Colors,
|
||||
pub dungeon: dungeon::Colors,
|
||||
pub dungeon: site2::plot::dungeon::Colors,
|
||||
pub settlement: settlement::Colors,
|
||||
}
|
||||
|
||||
@ -40,7 +39,7 @@ pub struct Site {
|
||||
|
||||
pub enum SiteKind {
|
||||
Settlement(Settlement),
|
||||
Dungeon(Dungeon),
|
||||
Dungeon(site2::Site),
|
||||
Castle(Castle),
|
||||
Refactor(site2::Site),
|
||||
Tree(tree::Tree),
|
||||
@ -54,7 +53,7 @@ impl Site {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dungeon(d: Dungeon) -> Self {
|
||||
pub fn dungeon(d: site2::Site) -> Self {
|
||||
Self {
|
||||
kind: SiteKind::Dungeon(d),
|
||||
economy: Economy::default(),
|
||||
@ -95,7 +94,7 @@ impl Site {
|
||||
pub fn get_origin(&self) -> Vec2<i32> {
|
||||
match &self.kind {
|
||||
SiteKind::Settlement(s) => s.get_origin(),
|
||||
SiteKind::Dungeon(d) => d.get_origin(),
|
||||
SiteKind::Dungeon(d) => d.origin,
|
||||
SiteKind::Castle(c) => c.get_origin(),
|
||||
SiteKind::Refactor(s) => s.origin,
|
||||
SiteKind::Tree(t) => t.origin,
|
||||
@ -117,7 +116,7 @@ impl Site {
|
||||
SiteKind::Settlement(s) => s.name(),
|
||||
SiteKind::Dungeon(d) => d.name(),
|
||||
SiteKind::Castle(c) => c.name(),
|
||||
SiteKind::Refactor(_) => "Town",
|
||||
SiteKind::Refactor(s) => s.name(),
|
||||
SiteKind::Tree(_) => "Giant Tree",
|
||||
}
|
||||
}
|
||||
@ -127,7 +126,7 @@ impl Site {
|
||||
let get_col = |wpos| info.col(wpos + info.wpos);
|
||||
match &self.kind {
|
||||
SiteKind::Settlement(s) => s.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
|
||||
SiteKind::Dungeon(d) => d.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
|
||||
SiteKind::Dungeon(d) => d.render(canvas, dynamic_rng),
|
||||
SiteKind::Castle(c) => c.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
|
||||
SiteKind::Refactor(s) => s.render(canvas, dynamic_rng),
|
||||
SiteKind::Tree(t) => t.render(canvas, dynamic_rng),
|
||||
@ -156,7 +155,7 @@ impl Site {
|
||||
};
|
||||
s.apply_supplement(dynamic_rng, wpos2d, get_column, supplement, economy)
|
||||
},
|
||||
SiteKind::Dungeon(d) => d.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
||||
SiteKind::Dungeon(d) => {}, //d.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
||||
SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
||||
SiteKind::Refactor(_) => {},
|
||||
SiteKind::Tree(_) => {},
|
||||
|
@ -17,6 +17,7 @@ pub enum Primitive {
|
||||
Cone(Aabb<i32>),
|
||||
Sphere(Aabb<i32>),
|
||||
Plane(Aabr<i32>, Vec3<i32>, Vec2<f32>),
|
||||
Sampling(Box<dyn Fn(Vec3<i32>) -> bool>),
|
||||
|
||||
// Combinators
|
||||
And(Id<Primitive>, Id<Primitive>),
|
||||
@ -26,8 +27,10 @@ pub enum Primitive {
|
||||
Diff(Id<Primitive>, Id<Primitive>),
|
||||
// Operators
|
||||
Rotate(Id<Primitive>, Mat3<i32>),
|
||||
Translate(Id<Primitive>, Vec3<i32>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Fill {
|
||||
Block(Block),
|
||||
Brick(BlockKind, Rgb<u8>, u8),
|
||||
@ -95,6 +98,7 @@ impl Fill {
|
||||
.as_()
|
||||
.dot(*gradient) as i32)
|
||||
},
|
||||
Primitive::Sampling(f) => f(pos),
|
||||
Primitive::And(a, b) => {
|
||||
self.contains_at(tree, *a, pos) && self.contains_at(tree, *b, pos)
|
||||
},
|
||||
@ -112,6 +116,9 @@ impl Fill {
|
||||
let diff = pos - (aabb.min + mat.cols.map(|x| x.reduce_min()));
|
||||
self.contains_at(tree, *prim, aabb.min + mat.transposed() * diff)
|
||||
},
|
||||
Primitive::Translate(prim, vec) => {
|
||||
self.contains_at(tree, *prim, pos.map2(*vec, i32::saturating_sub))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,6 +176,10 @@ impl Fill {
|
||||
};
|
||||
aabb.made_valid()
|
||||
},
|
||||
Primitive::Sampling(_) => Aabb {
|
||||
min: Vec3::broadcast(std::i32::MIN),
|
||||
max: Vec3::broadcast(std::i32::MAX),
|
||||
},
|
||||
Primitive::And(a, b) => or_zip_with(
|
||||
self.get_bounds_inner(tree, *a),
|
||||
self.get_bounds_inner(tree, *b),
|
||||
@ -189,6 +200,13 @@ impl Fill {
|
||||
};
|
||||
new_aabb.made_valid()
|
||||
},
|
||||
Primitive::Translate(prim, vec) => {
|
||||
let aabb = self.get_bounds_inner(tree, *prim)?;
|
||||
Aabb {
|
||||
min: aabb.min.map2(*vec, i32::saturating_add),
|
||||
max: aabb.max.map2(*vec, i32::saturating_add),
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
mod gen;
|
||||
mod plot;
|
||||
pub mod plot;
|
||||
mod tile;
|
||||
|
||||
use self::{
|
||||
@ -38,6 +38,7 @@ fn reseed(rng: &mut impl Rng) -> impl Rng { ChaChaRng::from_seed(rng.gen::<[u8;
|
||||
#[derive(Default)]
|
||||
pub struct Site {
|
||||
pub(crate) origin: Vec2<i32>,
|
||||
name: String,
|
||||
tiles: TileGrid,
|
||||
plots: Store<Plot>,
|
||||
plazas: Vec<Id<Plot>>,
|
||||
@ -275,7 +276,21 @@ impl Site {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn generate(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn difficulty(&self) -> Option<u32> {
|
||||
self.plots.iter().filter_map(|(_, plot)| {
|
||||
if let PlotKind::Dungeon(d) = &plot.kind {
|
||||
Some(d.difficulty())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).max()
|
||||
}
|
||||
|
||||
pub fn generate_dungeon(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
|
||||
let mut rng = reseed(rng);
|
||||
|
||||
let mut site = Site {
|
||||
@ -283,6 +298,41 @@ impl Site {
|
||||
..Site::default()
|
||||
};
|
||||
|
||||
site.demarcate_obstacles(land);
|
||||
let dungeon = plot::Dungeon::generate(origin, land, &mut rng);
|
||||
site.name = dungeon.name().to_string();
|
||||
//let size = (2.0 + rng.gen::<f32>().powf(8.0) * 3.0).round() as i32;
|
||||
let size = 8;
|
||||
|
||||
let aabr = Aabr {
|
||||
min: Vec2::broadcast(-size),
|
||||
max: Vec2::broadcast(size),
|
||||
};
|
||||
|
||||
let plot = site.create_plot(Plot {
|
||||
kind: PlotKind::Dungeon(dungeon),
|
||||
root_tile: aabr.center(),
|
||||
tiles: aabr_tiles(aabr).collect(),
|
||||
seed: rng.gen(),
|
||||
});
|
||||
|
||||
site.blit_aabr(aabr, Tile {
|
||||
kind: TileKind::Plaza,
|
||||
plot: Some(plot),
|
||||
});
|
||||
|
||||
site
|
||||
}
|
||||
|
||||
pub fn generate_city(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
|
||||
let mut rng = reseed(rng);
|
||||
|
||||
let mut site = Site {
|
||||
origin,
|
||||
name: "Town".into(),
|
||||
..Site::default()
|
||||
};
|
||||
|
||||
site.demarcate_obstacles(land);
|
||||
|
||||
site.make_plaza(land, &mut rng);
|
||||
@ -702,6 +752,7 @@ impl Site {
|
||||
}
|
||||
}
|
||||
}
|
||||
tracing::info!("{:?}: {:?}", canvas.wpos(), plots.len());
|
||||
|
||||
let mut plots_to_render = plots.into_iter().collect::<Vec<_>>();
|
||||
plots_to_render.sort_unstable();
|
||||
@ -710,6 +761,11 @@ impl Site {
|
||||
let (prim_tree, fills) = match &self.plots[plot].kind {
|
||||
PlotKind::House(house) => house.render_collect(self),
|
||||
PlotKind::Castle(castle) => castle.render_collect(self),
|
||||
PlotKind::Dungeon(dungeon) => {
|
||||
let (prim_tree, fills) = dungeon.render_collect(self);
|
||||
tracing::info!("{:?}: {:?} {:?}", dungeon.name(), prim_tree.ids().count(), fills.len());
|
||||
(prim_tree, fills)
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
@ -732,7 +788,7 @@ impl Site {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test_site() -> Site { Site::generate(&Land::empty(), &mut thread_rng(), Vec2::zero()) }
|
||||
pub fn test_site() -> Site { Site::generate_city(&Land::empty(), &mut thread_rng(), Vec2::zero()) }
|
||||
|
||||
fn wpos_is_hazard(land: &Land, wpos: Vec2<i32>) -> Option<HazardKind> {
|
||||
if land
|
||||
|
@ -1,7 +1,8 @@
|
||||
mod castle;
|
||||
pub mod dungeon;
|
||||
mod house;
|
||||
|
||||
pub use self::{castle::Castle, house::House};
|
||||
pub use self::{castle::Castle, dungeon::Dungeon, house::House};
|
||||
|
||||
use super::*;
|
||||
use crate::util::DHashSet;
|
||||
@ -30,4 +31,5 @@ pub enum PlotKind {
|
||||
Plaza,
|
||||
Castle(Castle),
|
||||
Road(Path<Vec2<i32>>),
|
||||
Dungeon(Dungeon),
|
||||
}
|
||||
|
@ -2,10 +2,10 @@ use super::SpawnRules;
|
||||
use crate::{
|
||||
block::block_from_structure,
|
||||
column::ColumnSample,
|
||||
sim::WorldSim,
|
||||
site::{namegen::NameGen, BlockMask},
|
||||
site2::{self, Primitive, Fill, Structure as SiteStructure},
|
||||
util::{attempt, Grid, RandomField, Sampler, CARDINALS, DIRS},
|
||||
IndexRef,
|
||||
IndexRef, Land,
|
||||
};
|
||||
|
||||
use common::{
|
||||
@ -36,7 +36,7 @@ pub struct Dungeon {
|
||||
}
|
||||
|
||||
pub struct GenCtx<'a, R: Rng> {
|
||||
sim: Option<&'a WorldSim>,
|
||||
land: &'a Land<'a>,
|
||||
rng: &'a mut R,
|
||||
}
|
||||
|
||||
@ -64,9 +64,8 @@ lazy_static! {
|
||||
}
|
||||
|
||||
impl Dungeon {
|
||||
pub fn generate(wpos: Vec2<i32>, sim: Option<&WorldSim>, rng: &mut impl Rng) -> Self {
|
||||
let mut ctx = GenCtx { sim, rng };
|
||||
|
||||
pub fn generate(wpos: Vec2<i32>, land: &Land, rng: &mut impl Rng) -> Self {
|
||||
let mut ctx = GenCtx { land, rng };
|
||||
let difficulty = DUNGEON_DISTRIBUTION
|
||||
.choose_weighted(&mut ctx.rng, |pair| pair.1)
|
||||
.map(|(difficulty, _)| *difficulty)
|
||||
@ -76,7 +75,6 @@ impl Dungeon {
|
||||
err
|
||||
)
|
||||
});
|
||||
|
||||
let floors = 3 + difficulty / 2;
|
||||
|
||||
Self {
|
||||
@ -91,11 +89,7 @@ impl Dungeon {
|
||||
}
|
||||
},
|
||||
origin: wpos - TILE_SIZE / 2,
|
||||
alt: ctx
|
||||
.sim
|
||||
.and_then(|sim| sim.get_alt_approx(wpos))
|
||||
.unwrap_or(0.0) as i32
|
||||
+ 6,
|
||||
alt: ctx.land.get_alt_approx(wpos) as i32 + 6,
|
||||
seed: ctx.rng.gen(),
|
||||
noise: RandomField::new(ctx.rng.gen()),
|
||||
floors: (0..floors)
|
||||
@ -1164,3 +1158,270 @@ mod tests {
|
||||
mini_boss_fallback(tile_wcenter);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spiral_staircase(
|
||||
origin: Vec3<i32>,
|
||||
radius: f32,
|
||||
inner_radius: f32,
|
||||
stretch: f32,
|
||||
) -> Box<dyn Fn(Vec3<i32>) -> bool> {
|
||||
Box::new(move |pos: Vec3<i32>| {
|
||||
let pos = pos + origin;
|
||||
if (pos.xy().magnitude_squared() as f32) < inner_radius.powi(2) {
|
||||
true
|
||||
} else if (pos.xy().magnitude_squared() as f32) < radius.powi(2) {
|
||||
if ((pos.x as f32).atan2(pos.y as f32) / (f32::consts::PI * 2.0) * stretch
|
||||
+ pos.z as f32)
|
||||
.rem_euclid(stretch)
|
||||
< 1.5
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn wall_staircase(
|
||||
origin: Vec3<i32>,
|
||||
radius: f32,
|
||||
stretch: f32,
|
||||
) -> Box<dyn Fn(Vec3<i32>) -> bool> {
|
||||
Box::new(move |pos: Vec3<i32>| {
|
||||
let pos = pos - origin;
|
||||
if (pos.x.abs().max(pos.y.abs())) as f32 > 0.6 * radius {
|
||||
if ((pos.x as f32).atan2(pos.y as f32) / (f32::consts::PI * 2.0) * stretch
|
||||
+ pos.z as f32)
|
||||
.rem_euclid(stretch)
|
||||
< 1.0
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
impl SiteStructure for Dungeon {
|
||||
fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Id<Primitive>, Fill)>(
|
||||
&self,
|
||||
site: &site2::Site,
|
||||
mut prim: F,
|
||||
mut fill: G,
|
||||
) {
|
||||
//let rpos = pos - self.tile_offset * TILE_SIZE;
|
||||
//let tile_pos = rpos.map(|e| e.div_euclid(TILE_SIZE));
|
||||
//let tile_center = tile_pos * TILE_SIZE + TILE_SIZE / 2;
|
||||
//let rtile_pos = rpos - tile_center;
|
||||
|
||||
//let colors = &index.colors.site.dungeon;
|
||||
|
||||
let vacant = Block::air(SpriteKind::Empty);
|
||||
//let stone = Block::new(BlockKind::Rock, colors.stone.into());
|
||||
let stone_red = Block::new(BlockKind::Rock, Rgb::new(255, 0, 0));
|
||||
let stone_green = Block::new(BlockKind::Rock, Rgb::new(0, 255, 0));
|
||||
let stone_blue = Block::new(BlockKind::Rock, Rgb::new(0, 0, 255));
|
||||
|
||||
use inline_tweak::tweak;
|
||||
let cutout_size = tweak!(9);
|
||||
|
||||
let origin = self.origin.with_z(self.alt);
|
||||
let cutout = prim(Primitive::Aabb(Aabb {
|
||||
min: origin - Vec2::broadcast(cutout_size * 7).with_z(self.alt-1),
|
||||
max: origin + Vec2::broadcast(cutout_size * 7).with_z(100),
|
||||
}));
|
||||
fill(cutout, Fill::Block(vacant));
|
||||
|
||||
|
||||
let stairs_inf = prim(Primitive::Sampling(wall_staircase(
|
||||
origin,
|
||||
TILE_SIZE as f32 / 2.0,
|
||||
tweak!(27.0),
|
||||
)));
|
||||
let bounding_box = prim(Primitive::Aabb(Aabb {
|
||||
min: origin - Vec3::new(8, 8, self.alt-1),
|
||||
max: origin + Vec3::new(8, 8, 400),
|
||||
}));
|
||||
//let stairs_inf = prim(Primitive::Sampling(Box::new(|_| true)));
|
||||
let stairs = prim(Primitive::And(bounding_box, stairs_inf));
|
||||
let stairs_tr1 = prim(Primitive::Translate(stairs, Vec3::unit_z()));
|
||||
let stairs_tr2 = prim(Primitive::Translate(stairs, Vec3::broadcast(tweak!(-16))));
|
||||
/*let stairs = prim(Primitive::Cone(Aabb {
|
||||
min: self.origin.with_z(self.alt) - Vec3::broadcast(16),
|
||||
max: self.origin.with_z(self.alt + 100) + Vec3::broadcast(16),
|
||||
}));*/
|
||||
fill(stairs, Fill::Block(stone_red));
|
||||
fill(stairs_tr1, Fill::Block(stone_green));
|
||||
fill(stairs_tr2, Fill::Block(stone_blue));
|
||||
|
||||
/*let make_staircase = move |kind: &StairsKind,
|
||||
pos: Vec3<i32>,
|
||||
radius: f32,
|
||||
inner_radius: f32,
|
||||
stretch: f32,
|
||||
height_limit: i32| {
|
||||
match kind {
|
||||
StairsKind::Spiral => make_spiral_staircase(pos, radius, inner_radius, stretch),
|
||||
StairsKind::WallSpiral => {
|
||||
make_wall_staircase(pos, radius, stretch * 3.0, height_limit)
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
let wall_thickness = 3.0;
|
||||
let dist_to_wall = self
|
||||
.nearest_wall(rpos)
|
||||
.map(|nearest| (nearest.distance_squared(rpos) as f32).sqrt())
|
||||
.unwrap_or(TILE_SIZE as f32);
|
||||
let tunnel_dist =
|
||||
1.0 - (dist_to_wall - wall_thickness).max(0.0) / (TILE_SIZE as f32 - wall_thickness);
|
||||
|
||||
let floor_sprite = if RandomField::new(7331).chance(Vec3::from(pos), 0.001) {
|
||||
BlockMask::new(
|
||||
with_sprite(
|
||||
match (RandomField::new(1337).get(Vec3::from(pos)) / 2) % 30 {
|
||||
0 => SpriteKind::Apple,
|
||||
1 => SpriteKind::VeloriteFrag,
|
||||
2 => SpriteKind::Velorite,
|
||||
3..=8 => SpriteKind::Mushroom,
|
||||
9..=15 => SpriteKind::FireBowlGround,
|
||||
_ => SpriteKind::ShortGrass,
|
||||
},
|
||||
),
|
||||
1,
|
||||
)
|
||||
} else if let Some(Tile::Room(room)) | Some(Tile::DownStair(room)) =
|
||||
self.tiles.get(tile_pos)
|
||||
{
|
||||
let room = &self.rooms[*room];
|
||||
if RandomField::new(room.seed).chance(Vec3::from(pos), room.loot_density * 0.5) {
|
||||
match room.difficulty {
|
||||
0 => BlockMask::new(with_sprite(SpriteKind::DungeonChest0), 1),
|
||||
1 => BlockMask::new(with_sprite(SpriteKind::DungeonChest1), 1),
|
||||
2 => BlockMask::new(with_sprite(SpriteKind::DungeonChest2), 1),
|
||||
3 => BlockMask::new(with_sprite(SpriteKind::DungeonChest3), 1),
|
||||
4 => BlockMask::new(with_sprite(SpriteKind::DungeonChest4), 1),
|
||||
5 => BlockMask::new(with_sprite(SpriteKind::DungeonChest5), 1),
|
||||
_ => BlockMask::new(with_sprite(SpriteKind::Chest), 1),
|
||||
}
|
||||
} else {
|
||||
vacant
|
||||
}
|
||||
} else {
|
||||
vacant
|
||||
};
|
||||
|
||||
let tunnel_height = if self.final_level { 16.0 } else { 8.0 };
|
||||
let pillar_thickness: i32 = 4;
|
||||
|
||||
move |z| match self.tiles.get(tile_pos) {
|
||||
Some(Tile::Solid) => BlockMask::nothing(),
|
||||
Some(Tile::Tunnel) => {
|
||||
let light_offset: i32 = 7;
|
||||
if (dist_to_wall - wall_thickness) as i32 == 1
|
||||
&& rtile_pos.map(|e| e % light_offset == 0).reduce_bitxor()
|
||||
&& z == 1
|
||||
{
|
||||
let ori =
|
||||
Floor::relative_ori(rpos, self.nearest_wall(rpos).unwrap_or_default());
|
||||
let furniture = SpriteKind::WallSconce;
|
||||
BlockMask::new(Block::air(furniture).with_ori(ori).unwrap(), 1)
|
||||
} else if dist_to_wall >= wall_thickness
|
||||
&& (z as f32) < tunnel_height * (1.0 - tunnel_dist.powi(4))
|
||||
{
|
||||
if z == 0 { floor_sprite } else { vacant }
|
||||
} else {
|
||||
BlockMask::nothing()
|
||||
}
|
||||
},
|
||||
Some(Tile::Room(room)) | Some(Tile::DownStair(room))
|
||||
if dist_to_wall < wall_thickness
|
||||
|| z as f32
|
||||
>= self.rooms[*room].height as f32 * (1.0 - tunnel_dist.powi(4)) =>
|
||||
{
|
||||
BlockMask::nothing()
|
||||
},
|
||||
|
||||
Some(Tile::Room(room)) | Some(Tile::DownStair(room))
|
||||
if self.rooms[*room]
|
||||
.pillars
|
||||
.map(|pillar_space| {
|
||||
tile_pos
|
||||
.map(|e| e.rem_euclid(pillar_space) == 0)
|
||||
.reduce_and()
|
||||
&& rtile_pos.map(|e| e as f32).magnitude_squared()
|
||||
< (pillar_thickness as f32 + 0.5).powi(2)
|
||||
})
|
||||
.unwrap_or(false) =>
|
||||
{
|
||||
if z == 1 && rtile_pos.product() == 0 && rtile_pos.sum().abs() == pillar_thickness {
|
||||
let ori = Floor::relative_ori(rtile_pos, Vec2::zero());
|
||||
let furniture = SpriteKind::WallSconce;
|
||||
BlockMask::new(Block::air(furniture).with_ori(ori).unwrap(), 1)
|
||||
} else if z < self.rooms[*room].height
|
||||
&& rtile_pos.map(|e| e as f32).magnitude_squared()
|
||||
> (pillar_thickness as f32 - 0.5).powi(2)
|
||||
{
|
||||
vacant
|
||||
} else {
|
||||
BlockMask::nothing()
|
||||
}
|
||||
}
|
||||
|
||||
Some(Tile::Room(_)) => {
|
||||
let light_offset = 7;
|
||||
if z == 0 {
|
||||
floor_sprite
|
||||
} else if dist_to_wall as i32 == 4
|
||||
&& rtile_pos.map(|e| e % light_offset == 0).reduce_bitxor()
|
||||
&& z == 1
|
||||
{
|
||||
let ori = Floor::relative_ori(
|
||||
rpos,
|
||||
self.nearest_wall(rpos).unwrap_or_else(Vec2::zero),
|
||||
);
|
||||
let furniture = SpriteKind::WallSconce;
|
||||
BlockMask::new(Block::air(furniture).with_ori(ori).unwrap(), 1)
|
||||
} else {
|
||||
vacant
|
||||
}
|
||||
},
|
||||
Some(Tile::DownStair(_)) => vacant,
|
||||
Some(Tile::UpStair(room, kind)) => {
|
||||
let inner_radius: f32 = 0.5;
|
||||
let stretch = 9;
|
||||
let block = make_staircase(
|
||||
kind,
|
||||
Vec3::new(rtile_pos.x, rtile_pos.y, z),
|
||||
TILE_SIZE as f32 / 2.0,
|
||||
inner_radius,
|
||||
stretch as f32,
|
||||
self.total_depth(),
|
||||
);
|
||||
let furniture = SpriteKind::WallSconce;
|
||||
let ori = Floor::relative_ori(Vec2::zero(), rtile_pos);
|
||||
if z < self.rooms[*room].height {
|
||||
block.resolve_with(vacant)
|
||||
} else if z % stretch == 0 && rtile_pos.x == 0 && rtile_pos.y == -TILE_SIZE / 2 {
|
||||
BlockMask::new(Block::air(furniture).with_ori(ori).unwrap(), 1)
|
||||
} else {
|
||||
make_staircase(
|
||||
kind,
|
||||
Vec3::new(rtile_pos.x, rtile_pos.y, z),
|
||||
TILE_SIZE as f32 / 2.0,
|
||||
inner_radius,
|
||||
stretch as f32,
|
||||
self.total_depth(),
|
||||
)
|
||||
}
|
||||
},
|
||||
None => BlockMask::nothing(),
|
||||
}*/
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user