2020-02-24 18:17:16 +00:00
|
|
|
use crate::{
|
2021-03-14 18:42:39 +00:00
|
|
|
comp::{CharacterState, Climb, EnergySource, InputKind, Ori, StateUpdate},
|
2020-12-01 00:28:00 +00:00
|
|
|
consts::GRAVITY,
|
2020-03-07 18:15:02 +00:00
|
|
|
event::LocalEvent,
|
2021-03-14 18:42:39 +00:00
|
|
|
states::{
|
|
|
|
behavior::{CharacterBehavior, JoinData},
|
|
|
|
utils::*,
|
|
|
|
},
|
2020-03-28 01:31:22 +00:00
|
|
|
util::Dir,
|
2020-02-24 18:17:16 +00:00
|
|
|
};
|
2020-07-06 14:23:08 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2020-02-24 18:17:16 +00:00
|
|
|
use vek::{
|
|
|
|
vec::{Vec2, Vec3},
|
|
|
|
Lerp,
|
|
|
|
};
|
2019-12-26 14:43:59 +00:00
|
|
|
|
2020-01-07 15:49:08 +00:00
|
|
|
const HUMANOID_CLIMB_ACCEL: f32 = 5.0;
|
|
|
|
const CLIMB_SPEED: f32 = 5.0;
|
|
|
|
|
2020-03-14 21:17:27 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
|
|
|
pub struct Data;
|
2019-12-26 14:43:59 +00:00
|
|
|
|
2020-03-14 21:17:27 +00:00
|
|
|
impl CharacterBehavior for Data {
|
|
|
|
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
2020-03-21 21:16:26 +00:00
|
|
|
let mut update = StateUpdate::from(data);
|
2020-02-24 18:17:16 +00:00
|
|
|
|
2020-03-24 07:38:16 +00:00
|
|
|
// If no wall is in front of character or we stopped climbing;
|
2020-03-28 01:31:22 +00:00
|
|
|
let (wall_dir, climb) = if let (Some(wall_dir), Some(climb), false) = (
|
|
|
|
data.physics.on_wall,
|
|
|
|
data.inputs.climb,
|
|
|
|
data.physics.on_ground,
|
|
|
|
) {
|
|
|
|
(wall_dir, climb)
|
|
|
|
} else {
|
2021-03-14 18:42:39 +00:00
|
|
|
if
|
|
|
|
/* data.inputs.jump.is_pressed() */
|
|
|
|
input_is_pressed(data, InputKind::Jump) {
|
2020-03-14 21:17:27 +00:00
|
|
|
// They've climbed atop something, give them a boost
|
|
|
|
update
|
|
|
|
.local_events
|
|
|
|
.push_front(LocalEvent::Jump(data.entity));
|
|
|
|
}
|
|
|
|
update.character = CharacterState::Idle {};
|
|
|
|
return update;
|
2020-03-28 01:31:22 +00:00
|
|
|
};
|
2019-12-26 14:43:59 +00:00
|
|
|
|
2020-03-14 21:17:27 +00:00
|
|
|
// Move player
|
|
|
|
update.vel.0 += Vec2::broadcast(data.dt.0)
|
|
|
|
* data.inputs.move_dir
|
2020-11-25 00:28:24 +00:00
|
|
|
* if update.vel.0.magnitude_squared() < CLIMB_SPEED.powi(2) {
|
2020-03-14 21:17:27 +00:00
|
|
|
HUMANOID_CLIMB_ACCEL
|
|
|
|
} else {
|
|
|
|
0.0
|
|
|
|
};
|
2019-12-26 14:43:59 +00:00
|
|
|
|
2020-03-24 07:38:16 +00:00
|
|
|
// Expend energy if climbing
|
2020-03-28 01:31:22 +00:00
|
|
|
let energy_use = match climb {
|
2020-08-02 05:09:11 +00:00
|
|
|
Climb::Up => 5,
|
|
|
|
Climb::Down => 1,
|
2020-03-28 01:31:22 +00:00
|
|
|
Climb::Hold => 1,
|
2020-03-24 07:38:16 +00:00
|
|
|
};
|
2020-06-08 18:37:41 +00:00
|
|
|
|
|
|
|
if update
|
2020-03-24 07:38:16 +00:00
|
|
|
.energy
|
|
|
|
.try_change_by(-energy_use, EnergySource::Climb)
|
2020-06-08 18:37:41 +00:00
|
|
|
.is_err()
|
2020-03-24 07:38:16 +00:00
|
|
|
{
|
|
|
|
update.character = CharacterState::Idle {};
|
|
|
|
}
|
|
|
|
|
2020-03-14 21:17:27 +00:00
|
|
|
// Set orientation direction based on wall direction
|
2021-02-04 09:17:38 +00:00
|
|
|
if let Some(ori_dir) = Dir::from_unnormalized(Vec2::from(wall_dir).into()) {
|
|
|
|
// Smooth orientation
|
|
|
|
update.ori = update.ori.slerped_towards(
|
|
|
|
Ori::from(ori_dir),
|
|
|
|
if data.physics.on_ground { 9.0 } else { 2.0 } * data.dt.0,
|
|
|
|
);
|
|
|
|
};
|
2020-03-07 18:15:02 +00:00
|
|
|
|
2020-03-14 21:17:27 +00:00
|
|
|
// Apply Vertical Climbing Movement
|
2020-03-28 01:31:22 +00:00
|
|
|
if update.vel.0.z <= CLIMB_SPEED {
|
2020-03-24 07:38:16 +00:00
|
|
|
match climb {
|
|
|
|
Climb::Down => {
|
|
|
|
update.vel.0 -=
|
2020-08-02 05:09:11 +00:00
|
|
|
data.dt.0 * update.vel.0.map(|e| e.abs().powf(1.5) * e.signum() * 1.0);
|
2020-03-24 07:38:16 +00:00
|
|
|
},
|
|
|
|
Climb::Up => {
|
|
|
|
update.vel.0.z = (update.vel.0.z + data.dt.0 * GRAVITY * 1.25).min(CLIMB_SPEED);
|
|
|
|
},
|
|
|
|
Climb::Hold => {
|
2020-03-25 05:37:09 +00:00
|
|
|
// Antigrav
|
2020-08-08 21:05:48 +00:00
|
|
|
update.vel.0.z =
|
|
|
|
(update.vel.0.z + data.dt.0 * GRAVITY * 1.075).min(CLIMB_SPEED);
|
2020-03-24 07:38:16 +00:00
|
|
|
update.vel.0 = Lerp::lerp(
|
|
|
|
update.vel.0,
|
|
|
|
Vec3::zero(),
|
|
|
|
30.0 * data.dt.0 / (1.0 - update.vel.0.z.min(0.0) * 5.0),
|
|
|
|
);
|
|
|
|
},
|
2020-03-14 21:17:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
update
|
|
|
|
}
|
2019-12-26 14:43:59 +00:00
|
|
|
}
|