mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Improved commands, fixed tether orientation
This commit is contained in:
parent
2d4278e94a
commit
1ac1c900c9
@ -688,12 +688,12 @@ impl ServerChatCommand {
|
|||||||
.collect(),
|
.collect(),
|
||||||
Optional,
|
Optional,
|
||||||
),
|
),
|
||||||
Float("destination_degrees_ccw_of_east", 90.0, Optional),
|
|
||||||
Boolean(
|
Boolean(
|
||||||
"Whether the ship should be tethered to the target (or its mount)",
|
"Whether the ship should be tethered to the target (or its mount)",
|
||||||
"false".to_string(),
|
"false".to_string(),
|
||||||
Optional,
|
Optional,
|
||||||
),
|
),
|
||||||
|
Float("destination_degrees_ccw_of_east", 90.0, Optional),
|
||||||
],
|
],
|
||||||
"Spawns a ship",
|
"Spawns a ship",
|
||||||
Some(Admin),
|
Some(Admin),
|
||||||
|
@ -88,7 +88,7 @@ impl Body {
|
|||||||
Body::Skiff => Vec3::new(7.0, 15.0, 10.0),
|
Body::Skiff => Vec3::new(7.0, 15.0, 10.0),
|
||||||
Body::Submarine => Vec3::new(2.0, 15.0, 8.0),
|
Body::Submarine => Vec3::new(2.0, 15.0, 8.0),
|
||||||
Body::Carriage => Vec3::new(5.0, 12.0, 2.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 {
|
match self {
|
||||||
Body::DefaultAirship | Body::AirBalloon | Body::Volume => Density(AIR_DENSITY),
|
Body::DefaultAirship | Body::AirBalloon | Body::Volume => Density(AIR_DENSITY),
|
||||||
Body::Submarine => Density(WATER_DENSITY), // Neutrally buoyant
|
Body::Submarine => Density(WATER_DENSITY), // Neutrally buoyant
|
||||||
Body::Carriage => Density(AIR_DENSITY * 1.5),
|
Body::Carriage => Density(WATER_DENSITY * 0.5),
|
||||||
Body::Cart => Density(AIR_DENSITY * 1.2),
|
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
|
_ => Density(AIR_DENSITY * 0.95 + WATER_DENSITY * 0.05), /* Most boats should be very
|
||||||
* buoyant */
|
* 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 {
|
pub fn can_fly(&self) -> bool {
|
||||||
matches!(self, Body::DefaultAirship | Body::AirBalloon | Body::Volume)
|
matches!(self, Body::DefaultAirship | Body::AirBalloon | Body::Volume)
|
||||||
|
@ -150,7 +150,7 @@ impl Body {
|
|||||||
quadruped_low::Species::Driggle => 120.0,
|
quadruped_low::Species::Driggle => 120.0,
|
||||||
quadruped_low::Species::HermitAlligator => 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::Ship(_) => 0.0,
|
||||||
Body::Arthropod(arthropod) => match arthropod.species {
|
Body::Arthropod(arthropod) => match arthropod.species {
|
||||||
arthropod::Species::Tarantula => 135.0,
|
arthropod::Species::Tarantula => 135.0,
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp,
|
comp,
|
||||||
link::{Is, Link, LinkHandle, Role},
|
link::{Is, Link, LinkHandle, Role},
|
||||||
mounting::{Mount, Rider, VolumeRider},
|
mounting::{Rider, VolumeRider},
|
||||||
uid::{Uid, UidAllocator},
|
uid::{Uid, UidAllocator},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{
|
use specs::{saveload::MarkerAllocator, Entities, Read, ReadStorage, WriteStorage};
|
||||||
saveload::MarkerAllocator, storage::GenericWriteStorage, Component, DenseVecStorage, Entities,
|
|
||||||
Entity, Read, ReadExpect, ReadStorage, Write, WriteStorage,
|
|
||||||
};
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
@ -44,25 +41,20 @@ impl Link for Tethered {
|
|||||||
WriteStorage<'a, Is<Leader>>,
|
WriteStorage<'a, Is<Leader>>,
|
||||||
WriteStorage<'a, Is<Follower>>,
|
WriteStorage<'a, Is<Follower>>,
|
||||||
ReadStorage<'a, Is<Rider>>,
|
ReadStorage<'a, Is<Rider>>,
|
||||||
ReadStorage<'a, Is<Mount>>,
|
|
||||||
ReadStorage<'a, Is<VolumeRider>>,
|
ReadStorage<'a, Is<VolumeRider>>,
|
||||||
);
|
);
|
||||||
type DeleteData<'a> = (
|
type DeleteData<'a> = (
|
||||||
Read<'a, UidAllocator>,
|
Read<'a, UidAllocator>,
|
||||||
WriteStorage<'a, Is<Leader>>,
|
WriteStorage<'a, Is<Leader>>,
|
||||||
WriteStorage<'a, Is<Follower>>,
|
WriteStorage<'a, Is<Follower>>,
|
||||||
WriteStorage<'a, comp::Pos>,
|
|
||||||
WriteStorage<'a, comp::ForceUpdate>,
|
|
||||||
);
|
);
|
||||||
type Error = TetherError;
|
type Error = TetherError;
|
||||||
type PersistData<'a> = (
|
type PersistData<'a> = (
|
||||||
Read<'a, UidAllocator>,
|
Read<'a, UidAllocator>,
|
||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
ReadStorage<'a, comp::Health>,
|
ReadStorage<'a, comp::Health>,
|
||||||
ReadStorage<'a, comp::Body>,
|
|
||||||
ReadStorage<'a, Is<Leader>>,
|
ReadStorage<'a, Is<Leader>>,
|
||||||
ReadStorage<'a, Is<Follower>>,
|
ReadStorage<'a, Is<Follower>>,
|
||||||
ReadStorage<'a, comp::CharacterState>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
fn create(
|
fn create(
|
||||||
@ -72,7 +64,6 @@ impl Link for Tethered {
|
|||||||
is_leaders,
|
is_leaders,
|
||||||
is_followers,
|
is_followers,
|
||||||
is_riders,
|
is_riders,
|
||||||
is_mounts,
|
|
||||||
is_volume_rider,
|
is_volume_rider,
|
||||||
): &mut Self::CreateData<'_>,
|
): &mut Self::CreateData<'_>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
@ -103,7 +94,7 @@ impl Link for Tethered {
|
|||||||
|
|
||||||
fn persist(
|
fn persist(
|
||||||
this: &LinkHandle<Self>,
|
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 {
|
) -> bool {
|
||||||
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());
|
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());
|
||||||
|
|
||||||
@ -124,9 +115,7 @@ impl Link for Tethered {
|
|||||||
|
|
||||||
fn delete(
|
fn delete(
|
||||||
this: &LinkHandle<Self>,
|
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());
|
let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into());
|
||||||
|
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{Body, Collider, InputKind, Mass, Ori, Pos, Scale, Vel},
|
comp::{Body, Mass, Ori, Pos, Scale, Vel},
|
||||||
link::Is,
|
link::Is,
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
tether::{Follower, Leader},
|
tether::Follower,
|
||||||
uid::UidAllocator,
|
uid::UidAllocator,
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
use specs::{
|
use specs::{
|
||||||
saveload::{Marker, MarkerAllocator},
|
saveload::{Marker, MarkerAllocator},
|
||||||
Entities, Join, Read, ReadExpect, ReadStorage, WriteStorage,
|
Entities, Join, Read, ReadStorage, WriteStorage,
|
||||||
};
|
};
|
||||||
use tracing::error;
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
/// This system is responsible for controlling mounts
|
/// This system is responsible for controlling mounts
|
||||||
@ -22,14 +21,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
Read<'a, UidAllocator>,
|
Read<'a, UidAllocator>,
|
||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
Read<'a, DeltaTime>,
|
Read<'a, DeltaTime>,
|
||||||
ReadStorage<'a, Is<Leader>>,
|
|
||||||
ReadStorage<'a, Is<Follower>>,
|
ReadStorage<'a, Is<Follower>>,
|
||||||
WriteStorage<'a, Pos>,
|
WriteStorage<'a, Pos>,
|
||||||
WriteStorage<'a, Vel>,
|
WriteStorage<'a, Vel>,
|
||||||
WriteStorage<'a, Ori>,
|
WriteStorage<'a, Ori>,
|
||||||
ReadStorage<'a, Body>,
|
ReadStorage<'a, Body>,
|
||||||
ReadStorage<'a, Scale>,
|
ReadStorage<'a, Scale>,
|
||||||
ReadStorage<'a, Collider>,
|
|
||||||
ReadStorage<'a, Mass>,
|
ReadStorage<'a, Mass>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -43,19 +40,17 @@ impl<'a> System<'a> for Sys {
|
|||||||
uid_allocator,
|
uid_allocator,
|
||||||
entities,
|
entities,
|
||||||
dt,
|
dt,
|
||||||
is_leaders,
|
|
||||||
is_followers,
|
is_followers,
|
||||||
mut positions,
|
positions,
|
||||||
mut velocities,
|
mut velocities,
|
||||||
mut orientations,
|
mut orientations,
|
||||||
bodies,
|
bodies,
|
||||||
scales,
|
scales,
|
||||||
colliders,
|
|
||||||
masses,
|
masses,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
for (follower, is_follower, follower_body) in
|
for (follower, is_follower, follower_body, scale) in
|
||||||
(&entities, &is_followers, bodies.maybe()).join()
|
(&entities, &is_followers, bodies.maybe(), scales.maybe()).join()
|
||||||
{
|
{
|
||||||
let Some(leader) = uid_allocator
|
let Some(leader) = uid_allocator
|
||||||
.retrieve_entity_internal(is_follower.leader.id())
|
.retrieve_entity_internal(is_follower.leader.id())
|
||||||
@ -75,13 +70,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
let tether_offset = orientations
|
let tether_offset = orientations
|
||||||
.get(follower)
|
.get(follower)
|
||||||
.map(|ori| {
|
.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();
|
.unwrap_or_default();
|
||||||
let tether_pos = follower_pos.0 + tether_offset;
|
let tether_pos = follower_pos.0 + tether_offset;
|
||||||
let pull_factor = (leader_pos.0.distance(tether_pos) - is_follower.tether_length)
|
let pull_factor =
|
||||||
.clamp(0.0, 1.0)
|
(leader_pos.0.distance(tether_pos) - is_follower.tether_length).max(0.0);
|
||||||
.powf(2.0);
|
|
||||||
let strength = pull_factor * 50000.0;
|
let strength = pull_factor * 50000.0;
|
||||||
let pull_dir = (leader_pos.0 - follower_pos.0)
|
let pull_dir = (leader_pos.0 - follower_pos.0)
|
||||||
.try_normalized()
|
.try_normalized()
|
||||||
@ -93,9 +90,10 @@ impl<'a> System<'a> for Sys {
|
|||||||
velocities.get_mut(leader).unwrap().0 -= impulse / leader_mass.0;
|
velocities.get_mut(leader).unwrap().0 -= impulse / leader_mass.0;
|
||||||
|
|
||||||
if let Some(follower_ori) = orientations.get_mut(follower) {
|
if let Some(follower_ori) = orientations.get_mut(follower) {
|
||||||
let turn_strength = pull_factor.min(0.2)
|
let turn_strength = pull_factor
|
||||||
// * (tether_offset.magnitude() - tether_offset.dot(pull_dir).abs())
|
* (tether_offset.magnitude() * (leader_pos.0 - tether_pos).magnitude()
|
||||||
* 50.0;
|
- tether_offset.dot(leader_pos.0 - tether_pos).abs())
|
||||||
|
* 2.0;
|
||||||
let target_ori = follower_ori.yawed_towards(Dir::new(pull_dir));
|
let target_ori = follower_ori.yawed_towards(Dir::new(pull_dir));
|
||||||
*follower_ori = follower_ori.slerped_towards(target_ori, turn_strength * dt.0);
|
*follower_ori = follower_ori.slerped_towards(target_ori, turn_strength * dt.0);
|
||||||
}
|
}
|
||||||
|
@ -1778,7 +1778,7 @@ fn handle_spawn_ship(
|
|||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
_action: &ServerChatCommand,
|
_action: &ServerChatCommand,
|
||||||
) -> CmdResult<()> {
|
) -> 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")?;
|
let mut pos = position(server, target, "target")?;
|
||||||
pos.0.z += 2.0;
|
pos.0.z += 2.0;
|
||||||
const DESTINATION_RADIUS: f32 = 2000.0;
|
const DESTINATION_RADIUS: f32 = 2000.0;
|
||||||
@ -1798,15 +1798,15 @@ fn handle_spawn_ship(
|
|||||||
.state
|
.state
|
||||||
.create_ship(pos, ori, ship, |ship| ship.make_collider());
|
.create_ship(pos, ori, ship, |ship| ship.make_collider());
|
||||||
|
|
||||||
// if let Some(pos) = destination {
|
if let Some(pos) = destination {
|
||||||
// let (kp, ki, kd) =
|
let (kp, ki, kd) =
|
||||||
// comp::agent::pid_coefficients(&comp::Body::Ship(ship)).unwrap_or((1.
|
comp::agent::pid_coefficients(&comp::Body::Ship(ship)).unwrap_or((1.0, 0.0, 0.0));
|
||||||
// 0, 0.0, 0.0)); fn pure_z(sp: Vec3<f32>, pv: Vec3<f32>) -> f32 { (sp -
|
fn pure_z(sp: Vec3<f32>, pv: Vec3<f32>) -> f32 { (sp - pv).z }
|
||||||
// pv).z } let agent = comp::Agent::from_body(&comp::Body::Ship(ship))
|
let agent = comp::Agent::from_body(&comp::Body::Ship(ship))
|
||||||
// .with_destination(pos)
|
.with_destination(pos)
|
||||||
// .with_position_pid_controller(comp::PidController::new(kp, ki, kd,
|
.with_position_pid_controller(comp::PidController::new(kp, ki, kd, pos, 0.0, pure_z));
|
||||||
// pos, 0.0, pure_z)); builder = builder.with(agent);
|
builder = builder.with(agent);
|
||||||
// }
|
}
|
||||||
|
|
||||||
let new_entity = builder.build();
|
let new_entity = builder.build();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user