Various improvements to castles, dungeons and more

This commit is contained in:
Joshua Barretto 2020-07-30 00:14:06 +01:00
parent 0bad704719
commit 9bb10a6d00
8 changed files with 137 additions and 69 deletions

View File

@ -22,6 +22,7 @@ pub mod event;
pub mod figure;
pub mod generation;
pub mod loadout_builder;
pub mod lottery;
pub mod msg;
pub mod npc;
pub mod outcome;
@ -39,6 +40,5 @@ pub mod terrain;
pub mod util;
pub mod vol;
pub mod volumes;
pub mod lottery;
pub use loadout_builder::LoadoutBuilder;

View File

@ -151,6 +151,7 @@ impl<'a> System<'a> for Sys {
const SEARCH_DIST: f32 = 48.0;
const SIGHT_DIST: f32 = 128.0;
const MIN_ATTACK_DIST: f32 = 3.5;
const MAX_FLEE_DIST: f32 = 32.0;
let scale = scales.get(entity).map(|s| s.0).unwrap_or(1.0);
@ -306,27 +307,31 @@ impl<'a> System<'a> for Sys {
// Flee
if 1.0 - agent.psyche.aggro > damage {
if let Some((bearing, speed)) = chaser.chase(
&*terrain,
pos.0,
vel.0,
// Away from the target (ironically)
tgt_pos.0 + (pos.0 - tgt_pos.0)
.try_normalized()
.unwrap_or_else(Vec3::unit_y) * 32.0,
TraversalConfig {
node_tolerance,
slow_factor,
on_ground: physics_state.on_ground,
min_tgt_dist: 1.25,
},
) {
inputs.move_dir = Vec2::from(bearing)
.try_normalized()
.unwrap_or(Vec2::zero())
* speed;
inputs.jump.set_state(bearing.z > 1.5);
inputs.swim.set_state(bearing.z > 0.5);
if dist_sqrd < MAX_FLEE_DIST.powf(2.0) {
if let Some((bearing, speed)) = chaser.chase(
&*terrain,
pos.0,
vel.0,
// Away from the target (ironically)
pos.0 + (pos.0 - tgt_pos.0)
.try_normalized()
.unwrap_or_else(Vec3::unit_y) * 8.0,
TraversalConfig {
node_tolerance,
slow_factor,
on_ground: physics_state.on_ground,
min_tgt_dist: 1.25,
},
) {
inputs.move_dir = Vec2::from(bearing)
.try_normalized()
.unwrap_or(Vec2::zero())
* speed;
inputs.jump.set_state(bearing.z > 1.5);
inputs.swim.set_state(bearing.z > 0.5);
}
} else {
do_idle = true;
}
} else if dist_sqrd < (MIN_ATTACK_DIST * scale).powf(2.0) {
// Close-range attack

View File

@ -157,9 +157,9 @@ impl<'a> System<'a> for Sys {
z_max,
} => {
// Scale collider
let radius = *radius * scale;
let z_min = *z_min * scale;
let z_max = *z_max * scale;
let radius = *radius;// * scale;
let z_min = *z_min;// * scale;
let z_max = *z_max;// * scale;
// Probe distances
let hdist = radius.ceil() as i32;

View File

@ -319,12 +319,12 @@ impl<'a> System<'a> for Sys {
pos: Pos(entity.pos),
stats,
loadout,
body,
agent: if entity.has_agency {
Some(comp::Agent::new(entity.pos, can_speak))
Some(comp::Agent::new(entity.pos, can_speak, &body))
} else {
None
},
body,
alignment,
scale: comp::Scale(scale),
drop_item: entity.loot_drop,

View File

@ -4,13 +4,16 @@ use crate::{
Index,
};
use common::{
assets,
lottery::Lottery,
terrain::{Block, BlockKind},
vol::{BaseVol, ReadVol, RectSizedVol, Vox, WriteVol},
lottery::Lottery,
assets,
};
use noise::NoiseFn;
use std::{f32, ops::{Sub, Mul}};
use std::{
f32,
ops::{Mul, Sub},
};
use vek::*;
pub fn apply_paths_to<'a>(
@ -136,28 +139,49 @@ pub fn apply_caves_to<'a>(
let cave_roof = (cave.alt + cave_height) as i32;
for z in cave_base..cave_roof {
let _ = vol.set(Vec3::new(offs.x, offs.y, z), Block::empty());
if cave_x < 0.95
|| index.noise.cave_nz.get(
Vec3::new(wpos2d.x, wpos2d.y, z)
.map(|e| e as f64 * 0.15)
.into_array(),
) < 0.0
{
let _ = vol.set(Vec3::new(offs.x, offs.y, z), Block::empty());
}
}
// Stalagtites
let stalagtites = index.noise.cave_nz
.get(wpos2d.map(|e| e as f64 * 0.1).into_array())
.sub(0.6)
let stalagtites = index
.noise
.cave_nz
.get(wpos2d.map(|e| e as f64 * 0.125).into_array())
.sub(0.5)
.max(0.0)
.mul((col_sample.alt - cave_roof as f32 - 5.0).mul(0.15).clamped(0.0, 1.0) as f64)
.mul(40.0) as i32;
.mul(
(col_sample.alt - cave_roof as f32 - 5.0)
.mul(0.15)
.clamped(0.0, 1.0) as f64,
)
.mul(45.0) as i32;
for z in cave_roof - stalagtites..cave_roof {
let _ = vol.set(Vec3::new(offs.x, offs.y, z), Block::new(BlockKind::Normal, Rgb::broadcast(200)));
let _ = vol.set(
Vec3::new(offs.x, offs.y, z),
Block::new(BlockKind::Rock, Rgb::broadcast(200)),
);
}
// Scatter things in caves
if RandomField::new(index.seed).chance(wpos2d.into(), 0.001) && cave_base < surface_z as i32 - 25 {
if RandomField::new(index.seed).chance(wpos2d.into(), 0.001)
&& cave_base < surface_z as i32 - 25
{
let kind = *assets::load_expect::<Lottery<BlockKind>>("common.cave_scatter")
.choose_seeded(RandomField::new(index.seed + 1).get(wpos2d.into()));
let _ = vol.set(Vec3::new(offs.x, offs.y, cave_base), Block::new(kind, Rgb::zero()));
let _ = vol.set(
Vec3::new(offs.x, offs.y, cave_base),
Block::new(kind, Rgb::zero()),
);
}
}
}
}

View File

@ -33,7 +33,7 @@ use vek::*;
struct Keep {
offset: Vec2<i32>,
locus: i32,
height: i32,
storeys: i32,
is_tower: bool,
alt: i32,
}
@ -123,12 +123,12 @@ impl Castle {
let locus = ctx.rng.gen_range(20, 26);
let offset = (dir * dist).map(|e| e as i32);
let height = ctx.rng.gen_range(25, 70).clamped(30, 48);
let storeys = ctx.rng.gen_range(1, 5).clamped(2, 3);
Keep {
offset,
locus,
height,
storeys,
is_tower: true,
alt: ctx
.sim
@ -301,7 +301,7 @@ impl Castle {
4,
0,
&Attr {
height: 16,
storeys: 1,
is_tower: false,
ridged: false,
rounded: true,
@ -336,7 +336,7 @@ impl Castle {
tower_locus,
0,
&Attr {
height: 28,
storeys: 2,
is_tower: true,
ridged: false,
rounded: self.rounded_towers,
@ -371,7 +371,7 @@ impl Castle {
keep.locus,
0,
&Attr {
height: keep.height,
storeys: keep.storeys,
is_tower: keep.is_tower,
ridged: true,
rounded: self.rounded_towers,

View File

@ -408,10 +408,12 @@ impl Floor {
* FLOOR_SIZE.x as f32
/ 2.0
- 8.0;
supplement.add_entity(
EntityInfo::at((origin + stair_rcenter).map(|e| e as f32) + Vec3::from(offs))
.into_waypoint(),
);
if !self.final_level {
supplement.add_entity(
EntityInfo::at((origin + stair_rcenter).map(|e| e as f32) + Vec3::from(offs))
.into_waypoint(),
);
}
}
for x in area.min.x..area.max.x {

View File

@ -1,5 +1,8 @@
use super::{super::skeleton::*, Archetype};
use crate::site::BlockMask;
use crate::{
site::BlockMask,
util::{RandomField, Sampler},
};
use common::{
terrain::{Block, BlockKind},
vol::Vox,
@ -12,7 +15,7 @@ pub struct Keep {
}
pub struct Attr {
pub height: i32,
pub storeys: i32,
pub is_tower: bool,
pub ridged: bool,
pub rounded: bool,
@ -29,7 +32,7 @@ impl Archetype for Keep {
root: Branch {
len,
attr: Attr {
height: rng.gen_range(12, 16),
storeys: 1,
is_tower: false,
ridged: false,
rounded: true,
@ -43,12 +46,12 @@ impl Archetype for Keep {
Branch {
len: 0,
attr: Attr {
height: rng.gen_range(20, 28),
storeys: 2,
is_tower: true,
ridged: false,
rounded: true,
},
locus: 4 + rng.gen_range(0, 5),
locus: 6 + rng.gen_range(0, 3),
border: 3,
children: Vec::new(),
},
@ -93,8 +96,10 @@ impl Archetype for Keep {
)
};
let foundation = make_block(100, 100, 100);
let wall = make_block(100, 100, 110);
let brick_tex_pos = (pos + Vec3::new(pos.z, pos.z, 0)) / Vec3::new(2, 2, 1);
let brick_tex = RandomField::new(0).get(brick_tex_pos) as u8 % 24;
let foundation = make_block(80 + brick_tex, 80 + brick_tex, 80 + brick_tex);
let wall = make_block(100 + brick_tex, 100 + brick_tex, 110 + brick_tex);
let floor = make_block(
80 + (pos.y.abs() % 2) as u8 * 15,
60 + (pos.y.abs() % 2) as u8 * 15,
@ -107,6 +112,26 @@ impl Archetype for Keep {
let internal = BlockMask::new(Block::empty(), internal_layer);
let empty = BlockMask::nothing();
let make_staircase = move |pos: Vec3<i32>, radius: f32, inner_radius: f32, stretch: f32| {
let stone = BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(150, 150, 175)), 5);
if (pos.xy().magnitude_squared() as f32) < inner_radius.powf(2.0) {
stone
} else if (pos.xy().magnitude_squared() as f32) < radius.powf(2.0) {
if ((pos.x as f32).atan2(pos.y as f32) / (std::f32::consts::PI * 2.0) * stretch
+ pos.z as f32)
.rem_euclid(stretch)
< 1.5
{
stone
} else {
internal
}
} else {
BlockMask::nothing()
}
};
let edge_pos = if (bound_offset.x.abs() > bound_offset.y.abs()) ^ (ori == Ori::East) {
pos.y
} else {
@ -114,15 +139,16 @@ impl Archetype for Keep {
};
let width = locus
+ if edge_pos % 4 == 0 && attr.ridged && !attr.rounded {
+ if (edge_pos + 1000) % 8 < 4 && attr.ridged && !attr.rounded {
1
} else {
0
};
let rampart_width = 2 + width;
let ceil_height = attr.height;
let storey_height = 16;
let roof_height = attr.storeys * storey_height;
let door_height = 6;
let rampart_height = ceil_height + if edge_pos % 2 == 0 { 3 } else { 4 };
let rampart_height = roof_height + if edge_pos % 2 == 0 { 3 } else { 4 };
let min_dist = if attr.rounded {
bound_offset.map(|e| e.pow(2) as f32).sum().powf(0.5) as i32
} else {
@ -132,31 +158,32 @@ impl Archetype for Keep {
if profile.y <= 0 - (min_dist - width - 1).max(0) && min_dist < width + 3 {
// Foundations
foundation
} else if profile.y == ceil_height && min_dist < rampart_width {
} else if (0..=roof_height).contains(&profile.y) && profile.y % storey_height == 0 && min_dist < rampart_width {
if min_dist < width { floor } else { wall }
} else if !attr.is_tower
&& bound_offset.x.abs() == 4
&& min_dist == width + 1
&& profile.y < ceil_height
&& profile.y < roof_height
{
wall
} else if bound_offset.x.abs() < 3
&& profile.y < door_height - bound_offset.x.abs()
&& profile.y > 0
&& min_dist >= width - 2
{
internal
} else if min_dist == width && profile.y <= ceil_height {
} else if min_dist == width && profile.y <= roof_height {
wall
} else if profile.y >= ceil_height {
if profile.y > ceil_height && min_dist < rampart_width {
if attr.is_tower && center_offset == Vec2::zero() && profile.y < ceil_height + 16 {
} else if profile.y >= roof_height {
if profile.y > roof_height && min_dist < rampart_width {
if attr.is_tower && center_offset == Vec2::zero() && profile.y < roof_height + 16 {
pole
} else if attr.is_tower
&& center_offset.x == 0
&& center_offset.y > 0
&& center_offset.y < 8
&& profile.y > ceil_height + 8
&& profile.y < ceil_height + 14
&& profile.y > roof_height + 8
&& profile.y < roof_height + 14
{
flag
} else {
@ -171,10 +198,20 @@ impl Archetype for Keep {
} else {
empty
}
} else if profile.y < ceil_height && min_dist < width {
} else if profile.y < roof_height && min_dist < width {
internal
} else {
empty
}
.resolve_with(if attr.is_tower && profile.y > 0 && profile.y <= roof_height {
make_staircase(
Vec3::new(center_offset.x, center_offset.y, pos.z),
7.0f32.min(width as f32 - 1.0),
0.5,
9.0,
)
} else {
BlockMask::nothing()
})
}
}