diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 4e7f1325ff..69d328ba40 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1191,7 +1191,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { stage_section: StageSection::Buildup, was_wielded: false, // false by default. utils might set it to true was_sneak: false, - was_combo: None, }), CharacterAbility::ComboMelee { stage_data, @@ -1216,7 +1215,6 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { ability_info, }, stage: 1, - combo: 0, timer: Duration::default(), stage_section: StageSection::Buildup, next_stage: false, diff --git a/common/src/states/behavior.rs b/common/src/states/behavior.rs index 73f1b054bc..f791dd13d1 100644 --- a/common/src/states/behavior.rs +++ b/common/src/states/behavior.rs @@ -1,6 +1,6 @@ use crate::{ comp::{ - item::MaterialStatManifest, Beam, Body, CharacterState, ControlAction, Controller, + item::MaterialStatManifest, Beam, Body, CharacterState, Combo, ControlAction, Controller, ControllerInputs, Energy, Health, Inventory, LoadoutManip, Melee, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel, }, @@ -68,6 +68,7 @@ pub struct JoinData<'a> { pub updater: &'a LazyUpdate, pub stats: &'a Stats, pub msm: &'a MaterialStatManifest, + pub combo: &'a Combo, } type RestrictedMut<'a, C> = PairedStorage< @@ -95,6 +96,7 @@ pub struct JoinStruct<'a> { pub melee_attack: Option<&'a Melee>, pub beam: Option<&'a Beam>, pub stat: &'a Stats, + pub combo: &'a Combo, } impl<'a> JoinData<'a> { @@ -123,6 +125,7 @@ impl<'a> JoinData<'a> { updater, dt, msm, + combo: j.combo, } } } diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index 55a97e52a3..476673e5e0 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -109,8 +109,6 @@ pub struct Data { pub static_data: StaticData, /// Indicates what stage the combo is in pub stage: u32, - /// Number of consecutive strikes - pub combo: u32, /// Timer for each stage pub timer: Duration, /// Checks what section a stage is in @@ -127,9 +125,6 @@ impl CharacterBehavior for Data { handle_move(data, &mut update, 0.3); if !ability_key_is_pressed(data, self.static_data.ability_info.key) { handle_interrupt(data, &mut update, self.static_data.is_interruptible); - if let CharacterState::Roll(roll) = &mut update.character { - roll.was_combo = Some((self.stage, self.combo)); - } match update.character { CharacterState::ComboMelee(_) => {}, _ => { @@ -142,7 +137,11 @@ impl CharacterBehavior for Data { let speed_modifer = 1.0 + self.static_data.max_speed_increase - * (1.0 - self.static_data.speed_increase.powi(self.combo as i32)); + * (1.0 + - self + .static_data + .speed_increase + .powi(data.combo.counter() as i32)); match self.stage_section { StageSection::Buildup => { @@ -170,7 +169,7 @@ impl CharacterBehavior for Data { + (self .static_data .scales_from_combo - .min(self.combo / self.static_data.num_stages) + .min(data.combo.counter() / self.static_data.num_stages) as f32) * self.static_data.stage_data[stage_index].damage_increase; @@ -178,7 +177,7 @@ impl CharacterBehavior for Data { + (self .static_data .scales_from_combo - .min(self.combo / self.static_data.num_stages) + .min(data.combo.counter() / self.static_data.num_stages) as f32) * self.static_data.stage_data[stage_index].poise_damage_increase; let poise = AttackEffect::new( @@ -196,7 +195,7 @@ impl CharacterBehavior for Data { .with_requirement(CombatRequirement::AnyDamage); let energy = self.static_data.max_energy_gain.min( self.static_data.initial_energy_gain - + self.combo as f32 * self.static_data.energy_increase, + + data.combo.counter() as f32 * self.static_data.energy_increase, ); let energy = AttackEffect::new(None, CombatEffect::EnergyReward(energy)) .with_requirement(CombatRequirement::AnyDamage); @@ -289,7 +288,6 @@ impl CharacterBehavior for Data { timer: Duration::default(), stage_section: StageSection::Buildup, next_stage: false, - ..*self }); } else { // Done @@ -312,7 +310,6 @@ impl CharacterBehavior for Data { update.character = CharacterState::ComboMelee(Data { static_data: self.static_data.clone(), stage: self.stage, - combo: self.combo + 1, timer: self.timer, stage_section: self.stage_section, next_stage: self.next_stage, diff --git a/common/src/states/roll.rs b/common/src/states/roll.rs index e36d80a6cb..1667407b36 100644 --- a/common/src/states/roll.rs +++ b/common/src/states/roll.rs @@ -36,8 +36,6 @@ pub struct Data { pub was_wielded: bool, /// Was sneaking pub was_sneak: bool, - /// Was combo, .0 is stage, .1 is combo counter - pub was_combo: Option<(u32, u32)>, } impl CharacterBehavior for Data { @@ -116,11 +114,6 @@ impl CharacterBehavior for Data { // Done if self.was_wielded { update.character = CharacterState::Wielding; - let combo_data = self.was_combo; - - if let Some(combo_data) = combo_data { - continue_combo(data, &mut update, combo_data); - } } else if self.was_sneak { update.character = CharacterState::Sneak; } else { @@ -132,11 +125,6 @@ impl CharacterBehavior for Data { // If it somehow ends up in an incorrect stage section if self.was_wielded { update.character = CharacterState::Wielding; - let combo_data = self.was_combo; - - if let Some(combo_data) = combo_data { - continue_combo(data, &mut update, combo_data); - } } else if self.was_sneak { update.character = CharacterState::Sneak; } else { diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 51e1623403..4c996ff15f 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -586,14 +586,6 @@ pub fn ability_key_is_pressed(data: &JoinData, ability_key: AbilityKey) -> bool } } -pub fn continue_combo(data: &JoinData, update: &mut StateUpdate, combo_data: (u32, u32)) { - handle_ability1_input(data, update); - if let CharacterState::ComboMelee(data) = &mut update.character { - data.stage = combo_data.0; - data.combo = combo_data.1; - } -} - /// Determines what portion a state is in. Used in all attacks (eventually). Is /// used to control aspects of animation code, as well as logic within the /// character states. diff --git a/common/sys/src/character_behavior.rs b/common/sys/src/character_behavior.rs index 5e67aa40d5..fc83ab21ec 100644 --- a/common/sys/src/character_behavior.rs +++ b/common/sys/src/character_behavior.rs @@ -9,8 +9,8 @@ use common::{ item::MaterialStatManifest, slot::{EquipSlot, Slot}, }, - Beam, Body, CharacterState, Controller, Energy, Health, Inventory, Melee, Mounting, Ori, - PhysicsState, Poise, PoiseState, Pos, StateUpdate, Stats, Vel, + Beam, Body, CharacterState, Combo, Controller, Energy, Health, Inventory, Melee, Mounting, + Ori, PhysicsState, Poise, PoiseState, Pos, StateUpdate, Stats, Vel, }, event::{EventBus, LocalEvent, ServerEvent}, metrics::SysMetrics, @@ -66,6 +66,7 @@ pub struct ReadData<'a> { mountings: ReadStorage<'a, Mounting>, stats: ReadStorage<'a, Stats>, msm: Read<'a, MaterialStatManifest>, + combos: ReadStorage<'a, Combo>, } /// ## Character Behavior System @@ -121,6 +122,7 @@ impl<'a> System<'a> for Sys { body, physics, stat, + combo, ) in ( &read_data.entities, &read_data.uids, @@ -135,6 +137,7 @@ impl<'a> System<'a> for Sys { &read_data.bodies, &read_data.physics_states, &read_data.stats, + &read_data.combos, ) .join() { @@ -253,6 +256,7 @@ impl<'a> System<'a> for Sys { melee_attack: read_data.melee_attacks.get(entity), beam: read_data.beams.get(entity), stat: &stat, + combo: &combo, }; for action in actions { diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index 93f2e20302..fa9fdb8e21 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -20,7 +20,7 @@ use vek::Vec3; const ENERGY_REGEN_ACCEL: f32 = 10.0; const POISE_REGEN_ACCEL: f32 = 2.0; -const COMBO_DECAY_START: f64 = 10.0; // seconds +const COMBO_DECAY_START: f64 = 5.0; // seconds #[derive(SystemData)] pub struct ReadData<'a> { diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs index 01ffd0b25d..517743f9e7 100644 --- a/server/src/sys/sentinel.rs +++ b/server/src/sys/sentinel.rs @@ -1,9 +1,9 @@ use super::SysTimer; use common::{ comp::{ - Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Energy, Gravity, - Group, Health, Inventory, Item, LightEmitter, Mass, MountState, Mounting, Ori, Player, - Poise, Pos, Scale, Shockwave, Stats, Sticky, Vel, + Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Combo, Energy, + Gravity, Group, Health, Inventory, Item, LightEmitter, Mass, MountState, Mounting, Ori, + Player, Poise, Pos, Scale, Shockwave, Stats, Sticky, Vel, }, span, uid::Uid, @@ -50,6 +50,7 @@ pub struct TrackedComps<'a> { pub buffs: ReadStorage<'a, Buffs>, pub auras: ReadStorage<'a, Auras>, pub energy: ReadStorage<'a, Energy>, + pub combo: ReadStorage<'a, Combo>, pub health: ReadStorage<'a, Health>, pub poise: ReadStorage<'a, Poise>, pub can_build: ReadStorage<'a, CanBuild>, @@ -104,6 +105,10 @@ impl<'a> TrackedComps<'a> { .get(entity) .cloned() .map(|c| comps.push(c.into())); + self.combo + .get(entity) + .cloned() + .map(|c| comps.push(c.into())); self.health .get(entity) .cloned() @@ -183,6 +188,7 @@ pub struct ReadTrackers<'a> { pub buffs: ReadExpect<'a, UpdateTracker>, pub auras: ReadExpect<'a, UpdateTracker>, pub energy: ReadExpect<'a, UpdateTracker>, + pub combo: ReadExpect<'a, UpdateTracker>, pub health: ReadExpect<'a, UpdateTracker>, pub poise: ReadExpect<'a, UpdateTracker>, pub can_build: ReadExpect<'a, UpdateTracker>, @@ -217,6 +223,7 @@ impl<'a> ReadTrackers<'a> { .with_component(&comps.uid, &*self.buffs, &comps.buffs, filter) .with_component(&comps.uid, &*self.auras, &comps.auras, filter) .with_component(&comps.uid, &*self.energy, &comps.energy, filter) + .with_component(&comps.uid, &*self.combo, &comps.combo, filter) .with_component(&comps.uid, &*self.health, &comps.health, filter) .with_component(&comps.uid, &*self.poise, &comps.poise, filter) .with_component(&comps.uid, &*self.can_build, &comps.can_build, filter) @@ -258,6 +265,7 @@ pub struct WriteTrackers<'a> { buffs: WriteExpect<'a, UpdateTracker>, auras: WriteExpect<'a, UpdateTracker>, energy: WriteExpect<'a, UpdateTracker>, + combo: WriteExpect<'a, UpdateTracker>, health: WriteExpect<'a, UpdateTracker>, poise: WriteExpect<'a, UpdateTracker>, can_build: WriteExpect<'a, UpdateTracker>, @@ -286,6 +294,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { trackers.buffs.record_changes(&comps.buffs); trackers.auras.record_changes(&comps.auras); trackers.energy.record_changes(&comps.energy); + trackers.combo.record_changes(&comps.combo); trackers.health.record_changes(&comps.health); trackers.poise.record_changes(&comps.poise); trackers.can_build.record_changes(&comps.can_build); @@ -327,6 +336,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) { log_counts!(player, "Players"); log_counts!(stats, "Stats"); log_counts!(energy, "Energies"); + log_counts!(combo, "Combos"); log_vounts!(health, "Healths"); log_vounts!(poise, "Poises"); log_counts!(light_emitter, "Light emitters"); @@ -353,6 +363,7 @@ pub fn register_trackers(world: &mut World) { world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); + world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); world.register_tracker::(); diff --git a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs index c48ca417df..c80195f90d 100644 --- a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs @@ -135,7 +135,6 @@ fn matches_ability_stage() { ability_info: empty_ability_info(), }, stage: 1, - combo: 0, timer: Duration::default(), stage_section: states::utils::StageSection::Swing, next_stage: false, @@ -194,7 +193,6 @@ fn ignores_different_ability_stage() { ability_info: empty_ability_info(), }, stage: 1, - combo: 0, timer: Duration::default(), stage_section: states::utils::StageSection::Swing, next_stage: false, diff --git a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs index 018deaaa0c..1e36ffc7c7 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs @@ -189,7 +189,6 @@ fn maps_roll() { stage_section: states::utils::StageSection::Buildup, was_wielded: true, was_sneak: false, - was_combo: None, }), &PhysicsState { on_ground: true,