bug fixes and airships land at airship stations

This commit is contained in:
Isse 2023-11-05 16:12:07 +01:00
parent 1f195fd848
commit 7fd255ec6c
7 changed files with 79 additions and 34 deletions

View File

@ -168,6 +168,19 @@ impl Body {
},
}
}
/// Max speed in block/s
pub fn get_speed(&self) -> f32 {
match self {
Body::DefaultAirship => 7.0,
Body::AirBalloon => 8.0,
Body::SailBoat => 5.0,
Body::Galleon => 6.0,
Body::Skiff => 6.0,
Body::Submarine => 4.0,
_ => 10.0,
}
}
}
/// Terrain is 11.0 scale relative to small-scale voxels,

View File

@ -184,7 +184,10 @@ impl Body {
// => 1 / (1 - drag).powi(2) - 1 = (dv / 30) / v
// => 1 / (1 / (1 - drag).powi(2) - 1) = v / (dv / 30)
// => (dv / 30) / (1 / (1 - drag).powi(2) - 1) = v
let v = (-self.base_accel() / 30.0) / ((1.0 - FRIC_GROUND).powi(2) - 1.0);
let v = match self {
Body::Ship(ship) => ship.get_speed(),
_ => (-self.base_accel() / 30.0) / ((1.0 - FRIC_GROUND).powi(2) - 1.0),
};
debug_assert!(v >= 0.0, "Speed must be positive!");
v
}

View File

