diff --git a/server/src/rtsim/entity.rs b/server/src/rtsim/entity.rs index b779b7fac1..09230a1c61 100644 --- a/server/src/rtsim/entity.rs +++ b/server/src/rtsim/entity.rs @@ -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!(), } } diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index 7728671edc..aedbf66b77 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -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 diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 90a2534eeb..3714f9137e 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -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,