Add charging back

This commit is contained in:
Adam Whitehurst 2020-03-08 10:04:26 -07:00
parent adf34d4f0f
commit f769c74bf4
8 changed files with 83 additions and 73 deletions

View File

@ -5,6 +5,7 @@ pub enum AbilityState {
BasicAttack, BasicAttack,
BasicBlock, BasicBlock,
Roll, Roll,
ChargeAttack,
} }
impl Default for AbilityState { impl Default for AbilityState {
fn default() -> Self { Self::BasicAttack } fn default() -> Self { Self::BasicAttack }
@ -26,7 +27,7 @@ impl Default for AbilityPool {
fn default() -> Self { fn default() -> Self {
Self { Self {
primary: Some(AbilityState::BasicAttack), primary: Some(AbilityState::BasicAttack),
secondary: Some(AbilityState::BasicBlock), secondary: Some(AbilityState::ChargeAttack),
block: None, block: None,
dodge: Some(AbilityState::Roll), dodge: Some(AbilityState::Roll),
} }

View File

@ -42,7 +42,10 @@ pub enum CharacterState {
}, },
/// A basic blocking state /// A basic blocking state
BasicBlock {}, BasicBlock {},
//Charge{}, ChargeAttack {
/// How long the state has until exiting
remaining_duration: Duration,
},
Roll { Roll {
/// How long the state has until exiting /// How long the state has until exiting
remaining_duration: Duration, remaining_duration: Duration,
@ -61,7 +64,7 @@ impl CharacterState {
pub fn is_attack(&self) -> bool { pub fn is_attack(&self) -> bool {
match self { match self {
CharacterState::BasicAttack { .. } => true, CharacterState::BasicAttack { .. } | CharacterState::ChargeAttack { .. } => true,
_ => false, _ => false,
} }
} }

View File

@ -22,14 +22,7 @@ pub fn behavior(data: &JoinData) -> StateUpdate {
handle_move(&data, &mut update); handle_move(&data, &mut update);
if !data.physics.on_ground || !data.inputs.secondary.is_pressed() { if !data.physics.on_ground || !data.inputs.secondary.is_pressed() {
if let Some(ItemKind::Tool(tool)) = data.stats.equipment.main.as_ref().map(|i| i.kind) { attempt_wield(data, &mut update);
update.character = CharacterState::Equipping {
tool,
time_left: tool.equip_time(),
};
} else {
update.character = CharacterState::Idle {};
};
} }
update update
} }

View File

@ -1,13 +1,10 @@
use super::utils::*; use super::utils::*;
use crate::{ use crate::{
comp::{ comp::{CharacterState::*, HealthChange, HealthSource, StateUpdate},
ActionState::Attack, AttackKind::Charge, CharacterEntityData, HealthChange, HealthSource,
ItemKind::Tool, MoveState::Run, StateUpdate, ToolData,
},
event::ServerEvent, event::ServerEvent,
sys::character_behavior::JoinData, sys::character_behavior::JoinData,
}; };
use std::time::Duration; use std::{collections::VecDeque, time::Duration};
use vek::Vec3; use vek::Vec3;
const CHARGE_SPEED: f32 = 20.0; const CHARGE_SPEED: f32 = 20.0;
@ -18,45 +15,49 @@ pub fn behavior(data: &JoinData) -> StateUpdate {
vel: *data.vel, vel: *data.vel,
ori: *data.ori, ori: *data.ori,
character: *data.character, character: *data.character,
energy: *data.energy,
local_events: VecDeque::new(),
server_events: VecDeque::new(),
}; };
// Move player if let ChargeAttack { remaining_duration } = data.character {
update.vel.0 = Vec3::new(0.0, 0.0, update.vel.0.z) // Move player
+ (update.vel.0 * Vec3::new(1.0, 1.0, 0.0) update.vel.0 = Vec3::new(0.0, 0.0, update.vel.0.z)
+ 1.5 * data.inputs.move_dir.try_normalized().unwrap_or_default()) + (update.vel.0 * Vec3::new(1.0, 1.0, 0.0)
.try_normalized() + 1.5 * data.inputs.move_dir.try_normalized().unwrap_or_default())
.unwrap_or_default() .try_normalized()
* CHARGE_SPEED; .unwrap_or_default()
* CHARGE_SPEED;
// Check if hitting another entity // Check if hitting another entity
if let Some(uid_b) = data.physics.touch_entity { if let Some(uid_b) = data.physics.touch_entity {
// Send Damage event // Send Damage event
data.server_bus.emitter().emit(ServerEvent::Damage { update.server_events.push_front(ServerEvent::Damage {
uid: uid_b, uid: uid_b,
change: HealthChange { change: HealthChange {
amount: -20, amount: -20,
cause: HealthSource::Attack { by: *data.uid }, cause: HealthSource::Attack { by: *data.uid },
}, },
}); });
// Go back to wielding or idling // Go back to wielding or idling
update.character.action_state = attempt_wield(data.stats); attempt_wield(data, &mut update);
return update; return update;
}
// Check if charge timed out or can't keep moving forward
if *remaining_duration == Duration::default() || update.vel.0.magnitude_squared() < 10.0 {
attempt_wield(data, &mut update);
return update;
}
// Tick remaining-duration and keep charging
update.character = ChargeAttack {
remaining_duration: remaining_duration
.checked_sub(Duration::from_secs_f32(data.dt.0))
.unwrap_or_default(),
};
} }
// Check if charge timed out or can't keep moving forward
if self.remaining_duration == Duration::default() || update.vel.0.magnitude_squared() < 10.0 {
update.character.action_state = attempt_wield(data.stats);
return update;
}
// Tick remaining-duration and keep charging
update.character.action_state = Attack(Charge(Some(State {
remaining_duration: self
.remaining_duration
.checked_sub(Duration::from_secs_f32(data.dt.0))
.unwrap_or_default(),
})));
update update
} }

View File

@ -1,6 +1,7 @@
// Module declarations // Module declarations
pub mod basic_attack; pub mod basic_attack;
pub mod basic_block; pub mod basic_block;
pub mod charge_attack;
pub mod climb; pub mod climb;
pub mod equipping; pub mod equipping;
pub mod glide; pub mod glide;

View File

@ -105,19 +105,26 @@ fn swim_move(data: &JoinData, update: &mut StateUpdate) {
} }
} }
/// First checks whether `primary` input is pressed, then
/// attempts to go into Equipping state, otherwise Idle
pub fn handle_wield(data: &JoinData, update: &mut StateUpdate) { pub fn handle_wield(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.primary.is_pressed() { if data.inputs.primary.is_pressed() {
if let Some(Tool(tool)) = data.stats.equipment.main.as_ref().map(|i| i.kind) { attempt_wield(data, update);
update.character = CharacterState::Equipping {
tool,
time_left: tool.equip_time(),
};
} else {
update.character = CharacterState::Idle {};
};
} }
} }
/// If a tool is equipped, goes into Equipping state, otherwise goes to Idle
pub fn attempt_wield(data: &JoinData, update: &mut StateUpdate) {
if let Some(Tool(tool)) = data.stats.equipment.main.as_ref().map(|i| i.kind) {
update.character = CharacterState::Equipping {
tool,
time_left: tool.equip_time(),
};
} else {
update.character = CharacterState::Idle {};
};
}
pub fn handle_sit(data: &JoinData, update: &mut StateUpdate) { pub fn handle_sit(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.sit.is_pressed() && data.physics.on_ground && data.body.is_humanoid() { if data.inputs.sit.is_pressed() && data.physics.on_ground && data.body.is_humanoid() {
update.character = CharacterState::Sit {}; update.character = CharacterState::Sit {};
@ -226,5 +233,8 @@ pub fn character_state_from_ability(
AbilityState::Roll { .. } => CharacterState::Roll { AbilityState::Roll { .. } => CharacterState::Roll {
remaining_duration: Duration::from_millis(600), remaining_duration: Duration::from_millis(600),
}, },
AbilityState::ChargeAttack { .. } => CharacterState::ChargeAttack {
remaining_duration: Duration::from_millis(600),
},
} }
} }

View File

@ -2,26 +2,26 @@ use super::utils::*;
use crate::{comp::StateUpdate, sys::character_behavior::JoinData}; use crate::{comp::StateUpdate, sys::character_behavior::JoinData};
use std::collections::VecDeque; use std::collections::VecDeque;
pub fn behavior(ecs_data: &JoinData) -> StateUpdate { pub fn behavior(data: &JoinData) -> StateUpdate {
let mut update = StateUpdate { let mut update = StateUpdate {
character: *ecs_data.character, character: *data.character,
pos: *ecs_data.pos, pos: *data.pos,
vel: *ecs_data.vel, vel: *data.vel,
ori: *ecs_data.ori, ori: *data.ori,
energy: *ecs_data.energy, energy: *data.energy,
local_events: VecDeque::new(), local_events: VecDeque::new(),
server_events: VecDeque::new(), server_events: VecDeque::new(),
}; };
handle_move(&ecs_data, &mut update); handle_move(&data, &mut update);
handle_jump(&ecs_data, &mut update); handle_jump(&data, &mut update);
handle_sit(&ecs_data, &mut update); handle_sit(&data, &mut update);
handle_climb(&ecs_data, &mut update); handle_climb(&data, &mut update);
handle_glide(&ecs_data, &mut update); handle_glide(&data, &mut update);
handle_unwield(&ecs_data, &mut update); handle_unwield(&data, &mut update);
handle_primary(&ecs_data, &mut update); handle_primary(&data, &mut update);
handle_secondary(&ecs_data, &mut update); handle_secondary(&data, &mut update);
handle_dodge(&ecs_data, &mut update); handle_dodge(&data, &mut update);
update update
} }

View File

@ -169,6 +169,7 @@ impl<'a> System<'a> for Sys {
CharacterState::Equipping { .. } => states::equipping::behavior(&j), CharacterState::Equipping { .. } => states::equipping::behavior(&j),
CharacterState::BasicAttack { .. } => states::basic_attack::behavior(&j), CharacterState::BasicAttack { .. } => states::basic_attack::behavior(&j),
CharacterState::BasicBlock { .. } => states::basic_block::behavior(&j), CharacterState::BasicBlock { .. } => states::basic_block::behavior(&j),
CharacterState::ChargeAttack { .. } => states::charge_attack::behavior(&j),
CharacterState::Sit { .. } => states::sit::behavior(&j), CharacterState::Sit { .. } => states::sit::behavior(&j),
// _ => StateUpdate { // _ => StateUpdate {