mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
bug fixes and airships land at airship stations
This commit is contained in:
parent
1f195fd848
commit
7fd255ec6c
@ -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,
|
/// Terrain is 11.0 scale relative to small-scale voxels,
|
||||||
|
@ -184,7 +184,10 @@ impl Body {
|
|||||||
// => 1 / (1 - drag).powi(2) - 1 = (dv / 30) / v
|
// => 1 / (1 - drag).powi(2) - 1 = (dv / 30) / v
|
||||||
// => 1 / (1 / (1 - drag).powi(2) - 1) = v / (dv / 30)
|
// => 1 / (1 / (1 - drag).powi(2) - 1) = v / (dv / 30)
|
||||||
// => (dv / 30) / (1 / (1 - drag).powi(2) - 1) = v
|
// => (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!");
|
debug_assert!(v >= 0.0, "Speed must be positive!");
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
@ -179,8 +179,14 @@ impl Data {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rng.gen_bool(0.4) {
|
for plot in site2
|
||||||
let wpos = rand_wpos(&mut rng, matches_plazas) + Vec3::unit_z() * 50.0;
|
.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(
|
let vehicle_id = this.npcs.create_npc(Npc::new(
|
||||||
rng.gen(),
|
rng.gen(),
|
||||||
wpos,
|
wpos,
|
||||||
|
@ -25,7 +25,7 @@ use common::{
|
|||||||
rtsim::{Actor, ChunkResource, NpcInput, Profession, Role, SiteId},
|
rtsim::{Actor, ChunkResource, NpcInput, Profession, Role, SiteId},
|
||||||
spiral::Spiral2d,
|
spiral::Spiral2d,
|
||||||
store::Id,
|
store::Id,
|
||||||
terrain::{CoordinateConversions, SiteKindMeta, TerrainChunkSize},
|
terrain::{CoordinateConversions, TerrainChunkSize},
|
||||||
time::DayPeriod,
|
time::DayPeriod,
|
||||||
util::Dir,
|
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
|
// Travel between different towns in a straight line
|
||||||
now(move |ctx, _| {
|
now(move |ctx, _| {
|
||||||
let data = &*ctx.state.data();
|
let data = &*ctx.state.data();
|
||||||
let site = data
|
let station_wpos = data
|
||||||
.sites
|
.sites
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(id, _)| Some(*id) != ctx.npc.current_site)
|
.filter(|(id, _)| Some(*id) != ctx.npc.current_site)
|
||||||
.filter(|(_, site)| {
|
.filter_map(|(_, site)| ctx.index.sites.get(site.world_site?).site2())
|
||||||
site.world_site
|
.flat_map(|site| {
|
||||||
.and_then(|site| ctx.index.sites.get(site).kind.convert_to_meta())
|
site.plots()
|
||||||
.map_or(false, |meta| matches!(meta, SiteKindMeta::Settlement(_)))
|
.filter(|plot| matches!(plot.kind(), PlotKind::AirshipDock(_)))
|
||||||
|
.map(|plot| site.tile_center_wpos(plot.root_tile()))
|
||||||
})
|
})
|
||||||
.choose(&mut ctx.rng);
|
.choose(&mut ctx.rng);
|
||||||
if let Some((_id, site)) = site {
|
if let Some(station_wpos) = station_wpos {
|
||||||
Either::Right(
|
Either::Right(
|
||||||
goto_2d_flying(
|
goto_2d_flying(
|
||||||
site.wpos.as_(),
|
station_wpos.as_(),
|
||||||
1.0,
|
1.0,
|
||||||
50.0,
|
50.0,
|
||||||
150.0,
|
150.0,
|
||||||
110.0,
|
110.0,
|
||||||
ship.flying_height(),
|
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 {
|
} else {
|
||||||
Either::Left(finish())
|
Either::Left(finish())
|
||||||
|
@ -242,16 +242,15 @@ fn on_tick(ctx: EventCtx<SimulateNpcs, OnTick>) {
|
|||||||
match activity {
|
match activity {
|
||||||
// Move NPCs if they have a target destination
|
// Move NPCs if they have a target destination
|
||||||
Some(NpcActivity::Goto(target, speed_factor)) => {
|
Some(NpcActivity::Goto(target, speed_factor)) => {
|
||||||
let diff = target.xy() - npc.wpos.xy();
|
let diff = target - npc.wpos;
|
||||||
let dist2 = diff.magnitude_squared();
|
let dist2 = diff.magnitude_squared();
|
||||||
|
|
||||||
if dist2 > 0.5f32.powi(2) {
|
if dist2 > 0.5f32.powi(2) {
|
||||||
let new_wpos = npc.wpos
|
let offset = diff
|
||||||
+ (diff
|
* (npc.body.max_speed_approx() * speed_factor * ctx.event.dt
|
||||||
* (npc.body.max_speed_approx() * speed_factor * ctx.event.dt
|
/ dist2.sqrt())
|
||||||
/ dist2.sqrt())
|
.min(1.0);
|
||||||
.min(1.0))
|
let new_wpos = npc.wpos + offset;
|
||||||
.with_z(0.0);
|
|
||||||
|
|
||||||
let is_valid = match npc.body {
|
let is_valid = match npc.body {
|
||||||
// Don't move water bound bodies outside of water.
|
// Don't move water bound bodies outside of water.
|
||||||
|
@ -854,11 +854,12 @@ impl Server {
|
|||||||
&self.state.ecs().read_storage::<comp::Pos>(),
|
&self.state.ecs().read_storage::<comp::Pos>(),
|
||||||
!&self.state.ecs().read_storage::<comp::Presence>(),
|
!&self.state.ecs().read_storage::<comp::Presence>(),
|
||||||
self.state.ecs().read_storage::<Anchor>().maybe(),
|
self.state.ecs().read_storage::<Anchor>().maybe(),
|
||||||
|
self.state.ecs().read_storage::<RtSimEntity>().maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.filter(|(_, pos, _, anchor)| {
|
.filter(|(_, pos, _, anchor, rtsim_entity)| {
|
||||||
let chunk_key = terrain.pos_key(pos.0.map(|e| e.floor() as i32));
|
let chunk_key = terrain.pos_key(pos.0.map(|e| e.floor() as i32));
|
||||||
match anchor {
|
let unload = match anchor {
|
||||||
Some(Anchor::Chunk(hc)) => {
|
Some(Anchor::Chunk(hc)) => {
|
||||||
// Check if both this chunk and the NPCs `home_chunk` is unloaded. If
|
// Check if both this chunk and the NPCs `home_chunk` is unloaded. If
|
||||||
// so, we delete them. We check for
|
// so, we delete them. We check for
|
||||||
@ -869,22 +870,27 @@ impl Server {
|
|||||||
},
|
},
|
||||||
Some(Anchor::Entity(entity)) => !self.state.ecs().is_alive(*entity),
|
Some(Anchor::Entity(entity)) => !self.state.ecs().is_alive(*entity),
|
||||||
None => terrain.get_key_real(chunk_key).is_none(),
|
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<_>>()
|
.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);
|
drop(rtsim);
|
||||||
|
|
||||||
// Actually perform entity deletion
|
// Actually perform entity deletion
|
||||||
|
@ -176,15 +176,25 @@ impl RtSim {
|
|||||||
.emit(event::OnBlockChange { changes }, world, index);
|
.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();
|
let data = self.state.get_data_mut();
|
||||||
if data.npcs.mounts.get_mount_link(entity.0).is_none() {
|
if data.npcs.mounts.get_mount_link(entity.0).is_none() {
|
||||||
if let Some(npc) = data.npcs.get_mut(entity.0) {
|
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;
|
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;
|
npc.mode = SimulationMode::Simulated;
|
||||||
}
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user