Merge branch 'fix-dungeon-collision' into 'master'

Fix dungeon collision

See merge request veloren/veloren!3131
This commit is contained in:
Joshua Barretto 2022-01-28 14:07:01 +00:00
commit cb45cea6a0

View File

@ -112,7 +112,7 @@ impl Civs {
29..=31 => (SiteKind::Tree, 4), 29..=31 => (SiteKind::Tree, 4),
_ => (SiteKind::Dungeon, 0), _ => (SiteKind::Dungeon, 0),
}; };
let loc = find_site_loc(&mut ctx, None, size)?; let loc = find_site_loc(&mut ctx, None, size, kind)?;
Some(this.establish_site(&mut ctx.reseed(), loc, |place| Site { Some(this.establish_site(&mut ctx.reseed(), loc, |place| Site {
kind, kind,
center: loc, center: loc,
@ -437,7 +437,7 @@ impl Civs {
fn birth_civ(&mut self, ctx: &mut GenCtx<impl Rng>) -> Option<Id<Civ>> { fn birth_civ(&mut self, ctx: &mut GenCtx<impl Rng>) -> Option<Id<Civ>> {
let site = attempt(5, || { let site = attempt(5, || {
let loc = find_site_loc(ctx, None, 1)?; let loc = find_site_loc(ctx, None, 1, SiteKind::Settlement)?;
Some(self.establish_site(ctx, loc, |place| Site { Some(self.establish_site(ctx, loc, |place| Site {
kind: SiteKind::Settlement, kind: SiteKind::Settlement,
site_tmp: None, site_tmp: None,
@ -911,14 +911,26 @@ fn loc_suitable_for_walking(sim: &WorldSim, loc: Vec2<i32>) -> bool {
/// Return true if a site could be constructed between a location and a chunk /// Return true if a site could be constructed between a location and a chunk
/// next to it is permitted (TODO: by whom?) /// next to it is permitted (TODO: by whom?)
fn site_in_dir(sim: &WorldSim, a: Vec2<i32>, dir: Vec2<i32>) -> bool { fn site_in_dir(sim: &WorldSim, a: Vec2<i32>, dir: Vec2<i32>, site_kind: SiteKind) -> bool {
loc_suitable_for_site(sim, a) && loc_suitable_for_site(sim, a + dir) loc_suitable_for_site(sim, a, site_kind) && loc_suitable_for_site(sim, a + dir, site_kind)
} }
/// Return true if a position is suitable for site construction (TODO: /// Return true if a position is suitable for site construction (TODO:
/// criteria?) /// criteria?)
fn loc_suitable_for_site(sim: &WorldSim, loc: Vec2<i32>) -> bool { fn loc_suitable_for_site(sim: &WorldSim, loc: Vec2<i32>, site_kind: SiteKind) -> bool {
if let Some(chunk) = sim.get(loc) { fn check_chunk_occupation(sim: &WorldSim, loc: Vec2<i32>, radius: i32) -> bool {
for x in (-radius)..radius {
for y in (-radius)..radius {
let check_loc =
loc + Vec2::new(x, y).map2(TerrainChunkSize::RECT_SIZE, |e, sz| e * sz as i32);
if sim.get(check_loc).map_or(true, |c| !c.sites.is_empty()) {
return false;
}
}
}
true
}
(if let Some(chunk) = sim.get(loc) {
!chunk.river.is_ocean() !chunk.river.is_ocean()
&& !chunk.river.is_lake() && !chunk.river.is_lake()
&& !chunk.river.is_river() && !chunk.river.is_river()
@ -928,7 +940,7 @@ fn loc_suitable_for_site(sim: &WorldSim, loc: Vec2<i32>) -> bool {
.unwrap_or(false) .unwrap_or(false)
} else { } else {
false false
} }) && check_chunk_occupation(sim, loc, site_kind.exclusion_radius())
} }
/// Attempt to search for a location that's suitable for site construction /// Attempt to search for a location that's suitable for site construction
@ -936,6 +948,7 @@ fn find_site_loc(
ctx: &mut GenCtx<impl Rng>, ctx: &mut GenCtx<impl Rng>,
near: Option<(Vec2<i32>, f32)>, near: Option<(Vec2<i32>, f32)>,
size: i32, size: i32,
site_kind: SiteKind,
) -> Option<Vec2<i32>> { ) -> Option<Vec2<i32>> {
const MAX_ATTEMPTS: usize = 100; const MAX_ATTEMPTS: usize = 100;
let mut loc = None; let mut loc = None;
@ -957,7 +970,7 @@ fn find_site_loc(
}); });
for offset in Spiral2d::new().take((size * 2 + 1).pow(2) as usize) { for offset in Spiral2d::new().take((size * 2 + 1).pow(2) as usize) {
if loc_suitable_for_site(ctx.sim, test_loc + offset) { if loc_suitable_for_site(ctx.sim, test_loc + offset, site_kind) {
return Some(test_loc); return Some(test_loc);
} }
} }
@ -1015,7 +1028,7 @@ impl fmt::Display for Site {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum SiteKind { pub enum SiteKind {
Settlement, Settlement,
Dungeon, Dungeon,
@ -1024,6 +1037,16 @@ pub enum SiteKind {
Tree, Tree,
} }
impl SiteKind {
pub fn exclusion_radius(&self) -> i32 {
// FIXME: Provide specific values for each individual SiteKind
match self {
SiteKind::Dungeon => 4,
_ => 2, // This is just an arbitrary value
}
}
}
impl Site { impl Site {
pub fn is_dungeon(&self) -> bool { matches!(self.kind, SiteKind::Dungeon) } pub fn is_dungeon(&self) -> bool { matches!(self.kind, SiteKind::Dungeon) }