From 63011241ea26680b9f570be53bff0c7839aff25a Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 16 Oct 2020 21:29:14 -0500 Subject: [PATCH] Added keyframes to all states that were lacking them. --- common/src/comp/ability.rs | 108 +++++---- common/src/comp/inventory/item/tool.rs | 124 +++++----- common/src/loadout_builder.rs | 10 +- common/src/states/basic_melee.rs | 165 ++++++++----- common/src/states/basic_ranged.rs | 160 ++++++------- common/src/states/boost.rs | 44 ++-- common/src/states/charged_ranged.rs | 309 ++++++++++++------------- common/src/states/equipping.rs | 34 ++- common/src/states/roll.rs | 115 +++++++-- common/src/states/utils.rs | 6 +- voxygen/src/hud/hotbar.rs | 2 +- voxygen/src/hud/skillbar.rs | 34 +-- voxygen/src/hud/slots.rs | 5 +- 13 files changed, 626 insertions(+), 490 deletions(-) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 04cf6e708f..32659deaee 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -59,16 +59,16 @@ pub enum CharacterAbility { BasicMelee { energy_cost: u32, buildup_duration: Duration, + swing_duration: Duration, recover_duration: Duration, - base_healthchange: i32, + base_damage: u32, knockback: f32, range: f32, max_angle: f32, }, BasicRanged { energy_cost: u32, - holdable: bool, - prepare_duration: Duration, + buildup_duration: Duration, recover_duration: Duration, projectile: Projectile, projectile_body: Body, @@ -91,7 +91,7 @@ pub enum CharacterAbility { reps_remaining: u32, }, Boost { - duration: Duration, + movement_duration: Duration, only_up: bool, }, DashMelee { @@ -169,7 +169,7 @@ pub enum CharacterAbility { max_damage: u32, initial_knockback: f32, max_knockback: f32, - prepare_duration: Duration, + buildup_duration: Duration, charge_duration: Duration, recover_duration: Duration, projectile_body: Body, @@ -356,24 +356,29 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { match ability { CharacterAbility::BasicMelee { buildup_duration, + swing_duration, recover_duration, - base_healthchange, + base_damage, knockback, range, max_angle, energy_cost: _, } => CharacterState::BasicMelee(basic_melee::Data { + static_data: basic_melee::StaticData { + buildup_duration: *buildup_duration, + swing_duration: *swing_duration, + recover_duration: *recover_duration, + base_damage: *base_damage, + knockback: *knockback, + range: *range, + max_angle: *max_angle, + }, + timer: Duration::default(), + stage_section: StageSection::Buildup, exhausted: false, - buildup_duration: *buildup_duration, - recover_duration: *recover_duration, - base_healthchange: *base_healthchange, - knockback: *knockback, - range: *range, - max_angle: *max_angle, }), CharacterAbility::BasicRanged { - holdable, - prepare_duration, + buildup_duration, recover_duration, projectile, projectile_body, @@ -382,21 +387,29 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { projectile_speed, energy_cost: _, } => CharacterState::BasicRanged(basic_ranged::Data { + static_data: basic_ranged::StaticData { + buildup_duration: *buildup_duration, + recover_duration: *recover_duration, + projectile: projectile.clone(), + projectile_body: *projectile_body, + projectile_light: *projectile_light, + projectile_gravity: *projectile_gravity, + projectile_speed: *projectile_speed, + ability_key: key, + }, + timer: Duration::default(), + stage_section: StageSection::Buildup, exhausted: false, - prepare_timer: Duration::default(), - holdable: *holdable, - prepare_duration: *prepare_duration, - recover_duration: *recover_duration, - projectile: projectile.clone(), - projectile_body: *projectile_body, - projectile_light: *projectile_light, - projectile_gravity: *projectile_gravity, - projectile_speed: *projectile_speed, - ability_key: key, }), - CharacterAbility::Boost { duration, only_up } => CharacterState::Boost(boost::Data { - duration: *duration, - only_up: *only_up, + CharacterAbility::Boost { + movement_duration, + only_up, + } => CharacterState::Boost(boost::Data { + static_data: boost::StaticData { + movement_duration: *movement_duration, + only_up: *only_up, + }, + timer: Duration::default(), }), CharacterAbility::DashMelee { energy_cost: _, @@ -438,7 +451,13 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { }), CharacterAbility::BasicBlock => CharacterState::BasicBlock, CharacterAbility::Roll => CharacterState::Roll(roll::Data { - remaining_duration: Duration::from_millis(500), + static_data: roll::StaticData { + buildup_duration: Duration::from_millis(100), + movement_duration: Duration::from_millis(300), + recover_duration: Duration::from_millis(100), + }, + timer: Duration::default(), + stage_section: StageSection::Buildup, was_wielded: false, // false by default. utils might set it to true }), CharacterAbility::ComboMelee { @@ -566,7 +585,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { max_damage, initial_knockback, max_knockback, - prepare_duration, + buildup_duration, charge_duration, recover_duration, projectile_body, @@ -575,21 +594,24 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState { initial_projectile_speed, max_projectile_speed, } => CharacterState::ChargedRanged(charged_ranged::Data { + static_data: charged_ranged::StaticData { + buildup_duration: *buildup_duration, + charge_duration: *charge_duration, + recover_duration: *recover_duration, + energy_drain: *energy_drain, + initial_damage: *initial_damage, + max_damage: *max_damage, + initial_knockback: *initial_knockback, + max_knockback: *max_knockback, + projectile_body: *projectile_body, + projectile_light: *projectile_light, + projectile_gravity: *projectile_gravity, + initial_projectile_speed: *initial_projectile_speed, + max_projectile_speed: *max_projectile_speed, + }, + timer: Duration::default(), + stage_section: StageSection::Buildup, exhausted: false, - energy_drain: *energy_drain, - initial_damage: *initial_damage, - max_damage: *max_damage, - initial_knockback: *initial_knockback, - max_knockback: *max_knockback, - prepare_duration: *prepare_duration, - charge_duration: *charge_duration, - charge_timer: Duration::default(), - recover_duration: *recover_duration, - projectile_body: *projectile_body, - projectile_light: *projectile_light, - projectile_gravity: *projectile_gravity, - initial_projectile_speed: *initial_projectile_speed, - max_projectile_speed: *max_projectile_speed, }), CharacterAbility::RepeaterRanged { energy_cost: _, diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 9e847bce6d..4cc50a926d 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -206,9 +206,10 @@ impl Tool { Axe(_) => vec![ BasicMelee { energy_cost: 0, - buildup_duration: Duration::from_millis(700), + buildup_duration: Duration::from_millis(600), + swing_duration: Duration::from_millis(100), recover_duration: Duration::from_millis(300), - base_healthchange: (-120.0 * self.base_power()) as i32, + base_damage: (120.0 * self.base_power()) as u32, knockback: 0.0, range: 3.5, max_angle: 20.0, @@ -244,9 +245,10 @@ impl Tool { Hammer(_) => vec![ BasicMelee { energy_cost: 0, - buildup_duration: Duration::from_millis(700), + buildup_duration: Duration::from_millis(600), + swing_duration: Duration::from_millis(100), recover_duration: Duration::from_millis(300), - base_healthchange: (-120.0 * self.base_power()) as i32, + base_damage: (120.0 * self.base_power()) as u32, knockback: 0.0, range: 3.5, max_angle: 20.0, @@ -280,9 +282,10 @@ impl Tool { ], Farming(_) => vec![BasicMelee { energy_cost: 1, - buildup_duration: Duration::from_millis(700), + buildup_duration: Duration::from_millis(600), + swing_duration: Duration::from_millis(100), recover_duration: Duration::from_millis(150), - base_healthchange: (-50.0 * self.base_power()) as i32, + base_damage: (50.0 * self.base_power()) as u32, knockback: 0.0, range: 3.5, max_angle: 20.0, @@ -290,8 +293,7 @@ impl Tool { Bow(_) => vec![ BasicRanged { energy_cost: 0, - holdable: true, - prepare_duration: Duration::from_millis(100), + buildup_duration: Duration::from_millis(100), recover_duration: Duration::from_millis(400), projectile: Projectile { hit_solid: vec![projectile::Effect::Stick], @@ -317,7 +319,7 @@ impl Tool { max_damage: (200.0 * self.base_power()) as u32, initial_knockback: 10.0, max_knockback: 20.0, - prepare_duration: Duration::from_millis(100), + buildup_duration: Duration::from_millis(100), charge_duration: Duration::from_millis(1500), recover_duration: Duration::from_millis(500), projectile_body: Body::Object(object::Body::MultiArrow), @@ -355,8 +357,9 @@ impl Tool { Dagger(_) => vec![BasicMelee { energy_cost: 0, buildup_duration: Duration::from_millis(100), - recover_duration: Duration::from_millis(400), - base_healthchange: (-50.0 * self.base_power()) as i32, + swing_duration: Duration::from_millis(100), + recover_duration: Duration::from_millis(300), + base_damage: (50.0 * self.base_power()) as u32, knockback: 0.0, range: 3.5, max_angle: 20.0, @@ -378,8 +381,7 @@ impl Tool { }, BasicRanged { energy_cost: 800, - holdable: true, - prepare_duration: Duration::from_millis(800), + buildup_duration: Duration::from_millis(800), recover_duration: Duration::from_millis(50), projectile: Projectile { hit_solid: vec![ @@ -422,8 +424,7 @@ impl Tool { Staff(_) => vec![ BasicRanged { energy_cost: 0, - holdable: false, - prepare_duration: Duration::from_millis(500), + buildup_duration: Duration::from_millis(500), recover_duration: Duration::from_millis(350), projectile: Projectile { hit_solid: vec![ @@ -495,8 +496,9 @@ impl Tool { BasicMelee { energy_cost: 0, buildup_duration: Duration::from_millis(100), - recover_duration: Duration::from_millis(400), - base_healthchange: (-40.0 * self.base_power()) as i32, + swing_duration: Duration::from_millis(100), + recover_duration: Duration::from_millis(300), + base_damage: (40.0 * self.base_power()) as u32, knockback: 0.0, range: 3.0, max_angle: 120.0, @@ -508,10 +510,11 @@ impl Tool { vec![ BasicMelee { energy_cost: 0, - buildup_duration: Duration::from_millis(500), + buildup_duration: Duration::from_millis(400), + swing_duration: Duration::from_millis(100), recover_duration: Duration::from_millis(250), knockback: 25.0, - base_healthchange: -200, + base_damage: 200, range: 5.0, max_angle: 120.0, }, @@ -533,10 +536,11 @@ impl Tool { } else if kind == "BeastClaws" { vec![BasicMelee { energy_cost: 0, - buildup_duration: Duration::from_millis(500), + buildup_duration: Duration::from_millis(250), + swing_duration: Duration::from_millis(250), recover_duration: Duration::from_millis(250), knockback: 25.0, - base_healthchange: -200, + base_damage: 200, range: 5.0, max_angle: 120.0, }] @@ -544,58 +548,50 @@ impl Tool { vec![BasicMelee { energy_cost: 0, buildup_duration: Duration::from_millis(100), - recover_duration: Duration::from_millis(300), - base_healthchange: -10, + swing_duration: Duration::from_millis(100), + recover_duration: Duration::from_millis(200), + base_damage: 10, knockback: 0.0, range: 1.0, max_angle: 30.0, }] } }, - Debug(kind) => { - if kind == "Boost" { - vec![ - CharacterAbility::Boost { - duration: Duration::from_millis(50), - only_up: false, - }, - CharacterAbility::Boost { - duration: Duration::from_millis(50), - only_up: true, - }, - BasicRanged { - energy_cost: 0, - holdable: false, - prepare_duration: Duration::from_millis(0), - recover_duration: Duration::from_millis(10), - projectile: Projectile { - hit_solid: vec![projectile::Effect::Stick], - hit_entity: vec![ - projectile::Effect::Stick, - projectile::Effect::Possess, - ], - time_left: Duration::from_secs(10), - owner: None, - ignore_group: false, - }, - projectile_body: Body::Object(object::Body::ArrowSnake), - projectile_light: Some(LightEmitter { - col: (0.0, 1.0, 0.33).into(), - ..Default::default() - }), - projectile_gravity: None, - projectile_speed: 100.0, - }, - ] - } else { - vec![] - } - }, + Debug(_) => vec![ + CharacterAbility::Boost { + movement_duration: Duration::from_millis(50), + only_up: false, + }, + CharacterAbility::Boost { + movement_duration: Duration::from_millis(50), + only_up: true, + }, + BasicRanged { + energy_cost: 0, + buildup_duration: Duration::from_millis(0), + recover_duration: Duration::from_millis(10), + projectile: Projectile { + hit_solid: vec![projectile::Effect::Stick], + hit_entity: vec![projectile::Effect::Stick, projectile::Effect::Possess], + time_left: Duration::from_secs(10), + owner: None, + ignore_group: false, + }, + projectile_body: Body::Object(object::Body::ArrowSnake), + projectile_light: Some(LightEmitter { + col: (0.0, 1.0, 0.33).into(), + ..Default::default() + }), + projectile_gravity: None, + projectile_speed: 100.0, + }, + ], Empty => vec![BasicMelee { energy_cost: 0, buildup_duration: Duration::from_millis(0), - recover_duration: Duration::from_millis(1000), - base_healthchange: -20, + swing_duration: Duration::from_millis(100), + recover_duration: Duration::from_millis(900), + base_damage: 20, knockback: 0.0, range: 3.5, max_angle: 15.0, diff --git a/common/src/loadout_builder.rs b/common/src/loadout_builder.rs index 3fcb1c2fbb..5511a7826d 100644 --- a/common/src/loadout_builder.rs +++ b/common/src/loadout_builder.rs @@ -163,8 +163,9 @@ impl LoadoutBuilder { ability1: Some(CharacterAbility::BasicMelee { energy_cost: 0, buildup_duration: Duration::from_millis(0), - recover_duration: Duration::from_millis(400), - base_healthchange: -40, + swing_duration: Duration::from_millis(100), + recover_duration: Duration::from_millis(300), + base_damage: 40, knockback: 0.0, range: 3.5, max_angle: 15.0, @@ -343,9 +344,10 @@ impl LoadoutBuilder { item: Item::new_from_asset_expect("common.items.weapons.empty.empty"), ability1: Some(CharacterAbility::BasicMelee { energy_cost: 10, - buildup_duration: Duration::from_millis(600), + buildup_duration: Duration::from_millis(500), + swing_duration: Duration::from_millis(100), recover_duration: Duration::from_millis(100), - base_healthchange: -(body.base_dmg() as i32), + base_damage: body.base_dmg(), knockback: 0.0, range: body.base_range(), max_angle: 20.0, diff --git a/common/src/states/basic_melee.rs b/common/src/states/basic_melee.rs index 0d98e0aeac..dc3f6a4041 100644 --- a/common/src/states/basic_melee.rs +++ b/common/src/states/basic_melee.rs @@ -6,20 +6,34 @@ use crate::{ use serde::{Deserialize, Serialize}; use std::time::Duration; +/// Separated out to condense update portions of character state #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Data { +pub struct StaticData { /// How long until state should deal damage pub buildup_duration: Duration, + /// How long the state is swinging for + pub swing_duration: Duration, /// How long the state has until exiting pub recover_duration: Duration, - /// Base damage (negative) or healing (positive) - pub base_healthchange: i32, + /// Base damage + pub base_damage: u32, /// 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, +} + +#[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, + /// 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, } @@ -31,65 +45,94 @@ impl CharacterBehavior for Data { handle_move(data, &mut update, 0.7); handle_jump(data, &mut update); - if self.buildup_duration != Duration::default() { - // Build up - update.character = CharacterState::BasicMelee(Data { - buildup_duration: self - .buildup_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - recover_duration: self.recover_duration, - base_healthchange: self.base_healthchange, - knockback: self.knockback, - range: self.range, - max_angle: self.max_angle, - exhausted: false, - }); - } else if !self.exhausted { - let (damage, heal) = if self.base_healthchange > 0 { - (0, self.base_healthchange as u32) - } else { - ((-self.base_healthchange) as u32, 0) - }; - // Hit attempt - data.updater.insert(data.entity, Attacking { - base_damage: damage, - base_heal: heal, - range: self.range, - max_angle: self.max_angle.to_radians(), - applied: false, - hit_count: 0, - knockback: self.knockback, - }); + match self.stage_section { + StageSection::Buildup => { + if self.timer < self.static_data.buildup_duration { + // Build up + update.character = CharacterState::BasicMelee(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 section of stage + update.character = CharacterState::BasicMelee(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Swing, + exhausted: self.exhausted, + }); + } + }, + StageSection::Swing => { + if !self.exhausted { + update.character = CharacterState::BasicMelee(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: self.stage_section, + exhausted: true, + }); - update.character = CharacterState::BasicMelee(Data { - buildup_duration: self.buildup_duration, - recover_duration: self.recover_duration, - base_healthchange: self.base_healthchange, - knockback: self.knockback, - range: self.range, - max_angle: self.max_angle, - exhausted: true, - }); - } else if self.recover_duration != Duration::default() { - // Recovery - update.character = CharacterState::BasicMelee(Data { - buildup_duration: self.buildup_duration, - recover_duration: self - .recover_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - base_healthchange: self.base_healthchange, - knockback: self.knockback, - range: self.range, - max_angle: self.max_angle, - exhausted: true, - }); - } else { - // Done - update.character = CharacterState::Wielding; - // Make sure attack component is removed - data.updater.remove::(data.entity); + // 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: 180_f32.to_radians(), + applied: false, + hit_count: 0, + knockback: self.static_data.knockback, + }); + } else if self.timer < self.static_data.swing_duration { + // Swings + update.character = CharacterState::BasicMelee(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 section of stage + update.character = CharacterState::BasicMelee(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Recover, + exhausted: self.exhausted, + }); + } + }, + StageSection::Recover => { + if self.timer < self.static_data.recover_duration { + // Recovery + update.character = CharacterState::BasicMelee(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); + }, } // Grant energy on successful hit diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index cbfc6afc7a..bb0950e605 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -7,27 +7,36 @@ use crate::{ use serde::{Deserialize, Serialize}; use std::time::Duration; +/// Separated out to condense update portions of character state #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Data { - /// Can you hold the ability beyond the prepare duration - pub holdable: bool, - /// How long we have to prepare the weapon - pub prepare_duration: Duration, - /// How long we prepared the weapon already - pub prepare_timer: Duration, +pub struct StaticData { + /// How much buildup is required before the attack + pub buildup_duration: Duration, /// How long the state has until exiting pub recover_duration: Duration, + /// Projectile variables pub projectile: Projectile, pub projectile_body: Body, pub projectile_light: Option, pub projectile_gravity: Option, pub projectile_speed: f32, - /// Whether the attack fired already - pub exhausted: bool, /// What key is used to press ability pub ability_key: AbilityKey, } +#[derive(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, + /// Timer for each stage + pub timer: Duration, + /// What section the character stage is in + pub stage_section: StageSection, + /// Whether the attack fired already + pub exhausted: bool, +} + impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); @@ -35,77 +44,70 @@ impl CharacterBehavior for Data { handle_move(data, &mut update, 0.3); handle_jump(data, &mut update); - if !self.exhausted - && if self.holdable { - ability_key_is_pressed(data, self.ability_key) - || self.prepare_timer < self.prepare_duration - } else { - self.prepare_timer < self.prepare_duration - } - { - // Prepare (draw the bow) - update.character = CharacterState::BasicRanged(Data { - prepare_timer: self.prepare_timer + Duration::from_secs_f32(data.dt.0), - holdable: self.holdable, - prepare_duration: self.prepare_duration, - recover_duration: self.recover_duration, - projectile: self.projectile.clone(), - projectile_body: self.projectile_body, - projectile_light: self.projectile_light, - projectile_gravity: self.projectile_gravity, - projectile_speed: self.projectile_speed, - exhausted: false, - ability_key: self.ability_key, - }); - } else if !self.exhausted { - // Fire - let mut projectile = self.projectile.clone(); - projectile.owner = Some(*data.uid); - update.server_events.push_front(ServerEvent::Shoot { - entity: data.entity, - dir: data.inputs.look_dir, - body: self.projectile_body, - projectile, - light: self.projectile_light, - gravity: self.projectile_gravity, - speed: self.projectile_speed, - }); + match self.stage_section { + StageSection::Buildup => { + if self.timer < self.static_data.buildup_duration { + // Build up + update.character = CharacterState::BasicRanged(Data { + static_data: self.static_data.clone(), + 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 section of stage + update.character = CharacterState::BasicRanged(Data { + static_data: self.static_data.clone(), + timer: Duration::default(), + stage_section: StageSection::Recover, + exhausted: self.exhausted, + }); + } + }, + StageSection::Recover => { + if !self.exhausted { + // Fire + let mut projectile = self.static_data.projectile.clone(); + projectile.owner = Some(*data.uid); + update.server_events.push_front(ServerEvent::Shoot { + entity: data.entity, + dir: data.inputs.look_dir, + body: self.static_data.projectile_body, + projectile, + light: self.static_data.projectile_light, + gravity: self.static_data.projectile_gravity, + speed: self.static_data.projectile_speed, + }); - update.character = CharacterState::BasicRanged(Data { - prepare_timer: self.prepare_timer, - holdable: self.holdable, - prepare_duration: self.prepare_duration, - recover_duration: self.recover_duration, - projectile: self.projectile.clone(), - projectile_body: self.projectile_body, - projectile_light: self.projectile_light, - projectile_gravity: self.projectile_gravity, - projectile_speed: self.projectile_speed, - exhausted: true, - ability_key: self.ability_key, - }); - } else if self.recover_duration != Duration::default() { - // Recovery - update.character = CharacterState::BasicRanged(Data { - prepare_timer: self.prepare_timer, - holdable: self.holdable, - prepare_duration: self.prepare_duration, - recover_duration: self - .recover_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - projectile: self.projectile.clone(), - projectile_body: self.projectile_body, - projectile_light: self.projectile_light, - projectile_gravity: self.projectile_gravity, - projectile_speed: self.projectile_speed, - exhausted: true, - ability_key: self.ability_key, - }); - return update; - } else { - // Done - update.character = CharacterState::Wielding; + update.character = CharacterState::BasicRanged(Data { + static_data: self.static_data.clone(), + timer: self.timer, + stage_section: self.stage_section, + exhausted: true, + }); + } else if self.timer < self.static_data.recover_duration { + // Recovers + update.character = CharacterState::BasicRanged(Data { + static_data: self.static_data.clone(), + 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; + } + }, + _ => { + // If it somehow ends up in an incorrect stage section + update.character = CharacterState::Wielding; + }, } update diff --git a/common/src/states/boost.rs b/common/src/states/boost.rs index 52f1994152..564a714c57 100644 --- a/common/src/states/boost.rs +++ b/common/src/states/boost.rs @@ -1,16 +1,25 @@ use crate::{ - comp::{Attacking, CharacterState, EnergySource, StateUpdate}, + comp::{CharacterState, StateUpdate}, states::utils::*, sys::character_behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; use std::time::Duration; +/// Separated out to condense update portions of character state +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct StaticData { + pub movement_duration: Duration, + pub only_up: bool, +} + #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Data { - /// How long the state has until exiting - pub duration: Duration, - pub only_up: bool, + /// 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, } impl CharacterBehavior for Data { @@ -19,34 +28,25 @@ impl CharacterBehavior for Data { handle_move(data, &mut update, 1.0); - // Still going - if self.duration != Duration::default() { - if self.only_up { + if self.timer < self.static_data.movement_duration { + // Movement + if self.static_data.only_up { update.vel.0.z += 500.0 * data.dt.0; } else { update.vel.0 += *data.inputs.look_dir * 500.0 * data.dt.0; } update.character = CharacterState::Boost(Data { - duration: self - .duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) + static_data: self.static_data, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) .unwrap_or_default(), - only_up: self.only_up, }); - } - // Done - else { + } else { + // Done update.character = CharacterState::Wielding; } - // Grant energy on successful hit - if let Some(attack) = data.attacking { - if attack.applied && attack.hit_count > 0 { - data.updater.remove::(data.entity); - update.energy.change_by(100, EnergySource::HitEnemy); - } - } - update } } diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 1386b8b4d5..5413eaa386 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -10,10 +10,15 @@ use crate::{ use serde::{Deserialize, Serialize}; use std::time::Duration; -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Data { - /// Whether the attack fired already - pub exhausted: bool, +/// Separated out to condense update portions of character state +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct StaticData { + /// How long the weapon needs to be prepared for + pub buildup_duration: Duration, + /// How long it takes to charge the weapon to max damage and knockback + pub charge_duration: Duration, + /// How long the state has until exiting + pub recover_duration: Duration, /// How much energy is drained per second when charging pub energy_drain: u32, /// How much damage is dealt with no charge @@ -24,14 +29,6 @@ pub struct Data { pub initial_knockback: f32, /// How much knockback there is at max charge pub max_knockback: f32, - /// How long the weapon needs to be prepared for - pub prepare_duration: Duration, - /// How long it takes to charge the weapon to max damage and knockback - pub charge_duration: Duration, - /// How long the state has been charging - pub charge_timer: Duration, - /// How long the state has until exiting - pub recover_duration: Duration, /// Projectile information pub projectile_body: Body, pub projectile_light: Option, @@ -40,6 +37,19 @@ pub struct Data { pub max_projectile_speed: f32, } +#[derive(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, + /// Timer for each stage + pub timer: Duration, + /// What section the character stage is in + pub stage_section: StageSection, + /// Whether the attack fired already + pub exhausted: bool, +} + impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); @@ -47,160 +57,133 @@ impl CharacterBehavior for Data { handle_move(data, &mut update, 0.3); handle_jump(data, &mut update); - if self.prepare_duration != Duration::default() { - // Prepare (draw the bow) - update.character = CharacterState::ChargedRanged(Data { - exhausted: self.exhausted, - energy_drain: self.energy_drain, - initial_damage: self.initial_damage, - max_damage: self.max_damage, - initial_knockback: self.initial_knockback, - max_knockback: self.max_knockback, - prepare_duration: self - .prepare_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - charge_duration: self.charge_duration, - charge_timer: self.charge_timer, - recover_duration: self.recover_duration, - projectile_body: self.projectile_body, - projectile_light: self.projectile_light, - projectile_gravity: self.projectile_gravity, - initial_projectile_speed: self.initial_projectile_speed, - max_projectile_speed: self.max_projectile_speed, - }); - } else if data.inputs.secondary.is_pressed() - && self.charge_timer < self.charge_duration - && update.energy.current() > 0 - { - // Charge the bow - update.character = CharacterState::ChargedRanged(Data { - exhausted: self.exhausted, - energy_drain: self.energy_drain, - initial_damage: self.initial_damage, - max_damage: self.max_damage, - initial_knockback: self.initial_knockback, - max_knockback: self.max_knockback, - prepare_duration: self.prepare_duration, - charge_timer: self - .charge_timer - .checked_add(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - charge_duration: self.charge_duration, - recover_duration: self.recover_duration, - projectile_body: self.projectile_body, - projectile_light: self.projectile_light, - projectile_gravity: self.projectile_gravity, - initial_projectile_speed: self.initial_projectile_speed, - max_projectile_speed: self.max_projectile_speed, - }); + match self.stage_section { + StageSection::Buildup => { + if self.timer < self.static_data.buildup_duration { + // Build up + update.character = CharacterState::ChargedRanged(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 section of stage + update.character = CharacterState::ChargedRanged(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Charge, + exhausted: self.exhausted, + }); + } + }, + StageSection::Charge => { + if !data.inputs.secondary.is_pressed() && !self.exhausted { + let charge_frac = (self.timer.as_secs_f32() + / self.static_data.charge_duration.as_secs_f32()) + .min(1.0); + let damage = self.static_data.initial_damage as f32 + + (charge_frac + * (self.static_data.max_damage - self.static_data.initial_damage) + as f32); + let knockback = self.static_data.initial_knockback as f32 + + (charge_frac + * (self.static_data.max_knockback - self.static_data.initial_knockback) + as f32); + // Fire + let mut projectile = Projectile { + hit_solid: vec![projectile::Effect::Stick], + hit_entity: vec![ + projectile::Effect::Damage(-damage as i32), + projectile::Effect::Knockback(knockback), + projectile::Effect::Vanish, + ], + time_left: Duration::from_secs(15), + owner: None, + ignore_group: true, + }; + projectile.owner = Some(*data.uid); + update.server_events.push_front(ServerEvent::Shoot { + entity: data.entity, + dir: data.inputs.look_dir, + body: self.static_data.projectile_body, + projectile, + light: self.static_data.projectile_light, + gravity: self.static_data.projectile_gravity, + speed: self.static_data.initial_projectile_speed + + charge_frac + * (self.static_data.max_projectile_speed + - self.static_data.initial_projectile_speed), + }); - // Consumes energy if there's enough left and RMB is held down - update.energy.change_by( - -(self.energy_drain as f32 * data.dt.0) as i32, - EnergySource::Ability, - ); - } else if data.inputs.secondary.is_pressed() { - // Charge the bow - update.character = CharacterState::ChargedRanged(Data { - exhausted: self.exhausted, - energy_drain: self.energy_drain, - initial_damage: self.initial_damage, - max_damage: self.max_damage, - initial_knockback: self.initial_knockback, - max_knockback: self.max_knockback, - prepare_duration: self.prepare_duration, - charge_timer: self.charge_timer, - charge_duration: self.charge_duration, - recover_duration: self.recover_duration, - projectile_body: self.projectile_body, - projectile_light: self.projectile_light, - projectile_gravity: self.projectile_gravity, - initial_projectile_speed: self.initial_projectile_speed, - max_projectile_speed: self.max_projectile_speed, - }); + update.character = CharacterState::ChargedRanged(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Recover, + exhausted: true, + }); + } else if self.timer < self.static_data.charge_duration + && data.inputs.secondary.is_pressed() + { + // Charges + update.character = CharacterState::ChargedRanged(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, + }); - // Consumes energy if there's enough left and RMB is held down - update.energy.change_by( - -(self.energy_drain as f32 * data.dt.0 / 5.0) as i32, - EnergySource::Ability, - ); - } else if !self.exhausted { - let charge_amount = - (self.charge_timer.as_secs_f32() / self.charge_duration.as_secs_f32()).min(1.0); - // Fire - let mut projectile = Projectile { - hit_solid: vec![projectile::Effect::Stick], - hit_entity: vec![ - projectile::Effect::Damage( - -(self.initial_damage as i32 - + (charge_amount * (self.max_damage - self.initial_damage) as f32) - as i32), - ), - projectile::Effect::Knockback( - self.initial_knockback - + charge_amount * (self.max_knockback - self.initial_knockback), - ), - projectile::Effect::Vanish, - ], - time_left: Duration::from_secs(15), - owner: None, - ignore_group: true, - }; - projectile.owner = Some(*data.uid); - update.server_events.push_front(ServerEvent::Shoot { - entity: data.entity, - dir: data.inputs.look_dir, - body: self.projectile_body, - projectile, - light: self.projectile_light, - gravity: self.projectile_gravity, - speed: self.initial_projectile_speed - + charge_amount * (self.max_projectile_speed - self.initial_projectile_speed), - }); + // Consumes energy if there's enough left and RMB is held down + update.energy.change_by( + -(self.static_data.energy_drain as f32 * data.dt.0) as i32, + EnergySource::Ability, + ); + } else if data.inputs.secondary.is_pressed() { + // Holds charge + update.character = CharacterState::ChargedRanged(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, + }); - update.character = CharacterState::ChargedRanged(Data { - exhausted: true, - energy_drain: self.energy_drain, - initial_damage: self.initial_damage, - max_damage: self.max_damage, - initial_knockback: self.initial_knockback, - max_knockback: self.max_knockback, - prepare_duration: self.prepare_duration, - charge_timer: self.charge_timer, - charge_duration: self.charge_duration, - recover_duration: self.recover_duration, - projectile_body: self.projectile_body, - projectile_light: self.projectile_light, - projectile_gravity: self.projectile_gravity, - initial_projectile_speed: self.initial_projectile_speed, - max_projectile_speed: self.max_projectile_speed, - }); - } else if self.recover_duration != Duration::default() { - // Recovery - update.character = CharacterState::ChargedRanged(Data { - exhausted: self.exhausted, - energy_drain: self.energy_drain, - initial_damage: self.initial_damage, - max_damage: self.max_damage, - initial_knockback: self.initial_knockback, - max_knockback: self.max_knockback, - prepare_duration: self.prepare_duration, - charge_timer: self.charge_timer, - charge_duration: self.charge_duration, - recover_duration: self - .recover_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - projectile_body: self.projectile_body, - projectile_light: self.projectile_light, - projectile_gravity: self.projectile_gravity, - initial_projectile_speed: self.initial_projectile_speed, - max_projectile_speed: self.max_projectile_speed, - }); - } else { - // Done - update.character = CharacterState::Wielding; + // Consumes energy if there's enough left and RMB is held down + update.energy.change_by( + -(self.static_data.energy_drain as f32 * data.dt.0 / 5.0) as i32, + EnergySource::Ability, + ); + } + }, + StageSection::Recover => { + if self.timer < self.static_data.recover_duration { + // Recovers + update.character = CharacterState::ChargedRanged(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; + } + }, + _ => { + // If it somehow ends up in an incorrect stage section + update.character = CharacterState::Wielding; + }, } update diff --git a/common/src/states/equipping.rs b/common/src/states/equipping.rs index ebc91062ff..b0e63c11ea 100644 --- a/common/src/states/equipping.rs +++ b/common/src/states/equipping.rs @@ -6,10 +6,20 @@ use crate::{ use serde::{Deserialize, Serialize}; use std::time::Duration; -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] +/// Separated out to condense update portions of character state +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct StaticData { + /// Time required to draw weapon + pub buildup_duration: Duration, +} + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Data { - /// Time left before next state - pub time_left: Duration, + /// 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, } impl CharacterBehavior for Data { @@ -19,18 +29,18 @@ impl CharacterBehavior for Data { handle_move(&data, &mut update, 1.0); handle_jump(&data, &mut update); - if self.time_left == Duration::default() { - // Wield delay has expired - update.character = CharacterState::Wielding; - } else { - // Wield delay hasn't expired yet - // Update wield delay + if self.timer < self.static_data.buildup_duration { + // Draw weapon update.character = CharacterState::Equipping(Data { - time_left: self - .time_left - .checked_sub(Duration::from_secs_f32(data.dt.0)) + static_data: self.static_data, + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0)) .unwrap_or_default(), }); + } else { + // Done + update.character = CharacterState::Wielding; } update diff --git a/common/src/states/roll.rs b/common/src/states/roll.rs index 3dc7887e7f..2a49f44445 100644 --- a/common/src/states/roll.rs +++ b/common/src/states/roll.rs @@ -1,5 +1,6 @@ use crate::{ comp::{CharacterState, StateUpdate}, + states::utils::*, sys::character_behavior::{CharacterBehavior, JoinData}, util::Dir, }; @@ -8,10 +9,27 @@ use std::time::Duration; use vek::Vec3; const ROLL_SPEED: f32 = 25.0; -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] + +/// Separated out to condense update portions of character state +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct StaticData { + /// How long until state should roll + pub buildup_duration: Duration, + /// How long state is rolling for + pub movement_duration: Duration, + /// How long it takes to recover from roll + pub recover_duration: Duration, +} + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Data { - /// How long the state has until exiting - pub remaining_duration: Duration, + /// 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, /// Had weapon pub was_wielded: bool, } @@ -31,23 +49,80 @@ impl CharacterBehavior for Data { // Smooth orientation update.ori.0 = Dir::slerp_to_vec3(update.ori.0, update.vel.0.xy().into(), 9.0 * data.dt.0); - if self.remaining_duration == Duration::default() { - // Roll duration has expired - update.vel.0 *= 0.3; - if self.was_wielded { - update.character = CharacterState::Wielding; - } else { - update.character = CharacterState::Idle; - } - } else { - // Otherwise, tick down remaining_duration - update.character = CharacterState::Roll(Data { - remaining_duration: self - .remaining_duration - .checked_sub(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - was_wielded: self.was_wielded, - }); + match self.stage_section { + StageSection::Buildup => { + if self.timer < self.static_data.buildup_duration { + // Build up + update.character = CharacterState::Roll(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, + was_wielded: self.was_wielded, + }); + } else { + // Transitions to movement section of stage + update.character = CharacterState::Roll(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Movement, + was_wielded: self.was_wielded, + }); + } + }, + StageSection::Movement => { + if self.timer < self.static_data.movement_duration { + // Movement + update.character = CharacterState::Roll(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, + was_wielded: self.was_wielded, + }); + } else { + // Transitions to recover section of stage + update.character = CharacterState::Roll(Data { + static_data: self.static_data, + timer: Duration::default(), + stage_section: StageSection::Recover, + was_wielded: self.was_wielded, + }); + } + }, + StageSection::Recover => { + if self.timer < self.static_data.recover_duration { + // Build up + update.character = CharacterState::Roll(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, + was_wielded: self.was_wielded, + }); + } else { + // Done + if self.was_wielded { + update.character = CharacterState::Wielding; + } else { + update.character = CharacterState::Idle; + } + } + }, + _ => { + // If it somehow ends up in an incorrect stage section + if self.was_wielded { + update.character = CharacterState::Wielding; + } else { + update.character = CharacterState::Idle; + } + }, } update diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index c0b71b7b5c..13e0f50269 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -9,6 +9,7 @@ use crate::{ util::Dir, }; use serde::{Deserialize, Serialize}; +use std::time::Duration; use vek::*; pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0; @@ -161,7 +162,10 @@ pub fn handle_wield(data: &JoinData, update: &mut StateUpdate) { pub fn attempt_wield(data: &JoinData, update: &mut StateUpdate) { if let Some(ItemKind::Tool(tool)) = data.loadout.active_item.as_ref().map(|i| i.item.kind()) { update.character = CharacterState::Equipping(equipping::Data { - time_left: tool.equip_time(), + static_data: equipping::StaticData { + buildup_duration: tool.equip_time(), + }, + timer: Duration::default(), }); } else { update.character = CharacterState::Idle; diff --git a/voxygen/src/hud/hotbar.rs b/voxygen/src/hud/hotbar.rs index e17245c2a8..7be45e7de9 100644 --- a/voxygen/src/hud/hotbar.rs +++ b/voxygen/src/hud/hotbar.rs @@ -79,7 +79,7 @@ impl State { if let ItemKind::Tool(kind) = kind { match &kind.kind { ToolKind::Staff(_) => true, - ToolKind::Debug(kind) => kind == "Boost", + ToolKind::Debug(_) => true, ToolKind::Sword(_) => true, ToolKind::Hammer(_) => true, ToolKind::Axe(_) => true, diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 172671622e..ad8045517d 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -524,6 +524,14 @@ impl<'a> Widget for Skillbar<'a> { .map(|i| i.item.kind()) .and_then(|kind| match kind { ItemKind::Tool(Tool { kind, .. }) => match kind { + ToolKind::Hammer(_) => Some(( + "Smash of Doom", + "\nAn AOE attack with knockback. \nLeaps to position of \ + cursor.", + )), + ToolKind::Axe(_) => { + Some(("Spin Leap", "\nA slashing running spin leap.")) + }, ToolKind::Staff(_) => Some(( "Firebomb", "\nWhirls a big fireball into the air. \nExplodes the ground \ @@ -533,14 +541,14 @@ impl<'a> Widget for Skillbar<'a> { "Whirlwind", "\nMove forward while spinning with \n your sword.", )), - ToolKind::Debug(kind) => match kind.as_ref() { - "Boost" => Some(( - "Possessing Arrow", - "\nShoots a poisonous arrow.\nLets you control your \ - target.", - )), - _ => None, - }, + ToolKind::Bow(_) => Some(( + "Burst", + "\nLaunches a burst of arrows at the top \nof a running leap.", + )), + ToolKind::Debug(_) => Some(( + "Possessing Arrow", + "\nShoots a poisonous arrow.\nLets you control your target.", + )), _ => None, }, _ => None, @@ -621,10 +629,7 @@ impl<'a> Widget for Skillbar<'a> { ToolKind::Bow(_) => self.imgs.bow_m1, ToolKind::Sceptre(_) => self.imgs.heal_0, ToolKind::Staff(_) => self.imgs.fireball, - ToolKind::Debug(kind) => match kind.as_ref() { - "Boost" => self.imgs.flyingrod_m1, - _ => self.imgs.nothing, - }, + ToolKind::Debug(_) => self.imgs.flyingrod_m1, _ => self.imgs.nothing, }, _ => self.imgs.nothing, @@ -671,10 +676,7 @@ impl<'a> Widget for Skillbar<'a> { Some(ToolKind::Bow(_)) => self.imgs.bow_m2, Some(ToolKind::Sceptre(_)) => self.imgs.heal_bomb, Some(ToolKind::Staff(_)) => self.imgs.flamethrower, - Some(ToolKind::Debug(kind)) => match kind.as_ref() { - "Boost" => self.imgs.flyingrod_m2, - _ => self.imgs.nothing, - }, + Some(ToolKind::Debug(_)) => self.imgs.flyingrod_m2, _ => self.imgs.nothing, }) .w_h(36.0, 36.0) diff --git a/voxygen/src/hud/slots.rs b/voxygen/src/hud/slots.rs index ab31c28cda..56bd3dda56 100644 --- a/voxygen/src/hud/slots.rs +++ b/voxygen/src/hud/slots.rs @@ -116,10 +116,7 @@ impl<'a> SlotKey, HotbarImageSource<'a>> for HotbarSlot { ToolKind::Hammer(_) => Some(HotbarImage::HammerLeap), ToolKind::Axe(_) => Some(HotbarImage::AxeLeapSlash), ToolKind::Bow(_) => Some(HotbarImage::BowJumpBurst), - ToolKind::Debug(kind) => match kind.as_ref() { - "Boost" => Some(HotbarImage::SnakeArrow), - _ => None, - }, + ToolKind::Debug(_) => Some(HotbarImage::SnakeArrow), ToolKind::Sword(_) => Some(HotbarImage::SwordWhirlwind), _ => None, },