From 21cf1e21686844eb7c58d4332d41953f9156ffd3 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 28 Sep 2020 18:55:38 -0500 Subject: [PATCH] Added keyframes to leap melee. --- common/src/comp/ability.rs | 40 ++-- common/src/comp/inventory/item/tool.rs | 18 +- common/src/states/leap_melee.rs | 278 +++++++++++++++---------- common/src/states/repeater_ranged.rs | 5 +- 4 files changed, 202 insertions(+), 139 deletions(-) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 9879bbf0de..0bfb26dfad 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -121,15 +121,16 @@ pub enum CharacterAbility { }, LeapMelee { energy_cost: u32, - movement_duration: Duration, buildup_duration: Duration, + movement_duration: Duration, + swing_duration: Duration, recover_duration: Duration, base_damage: u32, range: f32, max_angle: f32, knockback: f32, - leap_speed: f32, - leap_vert_speed: f32, + forward_leap_strength: f32, + vertical_leap_strength: f32, }, SpinMelee { buildup_duration: Duration, @@ -464,27 +465,32 @@ impl From<&CharacterAbility> for CharacterState { }), CharacterAbility::LeapMelee { energy_cost: _, - movement_duration, buildup_duration, + movement_duration, + swing_duration, recover_duration, base_damage, + knockback, range, max_angle, - knockback, - leap_speed, - leap_vert_speed, + forward_leap_strength, + vertical_leap_strength, } => CharacterState::LeapMelee(leap_melee::Data { - initialize: true, + static_data: leap_melee::StaticData { + buildup_duration: *buildup_duration, + movement_duration: *movement_duration, + swing_duration: *swing_duration, + recover_duration: *recover_duration, + base_damage: *base_damage, + knockback: *knockback, + range: *range, + max_angle: *max_angle, + forward_leap_strength: *forward_leap_strength, + vertical_leap_strength: *vertical_leap_strength, + }, + timer: Duration::default(), + stage_section: StageSection::Buildup, exhausted: false, - movement_duration: *movement_duration, - buildup_duration: *buildup_duration, - recover_duration: *recover_duration, - base_damage: *base_damage, - range: *range, - max_angle: *max_angle, - knockback: *knockback, - leap_speed: *leap_speed, - leap_vert_speed: *leap_vert_speed, }), CharacterAbility::SpinMelee { buildup_duration, diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 2e00935896..af9466e9b7 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -228,15 +228,16 @@ impl Tool { }, LeapMelee { energy_cost: 450, + buildup_duration: Duration::from_millis(100), movement_duration: Duration::from_millis(200), - buildup_duration: Duration::from_millis(1000), + swing_duration: Duration::from_millis(100), recover_duration: Duration::from_millis(600), base_damage: (160.0 * self.base_power()) as u32, + knockback: 15.0, range: 3.5, max_angle: 100.0, - knockback: 15.0, - leap_speed: 16.0, - leap_vert_speed: 6.0, + forward_leap_strength: 16.0, + vertical_leap_strength: 6.0, }, ], Hammer(_) => vec![ @@ -264,15 +265,16 @@ impl Tool { }, LeapMelee { energy_cost: 700, + buildup_duration: Duration::from_millis(100), movement_duration: Duration::from_millis(500), - buildup_duration: Duration::from_millis(1000), + swing_duration: Duration::from_millis(100), recover_duration: Duration::from_millis(100), base_damage: (240.0 * self.base_power()) as u32, + knockback: 25.0, range: 4.5, max_angle: 360.0, - knockback: 25.0, - leap_speed: 24.0, - leap_vert_speed: 4.0, + forward_leap_strength: 24.0, + vertical_leap_strength: 4.0, }, ], Farming(_) => vec![BasicMelee { diff --git a/common/src/states/leap_melee.rs b/common/src/states/leap_melee.rs index 4eea14cef5..bbd844f630 100644 --- a/common/src/states/leap_melee.rs +++ b/common/src/states/leap_melee.rs @@ -1,146 +1,198 @@ use crate::{ comp::{Attacking, CharacterState, StateUpdate}, - states::utils::*, + states::utils::{StageSection, *}, sys::character_behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; use std::time::Duration; use vek::Vec3; +/// Separated out to condense update portions of character state #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] -//#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] -pub struct Data { +pub struct StaticData { /// How long the state is moving pub movement_duration: Duration, /// How long until state should deal damage pub buildup_duration: Duration, + /// How long the weapon swings + pub swing_duration: Duration, /// How long the state has until exiting pub recover_duration: Duration, /// Base damage pub base_damage: u32, - /// Whether the attack can deal more damage - pub exhausted: bool, + /// Knockback + pub knockback: f32, /// Max range pub range: f32, /// Max angle (45.0 will give you a 90.0 angle window) pub max_angle: f32, - /// Knockback - pub knockback: f32, - /// Leap speed - pub leap_speed: f32, - /// Leap vertical speed? - pub leap_vert_speed: f32, - pub initialize: bool, + /// Affects how far forward the player leaps + pub forward_leap_strength: f32, + /// Affects how high the player leaps + pub vertical_leap_strength: f32, +} + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +//#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] +pub struct Data { + /// Struct containing data that does not change over the course of the + /// character state + pub static_data: StaticData, + /// Timer for each stage + pub timer: Duration, + /// What section the character stage is in + pub stage_section: StageSection, + /// Whether the attack can deal more damage + pub exhausted: bool, } impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); - if self.initialize { - update.vel.0 = *data.inputs.look_dir * 20.0; - if let Some(dir) = Vec3::from(data.inputs.look_dir.xy()).try_normalized() { - update.ori.0 = dir.into(); - } - } + handle_move(data, &mut update, 0.3); + handle_jump(data, &mut update); - if self.movement_duration != Duration::default() { - // Jumping - update.vel.0 = Vec3::new( - data.inputs.look_dir.x, - data.inputs.look_dir.y, - self.leap_vert_speed, - ) * (2.0) - + (update.vel.0 * Vec3::new(2.0, 2.0, 0.0) - + 0.25 * data.inputs.move_dir.try_normalized().unwrap_or_default()) - .try_normalized() - .unwrap_or_default() - * self.leap_speed - * (1.0 - data.inputs.look_dir.z.abs()); + match self.stage_section { + StageSection::Buildup => { + if self.timer < self.static_data.buildup_duration { + // Buildup + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + stage_section: self.stage_section, + exhausted: self.exhausted, + }); + } else { + // Transitions to leap portion of state + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Movement, + exhausted: self.exhausted, + }); + } + }, + StageSection::Movement => { + // Jumping + update.vel.0 = Vec3::new( + data.inputs.look_dir.x, + data.inputs.look_dir.y, + self.static_data.vertical_leap_strength, + ) * 2.0 + * (1.0 + - self.timer.as_secs_f32() + / self.static_data.movement_duration.as_secs_f32()) + + (update.vel.0 * Vec3::new(2.0, 2.0, 0.0) + + 0.25 * data.inputs.move_dir.try_normalized().unwrap_or_default()) + .try_normalized() + .unwrap_or_default() + * self.static_data.forward_leap_strength + * (1.0 - data.inputs.look_dir.z.abs()); - update.character = CharacterState::LeapMelee(Data { - movement_duration: self - .movement_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - buildup_duration: self.buildup_duration, - recover_duration: self.recover_duration, - base_damage: self.base_damage, - exhausted: false, - range: self.range, - max_angle: self.max_angle, - knockback: self.knockback, - leap_speed: self.leap_speed, - leap_vert_speed: self.leap_vert_speed, - initialize: false, - }); - } else if self.buildup_duration != Duration::default() && !data.physics.on_ground { - // Falling - update.character = CharacterState::LeapMelee(Data { - movement_duration: Duration::default(), - buildup_duration: self - .buildup_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - recover_duration: self.recover_duration, - base_damage: self.base_damage, - exhausted: false, - range: self.range, - max_angle: self.max_angle, - knockback: self.knockback, - leap_speed: self.leap_speed, - leap_vert_speed: self.leap_vert_speed, - initialize: false, - }); - } else if !self.exhausted { - // Hit attempt - data.updater.insert(data.entity, Attacking { - base_damage: self.base_damage, - base_heal: 0, - range: self.range, - max_angle: self.max_angle.to_radians(), - applied: false, - hit_count: 0, - knockback: self.knockback, - }); + if self.timer < self.static_data.movement_duration { + // Movement duration + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + stage_section: self.stage_section, + exhausted: self.exhausted, + }); + } else { + // Transitions to swing portion of state + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Swing, + exhausted: self.exhausted, + }); + } + }, + StageSection::Swing => { + if self.timer < self.static_data.swing_duration { + // Swings weapons + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + stage_section: self.stage_section, + exhausted: self.exhausted, + }); + } else { + // Transitions to recover portion + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Recover, + exhausted: self.exhausted, + }); + } + }, + StageSection::Recover => { + if !data.physics.on_ground { + // Falls + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + stage_section: self.stage_section, + exhausted: self.exhausted, + }); + } else if !self.exhausted { + // Hit attempt + data.updater.insert(data.entity, Attacking { + base_damage: self.static_data.base_damage, + base_heal: 0, + range: self.static_data.range, + max_angle: self.static_data.max_angle.to_radians(), + applied: false, + hit_count: 0, + knockback: self.static_data.knockback, + }); - update.character = CharacterState::LeapMelee(Data { - movement_duration: self.movement_duration, - buildup_duration: Duration::default(), - recover_duration: self.recover_duration, - base_damage: self.base_damage, - exhausted: true, - range: self.range, - max_angle: self.max_angle, - knockback: self.knockback, - leap_speed: self.leap_speed, - leap_vert_speed: self.leap_vert_speed, - initialize: false, - }); - } else if self.recover_duration != Duration::default() { - // Recovery - handle_move(data, &mut update, 0.7); - update.character = CharacterState::LeapMelee(Data { - movement_duration: self.movement_duration, - buildup_duration: self.buildup_duration, - recover_duration: self - .recover_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - base_damage: self.base_damage, - exhausted: true, - range: self.range, - max_angle: self.max_angle, - knockback: self.knockback, - leap_speed: self.leap_speed, - leap_vert_speed: self.leap_vert_speed, - initialize: false, - }); - } else { - // Done - update.character = CharacterState::Wielding; - // Make sure attack component is removed - data.updater.remove::(data.entity); + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + stage_section: self.stage_section, + exhausted: true, + }); + } else if self.timer < self.static_data.recover_duration { + // Recovers + update.character = CharacterState::LeapMelee(Data { + static_data: self.static_data, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), + stage_section: self.stage_section, + exhausted: self.exhausted, + }); + } else { + // Done + update.character = CharacterState::Wielding; + // Make sure attack component is removed + data.updater.remove::(data.entity); + } + }, + _ => { + // If it somehow ends up in an incorrect stage section + update.character = CharacterState::Wielding; + // Make sure attack component is removed + data.updater.remove::(data.entity); + }, } update diff --git a/common/src/states/repeater_ranged.rs b/common/src/states/repeater_ranged.rs index fcd7e5b119..85768cb17f 100644 --- a/common/src/states/repeater_ranged.rs +++ b/common/src/states/repeater_ranged.rs @@ -174,7 +174,10 @@ impl CharacterBehavior for Data { // Lands update.character = CharacterState::RepeaterRanged(Data { static_data: self.static_data.clone(), - timer: self.timer, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) + .unwrap_or_default(), stage_section: self.stage_section, reps_remaining: self.reps_remaining, });