From 0fe073fcdcc1006d59ad1e5ad2214923f2730ac3 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 23 Oct 2022 21:12:59 -0400 Subject: [PATCH] Addressed feedback from testing --- assets/common/abilities/bow/charged.ron | 4 +- assets/common/abilities/bow/repeater.ron | 2 +- .../common/abilities/sword/cleaving_combo.ron | 2 +- .../common/abilities/sword/cleaving_spin.ron | 4 +- .../abilities/sword/crippling_combo.ron | 14 +-- .../abilities/sword/crippling_finisher.ron | 4 +- .../abilities/sword/crippling_gouge.ron | 2 +- .../abilities/sword/defensive_combo.ron | 8 +- .../abilities/sword/defensive_retreat.ron | 2 +- assets/common/abilities/sword/heavy_combo.ron | 14 +-- .../common/abilities/sword/heavy_finisher.ron | 4 +- .../abilities/sword/heavy_pommelstrike.ron | 2 +- .../common/abilities/sword/mobility_combo.ron | 2 +- .../abilities/sword/offensive_combo.ron | 2 +- .../abilities/sword/offensive_finisher.ron | 2 +- .../common/abilities/sword/parrying_combo.ron | 6 +- .../abilities/sword/parrying_counter.ron | 2 +- .../common/abilities/sword/parrying_parry.ron | 2 +- .../abilities/sword/parrying_riposte.ron | 4 +- .../common/abilities/sword/reaching_combo.ron | 2 +- .../abilities/sword/reaching_flurry.ron | 4 +- .../modular/weapon/secondary/sword/long.ron | 8 +- .../modular/weapon/secondary/sword/short.ron | 8 +- .../element/de_buffs/buff_fortitude_0.png | 3 + .../element/de_buffs/debuff_parried_0.png | 3 + .../element/skills/sword/balanced_combo.png | 4 +- .../skills/sword/balanced_finisher.png | 4 +- .../element/skills/sword/balanced_thrust.png | 4 +- assets/voxygen/i18n/en/hud/ability.ftl | 2 +- common/src/combat.rs | 44 ++++++--- common/src/comp/ability.rs | 83 +++++++++++++--- common/src/comp/body.rs | 7 +- common/src/comp/character_state.rs | 18 +++- common/src/states/basic_aura.rs | 2 +- common/src/states/basic_beam.rs | 2 +- common/src/states/basic_block.rs | 2 +- common/src/states/basic_melee.rs | 2 +- common/src/states/basic_ranged.rs | 2 +- common/src/states/charged_melee.rs | 2 +- common/src/states/charged_ranged.rs | 2 +- common/src/states/combo_melee.rs | 2 +- common/src/states/combo_melee2.rs | 4 +- common/src/states/dash_melee.rs | 2 +- common/src/states/dive_melee.rs | 1 + common/src/states/finisher_melee.rs | 7 +- common/src/states/leap_melee.rs | 2 +- common/src/states/rapid_melee.rs | 2 +- common/src/states/repeater_ranged.rs | 2 +- common/src/states/riposte_melee.rs | 2 +- common/src/states/roll.rs | 6 +- common/src/states/self_buff.rs | 2 +- common/src/states/shockwave.rs | 2 +- common/src/states/spin_melee.rs | 2 +- common/src/states/utils.rs | 51 +++++----- common/systems/src/beam.rs | 8 +- common/systems/src/melee.rs | 3 +- common/systems/src/projectile.rs | 9 +- common/systems/src/shockwave.rs | 14 ++- common/systems/src/stats.rs | 7 +- server/agent/src/attack.rs | 12 +-- server/src/events/entity_manipulation.rs | 63 ++++++++++--- .../audio/sfx/event_mapper/movement/tests.rs | 13 ++- voxygen/src/hud/img_ids.rs | 2 + voxygen/src/hud/mod.rs | 46 +++------ voxygen/src/hud/skillbar.rs | 94 ++++++++++++++----- voxygen/src/hud/slots.rs | 12 ++- voxygen/src/hud/util.rs | 15 +++ 67 files changed, 440 insertions(+), 235 deletions(-) create mode 100644 assets/voxygen/element/de_buffs/buff_fortitude_0.png create mode 100644 assets/voxygen/element/de_buffs/debuff_parried_0.png diff --git a/assets/common/abilities/bow/charged.ron b/assets/common/abilities/bow/charged.ron index 9b2e4830c5..8b0697cdfa 100644 --- a/assets/common/abilities/bow/charged.ron +++ b/assets/common/abilities/bow/charged.ron @@ -4,9 +4,9 @@ ChargedRanged( initial_regen: 2, scaled_regen: 14, initial_damage: 2, - scaled_damage: 14, + scaled_damage: 12, initial_knockback: 0, - scaled_knockback: 15, + scaled_knockback: 12, buildup_duration: 0.25, charge_duration: 1.0, recover_duration: 0.4, diff --git a/assets/common/abilities/bow/repeater.ron b/assets/common/abilities/bow/repeater.ron index 7a39f420d5..bca5717269 100644 --- a/assets/common/abilities/bow/repeater.ron +++ b/assets/common/abilities/bow/repeater.ron @@ -1,5 +1,5 @@ RepeaterRanged( - energy_cost: 5.0, + energy_cost: 6.0, buildup_duration: 0.2, shoot_duration: 0.3, recover_duration: 0.5, diff --git a/assets/common/abilities/sword/cleaving_combo.ron b/assets/common/abilities/sword/cleaving_combo.ron index 4cef3160c4..3eef40a988 100644 --- a/assets/common/abilities/sword/cleaving_combo.ron +++ b/assets/common/abilities/sword/cleaving_combo.ron @@ -48,7 +48,7 @@ ComboMelee2( ), ], is_stance: true, - energy_cost_per_strike: 6, + energy_cost_per_strike: 5, meta: ( kind: Some(Sword(Cleaving)), ), diff --git a/assets/common/abilities/sword/cleaving_spin.ron b/assets/common/abilities/sword/cleaving_spin.ron index f7c72e2054..9dc4736fef 100644 --- a/assets/common/abilities/sword/cleaving_spin.ron +++ b/assets/common/abilities/sword/cleaving_spin.ron @@ -3,10 +3,10 @@ ComboMelee2( ( melee_constructor: ( kind: Slash( - damage: 20, + damage: 16, poise: 0, knockback: 0, - energy_regen: 10, + energy_regen: 5, ), range: 6.0, angle: 360.0, diff --git a/assets/common/abilities/sword/crippling_combo.ron b/assets/common/abilities/sword/crippling_combo.ron index 1a706770ef..4ba69ba6b9 100644 --- a/assets/common/abilities/sword/crippling_combo.ron +++ b/assets/common/abilities/sword/crippling_combo.ron @@ -14,7 +14,7 @@ ComboMelee2( kind: Bleeding, dur_secs: 10.0, strength: DamageFraction(0.2), - chance: 0.25, + chance: 0.1, ))), ), buildup_duration: 0.2, @@ -26,7 +26,7 @@ ComboMelee2( ( melee_constructor: ( kind: Slash( - damage: 22, + damage: 14, poise: 0, knockback: 0, energy_regen: 13, @@ -37,18 +37,18 @@ ComboMelee2( kind: Bleeding, dur_secs: 10.0, strength: DamageFraction(0.2), - chance: 0.5, + chance: 0.25, ))), ), - buildup_duration: 0.3, - swing_duration: 0.2, + buildup_duration: 0.2, + swing_duration: 0.1, hit_timing: 0.5, - recover_duration: 0.4, + recover_duration: 0.3, ori_modifier: 0.6, ), ], is_stance: true, - energy_cost_per_strike: 5, + energy_cost_per_strike: 4, meta: ( kind: Some(Sword(Crippling)), ), diff --git a/assets/common/abilities/sword/crippling_finisher.ron b/assets/common/abilities/sword/crippling_finisher.ron index dfe4f88604..a6cbec2d45 100644 --- a/assets/common/abilities/sword/crippling_finisher.ron +++ b/assets/common/abilities/sword/crippling_finisher.ron @@ -15,13 +15,13 @@ FinisherMelee( damage_effect: Some(Buff(( kind: Bleeding, dur_secs: 10.0, - strength: DamageFraction(0.5), + strength: DamageFraction(0.25), chance: 1.0, ))), ), scaling: Some(( target: Buff, - kind: Linear, + kind: Sqrt, )), minimum_combo: 10, meta: ( diff --git a/assets/common/abilities/sword/crippling_gouge.ron b/assets/common/abilities/sword/crippling_gouge.ron index 2ba27df471..4f672467ae 100644 --- a/assets/common/abilities/sword/crippling_gouge.ron +++ b/assets/common/abilities/sword/crippling_gouge.ron @@ -3,7 +3,7 @@ ComboMelee2( ( melee_constructor: ( kind: Slash( - damage: 20, + damage: 14, poise: 0, knockback: 0, energy_regen: 5, diff --git a/assets/common/abilities/sword/defensive_combo.ron b/assets/common/abilities/sword/defensive_combo.ron index d64e365dc2..383f0b1ae0 100644 --- a/assets/common/abilities/sword/defensive_combo.ron +++ b/assets/common/abilities/sword/defensive_combo.ron @@ -3,15 +3,15 @@ ComboMelee2( ( melee_constructor: ( kind: Slash( - damage: 10, + damage: 8, poise: 0, knockback: 0, - energy_regen: 6, + energy_regen: 8, ), range: 3.0, angle: 45.0, ), - buildup_duration: 0.4, + buildup_duration: 0.3, swing_duration: 0.1, hit_timing: 0.5, recover_duration: 0.5, @@ -36,7 +36,7 @@ ComboMelee2( ), ], is_stance: true, - energy_cost_per_strike: 3, + energy_cost_per_strike: 2, meta: ( kind: Some(Sword(Defensive)), capabilities: ( diff --git a/assets/common/abilities/sword/defensive_retreat.ron b/assets/common/abilities/sword/defensive_retreat.ron index 5417a9e685..612b5ebd43 100644 --- a/assets/common/abilities/sword/defensive_retreat.ron +++ b/assets/common/abilities/sword/defensive_retreat.ron @@ -18,7 +18,7 @@ ComboMelee2( movement: ( buildup: None, swing: None, - recover: Some(Reverse(1.0)), + recover: Some(Reverse(1.5)), ), ori_modifier: 0.6, ), diff --git a/assets/common/abilities/sword/heavy_combo.ron b/assets/common/abilities/sword/heavy_combo.ron index b3758e5958..3cda91a61f 100644 --- a/assets/common/abilities/sword/heavy_combo.ron +++ b/assets/common/abilities/sword/heavy_combo.ron @@ -4,8 +4,8 @@ ComboMelee2( melee_constructor: ( kind: Slash( damage: 18, - poise: 0, - knockback: 0, + poise: 5, + knockback: 5, energy_regen: 10, ), range: 3.0, @@ -21,8 +21,8 @@ ComboMelee2( melee_constructor: ( kind: Slash( damage: 30, - poise: 0, - knockback: 0, + poise: 5, + knockback: 5, energy_regen: 15, ), range: 3.0, @@ -36,12 +36,12 @@ ComboMelee2( ), ], is_stance: true, - energy_cost_per_strike: 5, + energy_cost_per_strike: 4, meta: ( kind: Some(Sword(Heavy)), capabilities: ( - // Poise resistant during attack - bits: 0b00001000, + // Poise and knockback resistant during attack + bits: 0b00011000, ), ), ) \ No newline at end of file diff --git a/assets/common/abilities/sword/heavy_finisher.ron b/assets/common/abilities/sword/heavy_finisher.ron index b6f8d8b0c2..6807864d79 100644 --- a/assets/common/abilities/sword/heavy_finisher.ron +++ b/assets/common/abilities/sword/heavy_finisher.ron @@ -5,8 +5,8 @@ FinisherMelee( recover_duration: 0.4, melee_constructor: ( kind: Bash( - damage: 30, - poise: 30, + damage: 40, + poise: 40, knockback: 0, energy_regen: 10, ), diff --git a/assets/common/abilities/sword/heavy_pommelstrike.ron b/assets/common/abilities/sword/heavy_pommelstrike.ron index 35db8114ff..e212952dec 100644 --- a/assets/common/abilities/sword/heavy_pommelstrike.ron +++ b/assets/common/abilities/sword/heavy_pommelstrike.ron @@ -4,7 +4,7 @@ ComboMelee2( melee_constructor: ( kind: Bash( damage: 20, - poise: 20, + poise: 25, knockback: 0, energy_regen: 5, ), diff --git a/assets/common/abilities/sword/mobility_combo.ron b/assets/common/abilities/sword/mobility_combo.ron index ca55273fa3..97f6c11d59 100644 --- a/assets/common/abilities/sword/mobility_combo.ron +++ b/assets/common/abilities/sword/mobility_combo.ron @@ -70,7 +70,7 @@ ComboMelee2( ), ], is_stance: true, - energy_cost_per_strike: 3, + energy_cost_per_strike: 2, meta: ( kind: Some(Sword(Mobility)), capabilities: ( diff --git a/assets/common/abilities/sword/offensive_combo.ron b/assets/common/abilities/sword/offensive_combo.ron index 1b8d11501e..e539465757 100644 --- a/assets/common/abilities/sword/offensive_combo.ron +++ b/assets/common/abilities/sword/offensive_combo.ron @@ -58,7 +58,7 @@ ComboMelee2( ), ], is_stance: true, - energy_cost_per_strike: 4, + energy_cost_per_strike: 3, meta: ( kind: Some(Sword(Offensive)), ), diff --git a/assets/common/abilities/sword/offensive_finisher.ron b/assets/common/abilities/sword/offensive_finisher.ron index 5b18883926..a88bb5b8a6 100644 --- a/assets/common/abilities/sword/offensive_finisher.ron +++ b/assets/common/abilities/sword/offensive_finisher.ron @@ -21,7 +21,7 @@ FinisherMelee( ), scaling: Some(( target: Attack, - kind: Linear, + kind: Sqrt, )), minimum_combo: 10, meta: ( diff --git a/assets/common/abilities/sword/parrying_combo.ron b/assets/common/abilities/sword/parrying_combo.ron index 7807d65753..9c551faf04 100644 --- a/assets/common/abilities/sword/parrying_combo.ron +++ b/assets/common/abilities/sword/parrying_combo.ron @@ -3,7 +3,7 @@ ComboMelee2( ( melee_constructor: ( kind: Slash( - damage: 7, + damage: 6, poise: 0, knockback: 0, energy_regen: 9, @@ -20,7 +20,7 @@ ComboMelee2( ( melee_constructor: ( kind: Slash( - damage: 13, + damage: 11, poise: 0, knockback: 0, energy_regen: 13, @@ -36,7 +36,7 @@ ComboMelee2( ), ], is_stance: true, - energy_cost_per_strike: 6, + energy_cost_per_strike: 5, meta: ( kind: Some(Sword(Parrying)), capabilities: ( diff --git a/assets/common/abilities/sword/parrying_counter.ron b/assets/common/abilities/sword/parrying_counter.ron index 2b3ed2689d..835c807e23 100644 --- a/assets/common/abilities/sword/parrying_counter.ron +++ b/assets/common/abilities/sword/parrying_counter.ron @@ -3,7 +3,7 @@ ComboMelee2( ( melee_constructor: ( kind: Slash( - damage: 25, + damage: 30, poise: 0, knockback: 0, energy_regen: 5, diff --git a/assets/common/abilities/sword/parrying_parry.ron b/assets/common/abilities/sword/parrying_parry.ron index 6bfab37ab2..e2ed066112 100644 --- a/assets/common/abilities/sword/parrying_parry.ron +++ b/assets/common/abilities/sword/parrying_parry.ron @@ -7,7 +7,7 @@ BasicBlock( buildup: true, recover: true, ), - energy_cost: 10, + energy_cost: 15, can_hold: false, meta: ( kind: Some(Sword(Parrying)), diff --git a/assets/common/abilities/sword/parrying_riposte.ron b/assets/common/abilities/sword/parrying_riposte.ron index 3bc4084608..06968664bc 100644 --- a/assets/common/abilities/sword/parrying_riposte.ron +++ b/assets/common/abilities/sword/parrying_riposte.ron @@ -1,8 +1,8 @@ RiposteMelee( energy_cost: 20, - buildup_duration: 0.2, + buildup_duration: 0.3, swing_duration: 0.2, - recover_duration: 0.4, + recover_duration: 0.3, melee_constructor: ( kind: Slash( damage: 25, diff --git a/assets/common/abilities/sword/reaching_combo.ron b/assets/common/abilities/sword/reaching_combo.ron index dbf042f0ad..a364243e75 100644 --- a/assets/common/abilities/sword/reaching_combo.ron +++ b/assets/common/abilities/sword/reaching_combo.ron @@ -36,7 +36,7 @@ ComboMelee2( ), ], is_stance: true, - energy_cost_per_strike: 5, + energy_cost_per_strike: 4, meta: ( kind: Some(Sword(Reaching)), ), diff --git a/assets/common/abilities/sword/reaching_flurry.ron b/assets/common/abilities/sword/reaching_flurry.ron index 1720e59a0f..0c9740ac35 100644 --- a/assets/common/abilities/sword/reaching_flurry.ron +++ b/assets/common/abilities/sword/reaching_flurry.ron @@ -7,12 +7,12 @@ RapidMelee( damage: 10, poise: 0, knockback: 0, - energy_regen: 5, + energy_regen: 4, ), range: 4.5, angle: 10.0, ), - energy_cost: 10, + energy_cost: 8, max_strikes: 6, meta: ( kind: Some(Sword(Reaching)), diff --git a/assets/common/items/modular/weapon/secondary/sword/long.ron b/assets/common/items/modular/weapon/secondary/sword/long.ron index 60b37f6f89..7c028a330c 100644 --- a/assets/common/items/modular/weapon/secondary/sword/long.ron +++ b/assets/common/items/modular/weapon/secondary/sword/long.ron @@ -6,12 +6,12 @@ ItemDef( toolkind: Sword, stats: ( equip_time_secs: 1.1, - power: 1.3, - effect_power: 1.2, - speed: 0.7, + power: 1.1, + effect_power: 1.1, + speed: 0.9, crit_chance: 0.9, range: 1.1, - energy_efficiency: 0.8, + energy_efficiency: 0.9, buff_strength: 1.1, ), hand_restriction: Some(Two), diff --git a/assets/common/items/modular/weapon/secondary/sword/short.ron b/assets/common/items/modular/weapon/secondary/sword/short.ron index 053ccba369..b1bf7c79d6 100644 --- a/assets/common/items/modular/weapon/secondary/sword/short.ron +++ b/assets/common/items/modular/weapon/secondary/sword/short.ron @@ -6,12 +6,12 @@ ItemDef( toolkind: Sword, stats: ( equip_time_secs: 0.9, - power: 0.7, - effect_power: 0.8, - speed: 1.3, + power: 0.9, + effect_power: 0.9, + speed: 1.1, crit_chance: 1.1, range: 0.9, - energy_efficiency: 1.2, + energy_efficiency: 1.1, buff_strength: 0.9, ), hand_restriction: Some(One), diff --git a/assets/voxygen/element/de_buffs/buff_fortitude_0.png b/assets/voxygen/element/de_buffs/buff_fortitude_0.png new file mode 100644 index 0000000000..998f5f9c5e --- /dev/null +++ b/assets/voxygen/element/de_buffs/buff_fortitude_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83eaf46c95db325400b33498b5e02670875139a4313ab68c1e9328ffc515f7a6 +size 2916 diff --git a/assets/voxygen/element/de_buffs/debuff_parried_0.png b/assets/voxygen/element/de_buffs/debuff_parried_0.png new file mode 100644 index 0000000000..f3567db3d8 --- /dev/null +++ b/assets/voxygen/element/de_buffs/debuff_parried_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a6b40ca115a36a7f2d2b9765097a6dadb99d628fe759c20144d6d3236c90e06 +size 2921 diff --git a/assets/voxygen/element/skills/sword/balanced_combo.png b/assets/voxygen/element/skills/sword/balanced_combo.png index d579aacb5c..bd7b9e3db0 100644 --- a/assets/voxygen/element/skills/sword/balanced_combo.png +++ b/assets/voxygen/element/skills/sword/balanced_combo.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1391c81abaf0d00652c058e648c403c4b142d3f7d28a3f29cfab6fbe7fb5d205 -size 3310 +oid sha256:8eb9be9976754154ee0b973dab1acc13f56a2615e35e7eeb42e41e2fcad33716 +size 3343 diff --git a/assets/voxygen/element/skills/sword/balanced_finisher.png b/assets/voxygen/element/skills/sword/balanced_finisher.png index 994216acfa..92d0363ddd 100644 --- a/assets/voxygen/element/skills/sword/balanced_finisher.png +++ b/assets/voxygen/element/skills/sword/balanced_finisher.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb8423b43e0d47573fa5df8ed56c7df36bd4be6c31e41c303ac07bdbbd2d832b -size 3357 +oid sha256:5bcaa70ac0bdca9cad8f07e08979403db669c9d2890dc6ee83375b25a89642b5 +size 3377 diff --git a/assets/voxygen/element/skills/sword/balanced_thrust.png b/assets/voxygen/element/skills/sword/balanced_thrust.png index 7485663f6e..a1079fb4f0 100644 --- a/assets/voxygen/element/skills/sword/balanced_thrust.png +++ b/assets/voxygen/element/skills/sword/balanced_thrust.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9fbfcbb3aa500fa641292d1effe9a88cd6c5c666caffb0480ff7a8624414f00c -size 3332 +oid sha256:09be07c326e9ef6c15c38c8a52f2a897536981170ab396b15c254631f2a934ef +size 3383 diff --git a/assets/voxygen/i18n/en/hud/ability.ftl b/assets/voxygen/i18n/en/hud/ability.ftl index aacf147734..043fe79376 100644 --- a/assets/voxygen/i18n/en/hud/ability.ftl +++ b/assets/voxygen/i18n/en/hud/ability.ftl @@ -15,7 +15,7 @@ common-abilities-sceptre-wardingaura = Warding Aura common-abilities-sword-balanced_combo = Balanced Stance .desc = This stance has few downsides, but is not particularly special. common-abilities-sword-balanced_thrust = Sword Thrust - .desc = Extend yourself to hit those a little further away. + .desc = Charge a thrust to hit enemies with a longer distance. common-abilities-sword-balanced_finisher = Finisher .desc = A powerful strike you can use after fighting long enough. common-abilities-sword-offensive_combo = Offensive Stance diff --git a/common/src/combat.rs b/common/src/combat.rs index 1d4a5b298b..06ae5816e9 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -2,6 +2,7 @@ use crate::comp::buff::{Buff, BuffChange, BuffData, BuffKind, BuffSource}; #[cfg(not(target_arch = "wasm32"))] use crate::{ comp::{ + ability::Capability, inventory::{ item::{armor::Protection, tool::ToolKind, ItemDesc, ItemKind, MaterialStatManifest}, slot::EquipSlot, @@ -334,7 +335,8 @@ impl Attack { for effect in damage.effects.iter() { match effect { CombatEffect::Knockback(kb) => { - let impulse = kb.calculate_impulse(dir) * strength_modifier; + let impulse = + kb.calculate_impulse(dir, target.char_state) * strength_modifier; if !impulse.is_approx_zero() { emit(ServerEvent::Knockback { entity: target.entity, @@ -432,7 +434,10 @@ impl Attack { }, CombatEffect::BuildupsVulnerable => { if target.char_state.map_or(false, |cs| { - matches!(cs.stage_section(), Some(StageSection::Buildup)) + matches!( + cs.stage_section(), + Some(StageSection::Buildup | StageSection::Charge) + ) }) { emit(ServerEvent::HealthChange { entity: target.entity, @@ -496,7 +501,8 @@ impl Attack { is_applied = true; match effect.effect { CombatEffect::Knockback(kb) => { - let impulse = kb.calculate_impulse(dir) * strength_modifier; + let impulse = + kb.calculate_impulse(dir, target.char_state) * strength_modifier; if !impulse.is_approx_zero() { emit(ServerEvent::Knockback { entity: target.entity, @@ -951,18 +957,26 @@ pub enum KnockbackDir { #[cfg(not(target_arch = "wasm32"))] impl Knockback { - pub fn calculate_impulse(self, dir: Dir) -> Vec3 { - // TEMP until source knockback values have been updated - 50.0 * match self.direction { - KnockbackDir::Away => self.strength * *Dir::slerp(dir, Dir::new(Vec3::unit_z()), 0.5), - KnockbackDir::Towards => { - self.strength * *Dir::slerp(-dir, Dir::new(Vec3::unit_z()), 0.5) - }, - KnockbackDir::Up => self.strength * Vec3::unit_z(), - KnockbackDir::TowardsUp => { - self.strength * *Dir::slerp(-dir, Dir::new(Vec3::unit_z()), 0.85) - }, - } + pub fn calculate_impulse(self, dir: Dir, char_state: Option<&CharacterState>) -> Vec3 { + let from_char = { + let resistant = char_state + .and_then(|cs| cs.ability_info()) + .and_then(|a| a.ability_meta) + .map_or(false, |a| { + a.capabilities.contains(Capability::KNOCKBACK_RESISTANT) + }); + if resistant { 0.5 } else { 1.0 } + }; + // TEMP: 50.0 multiplication kept until source knockback values have been + // updated + 50.0 * self.strength + * from_char + * match self.direction { + KnockbackDir::Away => *Dir::slerp(dir, Dir::new(Vec3::unit_z()), 0.5), + KnockbackDir::Towards => *Dir::slerp(-dir, Dir::new(Vec3::unit_z()), 0.5), + KnockbackDir::Up => Vec3::unit_z(), + KnockbackDir::TowardsUp => *Dir::slerp(-dir, Dir::new(Vec3::unit_z()), 0.85), + } } #[must_use] diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index d72eb34561..6c36972629 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -3,6 +3,7 @@ use crate::{ combat::{self, CombatEffect, DamageKind, Knockback}, comp::{ self, aura, beam, buff, + character_state::AttackImmunities, inventory::{ item::{ tool::{AbilityContext, AbilityItem, AuxiliaryAbilityKind, Stats, ToolKind}, @@ -534,7 +535,7 @@ pub enum CharacterAbility { movement_duration: f32, recover_duration: f32, roll_strength: f32, - immune_melee: bool, + attack_immunities: AttackImmunities, #[serde(default)] meta: AbilityMeta, }, @@ -871,8 +872,15 @@ impl CharacterAbility { buildup_duration: 0.05, movement_duration: 0.33, recover_duration: 0.125, - roll_strength: 2.0, - immune_melee: true, + roll_strength: 2.5, + attack_immunities: AttackImmunities { + melee: true, + projectiles: false, + beams: true, + ground_shockwaves: false, + air_shockwaves: true, + explosions: true, + }, meta: Default::default(), } } @@ -1002,7 +1010,7 @@ impl CharacterAbility { ref mut movement_duration, ref mut recover_duration, roll_strength: _, - immune_melee: _, + attack_immunities: _, meta: _, } => { *buildup_duration /= stats.speed; @@ -1346,7 +1354,7 @@ impl CharacterAbility { self } - pub fn get_energy_cost(&self) -> f32 { + pub fn energy_cost(&self) -> f32 { use CharacterAbility::*; match self { BasicMelee { energy_cost, .. } @@ -1386,6 +1394,46 @@ impl CharacterAbility { } } + #[allow(clippy::bool_to_int_with_if)] + pub fn combo_cost(&self) -> u32 { + use CharacterAbility::*; + match self { + BasicAura { + scales_with_combo, .. + } => { + if *scales_with_combo { + 1 + } else { + 0 + } + }, + FinisherMelee { minimum_combo, .. } => *minimum_combo, + BasicMelee { .. } + | BasicRanged { .. } + | RepeaterRanged { .. } + | DashMelee { .. } + | Roll { .. } + | LeapMelee { .. } + | SpinMelee { .. } + | ChargedMelee { .. } + | ChargedRanged { .. } + | Shockwave { .. } + | BasicBlock { .. } + | SelfBuff { .. } + | ComboMelee2 { .. } + | DiveMelee { .. } + | RiposteMelee { .. } + | RapidMelee { .. } + | BasicBeam { .. } + | Boost { .. } + | ComboMelee { .. } + | Blink { .. } + | Music { .. } + | BasicSummon { .. } + | SpriteSummon { .. } => 0, + } + } + // TODO: Maybe consider making CharacterAbility a struct at some point? pub fn ability_meta(&self) -> AbilityMeta { use CharacterAbility::*; @@ -2060,7 +2108,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { movement_duration, recover_duration, roll_strength, - immune_melee, + attack_immunities, meta: _, } => CharacterState::Roll(roll::Data { static_data: roll::StaticData { @@ -2068,7 +2116,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { movement_duration: Duration::from_secs_f32(*movement_duration), recover_duration: Duration::from_secs_f32(*recover_duration), roll_strength: *roll_strength, - immune_melee: *immune_melee, + attack_immunities: *attack_immunities, ability_info, }, timer: Duration::default(), @@ -2120,10 +2168,15 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { exhausted: false, start_next_strike: false, timer: Duration::default(), - // If ability is a stance, enter the stance without beginning a strike, otherwise - // immediately begin the strike + // If ability is a stance, if starting from wielding, get ready to enter stance, + // otherwise enter stance immediately, otherwise if not a stance immediately begin + // the strike stage_section: if *is_stance { - Some(StageSection::Ready) + if matches!(data.character, CharacterState::Wielding(_)) { + Some(StageSection::Ready) + } else { + None + } } else { Some(StageSection::Buildup) }, @@ -2608,12 +2661,14 @@ bitflags::bitflags! { #[derive(Default, Serialize, Deserialize)] pub struct Capability: u8 { // Allows rolls to interrupt the ability at any point, not just during buildup - const ROLL_INTERRUPT = 0b00000001; + const ROLL_INTERRUPT = 0b00000001; // Allows blocking to interrupt the ability at any point - const BLOCK_INTERRUPT = 0b00000010; + const BLOCK_INTERRUPT = 0b00000010; // When the ability is in the buildup section, it counts as a parry - const BUILDUP_PARRIES = 0b00000100; + const BUILDUP_PARRIES = 0b00000100; // When in the ability, an entity only receives half as much poise damage - const POISE_RESISTANT = 0b00001000; + const POISE_RESISTANT = 0b00001000; + // WHen in the ability, an entity only receives half as much knockback + const KNOCKBACK_RESISTANT = 0b00010000; } } diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 3981b75fe5..361f3fd487 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -828,7 +828,12 @@ impl Body { pub fn immune_to(&self, buff: BuffKind) -> bool { match buff { - BuffKind::Bleeding => matches!(self, Body::Object(_) | Body::Golem(_) | Body::Ship(_)), + BuffKind::Bleeding => match self { + Body::Object(_) | Body::Golem(_) | Body::Ship(_) => true, + Body::BipedSmall(b) => matches!(b.species, biped_small::Species::Husk), + Body::BipedLarge(b) => matches!(b.species, biped_large::Species::Huskbrute), + _ => false, + }, BuffKind::Burning => match self { Body::Golem(g) => matches!(g.species, golem::Species::ClayGolem), Body::BipedSmall(b) => matches!(b.species, biped_small::Species::Haniwa), diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 35bef436eb..9493939f90 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -323,8 +323,12 @@ impl CharacterState { pub fn is_music(&self) -> bool { matches!(self, CharacterState::Music(_)) } - pub fn is_melee_dodge(&self) -> bool { - matches!(self, CharacterState::Roll(d) if d.static_data.immune_melee) + pub fn attack_immunities(&self) -> Option { + if let CharacterState::Roll(c) = self { + Some(c.static_data.attack_immunities) + } else { + None + } } pub fn is_stunned(&self) -> bool { matches!(self, CharacterState::Stunned(_)) } @@ -854,6 +858,16 @@ pub struct DurationsInfo { pub ready: Option, } +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq)] +pub struct AttackImmunities { + pub melee: bool, + pub projectiles: bool, + pub beams: bool, + pub ground_shockwaves: bool, + pub air_shockwaves: bool, + pub explosions: bool, +} + impl Default for CharacterState { fn default() -> Self { Self::Idle(idle::Data { diff --git a/common/src/states/basic_aura.rs b/common/src/states/basic_aura.rs index 44f021020d..20bb8fac67 100644 --- a/common/src/states/basic_aura.rs +++ b/common/src/states/basic_aura.rs @@ -145,7 +145,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index 4c8200daed..0a416c4a51 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -219,7 +219,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/basic_block.rs b/common/src/states/basic_block.rs index 4e8e9d8e5b..ff9cbec272 100644 --- a/common/src/states/basic_block.rs +++ b/common/src/states/basic_block.rs @@ -111,7 +111,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/basic_melee.rs b/common/src/states/basic_melee.rs index b60a0a7e9b..712fc501d2 100644 --- a/common/src/states/basic_melee.rs +++ b/common/src/states/basic_melee.rs @@ -132,7 +132,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index a100985f90..d691d28f08 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -137,7 +137,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/charged_melee.rs b/common/src/states/charged_melee.rs index 7838e4cf8f..2fde729a7f 100644 --- a/common/src/states/charged_melee.rs +++ b/common/src/states/charged_melee.rs @@ -166,7 +166,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 21723b667f..f948493dc0 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -182,7 +182,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index fff8b92734..c48da9e88b 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -355,7 +355,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/combo_melee2.rs b/common/src/states/combo_melee2.rs index fe67dc93e0..97493c2af9 100644 --- a/common/src/states/combo_melee2.rs +++ b/common/src/states/combo_melee2.rs @@ -106,7 +106,7 @@ pub struct Data { } pub const STANCE_ENTER_TIME: Duration = Duration::from_millis(250); -pub const STANCE_LEAVE_TIME: Duration = Duration::from_secs(20); +pub const STANCE_LEAVE_TIME: Duration = Duration::from_secs(30); impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { @@ -127,7 +127,7 @@ impl CharacterBehavior for Data { 1.0 }; handle_move(data, &mut update, move_eff); - let interrupted = handle_interrupts(data, &mut update, Some(ability_input)); + let interrupted = handle_interrupts(data, &mut update); let strike_data = self.strike_data(); diff --git a/common/src/states/dash_melee.rs b/common/src/states/dash_melee.rs index 09c175d7f7..ebf876bbfd 100644 --- a/common/src/states/dash_melee.rs +++ b/common/src/states/dash_melee.rs @@ -257,7 +257,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/dive_melee.rs b/common/src/states/dive_melee.rs index 1713d5d172..9b21e3e74b 100644 --- a/common/src/states/dive_melee.rs +++ b/common/src/states/dive_melee.rs @@ -50,6 +50,7 @@ impl CharacterBehavior for Data { match self.stage_section { StageSection::Movement => { + handle_move(data, &mut update, 1.0); if data.physics.on_ground.is_some() { // Transitions to swing portion of state upon hitting ground if let CharacterState::DiveMelee(c) = &mut update.character { diff --git a/common/src/states/finisher_melee.rs b/common/src/states/finisher_melee.rs index f072b42c86..f3985d5796 100644 --- a/common/src/states/finisher_melee.rs +++ b/common/src/states/finisher_melee.rs @@ -51,7 +51,7 @@ impl CharacterBehavior for Data { handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.7); handle_jump(data, output_events, &mut update, 1.0); - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); match self.stage_section { StageSection::Buildup => { @@ -88,6 +88,9 @@ impl CharacterBehavior for Data { self.static_data.combo_on_use as f32 / self.static_data.minimum_combo as f32 }, + ScalingKind::Sqrt => { + (self.static_data.combo_on_use as f32 / self.static_data.minimum_combo as f32).sqrt() + }, }; match scaling.target { ScalingTarget::Attack => { @@ -155,6 +158,8 @@ pub enum ScalingKind { // Reaches a scaling of 1 when at minimum combo, and a scaling of 2 when at double minimum // combo Linear, + // Reaches a scaling of 1 when at minimum combo, and a scaling of 2 when at 4x minimum combo + Sqrt, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] diff --git a/common/src/states/leap_melee.rs b/common/src/states/leap_melee.rs index 0946eab755..99e0765080 100644 --- a/common/src/states/leap_melee.rs +++ b/common/src/states/leap_melee.rs @@ -149,7 +149,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/rapid_melee.rs b/common/src/states/rapid_melee.rs index 934c74d8bc..acc725d14c 100644 --- a/common/src/states/rapid_melee.rs +++ b/common/src/states/rapid_melee.rs @@ -48,7 +48,7 @@ impl CharacterBehavior for Data { handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.7); - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); match self.stage_section { StageSection::Buildup => { diff --git a/common/src/states/repeater_ranged.rs b/common/src/states/repeater_ranged.rs index ba1cb4b1a9..853f51e9ab 100644 --- a/common/src/states/repeater_ranged.rs +++ b/common/src/states/repeater_ranged.rs @@ -158,7 +158,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/riposte_melee.rs b/common/src/states/riposte_melee.rs index eae2e926f3..a1c4dcf608 100644 --- a/common/src/states/riposte_melee.rs +++ b/common/src/states/riposte_melee.rs @@ -43,7 +43,7 @@ impl CharacterBehavior for Data { handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, 0.7); handle_jump(data, output_events, &mut update, 1.0); - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); match self.stage_section { StageSection::Buildup => { diff --git a/common/src/states/roll.rs b/common/src/states/roll.rs index d1bccb5ed6..0ec617e85f 100644 --- a/common/src/states/roll.rs +++ b/common/src/states/roll.rs @@ -1,7 +1,7 @@ use crate::{ comp::{ buff::{BuffChange, BuffKind}, - character_state::OutputEvents, + character_state::{OutputEvents, AttackImmunities}, CharacterState, InputKind, StateUpdate, }, event::ServerEvent, @@ -24,8 +24,8 @@ pub struct StaticData { pub recover_duration: Duration, /// Affects the speed and distance of the roll pub roll_strength: f32, - /// Affects whether you are immune to melee attacks while rolling - pub immune_melee: bool, + /// Affects whether you are immune to various attacks while rolling + pub attack_immunities: AttackImmunities, /// Information about the ability pub ability_info: AbilityInfo, } diff --git a/common/src/states/self_buff.rs b/common/src/states/self_buff.rs index a821346dcd..e550472566 100644 --- a/common/src/states/self_buff.rs +++ b/common/src/states/self_buff.rs @@ -114,7 +114,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/shockwave.rs b/common/src/states/shockwave.rs index 849a720ca6..52a222272b 100644 --- a/common/src/states/shockwave.rs +++ b/common/src/states/shockwave.rs @@ -167,7 +167,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/spin_melee.rs b/common/src/states/spin_melee.rs index 2f1947e7bc..22332bb310 100644 --- a/common/src/states/spin_melee.rs +++ b/common/src/states/spin_melee.rs @@ -161,7 +161,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - handle_interrupts(data, &mut update, None); + handle_interrupts(data, &mut update); update } diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 59f44957a6..cd3046bc62 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -1096,40 +1096,28 @@ pub fn handle_dodge_input(data: &JoinData<'_>, update: &mut StateUpdate) -> bool pub fn handle_interrupts( data: &JoinData, update: &mut StateUpdate, - // Used when an input other than the one that activated the ability being pressed should block - // an interrupt - input_override: Option, ) -> bool { - // Check that the input used to enter current character state (if there was one) - // is not pressed - if input_override - .or_else(|| data.character.ability_info().and_then(|a| a.input)) - .map_or(true, |input| !input_is_pressed(data, input)) - { - let can_dodge = { - let in_buildup = data - .character - .stage_section() - .map_or(true, |stage_section| { - matches!(stage_section, StageSection::Buildup) - }); - let interruptible = data.character.ability_info().and_then(|info| info.ability_meta).map_or(false, |meta| { - meta.capabilities - .contains(Capability::ROLL_INTERRUPT) + let can_dodge = { + let in_buildup = data + .character + .stage_section() + .map_or(true, |stage_section| { + matches!(stage_section, StageSection::Buildup) }); - in_buildup || interruptible - }; - let can_block = data.character.ability_info().and_then(|info| info.ability_meta).map_or(false, |meta| { + let interruptible = data.character.ability_info().and_then(|info| info.ability_meta).map_or(false, |meta| { meta.capabilities - .contains(Capability::BLOCK_INTERRUPT) + .contains(Capability::ROLL_INTERRUPT) }); - if can_dodge { - handle_dodge_input(data, update) - } else if can_block { - handle_block_input(data, update) - } else { - false - } + in_buildup || interruptible + }; + let can_block = data.character.ability_info().and_then(|info| info.ability_meta).map_or(false, |meta| { + meta.capabilities + .contains(Capability::BLOCK_INTERRUPT) + }); + if can_dodge { + handle_dodge_input(data, update) + } else if can_block { + handle_block_input(data, update) } else { false } @@ -1358,6 +1346,9 @@ impl AbilityInfo { None }; + // If this ability should not be returned to, check if this ability was going to return to another ability, and return to that one instead + let return_ability = return_ability.or_else(|| char_state.ability_info().and_then(|info| info.return_ability)); + Self { tool: None, hand: None, diff --git a/common/systems/src/beam.rs b/common/systems/src/beam.rs index 1642ca7ee5..ed4a5718ff 100644 --- a/common/systems/src/beam.rs +++ b/common/systems/src/beam.rs @@ -229,6 +229,11 @@ impl<'a> System<'a> for Sys { energy: read_data.energies.get(target), }; + let target_dodging = read_data + .character_states + .get(target) + .and_then(|cs| cs.attack_immunities()) + .map_or(false, |i| i.beams); // PvP check let may_harm = combat::may_harm( &read_data.alignments, @@ -238,8 +243,7 @@ impl<'a> System<'a> for Sys { target, ); let attack_options = AttackOptions { - // No luck with dodging beams - target_dodging: false, + target_dodging, may_harm, target_group, }; diff --git a/common/systems/src/melee.rs b/common/systems/src/melee.rs index 2596bb5d34..335e85bcef 100644 --- a/common/systems/src/melee.rs +++ b/common/systems/src/melee.rs @@ -136,7 +136,8 @@ impl<'a> System<'a> for Sys { let target_dodging = read_data .char_states .get(target) - .map_or(false, |c_s| c_s.is_melee_dodge()); + .and_then(|cs| cs.attack_immunities()) + .map_or(false, |i| i.melee); // Check if it is a hit if attacker != target diff --git a/common/systems/src/projectile.rs b/common/systems/src/projectile.rs index 0865d40dd7..1ad2429316 100644 --- a/common/systems/src/projectile.rs +++ b/common/systems/src/projectile.rs @@ -307,10 +307,13 @@ fn dispatch_hit( target, ); + let target_dodging = read_data + .character_states + .get(target) + .and_then(|cs| cs.attack_immunities()) + .map_or(false, |i| i.projectiles); let attack_options = AttackOptions { - // They say witchers can dodge arrows, - // but we don't have witchers - target_dodging: false, + target_dodging, may_harm, target_group: projectile_target_info.target_group, }; diff --git a/common/systems/src/shockwave.rs b/common/systems/src/shockwave.rs index f0ad8268b3..4b740fbe15 100644 --- a/common/systems/src/shockwave.rs +++ b/common/systems/src/shockwave.rs @@ -211,6 +211,17 @@ impl<'a> System<'a> for Sys { energy: read_data.energies.get(target), }; + let target_dodging = read_data + .character_states + .get(target) + .and_then(|cs| cs.attack_immunities()) + .map_or(false, |i| { + if shockwave.requires_ground { + i.ground_shockwaves + } else { + i.air_shockwaves + } + }); // PvP check let may_harm = combat::may_harm( &read_data.alignments, @@ -220,8 +231,7 @@ impl<'a> System<'a> for Sys { target, ); let attack_options = AttackOptions { - // Trying roll during earthquake isn't the best idea - target_dodging: false, + target_dodging, may_harm, target_group, }; diff --git a/common/systems/src/stats.rs b/common/systems/src/stats.rs index a79df4702d..6d3c92ba41 100644 --- a/common/systems/src/stats.rs +++ b/common/systems/src/stats.rs @@ -9,6 +9,7 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::{DeltaTime, EntitiesDiedLastTick, Time}, + states, }; use common_ecs::{Job, Origin, Phase, System}; use specs::{ @@ -154,7 +155,11 @@ impl<'a> System<'a> for Sys { | CharacterState::GlideWield(_) | CharacterState::Wielding(_) | CharacterState::Equipping(_) - | CharacterState::Boost(_) => { + | CharacterState::Boost(_) + | CharacterState::ComboMelee2(states::combo_melee2::Data { + stage_section: None, + .. + }) => { let res = { energy.current() < energy.maximum() }; if res { diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index 5f7817cade..60830f84c9 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -1410,7 +1410,7 @@ impl<'a> AgentData<'a> { // Use shotgun if target close and have sufficient energy controller.push_basic_input(InputKind::Ability(0)); } else if self.body.map(|b| b.is_humanoid()).unwrap_or(false) - && self.energy.current() > CharacterAbility::default_roll().get_energy_cost() + && self.energy.current() > CharacterAbility::default_roll().energy_cost() && !matches!(self.char_state, CharacterState::BasicRanged(c) if !matches!(c.stage_section, StageSection::Recover)) { // Else roll away if can roll and have enough energy, and not using shotgun @@ -1536,10 +1536,10 @@ impl<'a> AgentData<'a> { CharacterAbility::BasicBeam { range, .. } => range, _ => 20.0_f32, }; - let shockwave_cost = shockwave.get_energy_cost(); + let shockwave_cost = shockwave.energy_cost(); if self.body.map_or(false, |b| b.is_humanoid()) && attack_data.in_min_range() - && self.energy.current() > CharacterAbility::default_roll().get_energy_cost() + && self.energy.current() > CharacterAbility::default_roll().energy_cost() && !matches!(self.char_state, CharacterState::Shockwave(_)) { // if a humanoid, have enough stamina, not in shockwave, and in melee range, @@ -1576,7 +1576,7 @@ impl<'a> AgentData<'a> { [ActionStateConditions::ConditionStaffCanShockwave as usize] = true; } } else if self.energy.current() - > shockwave_cost + CharacterAbility::default_roll().get_energy_cost() + > shockwave_cost + CharacterAbility::default_roll().energy_cost() && attack_data.dist_sqrd < flamethrower_range.powi(2) { controller.push_basic_input(InputKind::Secondary); @@ -1713,7 +1713,7 @@ impl<'a> AgentData<'a> { } } else if attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2) { if self.body.map_or(false, |b| b.is_humanoid()) - && self.energy.current() > CharacterAbility::default_roll().get_energy_cost() + && self.energy.current() > CharacterAbility::default_roll().energy_cost() && !matches!(self.char_state, CharacterState::BasicAura(c) if !matches!(c.stage_section, StageSection::Recover)) { // Else roll away if can roll and have enough energy, and not using aura or in @@ -3610,7 +3610,7 @@ impl<'a> AgentData<'a> { } } else if attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2) { if self.body.map_or(false, |b| b.is_humanoid()) - && self.energy.current() > CharacterAbility::default_roll().get_energy_cost() + && self.energy.current() > CharacterAbility::default_roll().energy_cost() && !matches!(self.char_state, CharacterState::BasicAura(c) if !matches!(c.stage_section, StageSection::Recover)) { // Else use steam beam diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 165be51adf..5b9a5f6569 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -543,16 +543,23 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3) let ecs = server.state.ecs(); if vel.z <= -30.0 { + let char_states = ecs.read_storage::(); + + let reduced_vel_z = if let Some(CharacterState::DiveMelee(c)) = char_states.get(entity) { + (vel.z + c.static_data.vertical_speed).min(0.0) + } else { + vel.z + }; + let mass = ecs .read_storage::() .get(entity) .copied() .unwrap_or_default(); - let impact_energy = mass.0 * vel.z.powi(2) / 2.0; + let impact_energy = mass.0 * reduced_vel_z.powi(2) / 2.0; let falldmg = impact_energy / 1000.0; let inventories = ecs.read_storage::(); - let char_states = ecs.read_storage::(); let stats = ecs.read_storage::(); let time = ecs.read_resource::