@ -179,8 +179,14 @@ impl Data {
}
}
if rng.gen_bool(0.4) {
let wpos = rand_wpos(&mut rng, matches_plazas) + Vec3::unit_z() * 50.0;
for plot in site2
.plots
.values()
.filter(|plot| matches!(plot.kind(), PlotKind::AirshipDock(_)))
{
let wpos = site2.tile_center_wpos(plot.root_tile());
let wpos = wpos.as_().with_z(world.sim().get_surface_alt_approx(wpos))
+ Vec3::unit_z() * 70.0;
let vehicle_id = this.npcs.create_npc(Npc::new(
rng.gen(),
wpos,

View File

@ -25,7 +25,7 @@ use common::{
rtsim::{Actor, ChunkResource, NpcInput, Profession, Role, SiteId},
spiral::Spiral2d,
store::Id,
terrain::{CoordinateConversions, SiteKindMeta, TerrainChunkSize},
terrain::{CoordinateConversions, TerrainChunkSize},
time::DayPeriod,
util::Dir,
};
@ -1012,27 +1012,35 @@ fn pilot<S: State>(ship: common::comp::ship::Body) -> impl Action<S> {
// Travel between different towns in a straight line
now(move |ctx, _| {
let data = &*ctx.state.data();
let site = data
let station_wpos = data
.sites
.iter()
.filter(|(id, _)| Some(*id) != ctx.npc.current_site)
.filter(|(_, site)| {
site.world_site
.and_then(|site| ctx.index.sites.get(site).kind.convert_to_meta())
.map_or(false, |meta| matches!(meta, SiteKindMeta::Settlement(_)))
.filter_map(|(_, site)| ctx.index.sites.get(site.world_site?).site2())
.flat_map(|site| {
site.plots()
.filter(|plot| matches!(plot.kind(), PlotKind::AirshipDock(_)))
.map(|plot| site.tile_center_wpos(plot.root_tile()))
})
.choose(&mut ctx.rng);
if let Some((_id, site)) = site {
if let Some(station_wpos) = station_wpos {
Either::Right(
goto_2d_flying(
site.wpos.as_(),
station_wpos.as_(),
1.0,
50.0,
150.0,
110.0,
ship.flying_height(),
)
.then(goto_2d_flying(site.wpos.as_(), 1.0, 10.0, 32.0, 16.0, 10.0)),
.then(goto_2d_flying(
station_wpos.as_(),
1.0,
10.0,
32.0,
16.0,
30.0,
)),
)
} else {
Either::Left(finish())

View File

@ -242,16 +242,15 @@ fn on_tick(ctx: EventCtx<SimulateNpcs, OnTick>) {
match activity {
// Move NPCs if they have a target destination
Some(NpcActivity::Goto(target, speed_factor)) => {
let diff = target.xy() - npc.wpos.xy();
let diff = target - npc.wpos;
let dist2 = diff.magnitude_squared();
if dist2 > 0.5f32.powi(2) {
let new_wpos = npc.wpos
+ (diff
* (npc.body.max_speed_approx() * speed_factor * ctx.event.dt
/ dist2.sqrt())
.min(1.0))
.with_z(0.0);
let offset = diff
* (npc.body.max_speed_approx() * speed_factor * ctx.event.dt
/ dist2.sqrt())
.min(1.0);
let new_wpos = npc.wpos + offset;
let is_valid = match npc.body {
// Don't move water bound bodies outside of water.

View File

@ -854,11 +854,12 @@ impl Server {
&self.state.ecs().read_storage::<comp::Pos>(),
!&self.state.ecs().read_storage::<comp::Presence>(),
self.state.ecs().read_storage::<Anchor>().maybe(),
self.state.ecs().read_storage::<RtSimEntity>().maybe(),
)
.join()
.filter(|(_, pos, _, anchor)| {
.filter(|(_, pos, _, anchor, rtsim_entity)| {
let chunk_key = terrain.pos_key(pos.0.map(|e| e.floor() as i32));
match anchor {
let unload = match anchor {
Some(Anchor::Chunk(hc)) => {
// Check if both this chunk and the NPCs `home_chunk` is unloaded. If
// so, we delete them. We check for
@ -869,22 +870,27 @@ impl Server {
},
Some(Anchor::Entity(entity)) => !self.state.ecs().is_alive(*entity),
None => terrain.get_key_real(chunk_key).is_none(),
};
if unload {
// For rtsim entities we only want to unload if assimilation succeeds
if let Some(rtsim_entity) = rtsim_entity {
#[cfg(feature = "worldgen")]
let res = rtsim.hook_rtsim_entity_unload(**rtsim_entity);
#[cfg(not(feature = "worldgen"))]
let res = true;
res
} else {
true
}
} else {
false
}
})
.map(|(entity, _, _, _)| entity)
.map(|(entity, _, _, _, _)| entity)
.collect::<Vec<_>>()
};
#[cfg(feature = "worldgen")]
{
let rtsim_entities = self.state.ecs().read_storage::<RtSimEntity>();
// Assimilate entities that are part of the real-time world simulation
for entity in &to_delete {
if let Some(rtsim_entity) = rtsim_entities.get(*entity) {
rtsim.hook_rtsim_entity_unload(*rtsim_entity);
}
}
}
drop(rtsim);
// Actually perform entity deletion

View File

@ -176,15 +176,25 @@ impl RtSim {
.emit(event::OnBlockChange { changes }, world, index);
}
pub fn hook_rtsim_entity_unload(&mut self, entity: RtSimEntity) {
pub fn hook_rtsim_entity_unload(&mut self, entity: RtSimEntity) -> bool {
let data = self.state.get_data_mut();
if data.npcs.mounts.get_mount_link(entity.0).is_none() {
if let Some(npc) = data.npcs.get_mut(entity.0) {
if matches!(npc.mode, SimulationMode::Simulated) {
error!("Unloaded already unloaded entity");
}
npc.mode = SimulationMode::Simulated;
}
if let Some(steerer) = data.npcs.mounts.get_steerer_link(entity.0) && let Actor::Npc(npc) = steerer.rider && let Some(npc) = data.npcs.get_mut(npc) {
if let Some(steerer) = data.npcs.mounts.get_steerer_link(entity.0) && let Actor::Npc(npc) = steerer.rider
&& let Some(npc) = data.npcs.get_mut(npc) {
if matches!(npc.mode, SimulationMode::Simulated) {
error!("Unloaded already unloaded steerer entity");
}
npc.mode = SimulationMode::Simulated;
}
true
} else {
false
}
}