veloren/common/src/states/climb.rs

135 lines
4.3 KiB
Rust
Raw Normal View History

2020-02-24 18:17:16 +00:00
use crate::{
comp::{
2021-08-16 17:43:57 +00:00
skills::{ClimbSkill::*, GeneralTreeModifiers, Skill},
CharacterState, Climb, EnergySource, InputKind, Ori, StateUpdate,
},
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::*,
},
util::Dir,
2020-02-24 18:17:16 +00:00
};
use serde::{Deserialize, Serialize};
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,
}
impl Data {
pub fn create_adjusted_by_skills(join_data: &JoinData) -> Self {
2021-08-16 17:43:57 +00:00
const GENERAL_MODIFIERS: GeneralTreeModifiers = GeneralTreeModifiers::get();
let modifiers = GENERAL_MODIFIERS.climb;
let mut data = Data::default();
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Cost)) {
2021-08-16 17:43:57 +00:00
data.static_data.energy_cost *= modifiers.energy_cost.powi(level.into());
}
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Speed)) {
2021-08-16 17:43:57 +00:00
data.static_data.movement_speed *= modifiers.speed.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 {
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;
2021-06-20 03:51:04 +00:00
let (wall_dir, climb) = if let (Some(wall_dir), Some(climb), None) = (
data.physics.on_wall,
data.inputs.climb,
data.physics.on_ground,
) {
(wall_dir, climb)
} else {
if let Some(impulse) = input_is_pressed(data, InputKind::Jump)
.then(|| data.body.jump_impulse())
.flatten()
{
// How strong the climb boost is relative to a normal jump
const CLIMB_BOOST_JUMP_FACTOR: f32 = 0.5;
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,
CLIMB_BOOST_JUMP_FACTOR * impulse / data.mass.0,
));
};
2020-03-14 21:17:27 +00:00
update.character = CharacterState::Idle {};
return update;
};
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
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,
Climb::Hold => 1,
2020-03-24 07:38:16 +00:00
};
if update
2020-03-24 07:38:16 +00:00
.energy
.try_change_by(-energy_use, EnergySource::Climb)
.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),
2021-06-20 03:51:04 +00:00
if data.physics.on_ground.is_some() {
9.0
} else {
2.0
} * data.dt.0,
2021-02-04 09:17:38 +00:00
);
};
2020-03-07 18:15:02 +00:00
2020-03-14 21:17:27 +00:00
// Apply Vertical Climbing Movement
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))
},
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
}