Rtsim now uses entity configs.

This commit is contained in:
Sam 2021-09-24 19:42:03 -04:00 committed by juliancoffee
parent 70c2e9bebe
commit 27823ce8fa
3 changed files with 86 additions and 105 deletions

View File

@ -1,6 +1,5 @@
use super::*;
use common::{
comp::inventory::loadout_builder::LoadoutBuilder,
resources::Time,
rtsim::{Memory, MemoryItem},
store::Id,
@ -39,6 +38,8 @@ const PERM_GENUS: u32 = 4;
impl Entity {
pub fn rng(&self, perm: u32) -> impl Rng { RandomPerm::new(self.seed + perm) }
pub fn loadout_rng(&self) -> impl Rng { self.rng(PERM_LOADOUT) }
pub fn get_body(&self) -> comp::Body {
match self.kind {
RtSimEntityKind::Random => {
@ -81,47 +82,30 @@ impl Entity {
}
}
pub fn get_name(&self) -> String {
match self.kind {
RtSimEntityKind::Random => {
use common::{generation::get_npc_name, npc::NPC_NAMES};
let npc_names = NPC_NAMES.read();
match self.get_body() {
comp::Body::BirdMedium(b) => {
get_npc_name(&npc_names.bird_medium, b.species).to_string()
},
comp::Body::BirdLarge(b) => {
get_npc_name(&npc_names.bird_large, b.species).to_string()
},
comp::Body::Dragon(b) => get_npc_name(&npc_names.dragon, b.species).to_string(),
comp::Body::Humanoid(b) => {
get_npc_name(&npc_names.humanoid, b.species).to_string()
},
comp::Body::Ship(_) => "Veloren Air".to_string(),
//TODO: finish match as necessary
_ => unimplemented!(),
}
pub fn get_entity_config(&self) -> &str {
match self.get_body() {
comp::Body::Humanoid(_) => match self.kind {
RtSimEntityKind::Cultist => "",
RtSimEntityKind::Random => "",
},
RtSimEntityKind::Cultist => "Cultist Raider".to_string(),
}
}
pub fn get_loadout(&self) -> comp::inventory::loadout::Loadout {
let mut rng = self.rng(PERM_LOADOUT);
match self.kind {
RtSimEntityKind::Random => {
LoadoutBuilder::from_asset_expect("common.loadout.world.traveler", Some(&mut rng))
.bag(
comp::inventory::slot::ArmorSlot::Bag1,
Some(comp::inventory::loadout_builder::make_potion_bag(100)),
)
.build()
comp::Body::BirdMedium(b) => match b.species {
comp::bird_medium::Species::Duck => "",
comp::bird_medium::Species::Chicken => "",
comp::bird_medium::Species::Goose => "",
comp::bird_medium::Species::Peacock => "",
comp::bird_medium::Species::Eagle => "",
comp::bird_medium::Species::Owl => "",
comp::bird_medium::Species::Parrot => "",
},
RtSimEntityKind::Cultist => LoadoutBuilder::from_asset_expect(
"common.loadout.dungeon.tier-5.cultist",
Some(&mut rng),
)
.build(),
comp::Body::BirdLarge(b) => match b.species {
comp::bird_large::Species::Phoenix => "",
comp::bird_large::Species::Cockatrice => "",
comp::bird_large::Species::Roc => "",
// Wildcard match used here as there is an array above which limits what species are
// used
_ => unimplemented!(),
},
_ => unimplemented!(),
}
}

View File

@ -1,9 +1,11 @@
#![allow(dead_code)] // TODO: Remove this when rtsim is fleshed out
use super::*;
use crate::sys::terrain::NpcData;
use common::{
comp::{self, inventory::loadout_builder::LoadoutBuilder, Behavior, BehaviorCapability},
comp,
event::{EventBus, ServerEvent},
generation::EntityInfo,
resources::{DeltaTime, Time},
terrain::TerrainGrid,
};
@ -106,75 +108,62 @@ impl<'a> System<'a> for Sys {
for id in to_reify {
rtsim.reify_entity(id);
let entity = &rtsim.entities[id];
let entity_config = entity.get_entity_config();
let rtsim_entity = Some(RtSimEntity(id));
let body = entity.get_body();
let alignment = match body {
comp::Body::Humanoid(_) => match entity.kind {
RtSimEntityKind::Random => comp::Alignment::Npc,
RtSimEntityKind::Cultist => comp::Alignment::Enemy,
},
comp::Body::BirdLarge(bird_large) => match bird_large.species {
comp::bird_large::Species::Roc => comp::Alignment::Enemy,
comp::bird_large::Species::Cockatrice => comp::Alignment::Enemy,
_ => comp::Alignment::Wild,
},
_ => comp::Alignment::Wild,
};
let spawn_pos = terrain
.find_space(entity.pos.map(|e| e.floor() as i32))
.map(|e| e as f32)
+ Vec3::new(0.5, 0.5, body.flying_height());
let pos = comp::Pos(spawn_pos);
let mut agent = Some(comp::Agent::from_body(&body).with_behavior(
if matches!(body, comp::Body::Humanoid(_)) {
Behavior::from(BehaviorCapability::SPEAK)
} else {
Behavior::default()
},
));
if matches!(alignment, comp::Alignment::Enemy) {
agent = agent.map(|a| a.with_aggro_no_warn());
}
let rtsim_entity = Some(RtSimEntity(id));
// TODO: this should be a bit more intelligent
let loadout = match body {
comp::Body::Humanoid(_) => entity.get_loadout(),
_ => LoadoutBuilder::empty().with_default_maintool(&body).build(),
};
let event = match body {
comp::Body::Ship(ship) => ServerEvent::CreateShip {
pos,
ship,
mountable: false,
agent,
rtsim_entity,
},
_ => ServerEvent::CreateNpc {
pos: comp::Pos(spawn_pos),
stats: comp::Stats::new(entity.get_name()),
skill_set: comp::SkillSet::default(),
health: Some(comp::Health::new(body, 10)),
loadout,
poise: comp::Poise::new(body),
body,
agent,
alignment,
scale: match body {
comp::Body::Ship(_) => comp::Scale(comp::ship::AIRSHIP_SCALE),
_ => comp::Scale(1.0),
let mut loadout_rng = entity.loadout_rng();
let entity_info = NpcData::from_entity_info(
EntityInfo::at(pos.0).with_asset_expect(entity_config),
&mut loadout_rng,
);
if let NpcData::Data {
pos,
stats,
skill_set,
health,
poise,
loadout,
agent,
// Body discarded here so that species and body type are consistent between
// reifications
body: _,
alignment,
scale,
drop_item,
} = entity_info
{
let event = match body {
comp::Body::Ship(ship) => ServerEvent::CreateShip {
pos,
ship,
mountable: false,
agent,
rtsim_entity,
},
// FIXME;
// Drop loot
drop_item: None,
anchor: None,
rtsim_entity,
projectile: None,
},
};
server_emitter.emit(event);
_ => ServerEvent::CreateNpc {
pos,
stats,
skill_set,
health,
poise,
loadout,
agent,
body,
alignment,
scale,
anchor: None,
drop_item,
rtsim_entity,
projectile: None,
},
};
server_emitter.emit(event);
}
}
// Update rtsim with real entity data

View File

@ -364,7 +364,7 @@ pub enum NpcData {
}
impl NpcData {
pub fn from_entity_info(entity: EntityInfo, rng: &mut impl Rng) -> Self {
pub fn from_entity_info(entity: EntityInfo, loadout_rng: &mut impl Rng) -> Self {
let EntityInfo {
// flags
is_waypoint,
@ -423,7 +423,7 @@ impl NpcData {
// If there is config, apply it.
// If not, use default equipement for this body.
if let Some(asset) = loadout_asset {
loadout_builder = loadout_builder.with_asset_expect(&asset, rng);
loadout_builder = loadout_builder.with_asset_expect(&asset, loadout_rng);
} else {
loadout_builder = loadout_builder.with_default_equipment(&body);
}
@ -465,6 +465,14 @@ impl NpcData {
.with_no_flee(!matches!(agent_mark, Some(agent::Mark::Guard)))
});
let agent = if matches!(alignment, comp::Alignment::Enemy)
&& matches!(body, comp::Body::Humanoid(_))
{
agent.map(|a| a.with_aggro_no_warn())
} else {
agent
};
NpcData::Data {
pos: Pos(pos),
stats,