Merge branch 'lboklin/auto-glide' into 'master'

Implement auto-glide

See merge request veloren/veloren!2321
This commit is contained in:
Marcel 2021-05-21 09:02:59 +00:00
commit ee93803f4a
3 changed files with 77 additions and 10 deletions

View File

@ -931,6 +931,11 @@ impl Client {
pub fn is_dead(&self) -> bool { self.current::<comp::Health>().map_or(false, |h| h.is_dead) } pub fn is_dead(&self) -> bool { self.current::<comp::Health>().map_or(false, |h| h.is_dead) }
pub fn is_gliding(&self) -> bool {
self.current::<comp::CharacterState>()
.map_or(false, |cs| matches!(cs, comp::CharacterState::Glide(_)))
}
pub fn split_swap_slots(&mut self, a: comp::slot::Slot, b: comp::slot::Slot) { pub fn split_swap_slots(&mut self, a: comp::slot::Slot, b: comp::slot::Slot) {
match (a, b) { match (a, b) {
(Slot::Equip(equip), slot) | (slot, Slot::Equip(equip)) => self.control_action( (Slot::Equip(equip), slot) | (slot, Slot::Equip(equip)) => self.control_action(
@ -1234,7 +1239,7 @@ impl Client {
} }
pub fn toggle_glide(&mut self) { pub fn toggle_glide(&mut self) {
let is_gliding = self let using_glider = self
.state .state
.ecs() .ecs()
.read_storage::<comp::CharacterState>() .read_storage::<comp::CharacterState>()
@ -1246,7 +1251,7 @@ impl Client {
) )
}); });
match is_gliding { match using_glider {
Some(true) => self.control_action(ControlAction::Unwield), Some(true) => self.control_action(ControlAction::Unwield),
Some(false) => self.control_action(ControlAction::GlideWield), Some(false) => self.control_action(ControlAction::GlideWield),
None => warn!("Can't toggle glide, client entity doesn't have a `CharacterState`"), None => warn!("Can't toggle glide, client entity doesn't have a `CharacterState`"),

View File

@ -22,6 +22,7 @@ pub struct Data {
pub ori: Ori, pub ori: Ori,
last_vel: Vel, last_vel: Vel,
timer: f32, timer: f32,
inputs_disabled: bool,
} }
impl Data { impl Data {
@ -40,13 +41,19 @@ impl Data {
ori, ori,
last_vel: Vel::zero(), last_vel: Vel::zero(),
timer: 0.0, timer: 0.0,
inputs_disabled: true,
} }
} }
fn tgt_dir(&self, data: &JoinData) -> Dir { fn tgt_dir(&self, data: &JoinData) -> Dir {
let move_dir = if self.inputs_disabled {
Vec2::zero()
} else {
data.inputs.move_dir
};
let look_ori = Ori::from(data.inputs.look_dir); let look_ori = Ori::from(data.inputs.look_dir);
look_ori look_ori
.yawed_right(PI / 3.0 * look_ori.right().xy().dot(data.inputs.move_dir)) .yawed_right(PI / 3.0 * look_ori.right().xy().dot(move_dir))
.pitched_up(PI * 0.04) .pitched_up(PI * 0.04)
.pitched_down( .pitched_down(
data.inputs data.inputs
@ -54,7 +61,7 @@ impl Data {
.xy() .xy()
.try_normalized() .try_normalized()
.map_or(0.0, |ld| { .map_or(0.0, |ld| {
PI * 0.1 * ld.dot(data.inputs.move_dir) * self.timer.min(PITCH_SLOW_TIME) PI * 0.1 * ld.dot(move_dir) * self.timer.min(PITCH_SLOW_TIME)
/ PITCH_SLOW_TIME / PITCH_SLOW_TIME
}), }),
) )
@ -84,6 +91,8 @@ impl CharacterBehavior for Data {
.map(|fluid| fluid.relative_flow(data.vel)) .map(|fluid| fluid.relative_flow(data.vel))
.unwrap_or_default(); .unwrap_or_default();
let inputs_disabled = self.inputs_disabled && !data.inputs.move_dir.is_approx_zero();
let ori = { let ori = {
let slerp_s = { let slerp_s = {
let angle = self.ori.look_dir().angle_between(*data.inputs.look_dir); let angle = self.ori.look_dir().angle_between(*data.inputs.look_dir);
@ -178,6 +187,7 @@ impl CharacterBehavior for Data {
ori, ori,
last_vel: *data.vel, last_vel: *data.vel,
timer: self.timer + data.dt.0, timer: self.timer + data.dt.0,
inputs_disabled,
..*self ..*self
}); });
} else { } else {

View File

@ -22,7 +22,7 @@ use common::{
trade::TradeResult, trade::TradeResult,
util::{ util::{
find_dist::{Cube, Cylinder, FindDist}, find_dist::{Cube, Cylinder, FindDist},
Dir, Dir, Plane,
}, },
vol::ReadVol, vol::ReadVol,
}; };
@ -520,6 +520,9 @@ impl PlayState for SessionState {
}, },
GameInput::Glide => { GameInput::Glide => {
if state { if state {
if global_state.settings.gameplay.stop_auto_walk_on_input {
self.stop_auto_walk();
}
self.client.borrow_mut().toggle_glide(); self.client.borrow_mut().toggle_glide();
} }
}, },
@ -682,7 +685,9 @@ impl PlayState for SessionState {
&mut self.auto_walk, &mut self.auto_walk,
|b| hud.auto_walk(b), |b| hud.auto_walk(b),
); );
self.key_state.auto_walk = self.auto_walk;
self.key_state.auto_walk =
self.auto_walk && !self.client.borrow().is_gliding();
}, },
GameInput::CameraClamp => { GameInput::CameraClamp => {
let hud = &mut self.hud; let hud = &mut self.hud;
@ -747,10 +752,57 @@ impl PlayState for SessionState {
} }
} }
if !self.free_look { // If auto-gliding, point camera into the wind
self.walk_forward_dir = self.scene.camera().forward_xy(); if let Some(dir) = self
self.walk_right_dir = self.scene.camera().right_xy(); .auto_walk
self.inputs.look_dir = Dir::from_unnormalized(cam_dir + aim_dir_offset).unwrap(); .then_some(self.client.borrow())
.filter(|client| client.is_gliding())
.and_then(|client| {
let ecs = client.state().ecs();
let entity = client.entity();
let fluid = ecs
.read_storage::<comp::PhysicsState>()
.get(entity)?
.in_fluid?;
ecs.read_storage::<comp::Vel>()
.get(entity)
.map(|vel| fluid.relative_flow(vel).0)
.map(|rel_flow| {
let is_wind_downwards = rel_flow.dot(Vec3::unit_z()).is_sign_negative();
if !self.free_look {
if is_wind_downwards {
self.scene.camera().forward_xy().into()
} else {
let windwards = rel_flow
* self
.scene
.camera()
.forward_xy()
.dot(rel_flow.xy())
.signum();
Plane::from(Dir::new(self.scene.camera().right()))
.projection(windwards)
}
} else if is_wind_downwards {
Vec3::from(-rel_flow.xy())
} else {
-rel_flow
}
})
.and_then(Dir::from_unnormalized)
})
{
self.key_state.auto_walk = false;
self.inputs.move_dir = Vec2::zero();
self.inputs.look_dir = dir;
} else {
self.key_state.auto_walk = self.auto_walk;
if !self.free_look {
self.walk_forward_dir = self.scene.camera().forward_xy();
self.walk_right_dir = self.scene.camera().right_xy();
self.inputs.look_dir =
Dir::from_unnormalized(cam_dir + aim_dir_offset).unwrap();
}
} }
// Get the current state of movement related inputs // Get the current state of movement related inputs