From 3f16d15bbb95daf5e4cf52c973117ff2499cb4fd Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 15 May 2021 22:09:39 -0500 Subject: [PATCH] Reworked bow --- .../common/abilities/ability_set_manifest.ron | 6 +- assets/common/abilities/bow/charged.ron | 27 ++-- assets/common/abilities/bow/repeater.ron | 11 +- .../abilities/bow/{basic.ron => shotgun.ron} | 9 +- assets/common/abilities/bowsimple/basic.ron | 1 + .../custom/birdlargebreathe/firebomb.ron | 1 + .../custom/birdlargefire/firebomb.ron | 1 + .../abilities/custom/claygolem/rocket.ron | 1 + .../custom/mindflayer/necroticsphere.ron | 1 + .../custom/quadlowranged/firebomb.ron | 1 + .../common/abilities/custom/turret/arrows.ron | 1 + .../custom/wendigomagic/frostbomb.ron | 1 + assets/common/abilities/debug/possess.ron | 1 + assets/common/abilities/staff/firebomb.ron | 1 + .../common/abilities/staffsimple/firebomb.ron | 1 + common/src/comp/ability.rs | 52 +++---- common/src/comp/projectile.rs | 4 +- common/src/states/basic_ranged.rs | 29 ++-- common/src/states/charged_ranged.rs | 64 +++----- common/src/states/repeater_ranged.rs | 142 ++++++------------ voxygen/src/scene/figure/mod.rs | 3 - 21 files changed, 148 insertions(+), 210 deletions(-) rename assets/common/abilities/bow/{basic.ron => shotgun.ron} (60%) diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index 277e5a7f42..6f20aa00ca 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -23,10 +23,10 @@ ], ), Tool(Bow): ( - primary: "common.abilities.bow.basic", - secondary: "common.abilities.bow.charged", + primary: "common.abilities.bow.charged", + secondary: "common.abilities.bow.repeater", abilities: [ - (Some(Bow(UnlockRepeater)), "common.abilities.bow.repeater"), + (Some(Bow(UnlockRepeater)), "common.abilities.bow.shotgun"), ], ), Custom("Husk"): ( diff --git a/assets/common/abilities/bow/charged.ron b/assets/common/abilities/bow/charged.ron index 482c17396b..a8a45e2f69 100644 --- a/assets/common/abilities/bow/charged.ron +++ b/assets/common/abilities/bow/charged.ron @@ -1,18 +1,19 @@ ChargedRanged( - energy_cost: 1, - energy_drain: 300, - initial_damage: 10, - scaled_damage: 190, - initial_knockback: 10.0, + energy_cost: 0, + energy_drain: 0, + initial_regen: 50, + scaled_regen: 150, + initial_damage: 0, + scaled_damage: 300, + initial_knockback: 0.0, scaled_knockback: 10.0, speed: 1.0, - buildup_duration: 0.1, - charge_duration: 1.5, - recover_duration: 0.5, - projectile_body: Object(MultiArrow), + buildup_duration: 0.2, + charge_duration: 3.0, + recover_duration: 0.3, + projectile_body: Object(Arrow), projectile_light: None, - initial_projectile_speed: 120.0, - scaled_projectile_speed: 160.0, - move_speed: 0.3, - damage_kind: Piercing, + initial_projectile_speed: 100.0, + scaled_projectile_speed: 150.0, + move_speed: 0.5, ) diff --git a/assets/common/abilities/bow/repeater.ron b/assets/common/abilities/bow/repeater.ron index b0535b23e6..ae98a6466a 100644 --- a/assets/common/abilities/bow/repeater.ron +++ b/assets/common/abilities/bow/repeater.ron @@ -1,10 +1,10 @@ RepeaterRanged( - energy_cost: 450, - movement_duration: 0.3, + energy_cost: 50, buildup_duration: 0.2, - shoot_duration: 0.2, + shoot_duration: 1.0, recover_duration: 0.8, - leap: Some(5.0), + max_speed: 5.0, + half_speed_at: 4, projectile: Arrow( damage: 40.0, knockback: 5.0, @@ -12,6 +12,5 @@ RepeaterRanged( ), projectile_body: Object(Arrow), projectile_light: None, - projectile_speed: 120.0, - reps_remaining: 3, + projectile_speed: 100.0, ) diff --git a/assets/common/abilities/bow/basic.ron b/assets/common/abilities/bow/shotgun.ron similarity index 60% rename from assets/common/abilities/bow/basic.ron rename to assets/common/abilities/bow/shotgun.ron index d86b0d684f..52e055041e 100644 --- a/assets/common/abilities/bow/basic.ron +++ b/assets/common/abilities/bow/shotgun.ron @@ -1,13 +1,14 @@ BasicRanged( - energy_cost: 0, + energy_cost: 350, buildup_duration: 0.4, recover_duration: 0.3, projectile: Arrow( - damage: 90.0, + damage: 50.0, knockback: 5.0, - energy_regen: 40, + energy_regen: 0, ), projectile_body: Object(Arrow), projectile_light: None, - projectile_speed: 120.0, + projectile_speed: 60.0, + num_projectiles: 8, ) diff --git a/assets/common/abilities/bowsimple/basic.ron b/assets/common/abilities/bowsimple/basic.ron index 91d4231346..0bcc5be454 100644 --- a/assets/common/abilities/bowsimple/basic.ron +++ b/assets/common/abilities/bowsimple/basic.ron @@ -10,4 +10,5 @@ BasicRanged( projectile_body: Object(Arrow), projectile_light: None, projectile_speed: 100.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/custom/birdlargebreathe/firebomb.ron b/assets/common/abilities/custom/birdlargebreathe/firebomb.ron index def79061ea..f96702e7d8 100644 --- a/assets/common/abilities/custom/birdlargebreathe/firebomb.ron +++ b/assets/common/abilities/custom/birdlargebreathe/firebomb.ron @@ -14,4 +14,5 @@ BasicRanged( }),*/ projectile_gravity: Some(Gravity(0.15)), projectile_speed: 60.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/custom/birdlargefire/firebomb.ron b/assets/common/abilities/custom/birdlargefire/firebomb.ron index def79061ea..f96702e7d8 100644 --- a/assets/common/abilities/custom/birdlargefire/firebomb.ron +++ b/assets/common/abilities/custom/birdlargefire/firebomb.ron @@ -14,4 +14,5 @@ BasicRanged( }),*/ projectile_gravity: Some(Gravity(0.15)), projectile_speed: 60.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/custom/claygolem/rocket.ron b/assets/common/abilities/custom/claygolem/rocket.ron index 2ac6c020e5..f3e7f354de 100644 --- a/assets/common/abilities/custom/claygolem/rocket.ron +++ b/assets/common/abilities/custom/claygolem/rocket.ron @@ -10,4 +10,5 @@ BasicRanged( projectile_body: Object(ClayRocket), projectile_light: None, projectile_speed: 30.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/custom/mindflayer/necroticsphere.ron b/assets/common/abilities/custom/mindflayer/necroticsphere.ron index c643a741c3..b2483fc77c 100644 --- a/assets/common/abilities/custom/mindflayer/necroticsphere.ron +++ b/assets/common/abilities/custom/mindflayer/necroticsphere.ron @@ -8,5 +8,6 @@ BasicRanged( ), projectile_body: Object(FireworkPurple), projectile_speed: 100.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/custom/quadlowranged/firebomb.ron b/assets/common/abilities/custom/quadlowranged/firebomb.ron index 5b3917892a..6e47e2b639 100644 --- a/assets/common/abilities/custom/quadlowranged/firebomb.ron +++ b/assets/common/abilities/custom/quadlowranged/firebomb.ron @@ -13,4 +13,5 @@ BasicRanged( ..Default::default() }),*/ projectile_speed: 70.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/custom/turret/arrows.ron b/assets/common/abilities/custom/turret/arrows.ron index 1ae6f9a79f..5e78f99acd 100644 --- a/assets/common/abilities/custom/turret/arrows.ron +++ b/assets/common/abilities/custom/turret/arrows.ron @@ -10,4 +10,5 @@ BasicRanged( projectile_body: Object(ArrowTurret), projectile_light: None, projectile_speed: 130.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/custom/wendigomagic/frostbomb.ron b/assets/common/abilities/custom/wendigomagic/frostbomb.ron index b6529121cf..4176b8e5a8 100644 --- a/assets/common/abilities/custom/wendigomagic/frostbomb.ron +++ b/assets/common/abilities/custom/wendigomagic/frostbomb.ron @@ -12,4 +12,5 @@ BasicRanged( ..Default::default() }),*/ projectile_speed: 60.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/debug/possess.ron b/assets/common/abilities/debug/possess.ron index e36ab3a45e..1ba1cd6c5a 100644 --- a/assets/common/abilities/debug/possess.ron +++ b/assets/common/abilities/debug/possess.ron @@ -9,4 +9,5 @@ BasicRanged( ..Default::default() }),*/ projectile_speed: 100.0, + num_projectiles: 1, ) \ No newline at end of file diff --git a/assets/common/abilities/staff/firebomb.ron b/assets/common/abilities/staff/firebomb.ron index 79494def06..34fddcc6c1 100644 --- a/assets/common/abilities/staff/firebomb.ron +++ b/assets/common/abilities/staff/firebomb.ron @@ -9,4 +9,5 @@ BasicRanged( ), projectile_body: Object(BoltFire), projectile_speed: 60.0, + num_projectiles: 1, ) diff --git a/assets/common/abilities/staffsimple/firebomb.ron b/assets/common/abilities/staffsimple/firebomb.ron index 33c14f0f0f..9ca5613ba2 100644 --- a/assets/common/abilities/staffsimple/firebomb.ron +++ b/assets/common/abilities/staffsimple/firebomb.ron @@ -13,4 +13,5 @@ BasicRanged( ..Default::default() }),*/ projectile_speed: 60.0, + num_projectiles: 1, ) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 21d9550d80..ec075ca12b 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -79,19 +79,19 @@ pub enum CharacterAbility { projectile_body: Body, projectile_light: Option, projectile_speed: f32, + num_projectiles: u32, }, RepeaterRanged { energy_cost: f32, - movement_duration: f32, buildup_duration: f32, shoot_duration: f32, recover_duration: f32, - leap: Option, + max_speed: f32, + half_speed_at: u32, projectile: ProjectileConstructor, projectile_body: Body, projectile_light: Option, projectile_speed: f32, - reps_remaining: u32, }, Boost { movement_duration: f32, @@ -201,6 +201,8 @@ pub enum CharacterAbility { ChargedRanged { energy_cost: f32, energy_drain: f32, + initial_regen: f32, + scaled_regen: f32, initial_damage: f32, scaled_damage: f32, initial_knockback: f32, @@ -214,7 +216,6 @@ pub enum CharacterAbility { initial_projectile_speed: f32, scaled_projectile_speed: f32, move_speed: f32, - damage_kind: DamageKind, }, Shockwave { energy_cost: f32, @@ -340,14 +341,9 @@ impl CharacterAbility { .energy .try_change_by(-(*energy_cost as i32), EnergySource::Ability) .is_ok(), - CharacterAbility::RepeaterRanged { - energy_cost, leap, .. - } => { - (leap.is_none() || update.vel.0.z >= 0.0) - && update - .energy - .try_change_by(-(*energy_cost as i32), EnergySource::Ability) - .is_ok() + // Consumes energy within state, so value only checked before entering state + CharacterAbility::RepeaterRanged { energy_cost, .. } => { + update.energy.current() as f32 >= *energy_cost }, CharacterAbility::LeapMelee { energy_cost, .. } => { update.vel.0.z >= 0.0 @@ -414,14 +410,12 @@ impl CharacterAbility { *projectile = projectile.modified_projectile(power, 1_f32, 1_f32); }, RepeaterRanged { - ref mut movement_duration, ref mut buildup_duration, ref mut shoot_duration, ref mut recover_duration, ref mut projectile, .. } => { - *movement_duration /= speed; *buildup_duration /= speed; *shoot_duration /= speed; *recover_duration /= speed; @@ -1000,7 +994,6 @@ impl CharacterAbility { ref mut energy_cost, ref mut buildup_duration, ref mut projectile, - ref mut reps_remaining, ref mut projectile_speed, .. } => { @@ -1014,9 +1007,6 @@ impl CharacterAbility { if !skillset.has_skill(Bow(RGlide)) { *buildup_duration = 0.001; } - if let Ok(Some(level)) = skillset.skill_level(Bow(RArrows)) { - *reps_remaining += level as u32; - } if let Ok(Some(level)) = skillset.skill_level(Bow(RCost)) { *energy_cost *= 0.70_f32.powi(level.into()); } @@ -1233,6 +1223,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { projectile_light, projectile_speed, energy_cost: _, + num_projectiles, } => CharacterState::BasicRanged(basic_ranged::Data { static_data: basic_ranged::StaticData { buildup_duration: Duration::from_secs_f32(*buildup_duration), @@ -1241,6 +1232,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { projectile_body: *projectile_body, projectile_light: *projectile_light, projectile_speed: *projectile_speed, + num_projectiles: *num_projectiles, ability_info, }, timer: Duration::default(), @@ -1500,6 +1492,8 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { CharacterAbility::ChargedRanged { energy_cost: _, energy_drain, + initial_regen, + scaled_regen, initial_damage, scaled_damage, initial_knockback, @@ -1513,13 +1507,14 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { initial_projectile_speed, scaled_projectile_speed, move_speed, - damage_kind, } => CharacterState::ChargedRanged(charged_ranged::Data { static_data: charged_ranged::StaticData { buildup_duration: Duration::from_secs_f32(*buildup_duration), charge_duration: Duration::from_secs_f32(*charge_duration), recover_duration: Duration::from_secs_f32(*recover_duration), energy_drain: *energy_drain, + initial_regen: *initial_regen, + scaled_regen: *scaled_regen, initial_damage: *initial_damage, scaled_damage: *scaled_damage, speed: *speed, @@ -1531,31 +1526,31 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { scaled_projectile_speed: *scaled_projectile_speed, move_speed: *move_speed, ability_info, - damage_kind: *damage_kind, }, timer: Duration::default(), stage_section: StageSection::Buildup, exhausted: false, }), CharacterAbility::RepeaterRanged { - energy_cost: _, - movement_duration, + energy_cost, buildup_duration, shoot_duration, recover_duration, - leap, + max_speed, + half_speed_at, projectile, projectile_body, projectile_light, projectile_speed, - reps_remaining, } => CharacterState::RepeaterRanged(repeater_ranged::Data { static_data: repeater_ranged::StaticData { - movement_duration: Duration::from_secs_f32(*movement_duration), buildup_duration: Duration::from_secs_f32(*buildup_duration), shoot_duration: Duration::from_secs_f32(*shoot_duration), recover_duration: Duration::from_secs_f32(*recover_duration), - leap: *leap, + energy_cost: *energy_cost, + // 1.0 is subtracted as 1.0 is added in state file + max_speed: *max_speed - 1.0, + half_speed_at: *half_speed_at, projectile: *projectile, projectile_body: *projectile_body, projectile_light: *projectile_light, @@ -1563,8 +1558,9 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { ability_info, }, timer: Duration::default(), - stage_section: StageSection::Movement, - reps_remaining: *reps_remaining, + stage_section: StageSection::Buildup, + projectiles_fired: 0, + speed: 1.0, }), CharacterAbility::Shockwave { energy_cost: _, diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index 5bc5daeffb..a50bbc3788 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -12,7 +12,7 @@ use specs::Component; use specs_idvs::IdvStorage; use std::time::Duration; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub enum Effect { Attack(Attack), Explode(Explosion), @@ -21,7 +21,7 @@ pub enum Effect { Possess, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Projectile { // TODO: use SmallVec for these effects pub hit_solid: Vec, diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index fa07e96fa0..93246e60ea 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -5,7 +5,9 @@ use crate::{ behavior::{CharacterBehavior, JoinData}, utils::*, }, + util::Dir, }; +use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -21,6 +23,8 @@ pub struct StaticData { pub projectile_body: Body, pub projectile_light: Option, pub projectile_speed: f32, + /// How many projectiles are simultaneously fired + pub num_projectiles: u32, /// What key is used to press ability pub ability_info: AbilityInfo, } @@ -76,15 +80,22 @@ impl CharacterBehavior for Data { crit_chance, crit_mult, ); - 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, - speed: self.static_data.projectile_speed, - object: None, - }); + for i in 0..self.static_data.num_projectiles { + let dir = Dir::from_unnormalized(data.inputs.look_dir.map(|x| { + let offset = (2.0 * thread_rng().gen::() - 1.0) * 0.03 * i as f32; + x + offset + })) + .unwrap_or(data.inputs.look_dir); + update.server_events.push_front(ServerEvent::Shoot { + entity: data.entity, + dir, + body: self.static_data.projectile_body, + projectile: projectile.clone(), + light: self.static_data.projectile_light, + speed: self.static_data.projectile_speed, + object: None, + }); + } update.character = CharacterState::BasicRanged(Data { exhausted: true, diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 9fa94ad283..2b8de1ac42 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -1,11 +1,7 @@ use crate::{ - combat::{ - Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement, Damage, - DamageKind, DamageSource, GroupTarget, Knockback, KnockbackDir, - }, comp::{ - projectile, Body, CharacterState, EnergyChange, EnergySource, LightEmitter, Projectile, - StateUpdate, + projectile::ProjectileConstructor, Body, CharacterState, EnergyChange, EnergySource, + LightEmitter, StateUpdate, }, event::ServerEvent, states::{ @@ -27,6 +23,10 @@ pub struct StaticData { pub recover_duration: Duration, /// How much energy is drained per second when charging pub energy_drain: f32, + /// How much energy is gained with no charge + pub initial_regen: f32, + /// How much the energy gain scales as it is charged + pub scaled_regen: f32, /// How much damage is dealt with no charge pub initial_damage: f32, /// How much the damage scales as it is charged @@ -46,8 +46,6 @@ pub struct StaticData { pub move_speed: f32, /// What key is used to press ability pub ability_info: AbilityInfo, - /// What kind of damage the attack does - pub damage_kind: DamageKind, } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -96,45 +94,19 @@ impl CharacterBehavior for Data { let charge_frac = (self.timer.as_secs_f32() / self.static_data.charge_duration.as_secs_f32()) .min(1.0); - let knockback = AttackEffect::new( - Some(GroupTarget::OutOfGroup), - CombatEffect::Knockback(Knockback { - strength: self.static_data.initial_knockback - + charge_frac * self.static_data.scaled_knockback, - direction: KnockbackDir::Away, - }), - ) - .with_requirement(CombatRequirement::AnyDamage); - let buff = CombatEffect::Buff(CombatBuff::default_physical()); - let damage = AttackDamage::new( - Damage { - source: DamageSource::Projectile, - kind: self.static_data.damage_kind, - value: self.static_data.initial_damage as f32 - + charge_frac * self.static_data.scaled_damage as f32, - }, - Some(GroupTarget::OutOfGroup), - ) - .with_effect(buff); + let arrow = ProjectileConstructor::Arrow { + damage: self.static_data.initial_damage as f32 + + charge_frac * self.static_data.scaled_damage as f32, + knockback: self.static_data.initial_knockback + + charge_frac * self.static_data.scaled_knockback, + energy_regen: self.static_data.initial_regen + + charge_frac * self.static_data.scaled_regen, + }; + // Fire let (crit_chance, crit_mult) = get_crit_data(data, self.static_data.ability_info); - let attack = Attack::default() - .with_damage(damage) - .with_crit(crit_chance, crit_mult) - .with_effect(knockback) - .with_combo_increment(); - - // Fire - let projectile = Projectile { - hit_solid: vec![projectile::Effect::Stick], - hit_entity: vec![ - projectile::Effect::Attack(attack), - projectile::Effect::Vanish, - ], - time_left: Duration::from_secs(15), - owner: Some(*data.uid), - ignore_group: true, - }; + let projectile = + arrow.create_projectile(Some(*data.uid), crit_chance, crit_mult); update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, dir: data.inputs.look_dir, @@ -166,7 +138,7 @@ impl CharacterBehavior for Data { ..*self }); - // Consumes energy if there's enough left and RMB is held down + // Consumes energy if there's enough left and input is held down update.energy.change_by(EnergyChange { amount: -(self.static_data.energy_drain as f32 * data.dt.0 diff --git a/common/src/states/repeater_ranged.rs b/common/src/states/repeater_ranged.rs index ef385edcdb..c4280219b5 100644 --- a/common/src/states/repeater_ranged.rs +++ b/common/src/states/repeater_ranged.rs @@ -1,29 +1,32 @@ use crate::{ - comp::{Body, CharacterState, LightEmitter, ProjectileConstructor, StateUpdate}, + comp::{ + Body, CharacterState, EnergyChange, EnergySource, LightEmitter, ProjectileConstructor, + StateUpdate, + }, event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, utils::{StageSection, *}, }, - util::dir::*, }; use serde::{Deserialize, Serialize}; use std::time::Duration; -use vek::Vec3; #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] /// Separated out to condense update portions of character state pub struct StaticData { - /// How long the state is in movement - pub movement_duration: Duration, /// How long we've readied the weapon pub buildup_duration: Duration, /// How long the state is shooting pub shoot_duration: Duration, /// How long the state has until exiting pub recover_duration: Duration, - /// Whether there should be a jump and how strong the leap is - pub leap: Option, + /// Energy cost per projectile + pub energy_cost: f32, + /// Max speed that can be reached + pub max_speed: f32, + /// Projectiles required to reach half of max speed + pub half_speed_at: u32, /// Projectile options pub projectile: ProjectileConstructor, pub projectile_body: Body, @@ -42,64 +45,20 @@ pub struct Data { pub timer: Duration, /// What section the character stage is in pub stage_section: StageSection, - /// How many repetitions remaining - pub reps_remaining: u32, + /// Speed of the state while in shoot section + pub speed: f32, + /// Number of projectiles fired so far + pub projectiles_fired: u32, } impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); handle_orientation(data, &mut update, 1.0); - handle_move(data, &mut update, 1.0); - handle_jump(data, &mut update, 1.0); + handle_move(data, &mut update, 0.1); match self.stage_section { - StageSection::Movement => { - // Jumping - if let Some(leap_strength) = self.static_data.leap { - let progress = 1.0 - - self.timer.as_secs_f32() - / self.static_data.movement_duration.as_secs_f32(); - handle_forced_movement( - data, - &mut update, - ForcedMovement::Leap { - vertical: leap_strength, - forward: 10.0, - progress, - direction: MovementDirection::Move, - }, - 1.0, - ); - } - if self.timer < self.static_data.movement_duration { - // Do movement - update.character = CharacterState::RepeaterRanged(Data { - timer: self - .timer - .checked_add(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - ..*self - }); - } else { - // Transition to buildup - update.character = CharacterState::RepeaterRanged(Data { - timer: Duration::default(), - stage_section: StageSection::Buildup, - ..*self - }); - } - }, StageSection::Buildup => { - // Aim gliding - if self.static_data.leap.is_some() { - handle_forced_movement( - data, - &mut update, - ForcedMovement::Hover { move_input: 0.1 }, - 1.0, - ); - } if self.timer < self.static_data.buildup_duration { // Buildup to attack update.character = CharacterState::RepeaterRanged(Data { @@ -119,12 +78,19 @@ impl CharacterBehavior for Data { } }, StageSection::Shoot => { - // Aim gliding - if self.static_data.leap.is_some() { - update.vel.0 = Vec3::new(data.vel.0.x, data.vel.0.y, 0.0); - } - if self.reps_remaining > 0 { - // Fire + if self.timer < self.static_data.shoot_duration { + // Draw projectile + update.character = CharacterState::RepeaterRanged(Data { + timer: self + .timer + .checked_add(Duration::from_secs_f32(data.dt.0 * self.speed)) + .unwrap_or_default(), + ..*self + }); + } else if input_is_pressed(data, self.static_data.ability_info.input) + && update.energy.current() as f32 >= self.static_data.energy_cost + { + // Fire if input is pressed still let (crit_chance, crit_mult) = get_crit_data(data, self.static_data.ability_info); let projectile = self.static_data.projectile.create_projectile( @@ -135,22 +101,7 @@ impl CharacterBehavior for Data { update.server_events.push_front(ServerEvent::Shoot { entity: data.entity, // Provides slight variation to projectile direction - dir: Dir::from_unnormalized(Vec3::new( - data.inputs.look_dir[0] - + (if self.reps_remaining % 2 == 0 { - self.reps_remaining as f32 / 400.0 - } else { - -1.0 * self.reps_remaining as f32 / 400.0 - }), - data.inputs.look_dir[1] - + (if self.reps_remaining % 2 == 0 { - -1.0 * self.reps_remaining as f32 / 400.0 - } else { - self.reps_remaining as f32 / 400.0 - }), - data.inputs.look_dir[2], - )) - .unwrap_or(data.inputs.look_dir), + dir: data.inputs.look_dir, body: self.static_data.projectile_body, projectile, light: self.static_data.projectile_light, @@ -158,22 +109,24 @@ impl CharacterBehavior for Data { object: None, }); - // Shoot projectiles - update.character = CharacterState::RepeaterRanged(Data { - timer: self - .timer - .checked_add(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), - reps_remaining: self.reps_remaining - 1, - ..*self + update.server_events.push_front(ServerEvent::EnergyChange { + entity: data.entity, + change: EnergyChange { + amount: -self.static_data.energy_cost as i32, + source: EnergySource::Ability, + }, }); - } else if self.timer < self.static_data.shoot_duration { - // Finish shooting + + let new_speed = 1.0 + + self.projectiles_fired as f32 + / (self.static_data.half_speed_at as f32 + + self.projectiles_fired as f32) + * self.static_data.max_speed; + update.character = CharacterState::RepeaterRanged(Data { - timer: self - .timer - .checked_add(Duration::from_secs_f32(data.dt.0)) - .unwrap_or_default(), + timer: Duration::default(), + speed: new_speed, + projectiles_fired: self.projectiles_fired + 1, ..*self }); } else { @@ -186,10 +139,7 @@ impl CharacterBehavior for Data { } }, StageSection::Recover => { - if self.static_data.leap.is_some() && data.physics.on_ground { - // Done - update.character = CharacterState::Wielding; - } else if self.timer < self.static_data.recover_duration { + if self.timer < self.static_data.recover_duration { // Recover from attack update.character = CharacterState::RepeaterRanged(Data { timer: self diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index b4b16a1778..0f5537c113 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -1015,9 +1015,6 @@ impl FigureMgr { StageSection::Buildup => { stage_time / s.static_data.buildup_duration.as_secs_f32() }, - StageSection::Movement => { - stage_time / s.static_data.movement_duration.as_secs_f32() - }, StageSection::Shoot => { stage_time / s.static_data.shoot_duration.as_secs_f32() },