From 90f3b671c39bfb357711a6e0a04d4ea262c9f17d Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 24 Feb 2024 13:05:18 -0500 Subject: [PATCH] Breach --- .../common/abilities/ability_set_manifest.ron | 2 +- assets/common/abilities/hammer/breach.ron | 21 +++++++++++++++++++ .../voxygen/element/skills/hammer/breach.png | 3 +++ assets/voxygen/i18n/en/hud/ability.ftl | 3 +++ common/src/combat.rs | 13 +++++++++++- common/src/comp/ability.rs | 1 + common/src/comp/melee.rs | 4 ++++ common/systems/src/beam.rs | 1 + common/systems/src/melee.rs | 1 + common/systems/src/projectile.rs | 2 +- voxygen/anim/src/character/alpha.rs | 21 +++++++++++++++++++ .../audio/sfx/event_mapper/combat/tests.rs | 1 + voxygen/src/hud/img_ids.rs | 1 + voxygen/src/hud/util.rs | 1 + 14 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 assets/common/abilities/hammer/breach.ron create mode 100644 assets/voxygen/element/skills/hammer/breach.png diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index ac2a77a4ce..a11122f77a 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -201,7 +201,7 @@ Simple(Hammer(VigorousBash), "common.abilities.hammer.vigorous_bash"), Simple(Hammer(Retaliate), "common.abilities.hammer.retaliate"), Simple(Hammer(SpineCracker), "common.abilities.hammer.spine_cracker"), - // Simple(Hammer(Breach), "common.abilities.hammer.breach"), + Simple(Hammer(Breach), "common.abilities.hammer.breach"), // Contextualized( // pseudo_id: "common.abilities.hammer.iron_tempest", // abilities: [ diff --git a/assets/common/abilities/hammer/breach.ron b/assets/common/abilities/hammer/breach.ron new file mode 100644 index 0000000000..38fba8b8be --- /dev/null +++ b/assets/common/abilities/hammer/breach.ron @@ -0,0 +1,21 @@ +BasicMelee( + energy_cost: 20, + buildup_duration: 0.4, + swing_duration: 0.1, + hit_timing: 0.5, + recover_duration: 0.2, + melee_constructor: ( + kind: Bash( + damage: 15, + poise: 20, + knockback: 0, + energy_regen: 0, + ), + range: 3.0, + angle: 15.0, + attack_effect: Some((Poise(40), TargetBlocking)), + precision_flank_multiplier: 1.5, + precision_flank_invert: true, + ), + ori_modifier: 0.6, +) \ No newline at end of file diff --git a/assets/voxygen/element/skills/hammer/breach.png b/assets/voxygen/element/skills/hammer/breach.png new file mode 100644 index 0000000000..1ce4087c1b --- /dev/null +++ b/assets/voxygen/element/skills/hammer/breach.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8a793dc16d7d97b5ef81e8eaef5c27326c41ab8cb97ae0a5566be1f4f4cb042 +size 1106 diff --git a/assets/voxygen/i18n/en/hud/ability.ftl b/assets/voxygen/i18n/en/hud/ability.ftl index ecf1ac2555..d46c4d636c 100644 --- a/assets/voxygen/i18n/en/hud/ability.ftl +++ b/assets/voxygen/i18n/en/hud/ability.ftl @@ -410,4 +410,7 @@ common-abilities-hammer-retaliate = Retaliate common-abilities-hammer-spine_cracker = Spine Cracker .desc = When you foe turns their back to you, strike them hard in the back, targeting the weak part of their spine. +common-abilities-hammer-breach = Breach + .desc = + Breach through your enemy's attempt at defense with a heavy strike from your hammer. diff --git a/common/src/combat.rs b/common/src/combat.rs index 06b0efe7e3..079bf82dd5 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -663,6 +663,9 @@ impl Attack { false } }, + CombatRequirement::TargetBlocking => target.char_state.map_or(false, |cs| { + cs.is_block(attack_source) || cs.is_parry(attack_source) + }), }); if requirements_met { is_applied = true; @@ -1023,6 +1026,7 @@ pub enum CombatRequirement { TargetHasBuff(BuffKind), TargetPoised, BehindTarget, + TargetBlocking, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] @@ -1643,8 +1647,15 @@ pub fn precision_mult_from_flank( attack_dir: Vec3, target_ori: Option<&Ori>, precision_flank_multiplier: f32, + precision_flank_invert: bool, ) -> Option { - let angle = target_ori.map(|t_ori| t_ori.look_dir().angle_between(attack_dir)); + let angle = target_ori.map(|t_ori| { + t_ori.look_dir().angle_between(if precision_flank_invert { + -attack_dir + } else { + attack_dir + }) + }); match angle { Some(angle) if angle < FULL_FLANK_ANGLE => { Some(MAX_BACK_FLANK_PRECISION * precision_flank_multiplier) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index d6fbef19b6..d1c1f5e194 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1114,6 +1114,7 @@ impl Default for CharacterAbility { simultaneous_hits: 1, custom_combo: None, precision_flank_multiplier: 1.0, + precision_flank_invert: false, }, ori_modifier: 1.0, frontend_specifier: None, diff --git a/common/src/comp/melee.rs b/common/src/comp/melee.rs index f808e8d35d..7efa21c480 100644 --- a/common/src/comp/melee.rs +++ b/common/src/comp/melee.rs @@ -24,6 +24,7 @@ pub struct Melee { pub break_block: Option<(Vec3, Option)>, pub simultaneous_hits: u32, pub precision_flank_multiplier: f32, + pub precision_flank_invert: bool, } #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -81,6 +82,8 @@ pub struct MeleeConstructor { pub custom_combo: Option, #[serde(default = "default_precision_flank_multiplier")] pub precision_flank_multiplier: f32, + #[serde(default)] + pub precision_flank_invert: bool, } #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -391,6 +394,7 @@ impl MeleeConstructor { break_block: None, simultaneous_hits: self.simultaneous_hits, precision_flank_multiplier: self.precision_flank_multiplier, + precision_flank_invert: self.precision_flank_invert, } } diff --git a/common/systems/src/beam.rs b/common/systems/src/beam.rs index a2e24b837f..74cc61671e 100644 --- a/common/systems/src/beam.rs +++ b/common/systems/src/beam.rs @@ -264,6 +264,7 @@ impl<'a> System<'a> for Sys { beam.bezier.ctrl - beam.bezier.start, target_info.ori, 1.0, + false, ); let precision_from_time = { diff --git a/common/systems/src/melee.rs b/common/systems/src/melee.rs index 30c6af5fa9..215e21b954 100644 --- a/common/systems/src/melee.rs +++ b/common/systems/src/melee.rs @@ -249,6 +249,7 @@ impl<'a> System<'a> for Sys { .unwrap_or(ori.look_vec()), target_ori, melee_attack.precision_flank_multiplier, + melee_attack.precision_flank_invert, ); let precision_from_poise = { diff --git a/common/systems/src/projectile.rs b/common/systems/src/projectile.rs index e5e4c818b3..55741cc5cd 100644 --- a/common/systems/src/projectile.rs +++ b/common/systems/src/projectile.rs @@ -390,7 +390,7 @@ fn dispatch_hit( .map_or(false, |i| i.projectiles); let precision_from_flank = - combat::precision_mult_from_flank(*projectile_dir, target_info.ori, 1.0); + combat::precision_mult_from_flank(*projectile_dir, target_info.ori, 1.0, false); let precision_from_head = { // This performs a cylinder and line segment intersection check. The cylinder is diff --git a/voxygen/anim/src/character/alpha.rs b/voxygen/anim/src/character/alpha.rs index 21b5e9cf91..4379bea5ab 100644 --- a/voxygen/anim/src/character/alpha.rs +++ b/voxygen/anim/src/character/alpha.rs @@ -133,6 +133,27 @@ impl Animation for AlphaAnimation { next.control_l.orientation.rotate_z(move2 * -2.3); next.control_r.orientation.rotate_z(move2 * -2.3); }, + Some("common.abilities.hammer.breach") => { + hammer_start(&mut next, s_a); + let (move1, move2, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time, 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let move1 = move1 * pullback; + let move2 = move2 * pullback; + + next.control.orientation.rotate_x(move1 * 2.5); + next.control.orientation.rotate_z(move1 * -4.8); + next.control.position += Vec3::new(-12.0, 0.0, 22.0) * move1; + twist_back(&mut next, move1, 0.6, 0.2, 0.0, 0.3); + + twist_forward(&mut next, move2, 1.6, 0.4, 0.2, 0.7); + next.control.orientation.rotate_x(move2 * -4.5); + next.control.position += Vec3::new(0.0, 0.0, -20.0) * move2; + }, _ => { let (move1, move2, _move3, move2h) = match stage_section { Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0, 0.0), diff --git a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs index 0dcd6e2e1d..e7a494f1de 100644 --- a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs @@ -91,6 +91,7 @@ fn maps_basic_melee() { simultaneous_hits: 1, custom_combo: None, precision_flank_multiplier: 1.0, + precision_flank_invert: false, }, ori_modifier: 1.0, ability_info: empty_ability_info(), diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index d335a632c9..916fd79d1c 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -324,6 +324,7 @@ image_ids! { hammer_intercept: "voxygen.element.skills.hammer.intercept", hammer_retaliate: "voxygen.element.skills.hammer.retaliate", hammer_spine_cracker: "voxygen.element.skills.hammer.spine_cracker", + hammer_breach: "voxygen.element.skills.hammer.breach", // Skilltree Icons health_plus_skill: "voxygen.element.skills.skilltree.health_plus", energy_plus_skill: "voxygen.element.skills.skilltree.energy_plus", diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index 4519afac59..755ef5ba05 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -633,6 +633,7 @@ pub fn ability_image(imgs: &img_ids::Imgs, ability_id: &str) -> image::Id { "common.abilities.hammer.dual_intercept" => imgs.hammer_intercept, "common.abilities.hammer.retaliate" => imgs.hammer_retaliate, "common.abilities.hammer.spine_cracker" => imgs.hammer_spine_cracker, + "common.abilities.hammer.breach" => imgs.hammer_breach, // Bow "common.abilities.bow.charged" => imgs.bow_m1, "common.abilities.bow.repeater" => imgs.bow_m2,