mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'james/lava-dungeons' into 'master'
Prettier site2 houses See merge request veloren/veloren!2852
This commit is contained in:
commit
2f1fe39e04
@ -125,6 +125,14 @@ impl Block {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn lava(sprite: SpriteKind) -> Self {
|
||||
Self {
|
||||
kind: BlockKind::Lava,
|
||||
attr: [sprite as u8, 0, 0],
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn empty() -> Self { Self::air(SpriteKind::Empty) }
|
||||
|
||||
|
@ -24,10 +24,23 @@ pub enum Primitive {
|
||||
aabb: Aabb<i32>,
|
||||
inset: i32,
|
||||
},
|
||||
Ramp {
|
||||
aabb: Aabb<i32>,
|
||||
inset: i32,
|
||||
dir: u8,
|
||||
},
|
||||
Gable {
|
||||
aabb: Aabb<i32>,
|
||||
inset: i32,
|
||||
// X axis parallel or Y axis parallel
|
||||
dir: bool,
|
||||
},
|
||||
Cylinder(Aabb<i32>),
|
||||
Cone(Aabb<i32>),
|
||||
Sphere(Aabb<i32>),
|
||||
Plane(Aabr<i32>, Vec3<i32>, Vec2<f32>),
|
||||
/// A line segment from start to finish point
|
||||
Segment(LineSegment3<i32>),
|
||||
/// A sampling function is always a subset of another primitive to avoid
|
||||
/// needing infinite bounds
|
||||
Sampling(Id<Primitive>, Box<dyn Fn(Vec3<i32>) -> bool>),
|
||||
@ -69,6 +82,34 @@ impl Fill {
|
||||
Primitive::Empty => false,
|
||||
|
||||
Primitive::Aabb(aabb) => aabb_contains(*aabb, pos),
|
||||
Primitive::Ramp { aabb, inset, dir } => {
|
||||
let inset = (*inset).max(aabb.size().reduce_min());
|
||||
let inner = match dir {
|
||||
0 => Aabr {
|
||||
min: Vec2::new(aabb.min.x - 1 + inset, aabb.min.y),
|
||||
max: Vec2::new(aabb.max.x, aabb.max.y),
|
||||
},
|
||||
1 => Aabr {
|
||||
min: Vec2::new(aabb.min.x, aabb.min.y),
|
||||
max: Vec2::new(aabb.max.x - inset, aabb.max.y),
|
||||
},
|
||||
2 => Aabr {
|
||||
min: Vec2::new(aabb.min.x, aabb.min.y - 1 + inset),
|
||||
max: Vec2::new(aabb.max.x, aabb.max.y),
|
||||
},
|
||||
_ => Aabr {
|
||||
min: Vec2::new(aabb.min.x, aabb.min.y),
|
||||
max: Vec2::new(aabb.max.x, aabb.max.y - inset),
|
||||
},
|
||||
};
|
||||
aabb_contains(*aabb, pos)
|
||||
&& (inner.projected_point(pos.xy()) - pos.xy())
|
||||
.map(|e| e.abs())
|
||||
.reduce_max() as f32
|
||||
/ (inset as f32)
|
||||
< 1.0
|
||||
- ((pos.z - aabb.min.z) as f32 + 0.5) / (aabb.max.z - aabb.min.z) as f32
|
||||
},
|
||||
Primitive::Pyramid { aabb, inset } => {
|
||||
let inset = (*inset).max(aabb.size().reduce_min());
|
||||
let inner = Aabr {
|
||||
@ -83,6 +124,27 @@ impl Fill {
|
||||
< 1.0
|
||||
- ((pos.z - aabb.min.z) as f32 + 0.5) / (aabb.max.z - aabb.min.z) as f32
|
||||
},
|
||||
Primitive::Gable { aabb, inset, dir } => {
|
||||
let inset = (*inset).max(aabb.size().reduce_min());
|
||||
let inner = if *dir {
|
||||
Aabr {
|
||||
min: Vec2::new(aabb.min.x - 1 + inset, aabb.min.y),
|
||||
max: Vec2::new(aabb.max.x - inset, aabb.max.y),
|
||||
}
|
||||
} else {
|
||||
Aabr {
|
||||
min: Vec2::new(aabb.min.x, aabb.min.y - 1 + inset),
|
||||
max: Vec2::new(aabb.max.x, aabb.max.y - inset),
|
||||
}
|
||||
};
|
||||
aabb_contains(*aabb, pos)
|
||||
&& (inner.projected_point(pos.xy()) - pos.xy())
|
||||
.map(|e| e.abs())
|
||||
.reduce_max() as f32
|
||||
/ (inset as f32)
|
||||
< 1.0
|
||||
- ((pos.z - aabb.min.z) as f32 + 0.5) / (aabb.max.z - aabb.min.z) as f32
|
||||
},
|
||||
Primitive::Cylinder(aabb) => {
|
||||
(aabb.min.z..aabb.max.z).contains(&pos.z)
|
||||
&& (pos
|
||||
@ -118,6 +180,12 @@ impl Fill {
|
||||
.as_()
|
||||
.dot(*gradient) as i32)
|
||||
},
|
||||
Primitive::Segment(segment) => {
|
||||
(segment.start.x..segment.end.x).contains(&pos.x)
|
||||
&& (segment.start.y..segment.end.y).contains(&pos.y)
|
||||
&& (segment.start.z..segment.end.z).contains(&pos.z)
|
||||
&& segment.as_().distance_to_point(pos.map(|e| e as f32)) < 0.75
|
||||
},
|
||||
Primitive::Sampling(a, f) => self.contains_at(tree, *a, pos) && f(pos),
|
||||
Primitive::Prefab(p) => !matches!(p.get(pos), Err(_) | Ok(StructureBlock::None)),
|
||||
Primitive::And(a, b) => {
|
||||
@ -200,6 +268,8 @@ impl Fill {
|
||||
Primitive::Empty => return None,
|
||||
Primitive::Aabb(aabb) => *aabb,
|
||||
Primitive::Pyramid { aabb, .. } => *aabb,
|
||||
Primitive::Gable { aabb, .. } => *aabb,
|
||||
Primitive::Ramp { aabb, .. } => *aabb,
|
||||
Primitive::Cylinder(aabb) => *aabb,
|
||||
Primitive::Cone(aabb) => *aabb,
|
||||
Primitive::Sphere(aabb) => *aabb,
|
||||
@ -220,6 +290,10 @@ impl Fill {
|
||||
};
|
||||
aabb.made_valid()
|
||||
},
|
||||
Primitive::Segment(segment) => Aabb {
|
||||
min: segment.start,
|
||||
max: segment.end,
|
||||
},
|
||||
Primitive::Sampling(a, _) => self.get_bounds_inner(tree, *a)?,
|
||||
Primitive::Prefab(p) => p.get_bounds(),
|
||||
Primitive::And(a, b) => or_zip_with(
|
||||
|
@ -192,6 +192,8 @@ enum RoomKind {
|
||||
Fight,
|
||||
Boss,
|
||||
Miniboss,
|
||||
#[allow(dead_code)]
|
||||
LavaPlatforming,
|
||||
}
|
||||
|
||||
pub struct Room {
|
||||
@ -201,6 +203,7 @@ pub struct Room {
|
||||
area: Rect<i32, i32>,
|
||||
height: i32,
|
||||
pillars: Option<i32>, // Pillars with the given separation
|
||||
pits: Option<i32>, // Pits filled with lava
|
||||
difficulty: u32,
|
||||
}
|
||||
|
||||
@ -393,6 +396,7 @@ impl Floor {
|
||||
area: Rect::from((stair_tile - tile_offset - 1, Extent2::broadcast(3))),
|
||||
height: STAIR_ROOM_HEIGHT,
|
||||
pillars: None,
|
||||
pits: None,
|
||||
difficulty,
|
||||
});
|
||||
if final_level {
|
||||
@ -407,6 +411,7 @@ impl Floor {
|
||||
)),
|
||||
height: height as i32,
|
||||
pillars: Some(2),
|
||||
pits: None,
|
||||
difficulty,
|
||||
});
|
||||
} else {
|
||||
@ -418,6 +423,7 @@ impl Floor {
|
||||
area: Rect::from((new_stair_tile - tile_offset - 1, Extent2::broadcast(3))),
|
||||
height: STAIR_ROOM_HEIGHT,
|
||||
pillars: None,
|
||||
pits: None,
|
||||
difficulty,
|
||||
});
|
||||
this.tiles.set(
|
||||
@ -506,8 +512,20 @@ impl Floor {
|
||||
area,
|
||||
height: ctx.rng.gen_range(15..20),
|
||||
pillars: Some(ctx.rng.gen_range(2..=4)),
|
||||
pits: None,
|
||||
difficulty: self.difficulty,
|
||||
}),
|
||||
//// Lava platforming room
|
||||
//1 => self.create_room(Room {
|
||||
// seed: ctx.rng.gen(),
|
||||
// loot_density: 0.0,
|
||||
// kind: RoomKind::LavaPlatforming,
|
||||
// area,
|
||||
// height: ctx.rng.gen_range(10..15),
|
||||
// pillars: None,
|
||||
// pits: Some(1),
|
||||
// difficulty: self.difficulty,
|
||||
//}),
|
||||
// Fight room with enemies in it
|
||||
_ => self.create_room(Room {
|
||||
seed: ctx.rng.gen(),
|
||||
@ -520,6 +538,7 @@ impl Floor {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
pits: None,
|
||||
difficulty: self.difficulty,
|
||||
}),
|
||||
};
|
||||
@ -631,7 +650,7 @@ impl Floor {
|
||||
RoomKind::Boss => {
|
||||
room.fill_boss_cell(supplement, tile_wcenter, wpos2d, tile_pos)
|
||||
},
|
||||
RoomKind::Peaceful => {},
|
||||
RoomKind::Peaceful | RoomKind::LavaPlatforming => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1018,8 +1037,22 @@ impl Floor {
|
||||
};
|
||||
let floor_prim = prim(Primitive::Aabb(floor_aabb));
|
||||
|
||||
// This is copied from `src/layer/mod.rs`. It should be moved into
|
||||
// a util file somewhere
|
||||
let noisy_color = |color: Rgb<u8>, factor: u32| {
|
||||
let nz = RandomField::new(0).get(Vec3::new(floor_corner.x, floor_corner.y, floor_z));
|
||||
color.map(|e| {
|
||||
(e as u32 + nz % (factor * 2))
|
||||
.saturating_sub(factor)
|
||||
.min(255) as u8
|
||||
})
|
||||
};
|
||||
|
||||
// Declare the various kinds of blocks that will be used as fills
|
||||
let vacant = Block::air(SpriteKind::Empty);
|
||||
// FIXME: Lava and stone color hardcoded here, it is available in colors.ron
|
||||
// but that file is not accessed from site2 yet
|
||||
let lava = Block::new(BlockKind::Lava, noisy_color(Rgb::new(184, 39, 0), 8));
|
||||
let stone = Block::new(BlockKind::Rock, Rgb::new(150, 150, 175));
|
||||
let stone_purple = Block::new(BlockKind::GlowingRock, Rgb::new(96, 0, 128));
|
||||
|
||||
@ -1227,10 +1260,44 @@ impl Floor {
|
||||
}));
|
||||
chests = Some((chest_sprite, chest_sprite_fill));
|
||||
|
||||
// If a room has pillars, the current tile aligns with
|
||||
// the pillar spacing, and we're not too close to a wall
|
||||
// (i.e. the adjacent tiles are rooms and not hallways/solid),
|
||||
// place a pillar
|
||||
// If a room has pits, place them
|
||||
if room.pits.is_some() {
|
||||
// Make an air pit
|
||||
let tile_pit = prim(Primitive::Aabb(aabr_with_z(
|
||||
tile_aabr,
|
||||
floor_z - 7..floor_z,
|
||||
)));
|
||||
let tile_pit = prim(Primitive::Diff(tile_pit, wall_contours));
|
||||
fill(tile_pit, Fill::Block(vacant));
|
||||
|
||||
// Fill with lava
|
||||
let tile_lava = prim(Primitive::Aabb(aabr_with_z(
|
||||
tile_aabr,
|
||||
floor_z - 7..floor_z - 5,
|
||||
)));
|
||||
let tile_lava = prim(Primitive::Diff(tile_lava, wall_contours));
|
||||
//pits.push(tile_pit);
|
||||
//pits.push(tile_lava);
|
||||
fill(tile_lava, Fill::Block(lava));
|
||||
}
|
||||
if room
|
||||
.pits
|
||||
.map(|pit_space| {
|
||||
tile_pos.map(|e| e.rem_euclid(pit_space) == 0).reduce_and()
|
||||
})
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let platform = prim(Primitive::Aabb(Aabb {
|
||||
min: (tile_center - Vec2::broadcast(pillar_thickness - 1))
|
||||
.with_z(floor_z - 7),
|
||||
max: (tile_center + Vec2::broadcast(pillar_thickness)).with_z(floor_z),
|
||||
}));
|
||||
fill(platform, Fill::Block(stone));
|
||||
}
|
||||
|
||||
// If a room has pillars, the current tile aligns with the pillar spacing, and
|
||||
// we're not too close to a wall (i.e. the adjacent tiles are rooms and not
|
||||
// hallways/solid), place a pillar
|
||||
if room
|
||||
.pillars
|
||||
.map(|pillar_space| {
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user