Improved commands, fixed tether orientation

This commit is contained in:
Joshua Barretto 2023-05-27 16:08:26 +01:00
parent 2d4278e94a
commit 1ac1c900c9
6 changed files with 43 additions and 49 deletions

View File

@ -688,12 +688,12 @@ impl ServerChatCommand {
.collect(),
Optional,
),
Float("destination_degrees_ccw_of_east", 90.0, Optional),
Boolean(
"Whether the ship should be tethered to the target (or its mount)",
"false".to_string(),
Optional,
),
Float("destination_degrees_ccw_of_east", 90.0, Optional),
],
"Spawns a ship",
Some(Admin),

View File

@ -88,7 +88,7 @@ impl Body {
Body::Skiff => Vec3::new(7.0, 15.0, 10.0),
Body::Submarine => Vec3::new(2.0, 15.0, 8.0),
Body::Carriage => Vec3::new(5.0, 12.0, 2.0),
Body::Cart => Vec3::new(5.0, 8.0, 5.0),
Body::Cart => Vec3::new(3.0, 6.0, 1.0),
}
}
@ -122,14 +122,21 @@ impl Body {
match self {
Body::DefaultAirship | Body::AirBalloon | Body::Volume => Density(AIR_DENSITY),
Body::Submarine => Density(WATER_DENSITY), // Neutrally buoyant
Body::Carriage => Density(AIR_DENSITY * 1.5),
Body::Cart => Density(AIR_DENSITY * 1.2),
Body::Carriage => Density(WATER_DENSITY * 0.5),
Body::Cart => Density(500.0 / self.dimensions().product()), /* Carts get a constant
* mass */
_ => Density(AIR_DENSITY * 0.95 + WATER_DENSITY * 0.05), /* Most boats should be very
* buoyant */
}
}
pub fn mass(&self) -> Mass { Mass((self.hull_vol() + self.balloon_vol()) * self.density().0) }
pub fn mass(&self) -> Mass {
if self.can_fly() {
Mass((self.hull_vol() + self.balloon_vol()) * self.density().0)
} else {
Mass(self.density().0 * self.dimensions().product())
}
}
pub fn can_fly(&self) -> bool {
matches!(self, Body::DefaultAirship | Body::AirBalloon | Body::Volume)

View File

@ -150,7 +150,7 @@ impl Body {
quadruped_low::Species::Driggle => 120.0,
quadruped_low::Species::HermitAlligator => 120.0,
},
Body::Ship(ship::Body::Carriage) => 35.0,
Body::Ship(ship::Body::Carriage) => 40.0,
Body::Ship(_) => 0.0,
Body::Arthropod(arthropod) => match arthropod.species {
arthropod::Species::Tarantula => 135.0,

View File

@ -1,14 +1,11 @@
use crate::{
comp,
link::{Is, Link, LinkHandle, Role},
mounting::{Mount, Rider, VolumeRider},
mounting::{Rider, VolumeRider},
uid::{Uid, UidAllocator},
};
use serde::{Deserialize, Serialize};
use specs::{
saveload::MarkerAllocator, storage::GenericWriteStorage, Component, DenseVecStorage, Entities,
Entity, Read, ReadExpect, ReadStorage, Write, WriteStorage,
};
use specs::{saveload::MarkerAllocator, Entities, Read, ReadStorage, WriteStorage};
use vek::*;
#[derive(Serialize, Deserialize, Debug)]
@ -44,25 +41,20 @@ impl Link for Tethered {
WriteStorage<'a, Is<Leader>>,
WriteStorage<'a, Is<Follower>>,
ReadStorage<'a, Is<Rider>>,
ReadStorage<'a, Is<Mount>>,
ReadStorage<'a, Is<VolumeRider>>,
);
type DeleteData<'a> = (
Read<'a, UidAllocator>,
WriteStorage<'a, Is<Leader>>,
WriteStorage<'a, Is<Follower>>,
WriteStorage<'a, comp::Pos>,
WriteStorage<'a, comp::ForceUpdate>,
);
type Error = TetherError;
type PersistData<'a> = (
Read<'a, UidAllocator>,
Entities<'a>,
ReadStorage<'a, comp::Health>,
ReadStorage<'a, comp::Body>,
ReadStorage<'a, Is<Leader>>,
ReadStorage<'a, Is<Follower>>,
ReadStorage<'a, comp::CharacterState>,
);
fn create(
@ -72,7 +64,6 @@ impl Link for Tethered {
is_leaders,
is_followers,
is_riders,
is_mounts,
is_volume_rider,
): &mut Self::CreateData<'_>,
) -> Result<(), Self::Error> {
@ -103,7 +94,7 @@ impl Link for Tethered {
fn persist(
this: &LinkHandle<Self>,
(uid_allocator, entities, healths, bodies, is_leaders, is_followers, character_states): &mut Self::PersistData<'_>,
(uid_allocator, entities, healths, is_leaders, is_followers): &mut Self::PersistData<'_>,
) -> bool {
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());
@ -124,9 +115,7 @@ impl Link for Tethered {
fn delete(
this: &LinkHandle<Self>,
(uid_allocator, is_leaders, is_followers, positions, force_update): &mut Self::DeleteData<
'_,
>,
(uid_allocator, is_leaders, is_followers): &mut Self::DeleteData<'_>,
) {
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());

View File

@ -1,17 +1,16 @@
use common::{
comp::{Body, Collider, InputKind, Mass, Ori, Pos, Scale, Vel},
comp::{Body, Mass, Ori, Pos, Scale, Vel},
link::Is,
resources::DeltaTime,
tether::{Follower, Leader},
tether::Follower,
uid::UidAllocator,
util::Dir,
};
use common_ecs::{Job, Origin, Phase, System};
use specs::{
saveload::{Marker, MarkerAllocator},
Entities, Join, Read, ReadExpect, ReadStorage, WriteStorage,
Entities, Join, Read, ReadStorage, WriteStorage,
};
use tracing::error;
use vek::*;
/// This system is responsible for controlling mounts
@ -22,14 +21,12 @@ impl<'a> System<'a> for Sys {
Read<'a, UidAllocator>,
Entities<'a>,
Read<'a, DeltaTime>,
ReadStorage<'a, Is<Leader>>,
ReadStorage<'a, Is<Follower>>,
WriteStorage<'a, Pos>,
WriteStorage<'a, Vel>,
WriteStorage<'a, Ori>,
ReadStorage<'a, Body>,
ReadStorage<'a, Scale>,
ReadStorage<'a, Collider>,
ReadStorage<'a, Mass>,
);
@ -43,19 +40,17 @@ impl<'a> System<'a> for Sys {
uid_allocator,
entities,
dt,
is_leaders,
is_followers,
mut positions,
positions,
mut velocities,
mut orientations,
bodies,
scales,
colliders,
masses,
): Self::SystemData,
) {
for (follower, is_follower, follower_body) in
(&entities, &is_followers, bodies.maybe()).join()
for (follower, is_follower, follower_body, scale) in
(&entities, &is_followers, bodies.maybe(), scales.maybe()).join()
{
let Some(leader) = uid_allocator
.retrieve_entity_internal(is_follower.leader.id())
@ -75,13 +70,15 @@ impl<'a> System<'a> for Sys {
let tether_offset = orientations
.get(follower)
.map(|ori| {
ori.to_quat() * follower_body.map(|b| b.tether_offset()).unwrap_or_default()
ori.to_quat()
* follower_body
.map(|b| b.tether_offset() * scale.copied().unwrap_or(Scale(1.0)).0)
.unwrap_or_default()
})
.unwrap_or_default();
let tether_pos = follower_pos.0 + tether_offset;
let pull_factor = (leader_pos.0.distance(tether_pos) - is_follower.tether_length)
.clamp(0.0, 1.0)
.powf(2.0);
let pull_factor =
(leader_pos.0.distance(tether_pos) - is_follower.tether_length).max(0.0);
let strength = pull_factor * 50000.0;
let pull_dir = (leader_pos.0 - follower_pos.0)
.try_normalized()
@ -93,9 +90,10 @@ impl<'a> System<'a> for Sys {
velocities.get_mut(leader).unwrap().0 -= impulse / leader_mass.0;
if let Some(follower_ori) = orientations.get_mut(follower) {
let turn_strength = pull_factor.min(0.2)
// * (tether_offset.magnitude() - tether_offset.dot(pull_dir).abs())
* 50.0;
let turn_strength = pull_factor
* (tether_offset.magnitude() * (leader_pos.0 - tether_pos).magnitude()
- tether_offset.dot(leader_pos.0 - tether_pos).abs())
* 2.0;
let target_ori = follower_ori.yawed_towards(Dir::new(pull_dir));
*follower_ori = follower_ori.slerped_towards(target_ori, turn_strength * dt.0);
}

View File

@ -1778,7 +1778,7 @@ fn handle_spawn_ship(
args: Vec<String>,
_action: &ServerChatCommand,
) -> CmdResult<()> {
let (body_name, angle, tethered) = parse_cmd_args!(args, String, f32, bool);
let (body_name, tethered, angle) = parse_cmd_args!(args, String, bool, f32);
let mut pos = position(server, target, "target")?;
pos.0.z += 2.0;
const DESTINATION_RADIUS: f32 = 2000.0;
@ -1798,15 +1798,15 @@ fn handle_spawn_ship(
.state
.create_ship(pos, ori, ship, |ship| ship.make_collider());
// if let Some(pos) = destination {
// let (kp, ki, kd) =
// comp::agent::pid_coefficients(&comp::Body::Ship(ship)).unwrap_or((1.
// 0, 0.0, 0.0)); fn pure_z(sp: Vec3<f32>, pv: Vec3<f32>) -> f32 { (sp -
// pv).z } let agent = comp::Agent::from_body(&comp::Body::Ship(ship))
// .with_destination(pos)
// .with_position_pid_controller(comp::PidController::new(kp, ki, kd,
// pos, 0.0, pure_z)); builder = builder.with(agent);
// }
if let Some(pos) = destination {
let (kp, ki, kd) =
comp::agent::pid_coefficients(&comp::Body::Ship(ship)).unwrap_or((1.0, 0.0, 0.0));
fn pure_z(sp: Vec3<f32>, pv: Vec3<f32>) -> f32 { (sp - pv).z }
let agent = comp::Agent::from_body(&comp::Body::Ship(ship))
.with_destination(pos)
.with_position_pid_controller(comp::PidController::new(kp, ki, kd, pos, 0.0, pure_z));
builder = builder.with(agent);
}
let new_entity = builder.build();