From 0ecf4fbe87f633127ad2f8f871259de66feeb50c Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 23 Apr 2023 01:47:31 -0400 Subject: [PATCH] Dual wielding weapons of the same kind added as a context --- .../common/abilities/ability_set_manifest.ron | 128 +++++++++--------- common/src/comp/inventory/item/tool.rs | 49 ++++--- common/src/states/utils.rs | 2 +- server/agent/src/attack.rs | 4 +- voxygen/src/hud/mod.rs | 4 +- voxygen/src/scene/figure/mod.rs | 2 +- 6 files changed, 103 insertions(+), 86 deletions(-) diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index 030c47f3a3..22e15d3238 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -5,92 +5,92 @@ Tool(Sword): ( primary: Contextualized( pseudo_id: "veloren.core.pseudo_abilities.sword.double_slash", - abilities: { - None: (None, "common.abilities.sword.basic_double_slash"), - Stance(Sword(Heavy)): (None, "common.abilities.sword.heavy_double_slash"), - Stance(Sword(Agile)): (None, "common.abilities.sword.agile_double_slash"), - Stance(Sword(Defensive)): (None, "common.abilities.sword.defensive_double_slash"), - Stance(Sword(Crippling)): (None, "common.abilities.sword.crippling_double_slash"), - Stance(Sword(Cleaving)): (None, "common.abilities.sword.cleaving_double_slash"), - }, + abilities: [ + ([Stance(Sword(Heavy))], (None, "common.abilities.sword.heavy_double_slash")), + ([Stance(Sword(Agile))], (None, "common.abilities.sword.agile_double_slash")), + ([Stance(Sword(Defensive))], (None, "common.abilities.sword.defensive_double_slash")), + ([Stance(Sword(Crippling))], (None, "common.abilities.sword.crippling_double_slash")), + ([Stance(Sword(Cleaving))], (None, "common.abilities.sword.cleaving_double_slash")), + ([], (None, "common.abilities.sword.basic_double_slash")), + ], ), secondary: Contextualized( pseudo_id: "veloren.core.pseudo_abilities.sword.secondary_ability", - abilities: { - None: (None, "common.abilities.sword.basic_thrust"), - Stance(Sword(Heavy)): (None, "common.abilities.sword.heavy_slam"), - Stance(Sword(Agile)): (None, "common.abilities.sword.agile_perforate"), - Stance(Sword(Defensive)): (None, "common.abilities.sword.defensive_vital_jab"), - Stance(Sword(Crippling)): (None, "common.abilities.sword.crippling_deep_rend"), - Stance(Sword(Cleaving)): (None, "common.abilities.sword.cleaving_spiral_slash"), - }, + abilities: [ + ([Stance(Sword(Heavy))], (None, "common.abilities.sword.heavy_slam")), + ([Stance(Sword(Agile))], (None, "common.abilities.sword.agile_perforate")), + ([Stance(Sword(Defensive))], (None, "common.abilities.sword.defensive_vital_jab")), + ([Stance(Sword(Crippling))], (None, "common.abilities.sword.crippling_deep_rend")), + ([Stance(Sword(Cleaving))], (None, "common.abilities.sword.cleaving_spiral_slash")), + ([], (None, "common.abilities.sword.basic_thrust")), + ], ), abilities: [ Contextualized( pseudo_id: "veloren.core.pseudo_abilities.sword.crescent_slash", - abilities: { - None: (Sword(CrescentSlash), "common.abilities.sword.basic_crescent_slash"), - Stance(Sword(Heavy)): (Sword(CrescentSlash), "common.abilities.sword.heavy_crescent_slash"), - Stance(Sword(Agile)): (Sword(CrescentSlash), "common.abilities.sword.agile_crescent_slash"), - Stance(Sword(Defensive)): (Sword(CrescentSlash), "common.abilities.sword.defensive_crescent_slash"), - Stance(Sword(Crippling)): (Sword(CrescentSlash), "common.abilities.sword.crippling_crescent_slash"), - Stance(Sword(Cleaving)): (Sword(CrescentSlash), "common.abilities.sword.cleaving_crescent_slash"), - }, + abilities: [ + ([Stance(Sword(Heavy))], (Sword(CrescentSlash), "common.abilities.sword.heavy_crescent_slash")), + ([Stance(Sword(Agile))], (Sword(CrescentSlash), "common.abilities.sword.agile_crescent_slash")), + ([Stance(Sword(Defensive))], (Sword(CrescentSlash), "common.abilities.sword.defensive_crescent_slash")), + ([Stance(Sword(Crippling))], (Sword(CrescentSlash), "common.abilities.sword.crippling_crescent_slash")), + ([Stance(Sword(Cleaving))], (Sword(CrescentSlash), "common.abilities.sword.cleaving_crescent_slash")), + ([], (Sword(CrescentSlash), "common.abilities.sword.basic_crescent_slash")), + ], ), Contextualized( pseudo_id: "veloren.core.pseudo_abilities.sword.fell_strike", - abilities: { - None: (Sword(FellStrike), "common.abilities.sword.basic_fell_strike"), - Stance(Sword(Heavy)): (Sword(FellStrike), "common.abilities.sword.heavy_fell_strike"), - Stance(Sword(Agile)): (Sword(FellStrike), "common.abilities.sword.agile_fell_strike"), - Stance(Sword(Defensive)): (Sword(FellStrike), "common.abilities.sword.defensive_fell_strike"), - Stance(Sword(Crippling)): (Sword(FellStrike), "common.abilities.sword.crippling_fell_strike"), - Stance(Sword(Cleaving)): (Sword(FellStrike), "common.abilities.sword.cleaving_fell_strike"), - }, + abilities: [ + ([Stance(Sword(Heavy))], (Sword(FellStrike), "common.abilities.sword.heavy_fell_strike")), + ([Stance(Sword(Agile))], (Sword(FellStrike), "common.abilities.sword.agile_fell_strike")), + ([Stance(Sword(Defensive))], (Sword(FellStrike), "common.abilities.sword.defensive_fell_strike")), + ([Stance(Sword(Crippling))], (Sword(FellStrike), "common.abilities.sword.crippling_fell_strike")), + ([Stance(Sword(Cleaving))], (Sword(FellStrike), "common.abilities.sword.cleaving_fell_strike")), + ([], (Sword(FellStrike), "common.abilities.sword.basic_fell_strike")), + ], ), Contextualized( pseudo_id: "veloren.core.pseudo_abilities.sword.skewer", - abilities: { - None: (Sword(Skewer), "common.abilities.sword.basic_skewer"), - Stance(Sword(Heavy)): (Sword(Skewer), "common.abilities.sword.heavy_skewer"), - Stance(Sword(Agile)): (Sword(Skewer), "common.abilities.sword.agile_skewer"), - Stance(Sword(Defensive)): (Sword(Skewer), "common.abilities.sword.defensive_skewer"), - Stance(Sword(Crippling)): (Sword(Skewer), "common.abilities.sword.crippling_skewer"), - Stance(Sword(Cleaving)): (Sword(Skewer), "common.abilities.sword.cleaving_skewer"), - }, + abilities: [ + ([Stance(Sword(Heavy))], (Sword(Skewer), "common.abilities.sword.heavy_skewer")), + ([Stance(Sword(Agile))], (Sword(Skewer), "common.abilities.sword.agile_skewer")), + ([Stance(Sword(Defensive))], (Sword(Skewer), "common.abilities.sword.defensive_skewer")), + ([Stance(Sword(Crippling))], (Sword(Skewer), "common.abilities.sword.crippling_skewer")), + ([Stance(Sword(Cleaving))], (Sword(Skewer), "common.abilities.sword.cleaving_skewer")), + ([], (Sword(Skewer), "common.abilities.sword.basic_skewer")), + ], ), Contextualized( pseudo_id: "veloren.core.pseudo_abilities.sword.cascade", - abilities: { - None: (Sword(Cascade), "common.abilities.sword.basic_cascade"), - Stance(Sword(Heavy)): (Sword(Cascade), "common.abilities.sword.heavy_cascade"), - Stance(Sword(Agile)): (Sword(Cascade), "common.abilities.sword.agile_cascade"), - Stance(Sword(Defensive)): (Sword(Cascade), "common.abilities.sword.defensive_cascade"), - Stance(Sword(Crippling)): (Sword(Cascade), "common.abilities.sword.crippling_cascade"), - Stance(Sword(Cleaving)): (Sword(Cascade), "common.abilities.sword.cleaving_cascade"), - }, + abilities: [ + ([Stance(Sword(Heavy))], (Sword(Cascade), "common.abilities.sword.heavy_cascade")), + ([Stance(Sword(Agile))], (Sword(Cascade), "common.abilities.sword.agile_cascade")), + ([Stance(Sword(Defensive))], (Sword(Cascade), "common.abilities.sword.defensive_cascade")), + ([Stance(Sword(Crippling))], (Sword(Cascade), "common.abilities.sword.crippling_cascade")), + ([Stance(Sword(Cleaving))], (Sword(Cascade), "common.abilities.sword.cleaving_cascade")), + ([], (Sword(Cascade), "common.abilities.sword.basic_cascade")), + ], ), Contextualized( pseudo_id: "veloren.core.pseudo_abilities.sword.cross_cut", - abilities: { - None: (Sword(CrossCut), "common.abilities.sword.basic_cross_cut"), - Stance(Sword(Heavy)): (Sword(CrossCut), "common.abilities.sword.heavy_cross_cut"), - Stance(Sword(Agile)): (Sword(CrossCut), "common.abilities.sword.agile_cross_cut"), - Stance(Sword(Defensive)): (Sword(CrossCut), "common.abilities.sword.defensive_cross_cut"), - Stance(Sword(Crippling)): (Sword(CrossCut), "common.abilities.sword.crippling_cross_cut"), - Stance(Sword(Cleaving)): (Sword(CrossCut), "common.abilities.sword.cleaving_cross_cut"), - }, + abilities: [ + ([Stance(Sword(Heavy))], (Sword(CrossCut), "common.abilities.sword.heavy_cross_cut")), + ([Stance(Sword(Agile))], (Sword(CrossCut), "common.abilities.sword.agile_cross_cut")), + ([Stance(Sword(Defensive))], (Sword(CrossCut), "common.abilities.sword.defensive_cross_cut")), + ([Stance(Sword(Crippling))], (Sword(CrossCut), "common.abilities.sword.crippling_cross_cut")), + ([Stance(Sword(Cleaving))], (Sword(CrossCut), "common.abilities.sword.cleaving_cross_cut")), + ([], (Sword(CrossCut), "common.abilities.sword.basic_cross_cut")), + ], ), Contextualized( pseudo_id: "veloren.core.pseudo_abilities.sword.finisher", - abilities: { - None: (Sword(Finisher), "common.abilities.sword.basic_mighty_strike"), - Stance(Sword(Heavy)): (Sword(Finisher), "common.abilities.sword.heavy_guillotine"), - Stance(Sword(Agile)): (Sword(Finisher), "common.abilities.sword.agile_hundred_cuts"), - Stance(Sword(Defensive)): (Sword(Finisher), "common.abilities.sword.defensive_counter"), - Stance(Sword(Crippling)): (Sword(Finisher), "common.abilities.sword.crippling_mutilate"), - Stance(Sword(Cleaving)): (Sword(Finisher), "common.abilities.sword.cleaving_bladestorm"), - }, + abilities: [ + ([Stance(Sword(Heavy))], (Sword(Finisher), "common.abilities.sword.heavy_guillotine")), + ([Stance(Sword(Agile))], (Sword(Finisher), "common.abilities.sword.agile_hundred_cuts")), + ([Stance(Sword(Defensive))], (Sword(Finisher), "common.abilities.sword.defensive_counter")), + ([Stance(Sword(Crippling))], (Sword(Finisher), "common.abilities.sword.crippling_mutilate")), + ([Stance(Sword(Cleaving))], (Sword(Finisher), "common.abilities.sword.cleaving_bladestorm")), + ([], (Sword(Finisher), "common.abilities.sword.basic_mighty_strike")), + ], ), Simple(Sword(HeavySweep), "common.abilities.sword.heavy_sweep"), Simple(Sword(HeavyPommelStrike), "common.abilities.sword.heavy_pommel_strike"), diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 5b934b1212..be676d8dde 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -4,7 +4,14 @@ use crate::{ assets::{self, Asset, AssetExt, AssetHandle}, comp::{ - ability::Stance, item::DurabilityMultiplier, skills::Skill, CharacterAbility, SkillSet, + ability::Stance, + inventory::{ + item::{DurabilityMultiplier, ItemKind}, + slot::EquipSlot, + Inventory, + }, + skills::Skill, + CharacterAbility, SkillSet, }, }; use hashbrown::HashMap; @@ -347,20 +354,15 @@ impl AbilityKind { AbilityKind::Contextualized { pseudo_id: _, abilities, - } => { - // In the event that the ability from the current context is not unlocked with - // the required skill, try falling back to the ability from this input that does - // not require a context - abilities - .iter() - .find_map(|(req_contexts, (s, a))| { - req_contexts - .iter() - .all(|req| contexts.contains(req)) - .then_some((s, a)) - }) - .and_then(|(s, a)| unlocked(*s, a)) - }, + } => abilities + .iter() + .filter_map(|(req_contexts, (s, a))| unlocked(*s, a).map(|a| (req_contexts, a))) + .find_map(|(req_contexts, a)| { + req_contexts + .iter() + .all(|req| contexts.contains(req)) + .then_some(a) + }), } } } @@ -372,16 +374,31 @@ pub enum AbilityContext { /// `AbilityContext::Stance(Stance::None)` in the ability map config /// files(s). Stance(Stance), + DualWieldingSameKind, } impl AbilityContext { - pub fn from(stance: Option<&Stance>) -> Vec { + pub fn from(stance: Option<&Stance>, inv: Option<&Inventory>) -> Vec { let mut contexts = Vec::new(); match stance { Some(Stance::None) => {}, Some(stance) => contexts.push(AbilityContext::Stance(*stance)), None => {}, } + if let Some(inv) = inv { + let tool_kind = |slot| { + inv.equipped(slot).and_then(|i| { + if let ItemKind::Tool(tool) = &*i.kind() { + Some(tool.kind) + } else { + None + } + }) + }; + if tool_kind(EquipSlot::ActiveMainhand) == tool_kind(EquipSlot::ActiveOffhand) { + contexts.push(AbilityContext::DualWieldingSameKind) + } + } contexts } } diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 58a8bab895..43d759d177 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -1107,7 +1107,7 @@ fn handle_ability( output_events: &mut OutputEvents, input: InputKind, ) -> bool { - let contexts = AbilityContext::from(data.stance); + let contexts = AbilityContext::from(data.stance, data.inventory); if let Some(ability_input) = input.into() { if let Some((ability, from_offhand)) = data .active_abilities diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index c6d6850c98..3b1ca27cb5 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -757,7 +757,7 @@ impl<'a> AgentData<'a> { ); let attack_failed = if attempt_attack { - let contexts = AbilityContext::from(self.stance); + let contexts = AbilityContext::from(self.stance, Some(self.inventory)); let extract_ability = |input: AbilityInput| { AbilityData::from_ability( &self @@ -1437,7 +1437,7 @@ impl<'a> AgentData<'a> { enum ActionStateConditions { ConditionStaffCanShockwave = 0, } - let contexts = AbilityContext::from(self.stance); + let contexts = AbilityContext::from(self.stance, Some(self.inventory)); let extract_ability = |input: AbilityInput| { self.active_abilities .activate_ability( diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index c1ee1ef4ac..95e0a9b7b0 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -3018,7 +3018,7 @@ impl Hud { bodies.get(entity), ) { let stance = stances.get(entity); - let contexts = AbilityContext::from(stance); + let contexts = AbilityContext::from(stance, Some(inventory)); match Skillbar::new( client, &info, @@ -3522,7 +3522,7 @@ impl Hud { bodies.get(entity), poises.get(entity), ) { - let contexts = AbilityContext::from(stances.get(entity)); + let contexts = AbilityContext::from(stances.get(entity), Some(inventory)); for event in Diary::new( &self.show, client, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 4133c9f5fb..ba4aae6a1f 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -931,7 +931,7 @@ impl FigureMgr { let second_tool_spec = second_tool_spec.as_deref(); let hands = (active_tool_hand, second_tool_hand); - let contexts = AbilityContext::from(stance); + let contexts = AbilityContext::from(stance, inventory); let ability_id = character.and_then(|c| { c.ability_info()