diff --git a/CHANGELOG.md b/CHANGELOG.md index b7274ce324..5ca4ece5ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Doubled range of ScaleMode slider when set to Custom +- Glider can now be deployed even when not on the ground +- Gliding now has an energy cost for strenuous maneuvers based on lift ### Removed diff --git a/common/src/comp/energy.rs b/common/src/comp/energy.rs index ff03c46a47..87959ab281 100644 --- a/common/src/comp/energy.rs +++ b/common/src/comp/energy.rs @@ -14,6 +14,7 @@ pub struct Energy { pub enum EnergySource { Ability, Climb, + Glide, LevelUp, HitEnemy, Regen, diff --git a/common/src/states/glide.rs b/common/src/states/glide.rs index 4a3efd21c8..5fa8b267e6 100644 --- a/common/src/states/glide.rs +++ b/common/src/states/glide.rs @@ -1,6 +1,6 @@ use super::utils::handle_climb; use crate::{ - comp::{CharacterState, StateUpdate}, + comp::{CharacterState, EnergySource, StateUpdate}, states::behavior::{CharacterBehavior, JoinData}, util::Dir, }; @@ -48,19 +48,28 @@ impl CharacterBehavior for Data { }; // Determine orientation vector from movement direction vector - let ori_dir = Vec2::from(update.vel.0); - update.ori.0 = Dir::slerp_to_vec3(update.ori.0, ori_dir.into(), 2.0 * data.dt.0); + let horiz_vel = Vec2::from(update.vel.0); + update.ori.0 = Dir::slerp_to_vec3(update.ori.0, horiz_vel.into(), 2.0 * data.dt.0); // Apply Glide antigrav lift - if Vec2::::from(update.vel.0).magnitude_squared() < GLIDE_SPEED.powi(2) - && update.vel.0.z < 0.0 - { - let lift = GLIDE_ANTIGRAV + update.vel.0.z.abs().powi(2) * 0.15; - update.vel.0.z += data.dt.0 - * lift - * (Vec2::::from(update.vel.0).magnitude() * 0.075) - .min(1.0) - .max(0.2); + let horiz_speed_sq = horiz_vel.magnitude_squared(); + if horiz_speed_sq < GLIDE_SPEED.powi(2) && update.vel.0.z < 0.0 { + let lift = (GLIDE_ANTIGRAV + update.vel.0.z.powi(2) * 0.15) + * (horiz_speed_sq * f32::powf(0.075, 2.0)).clamp(0.2, 1.0) + * data.dt.0; + + update.vel.0.z += lift; + + // Expend energy during strenuous maneuvers. + // Cost increases with lift exceeding that of calmly gliding. + let energy_cost = (10.0 * (lift - GLIDE_ANTIGRAV * data.dt.0)).max(0.0) as i32; + if update + .energy + .try_change_by(-energy_cost, EnergySource::Glide) + .is_err() + { + update.character = CharacterState::Idle {}; + } } update diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index d1a7991061..ea4f812fbd 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -348,8 +348,7 @@ pub fn attempt_swap_loadout(data: &JoinData, update: &mut StateUpdate) { /// Checks that player can wield the glider and updates `CharacterState` if so pub fn attempt_glide_wield(data: &JoinData, update: &mut StateUpdate) { - if data.physics.on_ground - && data.loadout.glider.is_some() + if data.loadout.glider.is_some() && !data .physics .in_liquid diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index c44d500de1..ad7321b4de 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -100,7 +100,6 @@ impl<'a> System<'a> for Sys { | CharacterState::Sit { .. } | CharacterState::Dance { .. } | CharacterState::Sneak { .. } - | CharacterState::Glide { .. } | CharacterState::GlideWield { .. } | CharacterState::Wielding { .. } | CharacterState::Equipping { .. } @@ -123,8 +122,9 @@ impl<'a> System<'a> for Sys { (energy.regen_rate + ENERGY_REGEN_ACCEL * dt.0).min(100.0); } }, - // Ability use does not regen and sets the rate back to zero. - CharacterState::BasicMelee { .. } + // Ability and glider use does not regen and sets the rate back to zero. + CharacterState::Glide { .. } + | CharacterState::BasicMelee { .. } | CharacterState::DashMelee { .. } | CharacterState::LeapMelee { .. } | CharacterState::SpinMelee { .. }