2020-02-24 18:17:16 +00:00
|
|
|
use crate::{
|
2021-03-20 23:22:04 +00:00
|
|
|
comp::{
|
|
|
|
skills::{ClimbSkill::*, Skill},
|
|
|
|
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};
|
2021-03-15 00:23:06 +00:00
|
|
|
use vek::*;
|
2019-12-26 14:43:59 +00:00
|
|
|
|
2021-03-20 21:56:54 +00:00
|
|
|
/// Separated out to condense update portions of character state
|
2021-03-20 16:13:59 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
2021-03-20 21:56:54 +00:00
|
|
|
pub struct StaticData {
|
2021-03-20 16:13:59 +00:00
|
|
|
pub energy_cost: f32,
|
|
|
|
pub movement_speed: f32,
|
|
|
|
}
|
2020-01-07 15:49:08 +00:00
|
|
|
|
2021-03-20 21:56:54 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
|
|
pub struct Data {
|
|
|
|
/// Struct containing data that does not change over the course of the
|
|
|
|
/// character state
|
|
|
|
pub static_data: StaticData,
|
|
|
|
}
|
|
|
|
|
2021-03-20 23:22:04 +00:00
|
|
|
impl Data {
|
|
|
|
pub fn create_adjusted_by_skills(join_data: &JoinData) -> Self {
|
|
|
|
let mut data = Data::default();
|
2021-04-14 15:35:34 +00:00
|
|
|
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Cost)) {
|
2021-03-20 23:22:04 +00:00
|
|
|
data.static_data.energy_cost *= 0.8_f32.powi(level.into());
|
|
|
|
}
|
2021-04-14 15:35:34 +00:00
|
|
|
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Speed)) {
|
2021-03-20 23:22:04 +00:00
|
|
|
data.static_data.movement_speed *= 1.2_f32.powi(level.into());
|
|
|
|
}
|
|
|
|
data
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-20 16:13:59 +00:00
|
|
|
impl Default for Data {
|
|
|
|
fn default() -> Self {
|
|
|
|
Data {
|
2021-03-20 21:56:54 +00:00
|
|
|
static_data: StaticData {
|
|
|
|
energy_cost: 5.0,
|
|
|
|
movement_speed: 5.0,
|
|
|
|
},
|
2021-03-20 16:13:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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 20:35:28 +00:00
|
|
|
if 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
|
2021-03-13 20:51:32 +00:00
|
|
|
.push_front(LocalEvent::Jump(data.entity, BASE_JUMP_IMPULSE * 0.5));
|
2020-03-14 21:17:27 +00:00
|
|
|
}
|
|
|
|
update.character = CharacterState::Idle {};
|
|
|
|
return update;
|
2020-03-28 01:31:22 +00:00
|
|
|
};
|
2020-03-14 21:17:27 +00:00
|
|
|
// Move player
|
|
|
|
update.vel.0 += Vec2::broadcast(data.dt.0)
|
|
|
|
* data.inputs.move_dir
|
2021-03-20 21:56:54 +00:00
|
|
|
* if update.vel.0.magnitude_squared() < self.static_data.movement_speed.powi(2) {
|
|
|
|
self.static_data.movement_speed.powi(2)
|
2020-03-14 21:17:27 +00:00
|
|
|
} 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 {
|
2021-03-20 21:56:54 +00:00
|
|
|
Climb::Up => self.static_data.energy_cost as i32,
|
2020-08-02 05:09:11 +00:00
|
|
|
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
|
2021-03-15 00:23:06 +00:00
|
|
|
match climb {
|
2021-03-20 21:56:54 +00:00
|
|
|
Climb::Down => {
|
|
|
|
update.vel.0.z += data.dt.0 * (GRAVITY - self.static_data.movement_speed.powi(2))
|
|
|
|
},
|
|
|
|
Climb::Up => {
|
|
|
|
update.vel.0.z += data.dt.0 * (GRAVITY + self.static_data.movement_speed.powi(2))
|
|
|
|
},
|
2021-03-15 00:23:06 +00:00
|
|
|
Climb::Hold => update.vel.0.z += data.dt.0 * GRAVITY,
|
2020-03-14 21:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
update
|
|
|
|
}
|
2019-12-26 14:43:59 +00:00
|
|
|
}
|