mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Gnarling cavern tweaks
This commit is contained in:
parent
86a00e75bb
commit
07d19bf03c
@ -1,5 +1,10 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::{assets::AssetHandle, site2::util::Dir, util::attempt, Land};
|
use crate::{
|
||||||
|
assets::AssetHandle,
|
||||||
|
site2::util::Dir,
|
||||||
|
util::{attempt, sampler::Sampler, RandomField},
|
||||||
|
Land,
|
||||||
|
};
|
||||||
use common::{
|
use common::{
|
||||||
generation::{ChunkSupplement, EntityInfo},
|
generation::{ChunkSupplement, EntityInfo},
|
||||||
terrain::{Structure as PrefabStructure, StructuresGroup},
|
terrain::{Structure as PrefabStructure, StructuresGroup},
|
||||||
@ -29,6 +34,7 @@ struct Tunnels {
|
|||||||
start: Vec3<i32>,
|
start: Vec3<i32>,
|
||||||
end: Vec3<i32>,
|
end: Vec3<i32>,
|
||||||
branches: Vec<(Vec3<i32>, Vec3<i32>)>,
|
branches: Vec<(Vec3<i32>, Vec3<i32>)>,
|
||||||
|
path: Vec<Vec3<i32>>,
|
||||||
terminals: Vec<Vec3<i32>>,
|
terminals: Vec<Vec3<i32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,8 +82,8 @@ impl GnarlingFortification {
|
|||||||
|
|
||||||
// Tunnels
|
// Tunnels
|
||||||
let alt = land.get_alt_approx(wpos) as i32;
|
let alt = land.get_alt_approx(wpos) as i32;
|
||||||
let start = wpos.with_z(alt - 8);
|
let start = wpos.with_z(alt);
|
||||||
let boss_room_shift = rng.gen_range(70..110);
|
let boss_room_shift = rng.gen_range(60..110);
|
||||||
let end_xy = match rng.gen_range(0..4) {
|
let end_xy = match rng.gen_range(0..4) {
|
||||||
0 => Vec2::new(start.x + boss_room_shift, start.y + boss_room_shift),
|
0 => Vec2::new(start.x + boss_room_shift, start.y + boss_room_shift),
|
||||||
1 => Vec2::new(start.x - boss_room_shift, start.y + boss_room_shift),
|
1 => Vec2::new(start.x - boss_room_shift, start.y + boss_room_shift),
|
||||||
@ -102,13 +108,15 @@ impl GnarlingFortification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (branches, terminals) =
|
let tunnel_length_range = (12.0, 27.0);
|
||||||
rrt(start, end, is_valid_edge, rng).unwrap_or((Vec::new(), Vec::new()));
|
let (branches, path, terminals) = rrt(start, end, is_valid_edge, tunnel_length_range, rng)
|
||||||
|
.unwrap_or((Vec::new(), Vec::new(), Vec::new()));
|
||||||
|
|
||||||
let tunnels = Tunnels {
|
let tunnels = Tunnels {
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
branches,
|
branches,
|
||||||
|
path,
|
||||||
terminals,
|
terminals,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1670,35 +1678,13 @@ impl Structure for GnarlingFortification {
|
|||||||
|
|
||||||
// Create tunnels beneath the fortification
|
// Create tunnels beneath the fortification
|
||||||
let wood = Fill::Brick(BlockKind::Wood, Rgb::new(55, 25, 8), 24);
|
let wood = Fill::Brick(BlockKind::Wood, Rgb::new(55, 25, 8), 24);
|
||||||
|
let dirt = Fill::Brick(BlockKind::Earth, Rgb::new(55, 25, 8), 24);
|
||||||
let alt = land.get_alt_approx(self.origin) as i32;
|
let alt = land.get_alt_approx(self.origin) as i32;
|
||||||
let entrance = painter.cylinder(Aabb {
|
let entrance_hollow = painter.line(
|
||||||
min: Vec3::new(self.tunnels.start.x - 3, self.tunnels.start.y - 3, alt),
|
self.tunnels.start,
|
||||||
max: Vec3::new(
|
self.tunnels.start.xy().with_z(alt + 10),
|
||||||
self.tunnels.start.x + 3 + 1,
|
9.0,
|
||||||
self.tunnels.start.y + 3 + 1,
|
);
|
||||||
alt + 5,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
let entrance_hollow = painter.cylinder(Aabb {
|
|
||||||
min: Vec3::new(
|
|
||||||
self.tunnels.start.x - 2,
|
|
||||||
self.tunnels.start.y - 2,
|
|
||||||
self.tunnels.start.z,
|
|
||||||
),
|
|
||||||
max: Vec3::new(
|
|
||||||
self.tunnels.start.x + 2 + 1,
|
|
||||||
self.tunnels.start.y + 2 + 1,
|
|
||||||
alt + 4,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
let entrance_door = painter.aabb(Aabb {
|
|
||||||
min: Vec3::new(self.tunnels.start.x - 1, self.tunnels.start.y, alt),
|
|
||||||
max: Vec3::new(
|
|
||||||
self.tunnels.start.x + 1 + 1,
|
|
||||||
self.tunnels.start.y + 3 + 1,
|
|
||||||
alt + 4,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
let boss_room = painter
|
let boss_room = painter
|
||||||
.sphere(Aabb {
|
.sphere(Aabb {
|
||||||
@ -1920,45 +1906,67 @@ impl Structure for GnarlingFortification {
|
|||||||
) + 14,
|
) + 14,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
let random_field = RandomField::new(self.seed);
|
||||||
|
|
||||||
let mut tunnels = painter.empty();
|
let mut tunnels = painter.empty();
|
||||||
|
let mut path_tunnels = painter.empty();
|
||||||
let mut tunnels_clear = painter.empty();
|
let mut tunnels_clear = painter.empty();
|
||||||
let mut ferns = painter.empty();
|
let mut ferns = painter.empty();
|
||||||
let mut scatter = painter.empty();
|
let mut velorite_ores = painter.empty();
|
||||||
|
let mut fire_bowls = painter.empty();
|
||||||
|
let mut fern_scatter = painter.empty();
|
||||||
|
let mut velorite_scatter = painter.empty();
|
||||||
|
let mut fire_bowl_scatter = painter.empty();
|
||||||
for branch in self.tunnels.branches.iter() {
|
for branch in self.tunnels.branches.iter() {
|
||||||
let tunnel_radius_i32 = 5 + branch.0.x % 4;
|
let tunnel_radius_i32 = 4 + branch.0.x % 4;
|
||||||
|
let in_path =
|
||||||
|
self.tunnels.path.contains(&branch.0) && self.tunnels.path.contains(&branch.1);
|
||||||
let tunnel_radius = tunnel_radius_i32 as f32;
|
let tunnel_radius = tunnel_radius_i32 as f32;
|
||||||
let tunnel = painter.line(branch.0, branch.1, tunnel_radius);
|
let start = branch.0;
|
||||||
let tunnel_clear = painter.line(branch.0, branch.1, tunnel_radius - 1.0);
|
let end = branch.1;
|
||||||
|
let ctrl0_offset = start.x % 6 * if start.y % 2 == 0 { -1 } else { 1 };
|
||||||
|
let ctrl1_offset = end.x % 6 * if end.y % 2 == 0 { -1 } else { 1 };
|
||||||
|
let ctrl0 = (((start + end) / 2) + start) / 2 + ctrl0_offset;
|
||||||
|
let ctrl1 = (((start + end) / 2) + end) / 2 + ctrl1_offset;
|
||||||
|
let tunnel = painter.cubic_bezier(start, ctrl0, ctrl1, end, tunnel_radius);
|
||||||
|
let tunnel_clear = painter.cubic_bezier(start, ctrl0, ctrl1, end, tunnel_radius - 1.0);
|
||||||
|
|
||||||
let min_z = branch.0.z.min(branch.1.z);
|
let min_z = branch.0.z.min(branch.1.z);
|
||||||
let max_z = branch.0.z.max(branch.1.z);
|
let max_z = branch.0.z.max(branch.1.z);
|
||||||
for i in branch.0.x - tunnel_radius_i32..branch.1.x + tunnel_radius_i32 {
|
for i in branch.0.x - tunnel_radius_i32..branch.1.x + tunnel_radius_i32 {
|
||||||
for j in branch.0.y - tunnel_radius_i32..branch.1.y + tunnel_radius_i32 {
|
for j in branch.0.y - tunnel_radius_i32..branch.1.y + tunnel_radius_i32 {
|
||||||
if i % 2 == 0 && j % 2 == 0 {
|
if random_field.get(Vec3::new(i, j, min_z)) % 6 == 0 {
|
||||||
scatter = scatter.union(painter.aabb(Aabb {
|
fern_scatter = fern_scatter.union(painter.aabb(Aabb {
|
||||||
|
min: Vec3::new(i, j, min_z),
|
||||||
|
max: Vec3::new(i + 1, j + 1, max_z),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if random_field.get(Vec3::new(i, j, min_z)) % 30 == 0 {
|
||||||
|
velorite_scatter = velorite_scatter.union(painter.aabb(Aabb {
|
||||||
|
min: Vec3::new(i, j, min_z),
|
||||||
|
max: Vec3::new(i + 1, j + 1, max_z),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if random_field.get(Vec3::new(i, j, min_z)) % 30 == 0 {
|
||||||
|
fire_bowl_scatter = fire_bowl_scatter.union(painter.aabb(Aabb {
|
||||||
min: Vec3::new(i, j, min_z),
|
min: Vec3::new(i, j, min_z),
|
||||||
max: Vec3::new(i + 1, j + 1, max_z),
|
max: Vec3::new(i + 1, j + 1, max_z),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let fern_clear = painter
|
let fern = tunnel_clear.intersect(fern_scatter);
|
||||||
.line(
|
let velorite = tunnel_clear.intersect(velorite_scatter);
|
||||||
branch.0 + Vec3::unit_z(),
|
let fire_bowl = tunnel_clear.intersect(fire_bowl_scatter);
|
||||||
branch.1 + Vec3::unit_z(),
|
if in_path {
|
||||||
tunnel_radius - 1.0,
|
path_tunnels = path_tunnels.union(tunnel);
|
||||||
)
|
} else {
|
||||||
.union(painter.sphere(Aabb {
|
tunnels = tunnels.union(tunnel);
|
||||||
min: branch.0 - (tunnel_radius_i32 + 1),
|
}
|
||||||
max: branch.0 + (tunnel_radius_i32 + 1),
|
|
||||||
}))
|
|
||||||
.union(painter.sphere(Aabb {
|
|
||||||
min: branch.1 - (tunnel_radius_i32 + 1),
|
|
||||||
max: branch.1 + (tunnel_radius_i32 + 1),
|
|
||||||
}));
|
|
||||||
let fern = tunnel_clear.without(fern_clear).intersect(scatter);
|
|
||||||
tunnels = tunnels.union(tunnel);
|
|
||||||
tunnels_clear = tunnels_clear.union(tunnel_clear);
|
tunnels_clear = tunnels_clear.union(tunnel_clear);
|
||||||
ferns = ferns.union(fern);
|
ferns = ferns.union(fern);
|
||||||
|
velorite_ores = velorite_ores.union(velorite);
|
||||||
|
fire_bowls = fire_bowls.union(fire_bowl);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rooms = painter.empty();
|
let mut rooms = painter.empty();
|
||||||
@ -1966,7 +1974,6 @@ impl Structure for GnarlingFortification {
|
|||||||
let mut chests_ori_0 = painter.empty();
|
let mut chests_ori_0 = painter.empty();
|
||||||
let mut chests_ori_2 = painter.empty();
|
let mut chests_ori_2 = painter.empty();
|
||||||
let mut chests_ori_4 = painter.empty();
|
let mut chests_ori_4 = painter.empty();
|
||||||
let mut fire_bowls = painter.empty();
|
|
||||||
for terminal in self.tunnels.terminals.iter() {
|
for terminal in self.tunnels.terminals.iter() {
|
||||||
let room = painter.sphere(Aabb {
|
let room = painter.sphere(Aabb {
|
||||||
min: terminal - 8,
|
min: terminal - 8,
|
||||||
@ -1987,7 +1994,7 @@ impl Structure for GnarlingFortification {
|
|||||||
fire_bowls = fire_bowls.union(fire_bowl);
|
fire_bowls = fire_bowls.union(fire_bowl);
|
||||||
|
|
||||||
// Chest
|
// Chest
|
||||||
let chest_seed = terminal.x % 5;
|
let chest_seed = random_field.get(*terminal) % 5;
|
||||||
if chest_seed < 4 {
|
if chest_seed < 4 {
|
||||||
let chest_pos = Vec3::new(terminal.x, terminal.y - 4, terminal.z - 6);
|
let chest_pos = Vec3::new(terminal.x, terminal.y - 4, terminal.z - 6);
|
||||||
let chest = painter.aabb(Aabb {
|
let chest = painter.aabb(Aabb {
|
||||||
@ -2013,17 +2020,23 @@ impl Structure for GnarlingFortification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entrance.fill(wood.clone());
|
|
||||||
tunnels.fill(wood.clone());
|
tunnels.fill(wood.clone());
|
||||||
|
path_tunnels.fill(dirt);
|
||||||
rooms.fill(wood.clone());
|
rooms.fill(wood.clone());
|
||||||
boss_room.fill(wood);
|
boss_room.fill(wood);
|
||||||
|
|
||||||
// Clear out insides after filling the walls in
|
// Clear out insides after filling the walls in
|
||||||
entrance_hollow.clear();
|
let cavern_clear = tunnels_clear.union(rooms_clear).union(boss_room_clear);
|
||||||
entrance_door.clear();
|
let sprite_clear = cavern_clear
|
||||||
rooms_clear.clear();
|
.translate(Vec3::new(0, 0, 1))
|
||||||
|
.intersect(cavern_clear);
|
||||||
|
cavern_clear.clear();
|
||||||
|
|
||||||
|
// Place sprites
|
||||||
|
ferns.fill(Fill::Block(Block::air(SpriteKind::JungleFern)));
|
||||||
|
velorite_ores.fill(Fill::Block(Block::air(SpriteKind::Velorite)));
|
||||||
|
fire_bowls.fill(Fill::Block(Block::air(SpriteKind::FireBowlGround)));
|
||||||
|
|
||||||
// Place room sprites after hollowing out
|
|
||||||
chests_ori_0.fill(Fill::Block(
|
chests_ori_0.fill(Fill::Block(
|
||||||
Block::air(SpriteKind::DungeonChest0).with_ori(0).unwrap(),
|
Block::air(SpriteKind::DungeonChest0).with_ori(0).unwrap(),
|
||||||
));
|
));
|
||||||
@ -2034,22 +2047,8 @@ impl Structure for GnarlingFortification {
|
|||||||
Block::air(SpriteKind::DungeonChest0).with_ori(4).unwrap(),
|
Block::air(SpriteKind::DungeonChest0).with_ori(4).unwrap(),
|
||||||
));
|
));
|
||||||
|
|
||||||
// Clear tunnels out after room sprites to prevent floating chests
|
entrance_hollow.clear();
|
||||||
tunnels_clear.clear();
|
sprite_clear.clear();
|
||||||
|
|
||||||
// Place ferns in tunnels
|
|
||||||
ferns.fill(Fill::Block(Block::air(SpriteKind::JungleFern)));
|
|
||||||
|
|
||||||
// Place lights after ferns to ensure there is a light
|
|
||||||
fire_bowls.fill(Fill::Block(Block::air(SpriteKind::FireBowlGround)));
|
|
||||||
|
|
||||||
// Finally clear boss room
|
|
||||||
boss_room_clear.clear();
|
|
||||||
|
|
||||||
//painter.fill(
|
|
||||||
// scatter,
|
|
||||||
// Fill::Block(Block::new(BlockKind::Wood, Rgb::new(255, 0, 0))),
|
|
||||||
//);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2106,8 +2105,9 @@ fn rrt<F>(
|
|||||||
start: Vec3<i32>,
|
start: Vec3<i32>,
|
||||||
end: Vec3<i32>,
|
end: Vec3<i32>,
|
||||||
is_valid_edge: F,
|
is_valid_edge: F,
|
||||||
|
radius_range: (f32, f32),
|
||||||
rng: &mut impl Rng,
|
rng: &mut impl Rng,
|
||||||
) -> Option<(Vec<(Vec3<i32>, Vec3<i32>)>, Vec<Vec3<i32>>)>
|
) -> Option<(Vec<(Vec3<i32>, Vec3<i32>)>, Vec<Vec3<i32>>, Vec<Vec3<i32>>)>
|
||||||
where
|
where
|
||||||
F: Fn(Vec3<i32>, Vec3<i32>) -> bool,
|
F: Fn(Vec3<i32>, Vec3<i32>) -> bool,
|
||||||
{
|
{
|
||||||
@ -2121,12 +2121,8 @@ where
|
|||||||
let start = start.map(|a| (a + 1) as f32);
|
let start = start.map(|a| (a + 1) as f32);
|
||||||
let end = end.map(|a| (a + 1) as f32);
|
let end = end.map(|a| (a + 1) as f32);
|
||||||
|
|
||||||
let min_x = start.x.min(end.x);
|
let min = Vec3::new(start.x.min(end.x), start.y.min(end.y), start.z.min(end.z));
|
||||||
let max_x = start.x.max(end.x);
|
let max = Vec3::new(start.x.max(end.x), start.y.max(end.y), start.z.max(end.z));
|
||||||
let min_y = start.y.min(end.y);
|
|
||||||
let max_y = start.y.max(end.y);
|
|
||||||
let min_z = start.z.min(end.z);
|
|
||||||
let max_z = start.z.max(end.z);
|
|
||||||
|
|
||||||
kdtree.add(&[start.x, start.y, start.z], node_index).ok()?;
|
kdtree.add(&[start.x, start.y, start.z], node_index).ok()?;
|
||||||
nodes.push(start);
|
nodes.push(start);
|
||||||
@ -2134,15 +2130,15 @@ where
|
|||||||
let mut connect = false;
|
let mut connect = false;
|
||||||
|
|
||||||
for _i in 0..7000 {
|
for _i in 0..7000 {
|
||||||
let radius: f32 = rng.gen_range(12.0..22.0);
|
let radius: f32 = rng.gen_range(radius_range.0..radius_range.1);
|
||||||
let radius_sqrd = radius.powi(2);
|
let radius_sqrd = radius.powi(2);
|
||||||
if connect {
|
if connect {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let sampled_point = Vec3::new(
|
let sampled_point = Vec3::new(
|
||||||
rng.gen_range(min_x - 20.0..max_x + 20.0),
|
rng.gen_range(min.x - 20.0..max.x + 20.0),
|
||||||
rng.gen_range(min_y - 20.0..max_y + 20.0),
|
rng.gen_range(min.y - 20.0..max.y + 20.0),
|
||||||
rng.gen_range(min_z - 5.0..max_z - 7.0),
|
rng.gen_range(min.z - 20.0..max.z - 7.0),
|
||||||
);
|
);
|
||||||
let nearest_index = *kdtree
|
let nearest_index = *kdtree
|
||||||
.nearest_one(
|
.nearest_one(
|
||||||
@ -2188,7 +2184,6 @@ where
|
|||||||
current_node_index = *parents.get(¤t_node_index).unwrap();
|
current_node_index = *parents.get(¤t_node_index).unwrap();
|
||||||
path.push(nodes[current_node_index]);
|
path.push(nodes[current_node_index]);
|
||||||
}
|
}
|
||||||
path.reverse();
|
|
||||||
|
|
||||||
let mut terminals = Vec::new();
|
let mut terminals = Vec::new();
|
||||||
let last = nodes.len() - 1;
|
let last = nodes.len() - 1;
|
||||||
@ -2207,8 +2202,12 @@ where
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<(Vec3<i32>, Vec3<i32>)>>();
|
.collect::<Vec<(Vec3<i32>, Vec3<i32>)>>();
|
||||||
|
let path = path
|
||||||
|
.iter()
|
||||||
|
.map(|a| a.map(|e| e.floor() as i32))
|
||||||
|
.collect::<Vec<Vec3<i32>>>();
|
||||||
|
|
||||||
Some((branches, terminals))
|
Some((branches, path, terminals))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Loading…
Reference in New Issue
Block a user