mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
very simple repopulation
This commit is contained in:
parent
dda1be58d4
commit
adb2e1ba85
@ -15,5 +15,7 @@
|
||||
(10, "common.items.consumable.potion_med"),
|
||||
],
|
||||
),
|
||||
meta: [],
|
||||
meta: [
|
||||
SkillSetAsset("common.skillset.preset.rank5.fullskill"),
|
||||
],
|
||||
)
|
||||
|
@ -52,6 +52,15 @@ pub type ReadError = rmp_serde::decode::Error;
|
||||
pub type WriteError = rmp_serde::encode::Error;
|
||||
|
||||
impl Data {
|
||||
pub fn spawn_npc(&mut self, npc: Npc) -> NpcId {
|
||||
let home = npc.home;
|
||||
let id = self.npcs.create_npc(npc);
|
||||
if let Some(home) = home.and_then(|home| self.sites.get_mut(home)) {
|
||||
home.population.insert(id);
|
||||
}
|
||||
id
|
||||
}
|
||||
|
||||
pub fn from_reader<R: Read>(reader: R) -> Result<Self, ReadError> {
|
||||
rmp_serde::decode::from_read(reader)
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
pub use common::rtsim::SiteId;
|
||||
use common::{rtsim::FactionId, store::Id, uid::Uid};
|
||||
use hashbrown::HashMap;
|
||||
use common::{
|
||||
rtsim::{FactionId, NpcId},
|
||||
store::Id,
|
||||
uid::Uid,
|
||||
};
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use slotmap::HopSlotMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
@ -27,6 +31,9 @@ pub struct Site {
|
||||
/// being too).
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
pub world_site: Option<Id<WorldSite>>,
|
||||
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
pub population: HashSet<NpcId>,
|
||||
}
|
||||
|
||||
impl Site {
|
||||
|
@ -76,7 +76,6 @@ impl Data {
|
||||
"Registering {} rtsim sites from world sites.",
|
||||
this.sites.len()
|
||||
);
|
||||
/*
|
||||
// Spawn some test entities at the sites
|
||||
for (site_id, site) in this.sites.iter()
|
||||
// TODO: Stupid
|
||||
@ -97,10 +96,7 @@ impl Data {
|
||||
};
|
||||
let random_humanoid = |rng: &mut SmallRng| {
|
||||
let species = comp::humanoid::ALL_SPECIES.choose(&mut *rng).unwrap();
|
||||
Body::Humanoid(comp::humanoid::Body::random_with(
|
||||
rng,
|
||||
species,
|
||||
))
|
||||
Body::Humanoid(comp::humanoid::Body::random_with(rng, species))
|
||||
};
|
||||
if good_or_evil {
|
||||
for _ in 0..32 {
|
||||
@ -152,7 +148,7 @@ impl Data {
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (site_id, site) in this.sites.iter()
|
||||
// TODO: Stupid
|
||||
.filter(|(_, site)| site.world_site.map_or(false, |ws|
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::data::{FactionId, Factions, Site};
|
||||
use common::store::Id;
|
||||
use hashbrown::HashSet;
|
||||
use vek::*;
|
||||
use world::{
|
||||
site::{Site as WorldSite, SiteKind},
|
||||
@ -48,6 +49,7 @@ impl Site {
|
||||
.min_by_key(|(faction_wpos, _)| faction_wpos.distance_squared(wpos))
|
||||
.map(|(_, faction)| *faction)
|
||||
}),
|
||||
population: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -329,11 +329,15 @@ fn goto(wpos: Vec3<f32>, speed_factor: f32, goal_dist: f32) -> impl Action {
|
||||
}
|
||||
|
||||
// Get the next waypoint on the route toward the goal
|
||||
let waypoint =
|
||||
waypoint.get_or_insert_with(|| {
|
||||
let waypoint = waypoint.get_or_insert_with(|| {
|
||||
let wpos = ctx.npc.wpos + (rpos / len) * len.min(STEP_DIST);
|
||||
|
||||
wpos.with_z(ctx.world.sim().get_surface_alt_approx(wpos.xy().as_()).unwrap_or(wpos.z))
|
||||
wpos.with_z(
|
||||
ctx.world
|
||||
.sim()
|
||||
.get_surface_alt_approx(wpos.xy().as_())
|
||||
.unwrap_or(wpos.z),
|
||||
)
|
||||
});
|
||||
|
||||
*ctx.controller = Controller::goto(*waypoint, speed_factor);
|
||||
|
@ -1,11 +1,17 @@
|
||||
use crate::{
|
||||
data::npc::SimulationMode,
|
||||
event::{OnSetup, OnTick},
|
||||
data::{npc::SimulationMode, Npc},
|
||||
event::{OnDeath, OnSetup, OnTick},
|
||||
RtState, Rule, RuleError,
|
||||
};
|
||||
use common::{grid::Grid, terrain::TerrainChunkSize, vol::RectVolSize};
|
||||
use tracing::info;
|
||||
use vek::*;
|
||||
use common::{
|
||||
comp::{self, Body},
|
||||
grid::Grid,
|
||||
terrain::TerrainChunkSize,
|
||||
vol::RectVolSize,
|
||||
};
|
||||
use rand::{rngs::ThreadRng, seq::SliceRandom, Rng};
|
||||
use tracing::warn;
|
||||
use world::site::SiteKind;
|
||||
|
||||
pub struct SimulateNpcs;
|
||||
|
||||
@ -27,8 +33,98 @@ impl Rule for SimulateNpcs {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(home) = npc.home.and_then(|home| data.sites.get_mut(home)) {
|
||||
home.population.insert(npc_id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rtstate.bind::<Self, OnDeath>(|ctx| {
|
||||
let data = &mut *ctx.state.data_mut();
|
||||
let npc_id = ctx.event.npc_id;
|
||||
let Some(npc) = data.npcs.get(npc_id) else {
|
||||
return;
|
||||
};
|
||||
if let Some(home) = npc.home.and_then(|home| data.sites.get_mut(home)) {
|
||||
home.population.remove(&npc_id);
|
||||
}
|
||||
let mut rng = rand::thread_rng();
|
||||
match npc.body {
|
||||
Body::Humanoid(_) => {
|
||||
if let Some((site_id, site)) = data
|
||||
.sites
|
||||
.iter()
|
||||
.filter(|(id, site)| {
|
||||
Some(*id) != npc.home
|
||||
&& site.faction == npc.faction
|
||||
&& site.world_site.map_or(false, |s| {
|
||||
matches!(ctx.index.sites.get(s).kind, SiteKind::Refactor(_))
|
||||
})
|
||||
})
|
||||
.min_by_key(|(_, site)| site.population.len())
|
||||
{
|
||||
let rand_wpos = |rng: &mut ThreadRng| {
|
||||
let wpos2d = site.wpos.map(|e| e + rng.gen_range(-10..10));
|
||||
wpos2d
|
||||
.map(|e| e as f32 + 0.5)
|
||||
.with_z(ctx.world.sim().get_alt_approx(wpos2d).unwrap_or(0.0))
|
||||
};
|
||||
let random_humanoid = |rng: &mut ThreadRng| {
|
||||
let species = comp::humanoid::ALL_SPECIES.choose(&mut *rng).unwrap();
|
||||
Body::Humanoid(comp::humanoid::Body::random_with(rng, species))
|
||||
};
|
||||
data.spawn_npc(
|
||||
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
||||
.with_home(site_id)
|
||||
.with_faction(npc.faction)
|
||||
.with_profession(npc.profession.clone()),
|
||||
);
|
||||
} else {
|
||||
warn!("No site found for respawning humaniod");
|
||||
}
|
||||
},
|
||||
Body::BirdLarge(_) => {
|
||||
if let Some((site_id, site)) = data
|
||||
.sites
|
||||
.iter()
|
||||
.filter(|(id, site)| {
|
||||
Some(*id) != npc.home
|
||||
&& site.world_site.map_or(false, |s| {
|
||||
matches!(ctx.index.sites.get(s).kind, SiteKind::Dungeon(_))
|
||||
})
|
||||
})
|
||||
.min_by_key(|(_, site)| site.population.len())
|
||||
{
|
||||
let rand_wpos = |rng: &mut ThreadRng| {
|
||||
let wpos2d = site.wpos.map(|e| e + rng.gen_range(-10..10));
|
||||
wpos2d
|
||||
.map(|e| e as f32 + 0.5)
|
||||
.with_z(ctx.world.sim().get_alt_approx(wpos2d).unwrap_or(0.0))
|
||||
};
|
||||
let species = [
|
||||
comp::body::bird_large::Species::Phoenix,
|
||||
comp::body::bird_large::Species::Cockatrice,
|
||||
comp::body::bird_large::Species::Roc,
|
||||
]
|
||||
.choose(&mut rng)
|
||||
.unwrap();
|
||||
data.npcs.create_npc(
|
||||
Npc::new(
|
||||
rng.gen(),
|
||||
rand_wpos(&mut rng),
|
||||
Body::BirdLarge(comp::body::bird_large::Body::random_with(&mut rng, species)),
|
||||
)
|
||||
.with_home(site_id),
|
||||
);
|
||||
} else {
|
||||
warn!("No site found for respawning bird");
|
||||
}
|
||||
},
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
});
|
||||
|
||||
rtstate.bind::<Self, OnTick>(|ctx| {
|
||||
let data = &mut *ctx.state.data_mut();
|
||||
for (vehicle_id, vehicle) in data.npcs.vehicles.iter_mut() {
|
||||
|
@ -1997,7 +1997,26 @@ fn handle_kill_npcs(
|
||||
true
|
||||
};
|
||||
|
||||
should_kill.then_some(entity)
|
||||
if should_kill {
|
||||
if let Some(rtsim_entity) = ecs
|
||||
.read_storage::<common::rtsim::RtSimEntity>()
|
||||
.get(entity)
|
||||
.copied()
|
||||
{
|
||||
ecs
|
||||
.write_resource::<crate::rtsim2::RtSim>()
|
||||
.hook_rtsim_entity_delete(
|
||||
&ecs.read_resource::<Arc<world::World>>(),
|
||||
ecs
|
||||
.read_resource::<world::IndexOwned>()
|
||||
.as_index_ref(),
|
||||
rtsim_entity,
|
||||
);
|
||||
}
|
||||
Some(entity)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
@ -6,12 +6,13 @@ use common::{
|
||||
comp::{self, inventory::loadout::Loadout, skillset::skills, Agent, Body},
|
||||
event::{EventBus, NpcBuilder, ServerEvent},
|
||||
generation::{BodyBuilder, EntityConfig, EntityInfo},
|
||||
lottery::LootSpec,
|
||||
resources::{DeltaTime, Time, TimeOfDay},
|
||||
rtsim::{RtSimController, RtSimEntity, RtSimVehicle},
|
||||
slowjob::SlowJobPool,
|
||||
terrain::CoordinateConversions,
|
||||
trade::{Good, SiteInformation},
|
||||
LoadoutBuilder, SkillSetBuilder, lottery::LootSpec,
|
||||
LoadoutBuilder, SkillSetBuilder,
|
||||
};
|
||||
use common_ecs::{Job, Origin, Phase, System};
|
||||
use rtsim2::data::{
|
||||
|
Loading…
Reference in New Issue
Block a user