Addressed feedback

This commit is contained in:
Sam 2022-02-12 20:52:01 -05:00
parent 49e8803ee0
commit c77270b799
10 changed files with 120 additions and 63 deletions

1
Cargo.lock generated
View File

@ -6656,7 +6656,6 @@ dependencies = [
"fxhash",
"hashbrown 0.11.2",
"image",
"inline_tweak",
"itertools",
"kiddo 0.2.1",
"lazy_static",

View File

@ -700,6 +700,7 @@ impl Body {
_ => 1000,
},
Body::Golem(golem) => match golem.species {
golem::Species::WoodGolem => 200,
golem::Species::ClayGolem => 450,
_ => 1000,
},
@ -778,7 +779,14 @@ impl Body {
_ => false,
},
BuffKind::Regeneration => {
matches!(self, Body::Object(object::Body::GnarlingTotemGreen))
matches!(
self,
Body::Object(
object::Body::GnarlingTotemRed
| object::Body::GnarlingTotemGreen
| object::Body::GnarlingTotemWhite
)
)
},
_ => false,
}

View File

@ -142,10 +142,24 @@ impl<'a> AgentData<'a> {
..self.traversal_config
},
) {
controller.inputs.move_dir =
-bearing.xy().try_normalized().unwrap_or_else(Vec2::zero);
if !self.char_state.is_attack() {
controller.inputs.look_dir = -controller.inputs.look_dir;
let flee_dir = -bearing.xy().try_normalized().unwrap_or_else(Vec2::zero);
let pos = self.pos.0.xy().with_z(self.pos.0.z + 1.5);
if read_data
.terrain
.ray(pos, pos + flee_dir * 2.0)
.until(|b| b.is_solid() || b.get_sprite().is_none())
.cast()
.0
> 1.0
{
// If able to flee, flee
controller.inputs.move_dir = flee_dir;
if !self.char_state.is_attack() {
controller.inputs.look_dir = -controller.inputs.look_dir;
}
} else {
// Otherwise, fight to the death
controller.push_basic_input(InputKind::Primary);
}
}
} else if attack_data.dist_sqrd < PREF_DIST.powi(2) {
@ -2272,7 +2286,21 @@ impl<'a> AgentData<'a> {
} else if agent.action_state.timer > TOTEM_TIMER {
// If time to summon a totem, do it
let input = rng.gen_range(1..=3);
controller.push_basic_input(InputKind::Ability(input));
let buff_kind = match input {
2 => Some(BuffKind::Regeneration),
3 => Some(BuffKind::Hastened),
_ => None,
};
if buff_kind.map_or(true, |b| self.has_buff(read_data, b))
&& matches!(self.char_state, CharacterState::Wielding { .. })
{
// If already under effects of buff from totem that would be summoned, don't
// summon totem (doesn't work for red totems since that applies debuff to
// enemies instead)
agent.action_state.timer = 0.0;
} else {
controller.push_basic_input(InputKind::Ability(input));
}
} else if agent.action_state.counter > HEAVY_ATTACK_WAIT_TIME {
// Else if time for a heavy attack
if attack_data.in_min_range() {

View File

@ -1,4 +1,4 @@
use crate::sys::agent::ReadData;
use crate::sys::agent::{AgentData, ReadData};
use common::{
comp::{buff::BuffKind, Alignment, Pos},
consts::GRAVITY,
@ -70,3 +70,12 @@ pub fn aim_projectile(speed: f32, pos: Vec3<f32>, tgt: Vec3<f32>) -> Option<Dir>
pub fn get_entity_by_id(id: u64, read_data: &ReadData) -> Option<EcsEntity> {
read_data.uid_allocator.retrieve_entity_internal(id)
}
impl<'a> AgentData<'a> {
pub fn has_buff(&self, read_data: &ReadData, buff: BuffKind) -> bool {
read_data
.buffs
.get(*self.entity)
.map_or(false, |b| b.kinds.contains_key(&buff))
}
}

View File

@ -35,7 +35,7 @@ packed_simd = { package = "packed_simd_2", version = "0.3.5", optional = true }
rayon = "1.5"
serde = { version = "1.0.110", features = ["derive"] }
ron = { version = "0.7", default-features = false }
inline_tweak = "1.0.2"
# inline_tweak = "1.0.2"
kiddo = "0.2"
# compression benchmarks

View File

@ -137,7 +137,7 @@ impl Civs {
SiteKind::Refactor => (32i32, 10.0),
SiteKind::Tree => (12i32, 8.0),
SiteKind::GiantTree => (12i32, 8.0),
SiteKind::Gnarling => (16i32, 5.0),
SiteKind::Gnarling => (16i32, 10.0),
};
let (raise, raise_dist, make_waypoint): (f32, i32, bool) = match &site.kind {

View File

@ -44,7 +44,7 @@ use crate::{
column::ColumnGen,
index::Index,
layer::spot::Spot,
site::SiteKind,
site::{SiteKind, SpawnRules},
util::{Grid, Sampler},
};
use common::{
@ -410,7 +410,16 @@ impl World {
};
if sim_chunk.contains_waypoint {
supplement.add_entity(EntityInfo::at(gen_entity_pos(&mut dynamic_rng)).into_waypoint());
let waypoint_pos = gen_entity_pos(&mut dynamic_rng);
if sim_chunk
.sites
.iter()
.map(|site| index.sites[*site].spawn_rules(waypoint_pos.xy().as_()))
.fold(SpawnRules::default(), |a, b| a.combine(b))
.waypoints
{
supplement.add_entity(EntityInfo::at(waypoint_pos).into_waypoint());
}
}
// Apply layer supplement

View File

@ -27,6 +27,7 @@ pub struct SpawnRules {
pub trees: bool,
pub max_warp: f32,
pub paths: bool,
pub waypoints: bool,
}
impl SpawnRules {
@ -37,6 +38,7 @@ impl SpawnRules {
trees: self.trees && other.trees,
max_warp: self.max_warp.min(other.max_warp),
paths: self.paths && other.paths,
waypoints: self.waypoints && other.waypoints,
}
}
}
@ -47,6 +49,7 @@ impl Default for SpawnRules {
trees: true,
max_warp: 1.0,
paths: true,
waypoints: true,
}
}
}

View File

@ -88,11 +88,20 @@ impl Site {
.min_by_key(|d2| *d2 as i32)
.map(|d2| d2.sqrt() as f32 / TILE_SIZE as f32)
.unwrap_or(1.0);
SpawnRules {
let base_spawn_rules = SpawnRules {
trees: max_warp == 1.0,
max_warp,
paths: max_warp > std::f32::EPSILON,
}
waypoints: true,
};
self.plots
.values()
.filter_map(|plot| match &plot.kind {
PlotKind::Dungeon(d) => Some(d.spawn_rules(wpos)),
PlotKind::Gnarling(g) => Some(g.spawn_rules(wpos)),
_ => None,
})
.fold(base_spawn_rules, |a, b| a.combine(b))
}
pub fn bounds(&self) -> Aabr<i32> {

View File

@ -221,11 +221,15 @@ impl GnarlingFortification {
+ corner_2.as_() * corner_2_weight)
.as_();
// Check that structure not too close to another structure
if structure_locations.iter().any(|(kind, loc, _door_dir)| {
structure_center.distance_squared(loc.xy())
< structure_kind.required_separation(kind).pow(2)
}) {
// Check that structure not in the water or too close to another structure
if land
.get_chunk_wpos(structure_center + origin)
.map_or(false, |c| c.is_underwater())
|| structure_locations.iter().any(|(kind, loc, _door_dir)| {
structure_center.distance_squared(loc.xy())
< structure_kind.required_separation(kind).pow(2)
})
{
None
} else {
Some((
@ -316,6 +320,15 @@ impl GnarlingFortification {
pub fn radius(&self) -> i32 { self.radius }
pub fn spawn_rules(&self, wpos: Vec2<i32>) -> SpawnRules {
SpawnRules {
trees: wpos.distance_squared(self.origin) > self.wall_radius.pow(2),
waypoints: false,
..SpawnRules::default()
}
}
// TODO: Find a better way of spawning entities in site2
pub fn apply_supplement<'a>(
&'a self,
// NOTE: Used only for dynamic elements like chests and entities!
@ -362,47 +375,45 @@ impl GnarlingFortification {
));
}
for (loc, pos, ori) in &self.structure_locations {
for (loc, pos, _ori) in &self.structure_locations {
let wpos = *pos + self.origin;
if area.contains_point(pos.xy()) {
match loc {
GnarlingStructure::Hut => {
supplement.add_entity(random_gnarling(wpos, dynamic_rng));
let num = dynamic_rng.gen_range(2..=3);
for _ in 0..num {
supplement.add_entity(random_gnarling(wpos, dynamic_rng));
}
},
GnarlingStructure::VeloriteHut => {
supplement.add_entity(random_gnarling(wpos, dynamic_rng));
},
GnarlingStructure::Banner => {
supplement.add_entity(random_gnarling(wpos, dynamic_rng));
let num = dynamic_rng.gen_range(2..=6);
for _ in 0..num {
supplement.add_entity(random_gnarling(
wpos.xy().with_z(wpos.z + 12),
dynamic_rng,
));
}
},
GnarlingStructure::Banner => {},
GnarlingStructure::ChieftainHut => {
supplement.add_entity(gnarling_chieftain(
wpos.xy().with_z(wpos.z + 8),
dynamic_rng,
));
let left_inner_guard_pos = wpos + ori.dir() * 8 + ori.cw().dir() * 2;
supplement.add_entity(wood_golem(left_inner_guard_pos, dynamic_rng));
let right_inner_guard_pos = wpos + ori.dir() * 8 + ori.ccw().dir() * 2;
supplement.add_entity(wood_golem(right_inner_guard_pos, dynamic_rng));
let left_outer_guard_pos = wpos + ori.dir() * 16 + ori.cw().dir() * 2;
supplement.add_entity(random_gnarling(left_outer_guard_pos, dynamic_rng));
let right_outer_guard_pos = wpos + ori.dir() * 16 + ori.ccw().dir() * 2;
supplement.add_entity(random_gnarling(right_outer_guard_pos, dynamic_rng));
let pos = wpos.xy().with_z(wpos.z + 8);
supplement.add_entity(gnarling_chieftain(pos, dynamic_rng));
for _ in 0..2 {
supplement.add_entity(wood_golem(pos, dynamic_rng));
}
},
GnarlingStructure::WatchTower => {
supplement.add_entity(wood_golem(wpos, dynamic_rng));
let spawn_pos = wpos.xy().with_z(wpos.z + 27);
for _ in 0..4 {
let num = dynamic_rng.gen_range(2..=4);
for _ in 0..num {
supplement.add_entity(gnarling_stalker(
spawn_pos + Vec2::broadcast(4),
dynamic_rng,
));
}
},
GnarlingStructure::Totem => {
let spawn_pos = wpos + pos.xy().map(|x| x.signum() * -5);
supplement.add_entity(wood_golem(spawn_pos, dynamic_rng));
},
GnarlingStructure::Totem => {},
}
}
}
@ -511,7 +522,7 @@ impl Structure for GnarlingFortification {
painter
.segment_prism(start, end, wall_mid_thickness, wall_mid_height)
.fill(darkwood.clone());
.fill(darkwood);
let start = start_wpos
.as_()
@ -850,12 +861,7 @@ impl Structure for GnarlingFortification {
painter: &Painter,
wpos: Vec2<i32>,
alt: i32,
_door_dir: Ori,
hut_radius: f32,
_hut_wall_height: f32,
_door_height: i32,
roof_height: f32,
_roof_overhang: f32,
) {
let darkwood = Fill::Brick(BlockKind::Wood, Rgb::new(55, 25, 8), 12);
let lightwood = Fill::Brick(BlockKind::Wood, Rgb::new(71, 33, 11), 12);
@ -1300,23 +1306,9 @@ impl Structure for GnarlingFortification {
.fill(Fill::Prefab(Box::new(totem), totem_pos, self.seed));
},
GnarlingStructure::ChieftainHut => {
let hut_radius = 5.0;
let hut_wall_height = 15.0;
let door_height = 3;
let roof_height = 3.0;
let roof_overhang = 1.0;
generate_chieftainhut(
painter,
wpos,
alt,
*door_dir,
hut_radius,
hut_wall_height,
door_height,
roof_height,
roof_overhang,
);
generate_chieftainhut(painter, wpos, alt, roof_height);
},
GnarlingStructure::Banner => {