From b376228d45f3e1c72127ad37a537c8b398e4c2d0 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 30 Oct 2022 14:40:20 -0400 Subject: [PATCH] Primary and secondary abilities can now be contextual. BasicStance character state added. --- .../common/abilities/ability_set_manifest.ron | 372 +++++++++--------- .../common/abilities/sword/balanced_combo.ron | 1 - .../common/abilities/sword/cleaving_combo.ron | 2 - .../common/abilities/sword/cleaving_spin.ron | 1 - .../abilities/sword/cleaving_stance.ron | 4 + .../abilities/sword/crippling_combo.ron | 2 - .../abilities/sword/crippling_gouge.ron | 1 - .../abilities/sword/crippling_stance.ron | 4 + .../abilities/sword/crippling_strike.ron | 1 - .../abilities/sword/defensive_combo.ron | 2 - .../abilities/sword/defensive_retreat.ron | 1 - .../abilities/sword/defensive_stance.ron | 4 + assets/common/abilities/sword/heavy_combo.ron | 2 - .../abilities/sword/heavy_pommelstrike.ron | 1 - .../common/abilities/sword/heavy_stance.ron | 4 + .../common/abilities/sword/mobility_combo.ron | 2 - .../common/abilities/sword/mobility_feint.ron | 1 - .../abilities/sword/mobility_stance.ron | 4 + .../abilities/sword/offensive_advance.ron | 1 - .../abilities/sword/offensive_combo.ron | 2 - .../abilities/sword/offensive_stance.ron | 4 + .../common/abilities/sword/parrying_combo.ron | 2 - .../abilities/sword/parrying_counter.ron | 1 - .../abilities/sword/parrying_stance.ron | 4 + .../common/abilities/sword/reaching_combo.ron | 2 - .../abilities/sword/reaching_skewer.ron | 1 - .../abilities/sword/reaching_stance.ron | 4 + .../skill_trees/skill_prerequisites.ron | 52 +-- .../skills_skill-groups_manifest.ron | 16 +- assets/common/skillset/preset/rank2/sword.ron | 6 +- assets/common/skillset/preset/rank3/sword.ron | 6 +- assets/common/skillset/preset/rank4/sword.ron | 16 +- assets/common/skillset/preset/rank5/sword.ron | 16 +- assets/server/manifests/presets.ron | 16 +- assets/voxygen/i18n/en/hud/ability.ftl | 16 + common/src/combat.rs | 2 +- common/src/comp/ability.rs | 153 ++++--- common/src/comp/character_state.rs | 47 +-- common/src/comp/inventory/item/tool.rs | 69 ++-- common/src/comp/poise.rs | 9 +- common/src/comp/skillset/skills.rs | 16 +- common/src/states/basic_beam.rs | 6 +- common/src/states/basic_block.rs | 6 +- common/src/states/basic_melee.rs | 16 +- common/src/states/basic_ranged.rs | 16 +- common/src/states/basic_stance.rs | 52 +++ common/src/states/boost.rs | 16 +- common/src/states/charged_melee.rs | 12 +- common/src/states/charged_ranged.rs | 21 +- common/src/states/combo_melee.rs | 20 +- common/src/states/combo_melee2.rs | 246 +----------- common/src/states/dash_melee.rs | 12 +- common/src/states/mod.rs | 1 + common/src/states/music.rs | 23 +- common/src/states/repeater_ranged.rs | 6 +- common/src/states/spin_melee.rs | 6 +- common/src/states/sprite_interact.rs | 2 - common/src/states/stunned.rs | 2 - common/src/states/use_item.rs | 6 +- common/src/states/utils.rs | 112 ++---- common/systems/src/character_behavior.rs | 5 +- common/systems/src/stats.rs | 10 +- server/agent/src/attack.rs | 8 +- server/src/events/entity_manipulation.rs | 22 +- voxygen/src/hud/diary.rs | 20 +- voxygen/src/hud/mod.rs | 4 +- voxygen/src/hud/skillbar.rs | 4 +- voxygen/src/hud/slots.rs | 4 +- voxygen/src/hud/util.rs | 8 + voxygen/src/scene/figure/mod.rs | 90 ++--- 70 files changed, 673 insertions(+), 953 deletions(-) create mode 100644 assets/common/abilities/sword/cleaving_stance.ron create mode 100644 assets/common/abilities/sword/crippling_stance.ron create mode 100644 assets/common/abilities/sword/defensive_stance.ron create mode 100644 assets/common/abilities/sword/heavy_stance.ron create mode 100644 assets/common/abilities/sword/mobility_stance.ron create mode 100644 assets/common/abilities/sword/offensive_stance.ron create mode 100644 assets/common/abilities/sword/parrying_stance.ron create mode 100644 assets/common/abilities/sword/reaching_stance.ron create mode 100644 common/src/states/basic_stance.rs diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index 7ae109b5e3..b54db14881 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -2,20 +2,30 @@ // A set of abilities is a primary, a secondary, and a vec of all extra abilities ({ Tool(Sword): ( - primary: "common.abilities.sword.balanced_combo", - secondary: "common.abilities.sword.balanced_thrust", + primary: Contextualized({ + None: (None, "common.abilities.sword.balanced_combo"), + Stance(Sword(Offensive)): (Some(Sword(OffensiveStance)), "common.abilities.sword.offensive_combo"), + Stance(Sword(Crippling)): (Some(Sword(CripplingStance)), "common.abilities.sword.crippling_combo"), + Stance(Sword(Cleaving)): (Some(Sword(CleavingStance)), "common.abilities.sword.cleaving_combo"), + Stance(Sword(Defensive)): (Some(Sword(DefensiveStance)), "common.abilities.sword.defensive_combo"), + Stance(Sword(Parrying)): (Some(Sword(ParryingStance)), "common.abilities.sword.parrying_combo"), + Stance(Sword(Heavy)): (Some(Sword(HeavyStance)), "common.abilities.sword.heavy_combo"), + Stance(Sword(Mobility)): (Some(Sword(MobilityStance)), "common.abilities.sword.mobility_combo"), + Stance(Sword(Reaching)): (Some(Sword(ReachingStance)), "common.abilities.sword.reaching_combo"), + }), + secondary: Simple(None, "common.abilities.sword.balanced_thrust"), abilities: [ - Simple(Some(Sword(OffensiveCombo)), "common.abilities.sword.offensive_combo"), - Simple(Some(Sword(CripplingCombo)), "common.abilities.sword.crippling_combo"), - Simple(Some(Sword(CleavingCombo)), "common.abilities.sword.cleaving_combo"), - Simple(Some(Sword(DefensiveCombo)), "common.abilities.sword.defensive_combo"), - Simple(Some(Sword(ParryingCombo)), "common.abilities.sword.parrying_combo"), - Simple(Some(Sword(HeavyCombo)), "common.abilities.sword.heavy_combo"), - Simple(Some(Sword(MobilityCombo)), "common.abilities.sword.mobility_combo"), - Simple(Some(Sword(ReachingCombo)), "common.abilities.sword.reaching_combo"), + Simple(Some(Sword(OffensiveStance)), "common.abilities.sword.offensive_stance"), + Simple(Some(Sword(CripplingStance)), "common.abilities.sword.crippling_stance"), + Simple(Some(Sword(CleavingStance)), "common.abilities.sword.cleaving_stance"), + Simple(Some(Sword(DefensiveStance)), "common.abilities.sword.defensive_stance"), + Simple(Some(Sword(ParryingStance)), "common.abilities.sword.parrying_stance"), + Simple(Some(Sword(HeavyStance)), "common.abilities.sword.heavy_stance"), + Simple(Some(Sword(MobilityStance)), "common.abilities.sword.mobility_stance"), + Simple(Some(Sword(ReachingStance)), "common.abilities.sword.reaching_stance"), // Damagey ones Contextualized({ - Stance(None): (Some(Sword(BalancedFinisher)), "common.abilities.sword.balanced_finisher"), + None: (Some(Sword(BalancedFinisher)), "common.abilities.sword.balanced_finisher"), Stance(Sword(Offensive)): (Some(Sword(OffensiveFinisher)), "common.abilities.sword.offensive_finisher"), Stance(Sword(Crippling)): (Some(Sword(CripplingFinisher)), "common.abilities.sword.crippling_finisher"), Stance(Sword(Cleaving)): (Some(Sword(CleavingFinisher)), "common.abilities.sword.cleaving_finisher"), @@ -47,79 +57,79 @@ ], ), Tool(Axe): ( - primary: "common.abilities.axe.doublestrike", - secondary: "common.abilities.axe.spin", + primary: Simple(None, "common.abilities.axe.doublestrike"), + secondary: Simple(None, "common.abilities.axe.spin"), abilities: [ Simple(Some(Axe(UnlockLeap)), "common.abilities.axe.leap"), ], ), Tool(Hammer): ( - primary: "common.abilities.hammer.singlestrike", - secondary: "common.abilities.hammer.charged", + primary: Simple(None, "common.abilities.hammer.singlestrike"), + secondary: Simple(None, "common.abilities.hammer.charged"), abilities: [ Simple(Some(Hammer(UnlockLeap)), "common.abilities.hammer.leap"), ], ), Tool(Bow): ( - primary: "common.abilities.bow.charged", - secondary: "common.abilities.bow.repeater", + primary: Simple(None, "common.abilities.bow.charged"), + secondary: Simple(None, "common.abilities.bow.repeater"), abilities: [ Simple(Some(Bow(UnlockShotgun)), "common.abilities.bow.shotgun"), ], ), Tool(Staff): ( - primary: "common.abilities.staff.firebomb", - secondary: "common.abilities.staff.flamethrower", + primary: Simple(None, "common.abilities.staff.firebomb"), + secondary: Simple(None, "common.abilities.staff.flamethrower"), abilities: [ Simple(Some(Staff(UnlockShockwave)), "common.abilities.staff.fireshockwave"), ], ), Tool(Sceptre): ( - primary: "common.abilities.sceptre.lifestealbeam", - secondary: "common.abilities.sceptre.healingaura", + primary: Simple(None, "common.abilities.sceptre.lifestealbeam"), + secondary: Simple(None, "common.abilities.sceptre.healingaura"), abilities: [ Simple(Some(Sceptre(UnlockAura)), "common.abilities.sceptre.wardingaura"), ], ), Custom("Husk"): ( - primary: "common.abilities.custom.husk.singlestrike", - secondary: "common.abilities.custom.husk.triplestrike", + primary: Simple(None, "common.abilities.custom.husk.singlestrike"), + secondary: Simple(None, "common.abilities.custom.husk.triplestrike"), abilities: [], ), Custom("Husk Brute"): ( - primary: "common.abilities.custom.husk_brute.singlestrike", - secondary: "common.abilities.custom.husk_brute.chargedmelee", + primary: Simple(None, "common.abilities.custom.husk_brute.singlestrike"), + secondary: Simple(None, "common.abilities.custom.husk_brute.chargedmelee"), abilities: [], ), Tool(Spear): ( - primary: "common.abilities.spear.doublestrike", - secondary: "common.abilities.spear.dash", + primary: Simple(None, "common.abilities.spear.doublestrike"), + secondary: Simple(None, "common.abilities.spear.dash"), abilities: [], ), Custom("Hammer Simple"): ( - primary: "common.abilities.hammersimple.doublestrike", - secondary: "common.abilities.hammersimple.doublestrike", + primary: Simple(None, "common.abilities.hammersimple.doublestrike"), + secondary: Simple(None, "common.abilities.hammersimple.doublestrike"), abilities: [], ), // TODO: Later investigate if we want to make this back to a simple axe when more things need a simpler axe ability set Custom("Gnarling Axe"): ( - primary: "common.abilities.gnarling.axe.chop", - secondary: "common.abilities.gnarling.axe.chop", + primary: Simple(None, "common.abilities.gnarling.axe.chop"), + secondary: Simple(None, "common.abilities.gnarling.axe.chop"), abilities: [], ), Custom("Gnarling Dagger"): ( - primary: "common.abilities.gnarling.dagger.stab", - secondary: "common.abilities.gnarling.dagger.stab", + primary: Simple(None, "common.abilities.gnarling.dagger.stab"), + secondary: Simple(None, "common.abilities.gnarling.dagger.stab"), abilities: [], ), Custom("Gnarling Blowgun"): ( - primary: "common.abilities.gnarling.blowgun.dart", - secondary: "common.abilities.gnarling.blowgun.dart", + primary: Simple(None, "common.abilities.gnarling.blowgun.dart"), + secondary: Simple(None, "common.abilities.gnarling.blowgun.dart"), abilities: [], ), Custom("Gnarling Chieftain"): ( - primary: "common.abilities.gnarling.chieftain.flamestrike", - secondary: "common.abilities.gnarling.chieftain.firebarrage", + primary: Simple(None, "common.abilities.gnarling.chieftain.flamestrike"), + secondary: Simple(None, "common.abilities.gnarling.chieftain.firebarrage"), abilities: [ Simple(None, "common.abilities.gnarling.chieftain.fireshockwave"), Simple(None, "common.abilities.gnarling.chieftain.redtotem"), @@ -128,87 +138,87 @@ ], ), Custom("Gnarling Totem Red"): ( - primary: "common.abilities.gnarling.totem.red", - secondary: "common.abilities.gnarling.totem.red", + primary: Simple(None, "common.abilities.gnarling.totem.red"), + secondary: Simple(None, "common.abilities.gnarling.totem.red"), abilities: [], ), Custom("Gnarling Totem Green"): ( - primary: "common.abilities.gnarling.totem.green", - secondary: "common.abilities.gnarling.totem.green", + primary: Simple(None, "common.abilities.gnarling.totem.green"), + secondary: Simple(None, "common.abilities.gnarling.totem.green"), abilities: [], ), Custom("Gnarling Totem White"): ( - primary: "common.abilities.gnarling.totem.white", - secondary: "common.abilities.gnarling.totem.white", + primary: Simple(None, "common.abilities.gnarling.totem.white"), + secondary: Simple(None, "common.abilities.gnarling.totem.white"), abilities: [], ), Custom("Deadwood"): ( - primary: "common.abilities.custom.deadwood.lifestealbeam", - secondary: "common.abilities.custom.deadwood.dash", + primary: Simple(None, "common.abilities.custom.deadwood.lifestealbeam"), + secondary: Simple(None, "common.abilities.custom.deadwood.dash"), abilities: [], ), Custom("Mandragora"): ( - primary: "common.abilities.custom.mandragora.basic", - secondary: "common.abilities.custom.mandragora.scream", + primary: Simple(None, "common.abilities.custom.mandragora.basic"), + secondary: Simple(None, "common.abilities.custom.mandragora.scream"), abilities: [], ), Custom("Wood Golem"): ( - primary: "common.abilities.custom.woodgolem.strike", - secondary: "common.abilities.custom.woodgolem.spin", + primary: Simple(None, "common.abilities.custom.woodgolem.strike"), + secondary: Simple(None, "common.abilities.custom.woodgolem.spin"), abilities: [ Simple(None, "common.abilities.custom.woodgolem.shockwave") ], ), Custom("Simple Flying Melee"): ( - primary: "common.abilities.custom.simpleflyingmelee.singlestrike", - secondary: "common.abilities.custom.simpleflyingmelee.singlestrike", + primary: Simple(None, "common.abilities.custom.simpleflyingmelee.singlestrike"), + secondary: Simple(None, "common.abilities.custom.simpleflyingmelee.singlestrike"), abilities: [], ), Custom("Sword Simple"): ( - primary: "common.abilities.swordsimple.doublestrike", - secondary: "common.abilities.swordsimple.dash", + primary: Simple(None, "common.abilities.swordsimple.doublestrike"), + secondary: Simple(None, "common.abilities.swordsimple.dash"), abilities: [], ), Custom("Staff Simple"): ( - primary: "common.abilities.staffsimple.firebomb", - secondary: "common.abilities.staffsimple.flamethrower", + primary: Simple(None, "common.abilities.staffsimple.firebomb"), + secondary: Simple(None, "common.abilities.staffsimple.flamethrower"), abilities: [], ), Custom("Bow Simple"): ( - primary: "common.abilities.bowsimple.basic", - secondary: "common.abilities.bowsimple.basic", + primary: Simple(None, "common.abilities.bowsimple.basic"), + secondary: Simple(None, "common.abilities.bowsimple.basic"), abilities: [], ), Custom("Axe Simple"): ( - primary: "common.abilities.axesimple.doublestrike", - secondary: "common.abilities.axesimple.doublestrike", + primary: Simple(None, "common.abilities.axesimple.doublestrike"), + secondary: Simple(None, "common.abilities.axesimple.doublestrike"), abilities: [], ), Custom("Dagger Simple"): ( - primary: "common.abilities.daggersimple.singlestrike", - secondary: "common.abilities.daggersimple.singlestrike", + primary: Simple(None, "common.abilities.daggersimple.singlestrike"), + secondary: Simple(None, "common.abilities.daggersimple.singlestrike"), abilities: [], ), Tool(Dagger): ( - primary: "common.abilities.dagger.tempbasic", - secondary: "common.abilities.dagger.tempbasic", + primary: Simple(None, "common.abilities.dagger.tempbasic"), + secondary: Simple(None, "common.abilities.dagger.tempbasic"), abilities: [], ), Tool(Shield): ( - primary: "common.abilities.shield.tempbasic", - secondary: "common.abilities.shield.block", + primary: Simple(None, "common.abilities.shield.tempbasic"), + secondary: Simple(None, "common.abilities.shield.block"), abilities: [], ), Custom("Stone Golem"): ( - primary: "common.abilities.custom.stonegolemfist.singlestrike", - secondary: "common.abilities.custom.stonegolemfist.shockwave", + primary: Simple(None, "common.abilities.custom.stonegolemfist.singlestrike"), + secondary: Simple(None, "common.abilities.custom.stonegolemfist.shockwave"), abilities: [ Simple(None, "common.abilities.custom.stonegolemfist.spin"), ], ), Custom("Beast Claws"): ( - primary: "common.abilities.custom.beastclaws.basic", - secondary: "common.abilities.custom.beastclaws.basic", + primary: Simple(None, "common.abilities.custom.beastclaws.basic"), + secondary: Simple(None, "common.abilities.custom.beastclaws.basic"), abilities: [], ), Custom("Tursus Claws"): ( @@ -217,50 +227,50 @@ abilities: [], ), Custom("Wendigo Magic"): ( - primary: "common.abilities.custom.wendigomagic.frostbomb", - secondary: "common.abilities.custom.wendigomagic.singlestrike", + primary: Simple(None, "common.abilities.custom.wendigomagic.frostbomb"), + secondary: Simple(None, "common.abilities.custom.wendigomagic.singlestrike"), abilities: [], ), Custom("Tidal Warrior"): ( - primary: "common.abilities.custom.tidalwarrior.pincer", - secondary: "common.abilities.custom.tidalwarrior.scuttle", + primary: Simple(None, "common.abilities.custom.tidalwarrior.pincer"), + secondary: Simple(None, "common.abilities.custom.tidalwarrior.scuttle"), abilities: [ Simple(None, "common.abilities.custom.tidalwarrior.bubbles"), Simple(None, "common.abilities.custom.tidalwarrior.totem"), ], ), Custom("Tidal Totem"): ( - primary: "common.abilities.custom.tidalwarrior.totem_wave", - secondary: "common.abilities.custom.tidalwarrior.totem_wave", + primary: Simple(None, "common.abilities.custom.tidalwarrior.totem_wave"), + secondary: Simple(None, "common.abilities.custom.tidalwarrior.totem_wave"), abilities: [], ), // Note: Consider making a ranking system once we get more entities // TODO: Make all purple item droppers have purple CR and a unique skillset Custom("Quad Med Quick"): ( - primary: "common.abilities.custom.quadmedquick.triplestrike", - secondary: "common.abilities.custom.quadmedquick.dash", + primary: Simple(None, "common.abilities.custom.quadmedquick.triplestrike"), + secondary: Simple(None, "common.abilities.custom.quadmedquick.dash"), abilities: [], ), Custom("Quad Med Jump"): ( - primary: "common.abilities.custom.quadmedjump.leap", - secondary: "common.abilities.custom.quadmedjump.doublestrike", + primary: Simple(None, "common.abilities.custom.quadmedjump.leap"), + secondary: Simple(None, "common.abilities.custom.quadmedjump.doublestrike"), abilities: [ Simple(None, "common.abilities.custom.quadmedjump.quickleap"), ], ), Custom("Quad Med Charge"): ( - primary: "common.abilities.custom.quadmedcharge.doublestrike", - secondary: "common.abilities.custom.quadmedcharge.dash", + primary: Simple(None, "common.abilities.custom.quadmedcharge.doublestrike"), + secondary: Simple(None, "common.abilities.custom.quadmedcharge.dash"), abilities: [], ), Custom("Quad Med Hoof"): ( - primary: "common.abilities.custom.quadmedhoof.basic", - secondary: "common.abilities.custom.quadmedhoof.basic", + primary: Simple(None, "common.abilities.custom.quadmedhoof.basic"), + secondary: Simple(None, "common.abilities.custom.quadmedhoof.basic"), abilities: [], ), Custom("Quad Med Basic"): ( - primary: "common.abilities.custom.quadmedbasic.singlestrike", - secondary: "common.abilities.custom.quadmedbasic.triplestrike", + primary: Simple(None, "common.abilities.custom.quadmedbasic.singlestrike"), + secondary: Simple(None, "common.abilities.custom.quadmedbasic.triplestrike"), abilities: [], ), Custom("Roshwalr"): ( @@ -271,129 +281,129 @@ ], ), Custom("Basilisk"): ( - primary: "common.abilities.custom.basilisk.petrify", - secondary: "common.abilities.custom.basilisk.triplestrike", + primary: Simple(None, "common.abilities.custom.basilisk.petrify"), + secondary: Simple(None, "common.abilities.custom.basilisk.triplestrike"), abilities: [ Simple(None, "common.abilities.custom.basilisk.dash"), ], ), Custom("Asp"): ( - primary: "common.abilities.custom.asp.singlestrike", - secondary: "common.abilities.custom.asp.firebomb", + primary: Simple(None, "common.abilities.custom.asp.singlestrike"), + secondary: Simple(None, "common.abilities.custom.asp.firebomb"), abilities: [], ), Custom("Maneater"): ( - primary: "common.abilities.custom.maneater.singlestrike", - secondary: "common.abilities.custom.maneater.poisonball", + primary: Simple(None, "common.abilities.custom.maneater.singlestrike"), + secondary: Simple(None, "common.abilities.custom.maneater.poisonball"), abilities: [], ), Custom("Quad Low Breathe"): ( - primary: "common.abilities.custom.quadlowbreathe.flamethrower", - secondary: "common.abilities.custom.quadlowbreathe.triplestrike", + primary: Simple(None, "common.abilities.custom.quadlowbreathe.flamethrower"), + secondary: Simple(None, "common.abilities.custom.quadlowbreathe.triplestrike"), abilities: [ Simple(None, "common.abilities.custom.quadlowbreathe.dash"), ], ), Custom("Quad Low Tail"): ( - primary: "common.abilities.custom.quadlowtail.charged", - secondary: "common.abilities.custom.quadlowtail.triplestrike", + primary: Simple(None, "common.abilities.custom.quadlowtail.charged"), + secondary: Simple(None, "common.abilities.custom.quadlowtail.triplestrike"), abilities: [], ), Custom("Quad Low Quick"): ( - primary: "common.abilities.custom.quadlowquick.dash", - secondary: "common.abilities.custom.quadlowquick.quadstrike", + primary: Simple(None, "common.abilities.custom.quadlowquick.dash"), + secondary: Simple(None, "common.abilities.custom.quadlowquick.quadstrike"), abilities: [], ), Custom("Quad Low Basic"): ( - primary: "common.abilities.custom.quadlowbasic.triplestrike", - secondary: "common.abilities.custom.quadlowbasic.singlestrike", + primary: Simple(None, "common.abilities.custom.quadlowbasic.triplestrike"), + secondary: Simple(None, "common.abilities.custom.quadlowbasic.singlestrike"), abilities: [], ), Custom("Quad Low Beam"): ( - primary: "common.abilities.custom.quadlowbeam.lifestealbeam", - secondary: "common.abilities.custom.quadlowbreathe.triplestrike", + primary: Simple(None, "common.abilities.custom.quadlowbeam.lifestealbeam"), + secondary: Simple(None, "common.abilities.custom.quadlowbreathe.triplestrike"), abilities: [ Simple(None, "common.abilities.custom.quadlowbreathe.dash"), ], ), Custom("Quad Small Basic"): ( - primary: "common.abilities.custom.quadsmallbasic.singlestrike", - secondary: "common.abilities.custom.quadsmallbasic.singlestrike", + primary: Simple(None, "common.abilities.custom.quadsmallbasic.singlestrike"), + secondary: Simple(None, "common.abilities.custom.quadsmallbasic.singlestrike"), abilities: [], ), Custom("Theropod Basic"): ( - primary: "common.abilities.custom.theropodbasic.triplestrike", - secondary: "common.abilities.custom.theropodbasic.triplestrike", + primary: Simple(None, "common.abilities.custom.theropodbasic.triplestrike"), + secondary: Simple(None, "common.abilities.custom.theropodbasic.triplestrike"), abilities: [], ), Custom("Theropod Small"): ( - primary: "common.abilities.custom.theropodsmall.triplestrike", - secondary: "common.abilities.custom.theropodsmall.triplestrike", + primary: Simple(None, "common.abilities.custom.theropodsmall.triplestrike"), + secondary: Simple(None, "common.abilities.custom.theropodsmall.triplestrike"), abilities: [], ), Custom("Theropod Bird"): ( - primary: "common.abilities.custom.theropodbird.triplestrike", - secondary: "common.abilities.custom.theropodbird.triplestrike", + primary: Simple(None, "common.abilities.custom.theropodbird.triplestrike"), + secondary: Simple(None, "common.abilities.custom.theropodbird.triplestrike"), abilities: [], ), Custom("Theropod Charge"): ( - primary: "common.abilities.custom.theropodbasic.triplestrike", - secondary: "common.abilities.custom.theropodbasic.dash", + primary: Simple(None, "common.abilities.custom.theropodbasic.triplestrike"), + secondary: Simple(None, "common.abilities.custom.theropodbasic.dash"), abilities: [], ), // Arthropods Custom("Antlion"): ( - primary: "common.abilities.custom.arthropods.antlion.singlestrike", - secondary: "common.abilities.custom.arthropods.antlion.charge", + primary: Simple(None, "common.abilities.custom.arthropods.antlion.singlestrike"), + secondary: Simple(None, "common.abilities.custom.arthropods.antlion.charge"), abilities: [], ), Custom("Black Widow"): ( - primary: "common.abilities.custom.arthropods.blackwidow.singlestrike", - secondary: "common.abilities.custom.arthropods.blackwidow.ensnaringwebs", + primary: Simple(None, "common.abilities.custom.arthropods.blackwidow.singlestrike"), + secondary: Simple(None, "common.abilities.custom.arthropods.blackwidow.ensnaringwebs"), abilities: [ Simple(None, "common.abilities.custom.arthropods.blackwidow.poisonball"), ], ), Custom("Horn Beetle"): ( - primary: "common.abilities.custom.arthropods.hornbeetle.singlestrike", - secondary: "common.abilities.custom.arthropods.hornbeetle.harden", + primary: Simple(None, "common.abilities.custom.arthropods.hornbeetle.singlestrike"), + secondary: Simple(None, "common.abilities.custom.arthropods.hornbeetle.harden"), abilities: [ Simple(None, "common.abilities.custom.arthropods.hornbeetle.leap"), ], ), Custom("Tarantula"): ( - primary: "common.abilities.custom.arthropods.tarantula.singlestrike", - secondary: "common.abilities.custom.arthropods.tarantula.ensnaringwebs", + primary: Simple(None, "common.abilities.custom.arthropods.tarantula.singlestrike"), + secondary: Simple(None, "common.abilities.custom.arthropods.tarantula.ensnaringwebs"), abilities: [ Simple(None, "common.abilities.custom.arthropods.tarantula.leap"), ], ), Custom("Weevil"): ( - primary: "common.abilities.custom.arthropods.weevil.singlestrike", - secondary: "common.abilities.custom.arthropods.weevil.harden", + primary: Simple(None, "common.abilities.custom.arthropods.weevil.singlestrike"), + secondary: Simple(None, "common.abilities.custom.arthropods.weevil.harden"), abilities: [ Simple(None, "common.abilities.custom.arthropods.weevil.threadshot"), ], ), /// TODO: Organize the rest into further catagories and give purple tier droppers+ custom skillsets Custom("Turret"): ( - primary: "common.abilities.custom.turret.arrows", - secondary: "common.abilities.custom.turret.arrows", + primary: Simple(None, "common.abilities.custom.turret.arrows"), + secondary: Simple(None, "common.abilities.custom.turret.arrows"), abilities: [], ), Custom("Organ"): ( - primary: "common.abilities.custom.organ.organaura", - secondary: "common.abilities.custom.organ.organaura", + primary: Simple(None, "common.abilities.custom.organ.organaura"), + secondary: Simple(None, "common.abilities.custom.organ.organaura"), abilities: [], ), Custom("Haniwa Sentry"): ( - primary: "common.abilities.custom.turret.flamethrower", - secondary: "common.abilities.custom.turret.flamethrower", + primary: Simple(None, "common.abilities.custom.turret.flamethrower"), + secondary: Simple(None, "common.abilities.custom.turret.flamethrower"), abilities: [], ), Custom("Mindflayer"): ( - primary: "common.abilities.custom.mindflayer.cursedflames", - secondary: "common.abilities.custom.mindflayer.necroticvortex", + primary: Simple(None, "common.abilities.custom.mindflayer.cursedflames"), + secondary: Simple(None, "common.abilities.custom.mindflayer.necroticvortex"), abilities: [ Simple(None, "common.abilities.custom.mindflayer.dimensionaldoor"), Simple(None, "common.abilities.custom.mindflayer.necroticsphere"), @@ -401,32 +411,32 @@ ], ), Custom("Minotaur"): ( - primary: "common.abilities.custom.minotaur.cleave", - secondary: "common.abilities.custom.minotaur.cripplingstrike", + primary: Simple(None, "common.abilities.custom.minotaur.cleave"), + secondary: Simple(None, "common.abilities.custom.minotaur.cripplingstrike"), abilities: [ Simple(None, "common.abilities.custom.minotaur.charge"), Simple(None, "common.abilities.custom.minotaur.frenzy"), ], ), Custom("Clay Golem"): ( - primary: "common.abilities.custom.claygolem.strike", - secondary: "common.abilities.custom.claygolem.laser", + primary: Simple(None, "common.abilities.custom.claygolem.strike"), + secondary: Simple(None, "common.abilities.custom.claygolem.laser"), abilities: [ Simple(None, "common.abilities.custom.claygolem.shockwave"), Simple(None, "common.abilities.custom.claygolem.rocket"), ], ), Custom("Yeti"): ( - primary: "common.abilities.custom.yeti.strike", - secondary: "common.abilities.custom.yeti.icespikes", + primary: Simple(None, "common.abilities.custom.yeti.strike"), + secondary: Simple(None, "common.abilities.custom.yeti.icespikes"), abilities: [ Simple(None, "common.abilities.custom.yeti.frostbreath"), Simple(None, "common.abilities.custom.yeti.snowball"), ], ), Custom("Harvester"): ( - primary: "common.abilities.custom.harvester.scythe", - secondary: "common.abilities.custom.harvester.firebreath", + primary: Simple(None, "common.abilities.custom.harvester.scythe"), + secondary: Simple(None, "common.abilities.custom.harvester.firebreath"), abilities: [ Simple(None, "common.abilities.custom.harvester.ensnaringvines"), Simple(None, "common.abilities.custom.harvester.explodingpumpkin"), @@ -434,8 +444,8 @@ ), // TODO: Allow ability sets to expand other ability sets Custom("Dagon"): ( - primary: "common.abilities.custom.dagon.dagonbombs", - secondary: "common.abilities.custom.dagon.seaurchins", + primary: Simple(None, "common.abilities.custom.dagon.dagonbombs"), + secondary: Simple(None, "common.abilities.custom.dagon.seaurchins"), abilities: [ Simple(None, "common.abilities.custom.dagon.steamwave"), Simple(None, "common.abilities.custom.cardinal.steambeam"), @@ -443,28 +453,28 @@ ], ), Custom("Cardinal"): ( - primary: "common.abilities.sceptre.lifestealbeam", - secondary: "common.abilities.sceptre.healingaura", + primary: Simple(None, "common.abilities.sceptre.lifestealbeam"), + secondary: Simple(None, "common.abilities.sceptre.healingaura"), abilities: [ Simple(None, "common.abilities.custom.cardinal.steambeam"), Simple(None, "common.abilities.custom.cardinal.summonseacrocs"), ], ), Custom("Oni"): ( - primary: "common.abilities.custom.oni.dash", - secondary: "common.abilities.custom.oni.doublestrike", + primary: Simple(None, "common.abilities.custom.oni.dash"), + secondary: Simple(None, "common.abilities.custom.oni.doublestrike"), abilities: [], ), Custom("Bird Large Breathe"): ( - primary: "common.abilities.custom.birdlargebreathe.firebomb", - secondary: "common.abilities.custom.birdlargebreathe.triplestrike", + primary: Simple(None, "common.abilities.custom.birdlargebreathe.firebomb"), + secondary: Simple(None, "common.abilities.custom.birdlargebreathe.triplestrike"), abilities: [ Simple(None, "common.abilities.custom.birdlargebreathe.flamethrower"), ], ), Custom("Bird Large Fire"): ( - primary: "common.abilities.custom.birdlargefire.firebomb", - secondary: "common.abilities.custom.birdlargefire.triplestrike", + primary: Simple(None, "common.abilities.custom.birdlargefire.firebomb"), + secondary: Simple(None, "common.abilities.custom.birdlargefire.triplestrike"), abilities: [ Simple(None, "common.abilities.custom.birdlargefire.fireshockwave"), ], @@ -510,8 +520,8 @@ ], ), Custom("Bird Large Basic"): ( - primary: "common.abilities.custom.birdlargebasic.triplestrike", - secondary: "common.abilities.custom.birdlargebasic.summontornadoes", + primary: Simple(None, "common.abilities.custom.birdlargebasic.triplestrike"), + secondary: Simple(None, "common.abilities.custom.birdlargebasic.summontornadoes"), abilities: [ Simple(None, "common.abilities.custom.birdlargebasic.dash"), ], @@ -547,33 +557,33 @@ ], ), Custom("Tornado"): ( - primary: "common.abilities.custom.tornado.spin", - secondary: "common.abilities.empty.basic", + primary: Simple(None, "common.abilities.custom.tornado.spin"), + secondary: Simple(None, "common.abilities.empty.basic"), abilities: [], ), Custom("Golf Club"): ( - primary: "common.abilities.hammer.singlestrike", - secondary: "common.abilities.tool.golf_club.charged", + primary: Simple(None, "common.abilities.hammer.singlestrike"), + secondary: Simple(None, "common.abilities.tool.golf_club.charged"), abilities: [], ), Custom("DoubleBass"): ( - primary: "common.abilities.music.double_bass", - secondary: "common.abilities.music.double_bass", + primary: Simple(None, "common.abilities.music.double_bass"), + secondary: Simple(None, "common.abilities.music.double_bass"), abilities: [], ), Custom("Flute"): ( - primary: "common.abilities.music.flute", - secondary: "common.abilities.music.flute", + primary: Simple(None, "common.abilities.music.flute"), + secondary: Simple(None, "common.abilities.music.flute"), abilities: [], ), Custom("GlassFlute"): ( - primary: "common.abilities.music.glass_flute", - secondary: "common.abilities.music.glass_flute", + primary: Simple(None, "common.abilities.music.glass_flute"), + secondary: Simple(None, "common.abilities.music.glass_flute"), abilities: [], ), Custom("Lyre"): ( - primary: "common.abilities.music.lyre", - secondary: "common.abilities.music.lyre", + primary: Simple(None, "common.abilities.music.lyre"), + secondary: Simple(None, "common.abilities.music.lyre"), abilities: [], ), Custom("IcyTalharpa"): ( @@ -582,28 +592,28 @@ abilities: [], ), Custom("Washboard"): ( - primary: "common.abilities.music.washboard", - secondary: "common.abilities.music.washboard", + primary: Simple(None, "common.abilities.music.washboard"), + secondary: Simple(None, "common.abilities.music.washboard"), abilities: [], ), Custom("Kalimba"): ( - primary: "common.abilities.music.kalimba", - secondary: "common.abilities.music.kalimba", + primary: Simple(None, "common.abilities.music.kalimba"), + secondary: Simple(None, "common.abilities.music.kalimba"), abilities: [], ), Custom("Melodica"): ( - primary: "common.abilities.music.melodica", - secondary: "common.abilities.music.melodica", + primary: Simple(None, "common.abilities.music.melodica"), + secondary: Simple(None, "common.abilities.music.melodica"), abilities: [], ), Custom("Lute"): ( - primary: "common.abilities.music.lute", - secondary: "common.abilities.music.lute", + primary: Simple(None, "common.abilities.music.lute"), + secondary: Simple(None, "common.abilities.music.lute"), abilities: [], ), Custom("Guitar"): ( - primary: "common.abilities.music.guitar", - secondary: "common.abilities.music.guitar", + primary: Simple(None, "common.abilities.music.guitar"), + secondary: Simple(None, "common.abilities.music.guitar"), abilities: [], ), Custom("DarkGuitar"): ( @@ -612,30 +622,30 @@ abilities: [], ), Custom("Sitar"): ( - primary: "common.abilities.music.sitar", - secondary: "common.abilities.music.sitar", + primary: Simple(None, "common.abilities.music.sitar"), + secondary: Simple(None, "common.abilities.music.sitar"), abilities: [], ), Tool(Debug): ( - primary: "common.abilities.debug.forwardboost", - secondary: "common.abilities.debug.upboost", + primary: Simple(None, "common.abilities.debug.forwardboost"), + secondary: Simple(None, "common.abilities.debug.upboost"), abilities: [ Simple(None, "common.abilities.debug.possess"), ], ), Tool(Farming): ( - primary: "common.abilities.farming.basic", - secondary: "common.abilities.farming.basic", + primary: Simple(None, "common.abilities.farming.basic"), + secondary: Simple(None, "common.abilities.farming.basic"), abilities: [], ), Tool(Pick): ( - primary: "common.abilities.pick.swing", - secondary: "common.abilities.pick.swing", + primary: Simple(None, "common.abilities.pick.swing"), + secondary: Simple(None, "common.abilities.pick.swing"), abilities: [], ), Tool(Empty): ( - primary: "common.abilities.empty.basic", - secondary: "common.abilities.empty.basic", + primary: Simple(None, "common.abilities.empty.basic"), + secondary: Simple(None, "common.abilities.empty.basic"), abilities: [], ), }) diff --git a/assets/common/abilities/sword/balanced_combo.ron b/assets/common/abilities/sword/balanced_combo.ron index 2f4ff6121a..d4f5e3728f 100644 --- a/assets/common/abilities/sword/balanced_combo.ron +++ b/assets/common/abilities/sword/balanced_combo.ron @@ -35,6 +35,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, energy_cost_per_strike: 0, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/cleaving_combo.ron b/assets/common/abilities/sword/cleaving_combo.ron index d76d9317ee..66838291c2 100644 --- a/assets/common/abilities/sword/cleaving_combo.ron +++ b/assets/common/abilities/sword/cleaving_combo.ron @@ -47,7 +47,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, - stance: Some(Sword(Cleaving)), energy_cost_per_strike: 5, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/cleaving_spin.ron b/assets/common/abilities/sword/cleaving_spin.ron index f4575e77f8..631e95006b 100644 --- a/assets/common/abilities/sword/cleaving_spin.ron +++ b/assets/common/abilities/sword/cleaving_spin.ron @@ -19,6 +19,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 20, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/cleaving_stance.ron b/assets/common/abilities/sword/cleaving_stance.ron new file mode 100644 index 0000000000..a9c55a20dd --- /dev/null +++ b/assets/common/abilities/sword/cleaving_stance.ron @@ -0,0 +1,4 @@ +BasicStance( + buildup_duration: 0.25, + stance: Sword(Cleaving), +) \ No newline at end of file diff --git a/assets/common/abilities/sword/crippling_combo.ron b/assets/common/abilities/sword/crippling_combo.ron index d0e722b6e7..670bf67ac6 100644 --- a/assets/common/abilities/sword/crippling_combo.ron +++ b/assets/common/abilities/sword/crippling_combo.ron @@ -47,7 +47,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, - stance: Some(Sword(Crippling)), energy_cost_per_strike: 4, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/crippling_gouge.ron b/assets/common/abilities/sword/crippling_gouge.ron index 7455d7779c..5b3fd668b3 100644 --- a/assets/common/abilities/sword/crippling_gouge.ron +++ b/assets/common/abilities/sword/crippling_gouge.ron @@ -24,6 +24,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 25, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/crippling_stance.ron b/assets/common/abilities/sword/crippling_stance.ron new file mode 100644 index 0000000000..8d7a3fffe8 --- /dev/null +++ b/assets/common/abilities/sword/crippling_stance.ron @@ -0,0 +1,4 @@ +BasicStance( + buildup_duration: 0.25, + stance: Sword(Crippling), +) \ No newline at end of file diff --git a/assets/common/abilities/sword/crippling_strike.ron b/assets/common/abilities/sword/crippling_strike.ron index 33b0d692b3..eb86f370d4 100644 --- a/assets/common/abilities/sword/crippling_strike.ron +++ b/assets/common/abilities/sword/crippling_strike.ron @@ -24,6 +24,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 25, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/defensive_combo.ron b/assets/common/abilities/sword/defensive_combo.ron index f6f85e4203..2e1f8c1b63 100644 --- a/assets/common/abilities/sword/defensive_combo.ron +++ b/assets/common/abilities/sword/defensive_combo.ron @@ -35,8 +35,6 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, - stance: Some(Sword(Defensive)), energy_cost_per_strike: 2, meta: ( capabilities: ( diff --git a/assets/common/abilities/sword/defensive_retreat.ron b/assets/common/abilities/sword/defensive_retreat.ron index beef3eb633..4b1136483f 100644 --- a/assets/common/abilities/sword/defensive_retreat.ron +++ b/assets/common/abilities/sword/defensive_retreat.ron @@ -23,6 +23,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 10, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/defensive_stance.ron b/assets/common/abilities/sword/defensive_stance.ron new file mode 100644 index 0000000000..b7fd53055b --- /dev/null +++ b/assets/common/abilities/sword/defensive_stance.ron @@ -0,0 +1,4 @@ +BasicStance( + buildup_duration: 0.25, + stance: Sword(Defensive), +) \ No newline at end of file diff --git a/assets/common/abilities/sword/heavy_combo.ron b/assets/common/abilities/sword/heavy_combo.ron index a87f747dc4..8a84f733b7 100644 --- a/assets/common/abilities/sword/heavy_combo.ron +++ b/assets/common/abilities/sword/heavy_combo.ron @@ -35,8 +35,6 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, - stance: Some(Sword(Heavy)), energy_cost_per_strike: 4, meta: ( capabilities: ( diff --git a/assets/common/abilities/sword/heavy_pommelstrike.ron b/assets/common/abilities/sword/heavy_pommelstrike.ron index 6dbcde88ce..ec6608af9c 100644 --- a/assets/common/abilities/sword/heavy_pommelstrike.ron +++ b/assets/common/abilities/sword/heavy_pommelstrike.ron @@ -18,6 +18,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 15, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/heavy_stance.ron b/assets/common/abilities/sword/heavy_stance.ron new file mode 100644 index 0000000000..3e1149c43e --- /dev/null +++ b/assets/common/abilities/sword/heavy_stance.ron @@ -0,0 +1,4 @@ +BasicStance( + buildup_duration: 0.25, + stance: Sword(Heavy), +) \ No newline at end of file diff --git a/assets/common/abilities/sword/mobility_combo.ron b/assets/common/abilities/sword/mobility_combo.ron index 60ea4791c4..fa679069c0 100644 --- a/assets/common/abilities/sword/mobility_combo.ron +++ b/assets/common/abilities/sword/mobility_combo.ron @@ -69,8 +69,6 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, - stance: Some(Sword(Mobility)), energy_cost_per_strike: 2, meta: ( capabilities: ( diff --git a/assets/common/abilities/sword/mobility_feint.ron b/assets/common/abilities/sword/mobility_feint.ron index 93194c7199..fd8f33dda5 100644 --- a/assets/common/abilities/sword/mobility_feint.ron +++ b/assets/common/abilities/sword/mobility_feint.ron @@ -23,6 +23,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 10, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/mobility_stance.ron b/assets/common/abilities/sword/mobility_stance.ron new file mode 100644 index 0000000000..8d9368328b --- /dev/null +++ b/assets/common/abilities/sword/mobility_stance.ron @@ -0,0 +1,4 @@ +BasicStance( + buildup_duration: 0.25, + stance: Sword(Mobility), +) \ No newline at end of file diff --git a/assets/common/abilities/sword/offensive_advance.ron b/assets/common/abilities/sword/offensive_advance.ron index cac494b062..dac25df086 100644 --- a/assets/common/abilities/sword/offensive_advance.ron +++ b/assets/common/abilities/sword/offensive_advance.ron @@ -23,6 +23,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 10, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/offensive_combo.ron b/assets/common/abilities/sword/offensive_combo.ron index 7d1b9b3d1e..19d8e4b023 100644 --- a/assets/common/abilities/sword/offensive_combo.ron +++ b/assets/common/abilities/sword/offensive_combo.ron @@ -57,7 +57,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, - stance: Some(Sword(Offensive)), energy_cost_per_strike: 3, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/offensive_stance.ron b/assets/common/abilities/sword/offensive_stance.ron new file mode 100644 index 0000000000..36e67a247b --- /dev/null +++ b/assets/common/abilities/sword/offensive_stance.ron @@ -0,0 +1,4 @@ +BasicStance( + buildup_duration: 0.25, + stance: Sword(Offensive), +) \ No newline at end of file diff --git a/assets/common/abilities/sword/parrying_combo.ron b/assets/common/abilities/sword/parrying_combo.ron index b9c0e2d2cb..6cfd63d5d5 100644 --- a/assets/common/abilities/sword/parrying_combo.ron +++ b/assets/common/abilities/sword/parrying_combo.ron @@ -35,8 +35,6 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, - stance: Some(Sword(Parrying)), energy_cost_per_strike: 5, meta: ( capabilities: ( diff --git a/assets/common/abilities/sword/parrying_counter.ron b/assets/common/abilities/sword/parrying_counter.ron index b4b2519ff6..ae98ad1166 100644 --- a/assets/common/abilities/sword/parrying_counter.ron +++ b/assets/common/abilities/sword/parrying_counter.ron @@ -24,6 +24,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 15, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/parrying_stance.ron b/assets/common/abilities/sword/parrying_stance.ron new file mode 100644 index 0000000000..fd71bc9a43 --- /dev/null +++ b/assets/common/abilities/sword/parrying_stance.ron @@ -0,0 +1,4 @@ +BasicStance( + buildup_duration: 0.25, + stance: Sword(Parrying), +) \ No newline at end of file diff --git a/assets/common/abilities/sword/reaching_combo.ron b/assets/common/abilities/sword/reaching_combo.ron index d5fd92abd8..b7e7dff66e 100644 --- a/assets/common/abilities/sword/reaching_combo.ron +++ b/assets/common/abilities/sword/reaching_combo.ron @@ -35,7 +35,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: true, - stance: Some(Sword(Reaching)), energy_cost_per_strike: 4, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/reaching_skewer.ron b/assets/common/abilities/sword/reaching_skewer.ron index e587c430c9..4be61d097b 100644 --- a/assets/common/abilities/sword/reaching_skewer.ron +++ b/assets/common/abilities/sword/reaching_skewer.ron @@ -24,6 +24,5 @@ ComboMelee2( ori_modifier: 0.6, ), ], - is_stance: false, energy_cost_per_strike: 15, ) \ No newline at end of file diff --git a/assets/common/abilities/sword/reaching_stance.ron b/assets/common/abilities/sword/reaching_stance.ron new file mode 100644 index 0000000000..23a8dd0591 --- /dev/null +++ b/assets/common/abilities/sword/reaching_stance.ron @@ -0,0 +1,4 @@ +BasicStance( + buildup_duration: 0.25, + stance: Sword(Reaching), +) \ No newline at end of file diff --git a/assets/common/skill_trees/skill_prerequisites.ron b/assets/common/skill_trees/skill_prerequisites.ron index 187e71107e..06a0792328 100644 --- a/assets/common/skill_trees/skill_prerequisites.ron +++ b/assets/common/skill_trees/skill_prerequisites.ron @@ -1,30 +1,30 @@ ({ - Sword(OffensiveFinisher): {Sword(OffensiveCombo): 1}, - Sword(OffensiveAdvance): {Sword(OffensiveCombo): 1}, - Sword(CripplingCombo): {Sword(OffensiveCombo): 1}, - Sword(CripplingFinisher): {Sword(CripplingCombo): 1}, - Sword(CripplingStrike): {Sword(CripplingCombo): 1}, - Sword(CripplingGouge): {Sword(CripplingCombo): 1}, - Sword(CleavingCombo): {Sword(OffensiveCombo): 1}, - Sword(CleavingFinisher): {Sword(CleavingCombo): 1}, - Sword(CleavingSpin): {Sword(CleavingCombo): 1}, - Sword(CleavingDive): {Sword(CleavingCombo): 1}, - Sword(DefensiveBulwark): {Sword(DefensiveCombo): 1}, - Sword(DefensiveRetreat): {Sword(DefensiveCombo): 1}, - Sword(ParryingCombo): {Sword(DefensiveCombo): 1}, - Sword(ParryingParry): {Sword(ParryingCombo): 1}, - Sword(ParryingRiposte): {Sword(ParryingCombo): 1}, - Sword(ParryingCounter): {Sword(ParryingCombo): 1}, - Sword(HeavyCombo): {Sword(DefensiveCombo): 1}, - Sword(HeavyFinisher): {Sword(HeavyCombo): 1}, - Sword(HeavyPommelStrike): {Sword(HeavyCombo): 1}, - Sword(HeavyFortitude): {Sword(HeavyCombo): 1}, - Sword(MobilityFeint): {Sword(MobilityCombo): 1}, - Sword(MobilityAgility): {Sword(MobilityCombo): 1}, - Sword(ReachingCombo): {Sword(MobilityCombo): 1}, - Sword(ReachingCharge): {Sword(ReachingCombo): 1}, - Sword(ReachingFlurry): {Sword(ReachingCombo): 1}, - Sword(ReachingSkewer): {Sword(ReachingCombo): 1}, + Sword(OffensiveFinisher): {Sword(OffensiveStance): 1}, + Sword(OffensiveAdvance): {Sword(OffensiveStance): 1}, + Sword(CripplingStance): {Sword(OffensiveStance): 1}, + Sword(CripplingFinisher): {Sword(CripplingStance): 1}, + Sword(CripplingStrike): {Sword(CripplingStance): 1}, + Sword(CripplingGouge): {Sword(CripplingStance): 1}, + Sword(CleavingStance): {Sword(OffensiveStance): 1}, + Sword(CleavingFinisher): {Sword(CleavingStance): 1}, + Sword(CleavingSpin): {Sword(CleavingStance): 1}, + Sword(CleavingDive): {Sword(CleavingStance): 1}, + Sword(DefensiveBulwark): {Sword(DefensiveStance): 1}, + Sword(DefensiveRetreat): {Sword(DefensiveStance): 1}, + Sword(ParryingStance): {Sword(DefensiveStance): 1}, + Sword(ParryingParry): {Sword(ParryingStance): 1}, + Sword(ParryingRiposte): {Sword(ParryingStance): 1}, + Sword(ParryingCounter): {Sword(ParryingStance): 1}, + Sword(HeavyStance): {Sword(DefensiveStance): 1}, + Sword(HeavyFinisher): {Sword(HeavyStance): 1}, + Sword(HeavyPommelStrike): {Sword(HeavyStance): 1}, + Sword(HeavyFortitude): {Sword(HeavyStance): 1}, + Sword(MobilityFeint): {Sword(MobilityStance): 1}, + Sword(MobilityAgility): {Sword(MobilityStance): 1}, + Sword(ReachingStance): {Sword(MobilityStance): 1}, + Sword(ReachingCharge): {Sword(ReachingStance): 1}, + Sword(ReachingFlurry): {Sword(ReachingStance): 1}, + Sword(ReachingSkewer): {Sword(ReachingStance): 1}, Axe(LDamage): {Axe(UnlockLeap): 1}, Axe(LKnockback): {Axe(UnlockLeap): 1}, Axe(LCost): {Axe(UnlockLeap): 1}, diff --git a/assets/common/skill_trees/skills_skill-groups_manifest.ron b/assets/common/skill_trees/skills_skill-groups_manifest.ron index 752320658c..df8144b27c 100644 --- a/assets/common/skill_trees/skills_skill-groups_manifest.ron +++ b/assets/common/skill_trees/skills_skill-groups_manifest.ron @@ -17,32 +17,32 @@ ], Weapon(Sword): [ Sword(BalancedFinisher), - Sword(OffensiveCombo), + Sword(OffensiveStance), Sword(OffensiveFinisher), Sword(OffensiveAdvance), - Sword(CripplingCombo), + Sword(CripplingStance), Sword(CripplingFinisher), Sword(CripplingStrike), Sword(CripplingGouge), - Sword(CleavingCombo), + Sword(CleavingStance), Sword(CleavingFinisher), Sword(CleavingSpin), Sword(CleavingDive), - Sword(DefensiveCombo), + Sword(DefensiveStance), Sword(DefensiveBulwark), Sword(DefensiveRetreat), - Sword(ParryingCombo), + Sword(ParryingStance), Sword(ParryingParry), Sword(ParryingRiposte), Sword(ParryingCounter), - Sword(HeavyCombo), + Sword(HeavyStance), Sword(HeavyFinisher), Sword(HeavyPommelStrike), Sword(HeavyFortitude), - Sword(MobilityCombo), + Sword(MobilityStance), Sword(MobilityFeint), Sword(MobilityAgility), - Sword(ReachingCombo), + Sword(ReachingStance), Sword(ReachingCharge), Sword(ReachingFlurry), Sword(ReachingSkewer), diff --git a/assets/common/skillset/preset/rank2/sword.ron b/assets/common/skillset/preset/rank2/sword.ron index eda3abc8f5..799cf1eec3 100644 --- a/assets/common/skillset/preset/rank2/sword.ron +++ b/assets/common/skillset/preset/rank2/sword.ron @@ -1,13 +1,13 @@ ([ Group(Weapon(Sword)), Skill((Sword(BalancedFinisher), 1)), - Skill((Sword(OffensiveCombo), 1)), + Skill((Sword(OffensiveStance), 1)), Skill((Sword(OffensiveFinisher), 1)), Skill((Sword(OffensiveAdvance), 1)), - Skill((Sword(DefensiveCombo), 1)), + Skill((Sword(DefensiveStance), 1)), Skill((Sword(DefensiveBulwark), 1)), Skill((Sword(DefensiveRetreat), 1)), - Skill((Sword(MobilityCombo), 1)), + Skill((Sword(MobilityStance), 1)), Skill((Sword(MobilityFeint), 1)), Skill((Sword(MobilityAgility), 1)), ]) diff --git a/assets/common/skillset/preset/rank3/sword.ron b/assets/common/skillset/preset/rank3/sword.ron index eda3abc8f5..799cf1eec3 100644 --- a/assets/common/skillset/preset/rank3/sword.ron +++ b/assets/common/skillset/preset/rank3/sword.ron @@ -1,13 +1,13 @@ ([ Group(Weapon(Sword)), Skill((Sword(BalancedFinisher), 1)), - Skill((Sword(OffensiveCombo), 1)), + Skill((Sword(OffensiveStance), 1)), Skill((Sword(OffensiveFinisher), 1)), Skill((Sword(OffensiveAdvance), 1)), - Skill((Sword(DefensiveCombo), 1)), + Skill((Sword(DefensiveStance), 1)), Skill((Sword(DefensiveBulwark), 1)), Skill((Sword(DefensiveRetreat), 1)), - Skill((Sword(MobilityCombo), 1)), + Skill((Sword(MobilityStance), 1)), Skill((Sword(MobilityFeint), 1)), Skill((Sword(MobilityAgility), 1)), ]) diff --git a/assets/common/skillset/preset/rank4/sword.ron b/assets/common/skillset/preset/rank4/sword.ron index 4f9643f0e0..4a0e502760 100644 --- a/assets/common/skillset/preset/rank4/sword.ron +++ b/assets/common/skillset/preset/rank4/sword.ron @@ -1,32 +1,32 @@ ([ Group(Weapon(Sword)), Skill((Sword(BalancedFinisher), 1)), - Skill((Sword(OffensiveCombo), 1)), + Skill((Sword(OffensiveStance), 1)), Skill((Sword(OffensiveFinisher), 1)), Skill((Sword(OffensiveAdvance), 1)), - Skill((Sword(CripplingCombo), 1)), + Skill((Sword(CripplingStance), 1)), Skill((Sword(CripplingFinisher), 1)), Skill((Sword(CripplingStrike), 1)), Skill((Sword(CripplingGouge), 1)), - Skill((Sword(CleavingCombo), 1)), + Skill((Sword(CleavingStance), 1)), Skill((Sword(CleavingFinisher), 1)), Skill((Sword(CleavingSpin), 1)), Skill((Sword(CleavingDive), 1)), - Skill((Sword(DefensiveCombo), 1)), + Skill((Sword(DefensiveStance), 1)), Skill((Sword(DefensiveBulwark), 1)), Skill((Sword(DefensiveRetreat), 1)), - Skill((Sword(ParryingCombo), 1)), + Skill((Sword(ParryingStance), 1)), Skill((Sword(ParryingParry), 1)), Skill((Sword(ParryingRiposte), 1)), Skill((Sword(ParryingCounter), 1)), - Skill((Sword(HeavyCombo), 1)), + Skill((Sword(HeavyStance), 1)), Skill((Sword(HeavyFinisher), 1)), Skill((Sword(HeavyPommelStrike), 1)), Skill((Sword(HeavyFortitude), 1)), - Skill((Sword(MobilityCombo), 1)), + Skill((Sword(MobilityStance), 1)), Skill((Sword(MobilityFeint), 1)), Skill((Sword(MobilityAgility), 1)), - Skill((Sword(ReachingCombo), 1)), + Skill((Sword(ReachingStance), 1)), Skill((Sword(ReachingCharge), 1)), Skill((Sword(ReachingFlurry), 1)), Skill((Sword(ReachingSkewer), 1)), diff --git a/assets/common/skillset/preset/rank5/sword.ron b/assets/common/skillset/preset/rank5/sword.ron index 4f9643f0e0..4a0e502760 100644 --- a/assets/common/skillset/preset/rank5/sword.ron +++ b/assets/common/skillset/preset/rank5/sword.ron @@ -1,32 +1,32 @@ ([ Group(Weapon(Sword)), Skill((Sword(BalancedFinisher), 1)), - Skill((Sword(OffensiveCombo), 1)), + Skill((Sword(OffensiveStance), 1)), Skill((Sword(OffensiveFinisher), 1)), Skill((Sword(OffensiveAdvance), 1)), - Skill((Sword(CripplingCombo), 1)), + Skill((Sword(CripplingStance), 1)), Skill((Sword(CripplingFinisher), 1)), Skill((Sword(CripplingStrike), 1)), Skill((Sword(CripplingGouge), 1)), - Skill((Sword(CleavingCombo), 1)), + Skill((Sword(CleavingStance), 1)), Skill((Sword(CleavingFinisher), 1)), Skill((Sword(CleavingSpin), 1)), Skill((Sword(CleavingDive), 1)), - Skill((Sword(DefensiveCombo), 1)), + Skill((Sword(DefensiveStance), 1)), Skill((Sword(DefensiveBulwark), 1)), Skill((Sword(DefensiveRetreat), 1)), - Skill((Sword(ParryingCombo), 1)), + Skill((Sword(ParryingStance), 1)), Skill((Sword(ParryingParry), 1)), Skill((Sword(ParryingRiposte), 1)), Skill((Sword(ParryingCounter), 1)), - Skill((Sword(HeavyCombo), 1)), + Skill((Sword(HeavyStance), 1)), Skill((Sword(HeavyFinisher), 1)), Skill((Sword(HeavyPommelStrike), 1)), Skill((Sword(HeavyFortitude), 1)), - Skill((Sword(MobilityCombo), 1)), + Skill((Sword(MobilityStance), 1)), Skill((Sword(MobilityFeint), 1)), Skill((Sword(MobilityAgility), 1)), - Skill((Sword(ReachingCombo), 1)), + Skill((Sword(ReachingStance), 1)), Skill((Sword(ReachingCharge), 1)), Skill((Sword(ReachingFlurry), 1)), Skill((Sword(ReachingSkewer), 1)), diff --git a/assets/server/manifests/presets.ron b/assets/server/manifests/presets.ron index 2e5fccbd26..626a03f9de 100644 --- a/assets/server/manifests/presets.ron +++ b/assets/server/manifests/presets.ron @@ -15,32 +15,32 @@ // Sword (UnlockGroup(Weapon(Sword)), 1), (Sword(BalancedFinisher), 1), - (Sword(OffensiveCombo), 1), + (Sword(OffensiveStance), 1), (Sword(OffensiveFinisher), 1), (Sword(OffensiveAdvance), 1), - (Sword(CripplingCombo), 1), + (Sword(CripplingStance), 1), (Sword(CripplingFinisher), 1), (Sword(CripplingStrike), 1), (Sword(CripplingGouge), 1), - (Sword(CleavingCombo), 1), + (Sword(CleavingStance), 1), (Sword(CleavingFinisher), 1), (Sword(CleavingSpin), 1), (Sword(CleavingDive), 1), - (Sword(DefensiveCombo), 1), + (Sword(DefensiveStance), 1), (Sword(DefensiveBulwark), 1), (Sword(DefensiveRetreat), 1), - (Sword(ParryingCombo), 1), + (Sword(ParryingStance), 1), (Sword(ParryingParry), 1), (Sword(ParryingRiposte), 1), (Sword(ParryingCounter), 1), - (Sword(HeavyCombo), 1), + (Sword(HeavyStance), 1), (Sword(HeavyFinisher), 1), (Sword(HeavyPommelStrike), 1), (Sword(HeavyFortitude), 1), - (Sword(MobilityCombo), 1), + (Sword(MobilityStance), 1), (Sword(MobilityFeint), 1), (Sword(MobilityAgility), 1), - (Sword(ReachingCombo), 1), + (Sword(ReachingStance), 1), (Sword(ReachingCharge), 1), (Sword(ReachingFlurry), 1), (Sword(ReachingSkewer), 1), diff --git a/assets/voxygen/i18n/en/hud/ability.ftl b/assets/voxygen/i18n/en/hud/ability.ftl index 043fe79376..cdffb13e2f 100644 --- a/assets/voxygen/i18n/en/hud/ability.ftl +++ b/assets/voxygen/i18n/en/hud/ability.ftl @@ -20,12 +20,16 @@ common-abilities-sword-balanced_finisher = Finisher .desc = A powerful strike you can use after fighting long enough. common-abilities-sword-offensive_combo = Offensive Stance .desc = This stance hits harder, but is more tiring to use. +common-abilities-sword-offensive_stance = Offensive Stance + .desc = This stance hits harder, but is more tiring to use. common-abilities-sword-offensive_finisher = Offensive Finisher .desc = A strike that becomes more powerful the longer you have fought. common-abilities-sword-offensive_advance = Offensive Advance .desc = Swiftly engage the enemy with a powerful strike. common-abilities-sword-crippling_combo = Crippling Stance .desc = This stance is for the dishonorable that enjoy maiming their foes. +common-abilities-sword-crippling_stance = Crippling Stance + .desc = This stance is for the dishonorable that enjoy maiming their foes. common-abilities-sword-crippling_finisher = Crippling Finisher .desc = This strike becomes more crippling to your target the longer you have fought. common-abilities-sword-crippling_strike = Crippling Strike @@ -34,6 +38,8 @@ common-abilities-sword-crippling_gouge = Crippling Gouge .desc = Inflict a lasting wound on your foe. common-abilities-sword-cleaving_combo = Cleaving Stance .desc = This stance focuses on wide, arcing strikes that can hit multiple foes. +common-abilities-sword-cleaving_stance = Cleaving Stance + .desc = This stance focuses on wide, arcing strikes that can hit multiple foes. common-abilities-sword-cleaving_finisher = Cleaving Finisher .desc = A cleaving strike that has the potential to finish multiple foes. common-abilities-sword-cleaving_spin = Cleaving Spin @@ -42,12 +48,16 @@ common-abilities-sword-cleaving_dive = Cleaving Dive .desc = Able to cleave through even the largest enemies if you are falling fast. common-abilities-sword-defensive_combo = Defensive Stance .desc = A more guarded form, where you keep your blade ready to fend off attacks. +common-abilities-sword-defensive_stance = Defensive Stance + .desc = A more guarded form, where you keep your blade ready to fend off attacks. common-abilities-sword-defensive_bulwark = Defensive Bulwark .desc = You ready yourself against incoming attacks, defending yourself against the brunt of them. common-abilities-sword-defensive_retreat = Defensive Retreat .desc = Strike your enemies as you tactically backstep. common-abilities-sword-parrying_combo = Parrying Stance .desc = In this stance, you ready yourself to stop each strike and parry an attack. +common-abilities-sword-parrying_stance = Parrying Stance + .desc = In this stance, you ready yourself to stop each strike and parry an attack. common-abilities-sword-parrying_parry = Parry .desc = You wait for the next attack and deflect it. common-abilities-sword-parrying_riposte = Riposte @@ -56,6 +66,8 @@ common-abilities-sword-parrying_counter = Counter .desc = You strike with lightning speed in an attempt to finish your foe before their attack lands. common-abilities-sword-heavy_combo = Heavy Stance .desc = In this stance, you keep your strikes more controlled to retain your poise. +common-abilities-sword-heavy_stance = Heavy Stance + .desc = In this stance, you keep your strikes more controlled to retain your poise. common-abilities-sword-heavy_finisher = Heavy Finisher .desc = A powerful blow that is more staggering to your target the longer you have fought. common-abilities-sword-heavy_pommelstrike = Pommel Strike @@ -64,12 +76,16 @@ common-abilities-sword-heavy_fortitude = Heavy Fortitude .desc = You steady yourself so that the next few strikes do not stagger you at all. common-abilities-sword-mobility_combo = Mobility Stance .desc = In this stance, you hold your sword closer, ready to roll with the slightest reason. +common-abilities-sword-mobility_stance = Mobility Stance + .desc = In this stance, you hold your sword closer, ready to roll with the slightest reason. common-abilities-sword-mobility_feint = Feint .desc = Deceive your foe by beginning to strike, before stepping to the side and attacking from there. common-abilities-sword-mobility_agility = Agility .desc = Draw on a reserve of energy to move and attack more swiftly. common-abilities-sword-reaching_combo = Reaching Stance .desc = This stance focuses on thrusts over slashes. +common-abilities-sword-reaching_stance = Reaching Stance + .desc = This stance focuses on thrusts over slashes. common-abilities-sword-reaching_charge = Charge .desc = Quickly close the gap to your foe by charging forward in a lunging attack. common-abilities-sword-reaching_flurry = Lunging Flurry diff --git a/common/src/combat.rs b/common/src/combat.rs index 347343f6de..378a62ecb8 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -968,7 +968,7 @@ impl Knockback { let from_char = { let resistant = char_state .and_then(|cs| cs.ability_info()) - .and_then(|a| a.ability_meta) + .map(|a| a.ability_meta) .map_or(false, |a| { a.capabilities.contains(Capability::KNOCKBACK_RESISTANT) }); diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index c328eb1f4f..391b60839f 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -6,7 +6,7 @@ use crate::{ character_state::AttackImmunities, inventory::{ item::{ - tool::{AbilityContext, AbilityItem, AuxiliaryAbilityKind, Stats, ToolKind}, + tool::{AbilityContext, AbilityItem, AbilityKind, Stats, ToolKind}, ItemKind, }, slot::EquipSlot, @@ -143,7 +143,7 @@ impl ActiveAbilities { inv: Option<&Inventory>, skill_set: &SkillSet, body: Option<&Body>, - context: Option, + context: AbilityContext, // bool is from_offhand ) -> Option<(CharacterAbility, bool)> { let ability = self.get_ability(input, inv, Some(skill_set)); @@ -175,14 +175,17 @@ impl ActiveAbilities { match ability { Ability::ToolPrimary => ability_set(EquipSlot::ActiveMainhand) - .map(|abilities| abilities.primary.ability.clone()) + .and_then(|abilities| abilities.primary(context).map(unwrap_ability)) + .and_then(unlocked) .map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), false)), Ability::ToolSecondary => ability_set(EquipSlot::ActiveOffhand) - .map(|abilities| abilities.secondary.ability.clone()) + .and_then(|abilities| abilities.secondary(context).map(unwrap_ability)) + .and_then(unlocked) .map(|ability| (scale_ability(ability, EquipSlot::ActiveOffhand), true)) .or_else(|| { ability_set(EquipSlot::ActiveMainhand) - .map(|abilities| abilities.secondary.ability.clone()) + .and_then(|abilities| abilities.secondary(context).map(unwrap_ability)) + .and_then(unlocked) .map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), false)) }), Ability::SpeciesMovement => matches!(body, Some(Body::Humanoid(_))) @@ -210,10 +213,10 @@ impl ActiveAbilities { .flat_map(|i| &i.item_config_expect().abilities.abilities) .enumerate() .filter_map(move |(i, a)| match a { - AuxiliaryAbilityKind::Simple(skill, _) => skill + AbilityKind::Simple(skill, _) => skill .map_or(true, |s| skill_set.map_or(false, |ss| ss.has_skill(s))) .then_some(i), - AuxiliaryAbilityKind::Contextualized(abilities) => abilities + AbilityKind::Contextualized(abilities) => abilities .values() .any(|(skill, _)| { skill.map_or(true, |s| skill_set.map_or(false, |ss| ss.has_skill(s))) @@ -257,46 +260,40 @@ pub enum Ability { } impl Ability { - pub fn ability_id( - self, - inv: Option<&Inventory>, - context: Option, - ) -> Option<&str> { + pub fn ability_id(self, inv: Option<&Inventory>, context: AbilityContext) -> Option<&str> { let ability_set = |equip_slot| { inv.and_then(|inv| inv.equipped(equip_slot)) .map(|i| &i.item_config_expect().abilities) }; - let contextual_id = |auxiliary_kind: Option<&AuxiliaryAbilityKind<_>>, equip_slot| { - matches!( - auxiliary_kind, - Some(AuxiliaryAbilityKind::Contextualized(_)) - ) - .then_some( - match inv.and_then(|inv| inv.equipped(equip_slot)).and_then(|i| { - if let ItemKind::Tool(tool) = &*i.kind() { - Some(tool.kind) - } else { - None - } - }) { - Some(ToolKind::Sword) => { - Some("veloren.core.pseudo_abilities.sword.stance_ability") + let contextual_id = |auxiliary_kind: Option<&AbilityKind<_>>, equip_slot| { + matches!(auxiliary_kind, Some(AbilityKind::Contextualized(_))) + .then_some( + match inv.and_then(|inv| inv.equipped(equip_slot)).and_then(|i| { + if let ItemKind::Tool(tool) = &*i.kind() { + Some(tool.kind) + } else { + None + } + }) { + Some(ToolKind::Sword) => { + Some("veloren.core.pseudo_abilities.sword.stance_ability") + }, + _ => None, }, - _ => None, - }, - ) - .flatten() + ) + .flatten() }; match self { Ability::ToolPrimary => ability_set(EquipSlot::ActiveMainhand) - .map(|abilities| abilities.primary.id.as_str()), + .and_then(|abilities| abilities.primary(context).map(|(_, a)| a.id.as_str())), Ability::ToolSecondary => ability_set(EquipSlot::ActiveOffhand) - .map(|abilities| abilities.secondary.id.as_str()) + .and_then(|abilities| abilities.secondary(context).map(|(_, a)| a.id.as_str())) .or_else(|| { - ability_set(EquipSlot::ActiveMainhand) - .map(|abilities| abilities.secondary.id.as_str()) + ability_set(EquipSlot::ActiveMainhand).and_then(|abilities| { + abilities.secondary(context).map(|(_, a)| a.id.as_str()) + }) }), Ability::SpeciesMovement => None, // TODO: Make not None Ability::MainWeaponAux(index) => { @@ -428,9 +425,7 @@ impl From<&CharacterState> for CharacterAbilityType { CharacterState::LeapMelee(data) => Self::LeapMelee(data.stage_section), CharacterState::LeapShockwave(data) => Self::LeapShockwave(data.stage_section), CharacterState::ComboMelee(data) => Self::ComboMelee(data.stage_section, data.stage), - CharacterState::ComboMelee2(data) => { - data.stage_section.map_or(Self::Other, Self::ComboMelee2) - }, + CharacterState::ComboMelee2(data) => Self::ComboMelee2(data.stage_section), CharacterState::FinisherMelee(data) => Self::FinisherMelee(data.stage_section), CharacterState::DiveMelee(data) => Self::DiveMelee(data.stage_section), CharacterState::RiposteMelee(data) => Self::RiposteMelee(data.stage_section), @@ -461,7 +456,8 @@ impl From<&CharacterState> for CharacterAbilityType { | CharacterState::UseItem(_) | CharacterState::SpriteInteract(_) | CharacterState::Skate(_) - | CharacterState::Wallrun(_) => Self::Other, + | CharacterState::Wallrun(_) + | CharacterState::BasicStance(_) => Self::Other, } } } @@ -565,8 +561,6 @@ pub enum CharacterAbility { }, ComboMelee2 { strikes: Vec>, - is_stance: bool, - stance: Option, energy_cost_per_strike: f32, #[serde(default)] meta: AbilityMeta, @@ -793,6 +787,12 @@ pub enum CharacterAbility { #[serde(default)] meta: AbilityMeta, }, + BasicStance { + buildup_duration: f32, + stance: Stance, + #[serde(default)] + meta: AbilityMeta, + }, } impl Default for CharacterAbility { @@ -847,9 +847,11 @@ impl CharacterAbility { | CharacterAbility::BasicBlock { energy_cost, .. } | CharacterAbility::SelfBuff { energy_cost, .. } | CharacterAbility::RiposteMelee { energy_cost, .. } - | CharacterAbility::RapidMelee { energy_cost, .. } => { - update.energy.try_change_by(-*energy_cost).is_ok() - }, + | CharacterAbility::RapidMelee { energy_cost, .. } + | CharacterAbility::ComboMelee2 { + energy_cost_per_strike: energy_cost, + .. + } => update.energy.try_change_by(-*energy_cost).is_ok(), // Consumes energy within state, so value only checked before entering state CharacterAbility::RepeaterRanged { energy_cost, .. } => { update.energy.current() >= *energy_cost @@ -869,22 +871,6 @@ impl CharacterAbility { | !*scales_with_combo) && update.energy.try_change_by(-*energy_cost).is_ok() }, - CharacterAbility::ComboMelee2 { - is_stance, - energy_cost_per_strike, - .. - } => { - // If it is a stance, just check that enough energy is present, otherwise - // consume the required energy now - if *is_stance { - update.energy.current() > *energy_cost_per_strike - } else { - update - .energy - .try_change_by(-*energy_cost_per_strike) - .is_ok() - } - }, CharacterAbility::FinisherMelee { energy_cost, minimum_combo, @@ -907,7 +893,8 @@ impl CharacterAbility { | CharacterAbility::Blink { .. } | CharacterAbility::Music { .. } | CharacterAbility::BasicSummon { .. } - | CharacterAbility::SpriteSummon { .. } => true, + | CharacterAbility::SpriteSummon { .. } + | CharacterAbility::BasicStance { .. } => true, } } @@ -1083,10 +1070,8 @@ impl CharacterAbility { }, ComboMelee2 { ref mut strikes, - is_stance: _, ref mut energy_cost_per_strike, meta: _, - stance: _, } => { *energy_cost_per_strike /= stats.energy_efficiency; *strikes = strikes @@ -1463,6 +1448,13 @@ impl CharacterAbility { *energy_cost /= stats.energy_efficiency; *melee_constructor = melee_constructor.adjusted_by_stats(stats); }, + BasicStance { + ref mut buildup_duration, + stance: _, + meta: _, + } => { + *buildup_duration /= stats.speed; + }, } self } @@ -1504,7 +1496,8 @@ impl CharacterAbility { | Blink { .. } | Music { .. } | BasicSummon { .. } - | SpriteSummon { .. } => 0.0, + | SpriteSummon { .. } + | BasicStance { .. } => 0.0, } } @@ -1545,7 +1538,8 @@ impl CharacterAbility { | Blink { .. } | Music { .. } | BasicSummon { .. } - | SpriteSummon { .. } => 0, + | SpriteSummon { .. } + | BasicStance { .. } => 0, } } @@ -1578,7 +1572,8 @@ impl CharacterAbility { | Music { meta, .. } | DiveMelee { meta, .. } | RiposteMelee { meta, .. } - | RapidMelee { meta, .. } => *meta, + | RapidMelee { meta, .. } + | BasicStance { meta, .. } => *meta, } } @@ -2274,14 +2269,10 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { CharacterAbility::ComboMelee2 { strikes, energy_cost_per_strike, - is_stance, - stance, meta: _, } => CharacterState::ComboMelee2(combo_melee2::Data { static_data: combo_melee2::StaticData { strikes: strikes.iter().map(|s| s.to_duration()).collect(), - is_stance: *is_stance, - stance: *stance, energy_cost_per_strike: *energy_cost_per_strike, ability_info, }, @@ -2291,15 +2282,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { // 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 { - if matches!(data.character, CharacterState::Wielding(_)) { - Some(StageSection::Ready) - } else { - None - } - } else { - Some(StageSection::Buildup) - }, + stage_section: StageSection::Buildup, completed_strikes: 0, }), CharacterAbility::LeapMelee { @@ -2806,6 +2789,18 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { stage_section: StageSection::Buildup, exhausted: false, }), + CharacterAbility::BasicStance { + buildup_duration, + stance, + meta: _, + } => CharacterState::BasicStance(basic_stance::Data { + static_data: basic_stance::StaticData { + buildup_duration: Duration::from_secs_f32(*buildup_duration), + stance: *stance, + ability_info, + }, + timer: Duration::default(), + }), } } } diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 6928570902..882d25ed27 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -143,6 +143,8 @@ pub enum CharacterState { /// A series of consecutive, identical attacks that only go through buildup /// and recover once for the entire state RapidMelee(rapid_melee::Data), + /// Causes the character to enter a new stance, or leave the current stance + BasicStance(basic_stance::Data), } impl CharacterState { @@ -182,6 +184,7 @@ impl CharacterState { | CharacterState::DiveMelee(_) | CharacterState::RiposteMelee(_) | CharacterState::RapidMelee(_) + | CharacterState::BasicStance(_) ) } @@ -263,6 +266,7 @@ impl CharacterState { | CharacterState::DiveMelee(_) | CharacterState::RiposteMelee(_) | CharacterState::RapidMelee(_) + | CharacterState::BasicStance(_) ) } @@ -290,7 +294,7 @@ impl CharacterState { pub fn is_parry(&self) -> bool { let from_capability = if let Some(capabilities) = self .ability_info() - .and_then(|a| a.ability_meta) + .map(|a| a.ability_meta) .map(|m| m.capabilities) { capabilities.contains(Capability::BUILDUP_PARRIES) @@ -343,7 +347,7 @@ impl CharacterState { pub fn is_forced_movement(&self) -> bool { matches!(self, CharacterState::ComboMelee(s) if s.stage_section == StageSection::Action) - || matches!(self, CharacterState::ComboMelee2(s) if s.stage_section == Some(StageSection::Action)) + || matches!(self, CharacterState::ComboMelee2(s) if s.stage_section == StageSection::Action) || matches!(self, CharacterState::DashMelee(s) if s.stage_section == StageSection::Charge) || matches!(self, CharacterState::LeapMelee(s) if s.stage_section == StageSection::Movement) || matches!(self, CharacterState::SpinMelee(s) if s.stage_section == StageSection::Action) @@ -394,6 +398,7 @@ impl CharacterState { | CharacterState::Music(_) | CharacterState::RiposteMelee(_) | CharacterState::RapidMelee(_) + | CharacterState::BasicStance(_) ) } @@ -462,6 +467,7 @@ impl CharacterState { CharacterState::DiveMelee(data) => data.behavior(j, output_events), CharacterState::RiposteMelee(data) => data.behavior(j, output_events), CharacterState::RapidMelee(data) => data.behavior(j, output_events), + CharacterState::BasicStance(data) => data.behavior(j, output_events), } } @@ -516,6 +522,7 @@ impl CharacterState { CharacterState::DiveMelee(data) => data.handle_event(j, output_events, action), CharacterState::RiposteMelee(data) => data.handle_event(j, output_events, action), CharacterState::RapidMelee(data) => data.handle_event(j, output_events, action), + CharacterState::BasicStance(data) => data.handle_event(j, output_events, action), } } @@ -536,7 +543,7 @@ impl CharacterState { CharacterState::Skate(_) => None, CharacterState::Glide(_) => None, CharacterState::GlideWield(_) => None, - CharacterState::Stunned(data) => Some(data.static_data.ability_info), + CharacterState::Stunned(_) => None, CharacterState::Sit => None, CharacterState::Dance => None, CharacterState::BasicBlock(data) => Some(data.static_data.ability_info), @@ -562,13 +569,14 @@ impl CharacterState { CharacterState::BasicSummon(data) => Some(data.static_data.ability_info), CharacterState::SelfBuff(data) => Some(data.static_data.ability_info), CharacterState::SpriteSummon(data) => Some(data.static_data.ability_info), - CharacterState::UseItem(data) => Some(data.static_data.ability_info), - CharacterState::SpriteInteract(data) => Some(data.static_data.ability_info), + CharacterState::UseItem(_) => None, + CharacterState::SpriteInteract(_) => None, CharacterState::FinisherMelee(data) => Some(data.static_data.ability_info), CharacterState::Music(data) => Some(data.static_data.ability_info), CharacterState::DiveMelee(data) => Some(data.static_data.ability_info), CharacterState::RiposteMelee(data) => Some(data.static_data.ability_info), CharacterState::RapidMelee(data) => Some(data.static_data.ability_info), + CharacterState::BasicStance(data) => Some(data.static_data.ability_info), } } @@ -586,10 +594,10 @@ impl CharacterState { CharacterState::Dance => None, CharacterState::BasicBlock(data) => Some(data.stage_section), CharacterState::Roll(data) => Some(data.stage_section), + CharacterState::Equipping(_) => Some(StageSection::Buildup), CharacterState::Wielding(_) => None, - CharacterState::Equipping(_) => None, CharacterState::ComboMelee(data) => Some(data.stage_section), - CharacterState::ComboMelee2(data) => data.stage_section, + CharacterState::ComboMelee2(data) => Some(data.stage_section), CharacterState::BasicMelee(data) => Some(data.stage_section), CharacterState::BasicRanged(data) => Some(data.stage_section), CharacterState::Boost(_) => None, @@ -614,6 +622,7 @@ impl CharacterState { CharacterState::DiveMelee(data) => Some(data.stage_section), CharacterState::RiposteMelee(data) => Some(data.stage_section), CharacterState::RapidMelee(data) => Some(data.stage_section), + CharacterState::BasicStance(_) => Some(StageSection::Buildup), } } @@ -645,7 +654,10 @@ impl CharacterState { ..Default::default() }), CharacterState::Wielding(_) => None, - CharacterState::Equipping(_) => None, + CharacterState::Equipping(data) => Some(DurationsInfo { + buildup: Some(data.static_data.buildup_duration), + ..Default::default() + }), CharacterState::ComboMelee(data) => { let stage_index = data.stage_index(); let stage = data.static_data.stage_data[stage_index]; @@ -662,10 +674,6 @@ impl CharacterState { buildup: Some(strike.buildup_duration), action: Some(strike.swing_duration), recover: Some(strike.recover_duration), - ready: data - .static_data - .is_stance - .then_some(combo_melee2::STANCE_ENTER_TIME), ..Default::default() }) }, @@ -809,6 +817,10 @@ impl CharacterState { recover: Some(data.static_data.recover_duration), ..Default::default() }), + CharacterState::BasicStance(data) => Some(DurationsInfo { + buildup: Some(data.static_data.buildup_duration), + ..Default::default() + }), } } @@ -854,15 +866,7 @@ impl CharacterState { CharacterState::DiveMelee(data) => Some(data.timer), CharacterState::RiposteMelee(data) => Some(data.timer), CharacterState::RapidMelee(data) => Some(data.timer), - } - } - - // Determines if a character state should be returned to when using another - // ability from that character state - pub fn should_be_returned_to(&self) -> bool { - match self { - CharacterState::ComboMelee2(data) => data.static_data.is_stance, - _ => false, + CharacterState::BasicStance(data) => Some(data.timer), } } } @@ -874,7 +878,6 @@ pub struct DurationsInfo { pub recover: Option, pub movement: Option, pub charge: Option, - pub ready: Option, } #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq)] diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 1d76745219..d959e39c71 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -281,22 +281,22 @@ impl Tool { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AbilitySet { - pub primary: T, - pub secondary: T, - pub abilities: Vec>, + pub primary: AbilityKind, + pub secondary: AbilityKind, + pub abilities: Vec>, } #[derive(Clone, Debug, Serialize, Deserialize)] -pub enum AuxiliaryAbilityKind { +pub enum AbilityKind { Simple(Option, T), Contextualized(HashMap, T)>), } -impl AuxiliaryAbilityKind { - pub fn map U>(self, mut f: F) -> AuxiliaryAbilityKind { +impl AbilityKind { + pub fn map U>(self, mut f: F) -> AbilityKind { match self { - Self::Simple(s, x) => AuxiliaryAbilityKind::::Simple(s, f(x)), - Self::Contextualized(abilities) => AuxiliaryAbilityKind::::Contextualized( + Self::Simple(s, x) => AbilityKind::::Simple(s, f(x)), + Self::Contextualized(abilities) => AbilityKind::::Contextualized( abilities .into_iter() .map(|(c, (s, x))| (c, (s, f(x)))) @@ -305,10 +305,10 @@ impl AuxiliaryAbilityKind { } } - pub fn map_ref U>(&self, mut f: F) -> AuxiliaryAbilityKind { + pub fn map_ref U>(&self, mut f: F) -> AbilityKind { match self { - Self::Simple(s, x) => AuxiliaryAbilityKind::::Simple(*s, f(x)), - Self::Contextualized(abilities) => AuxiliaryAbilityKind::::Contextualized( + Self::Simple(s, x) => AbilityKind::::Simple(*s, f(x)), + Self::Contextualized(abilities) => AbilityKind::::Contextualized( abilities .into_iter() .map(|(c, (s, x))| (*c, (*s, f(x)))) @@ -317,12 +317,10 @@ impl AuxiliaryAbilityKind { } } - pub fn ability(&self, context: Option) -> Option<(Option, &T)> { + pub fn ability(&self, context: AbilityContext) -> Option<(Option, &T)> { match self { - AuxiliaryAbilityKind::Simple(s, a) => Some((*s, a)), - AuxiliaryAbilityKind::Contextualized(abilities) => { - context.and_then(|c| abilities.get(&c).map(|(s, a)| (*s, a))) - }, + AbilityKind::Simple(s, a) => Some((*s, a)), + AbilityKind::Contextualized(abilities) => abilities.get(&context).map(|(s, a)| (*s, a)), } } } @@ -330,11 +328,16 @@ impl AuxiliaryAbilityKind { #[derive(Clone, Debug, Serialize, Deserialize, Copy, Eq, PartialEq, Hash)] pub enum AbilityContext { Stance(Stance), + None, } impl AbilityContext { - pub fn try_from(stance: Option<&Stance>) -> Option { - stance.map(|stance| Self::Stance(*stance)) + pub fn from(stance: Option<&Stance>) -> Self { + match stance { + Some(Stance::None) => AbilityContext::None, + Some(stance) => AbilityContext::Stance(*stance), + None => AbilityContext::None, + } } } @@ -351,25 +354,29 @@ impl AbilitySet { impl AbilitySet { pub fn map U>(self, mut f: F) -> AbilitySet { AbilitySet { - primary: f(self.primary), - secondary: f(self.secondary), + primary: self.primary.map(&mut f), + secondary: self.secondary.map(&mut f), abilities: self.abilities.into_iter().map(|x| x.map(&mut f)).collect(), } } pub fn map_ref U>(&self, mut f: F) -> AbilitySet { AbilitySet { - primary: f(&self.primary), - secondary: f(&self.secondary), + primary: self.primary.map_ref(&mut f), + secondary: self.secondary.map_ref(&mut f), abilities: self.abilities.iter().map(|x| x.map_ref(&mut f)).collect(), } } - pub fn auxiliary( - &self, - index: usize, - context: Option, - ) -> Option<(Option, &T)> { + pub fn primary(&self, context: AbilityContext) -> Option<(Option, &T)> { + self.primary.ability(context) + } + + pub fn secondary(&self, context: AbilityContext) -> Option<(Option, &T)> { + self.secondary.ability(context) + } + + pub fn auxiliary(&self, index: usize, context: AbilityContext) -> Option<(Option, &T)> { self.abilities.get(index).and_then(|a| a.ability(context)) } } @@ -377,14 +384,14 @@ impl AbilitySet { impl Default for AbilitySet { fn default() -> Self { AbilitySet { - primary: AbilityItem { + primary: AbilityKind::Simple(None, AbilityItem { id: String::new(), ability: CharacterAbility::default(), - }, - secondary: AbilityItem { + }), + secondary: AbilityKind::Simple(None, AbilityItem { id: String::new(), ability: CharacterAbility::default(), - }, + }), abilities: Vec::new(), } } diff --git a/common/src/comp/poise.rs b/common/src/comp/poise.rs index cfeb9fedb0..8fdc8a9ca6 100644 --- a/common/src/comp/poise.rs +++ b/common/src/comp/poise.rs @@ -78,11 +78,7 @@ pub enum PoiseState { impl PoiseState { /// Returns the optional stunned character state and duration of stun, and /// optional impulse strength corresponding to a particular poise state - pub fn poise_effect( - &self, - was_wielded: bool, - ability_info: states::utils::AbilityInfo, - ) -> (Option<(CharacterState, f64)>, Option) { + pub fn poise_effect(&self, was_wielded: bool) -> (Option<(CharacterState, f64)>, Option) { use states::{ stunned::{Data, StaticData}, utils::StageSection, @@ -117,7 +113,6 @@ impl PoiseState { recover_duration, movement_speed, poise_state: *self, - ability_info, }, timer: Duration::default(), stage_section: StageSection::Buildup, @@ -285,7 +280,7 @@ impl Poise { let from_char = { let resistant = char_state .and_then(|cs| cs.ability_info()) - .and_then(|a| a.ability_meta) + .map(|a| a.ability_meta) .map_or(false, |a| { a.capabilities.contains(Capability::POISE_RESISTANT) }); diff --git a/common/src/comp/skillset/skills.rs b/common/src/comp/skillset/skills.rs index 7b04e1ad98..6a74c18b56 100644 --- a/common/src/comp/skillset/skills.rs +++ b/common/src/comp/skillset/skills.rs @@ -28,32 +28,32 @@ pub enum Skill { #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)] pub enum SwordSkill { BalancedFinisher, - OffensiveCombo, + OffensiveStance, OffensiveFinisher, OffensiveAdvance, - CripplingCombo, + CripplingStance, CripplingFinisher, CripplingStrike, CripplingGouge, - CleavingCombo, + CleavingStance, CleavingFinisher, CleavingSpin, CleavingDive, - DefensiveCombo, + DefensiveStance, DefensiveBulwark, DefensiveRetreat, - ParryingCombo, + ParryingStance, ParryingParry, ParryingRiposte, ParryingCounter, - HeavyCombo, + HeavyStance, HeavyFinisher, HeavyPommelStrike, HeavyFortitude, - MobilityCombo, + MobilityStance, MobilityFeint, MobilityAgility, - ReachingCombo, + ReachingStance, ReachingCharge, ReachingFlurry, ReachingSkewer, diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index b000a3727f..c710eeca76 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -96,11 +96,7 @@ impl CharacterBehavior for Data { } }, StageSection::Action => { - if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) + if input_is_pressed(data, self.static_data.ability_info.input) && (self.static_data.energy_drain <= f32::EPSILON || update.energy.current() > 0.0) { diff --git a/common/src/states/basic_block.rs b/common/src/states/basic_block.rs index 1c7d5222b3..0aada76601 100644 --- a/common/src/states/basic_block.rs +++ b/common/src/states/basic_block.rs @@ -74,11 +74,7 @@ impl CharacterBehavior for Data { }, StageSection::Action => { if self.static_data.can_hold - && self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) + && input_is_pressed(data, self.static_data.ability_info.input) { // Block update.character = CharacterState::BasicBlock(Data { diff --git a/common/src/states/basic_melee.rs b/common/src/states/basic_melee.rs index b6b57caf64..b134cf737c 100644 --- a/common/src/states/basic_melee.rs +++ b/common/src/states/basic_melee.rs @@ -118,12 +118,7 @@ impl CharacterBehavior for Data { }); } else { // Done - if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - { + if input_is_pressed(data, self.static_data.ability_info.input) { reset_state(self, data, output_events, &mut update); } else { end_melee_ability(data, &mut update); @@ -149,7 +144,10 @@ fn reset_state( output_events: &mut OutputEvents, update: &mut StateUpdate, ) { - if let Some(input) = data.static_data.ability_info.input { - handle_input(join, output_events, update, input); - } + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); } diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index 678d6bb2e4..86c6b5fa61 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -127,12 +127,7 @@ impl CharacterBehavior for Data { }); } else { // Done - if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - { + if input_is_pressed(data, self.static_data.ability_info.input) { reset_state(self, data, output_events, &mut update); } else { end_ability(data, &mut update); @@ -158,7 +153,10 @@ fn reset_state( output_events: &mut OutputEvents, update: &mut StateUpdate, ) { - if let Some(input) = data.static_data.ability_info.input { - handle_input(join, output_events, update, input); - } + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); } diff --git a/common/src/states/basic_stance.rs b/common/src/states/basic_stance.rs new file mode 100644 index 0000000000..ab1c17f283 --- /dev/null +++ b/common/src/states/basic_stance.rs @@ -0,0 +1,52 @@ +use super::utils::*; +use crate::{ + comp::{character_state::OutputEvents, CharacterState, Stance, StateUpdate}, + event::ServerEvent, + states::behavior::{CharacterBehavior, JoinData}, +}; +use serde::{Deserialize, Serialize}; +use std::time::Duration; + +/// Separated out to condense update portions of character state +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct StaticData { + pub buildup_duration: Duration, + pub stance: Stance, + pub ability_info: AbilityInfo, +} + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Data { + pub static_data: StaticData, + pub timer: Duration, +} + +impl CharacterBehavior for Data { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { + let mut update = StateUpdate::from(data); + + handle_orientation(data, &mut update, 1.0, None); + handle_move(data, &mut update, 1.0); + handle_jump(data, output_events, &mut update, 1.0); + handle_interrupts(data, &mut update); + + if self.timer < self.static_data.buildup_duration { + if let CharacterState::BasicStance(c) = &mut update.character { + c.timer = tick_attack_or_default(data, self.timer, None); + } + } else { + let stance = if Some(self.static_data.stance) == data.stance.copied() { + Stance::None + } else { + self.static_data.stance + }; + output_events.emit_server(ServerEvent::ChangeStance { + entity: data.entity, + stance, + }); + end_ability(data, &mut update); + } + + update + } +} diff --git a/common/src/states/boost.rs b/common/src/states/boost.rs index b14ceb7adf..b453cb061f 100644 --- a/common/src/states/boost.rs +++ b/common/src/states/boost.rs @@ -46,12 +46,7 @@ impl CharacterBehavior for Data { }); } else { // Done - if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - { + if input_is_pressed(data, self.static_data.ability_info.input) { reset_state(self, data, output_events, &mut update); } else { update.vel.0 = update.vel.0.try_normalized().unwrap_or_default() @@ -74,7 +69,10 @@ fn reset_state( output_events: &mut OutputEvents, update: &mut StateUpdate, ) { - if let Some(input) = data.static_data.ability_info.input { - handle_input(join, output_events, update, input); - } + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); } diff --git a/common/src/states/charged_melee.rs b/common/src/states/charged_melee.rs index e99d508223..d750916a62 100644 --- a/common/src/states/charged_melee.rs +++ b/common/src/states/charged_melee.rs @@ -61,11 +61,7 @@ impl CharacterBehavior for Data { match self.stage_section { StageSection::Charge => { - if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) + if input_is_pressed(data, self.static_data.ability_info.input) && update.energy.current() >= self.static_data.energy_cost && self.timer < self.static_data.charge_duration { @@ -84,11 +80,7 @@ impl CharacterBehavior for Data { update .energy .change_by(-self.static_data.energy_drain * data.dt.0); - } else if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) + } else if input_is_pressed(data, self.static_data.ability_info.input) && update.energy.current() >= self.static_data.energy_cost { // Maintains charge diff --git a/common/src/states/charged_ranged.rs b/common/src/states/charged_ranged.rs index 4f70b7ef66..c625ea1278 100644 --- a/common/src/states/charged_ranged.rs +++ b/common/src/states/charged_ranged.rs @@ -99,13 +99,7 @@ impl CharacterBehavior for Data { } }, StageSection::Charge => { - if !self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - && !self.exhausted - { + if !input_is_pressed(data, self.static_data.ability_info.input) && !self.exhausted { let charge_frac = self.charge_frac(); let arrow = ProjectileConstructor::Arrow { damage: self.static_data.initial_damage @@ -148,11 +142,7 @@ impl CharacterBehavior for Data { ..*self }); } else if self.timer < self.static_data.charge_duration - && self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) + && input_is_pressed(data, self.static_data.ability_info.input) { // Charges update.character = CharacterState::ChargedRanged(Data { @@ -164,12 +154,7 @@ impl CharacterBehavior for Data { update .energy .change_by(-self.static_data.energy_drain * data.dt.0); - } else if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - { + } else if input_is_pressed(data, self.static_data.ability_info.input) { // Holds charge update.character = CharacterState::ChargedRanged(Data { timer: tick_attack_or_default(data, self.timer, None), diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index 6afd41d9cc..0ab6bb72fa 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -342,12 +342,7 @@ impl CharacterBehavior for Data { }); } else { // Done - if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - { + if input_is_pressed(data, self.static_data.ability_info.input) { reset_state(self, data, output_events, &mut update); } else { end_melee_ability(data, &mut update); @@ -385,11 +380,14 @@ fn reset_state( output_events: &mut OutputEvents, update: &mut StateUpdate, ) { - if let Some(input) = data.static_data.ability_info.input { - handle_input(join, output_events, update, input); + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); - if let CharacterState::ComboMelee(c) = &mut update.character { - c.stage = (data.stage % data.static_data.num_stages) + 1; - } + if let CharacterState::ComboMelee(c) = &mut update.character { + c.stage = (data.stage % data.static_data.num_stages) + 1; } } diff --git a/common/src/states/combo_melee2.rs b/common/src/states/combo_melee2.rs index 99780a8726..d75d9d0bba 100644 --- a/common/src/states/combo_melee2.rs +++ b/common/src/states/combo_melee2.rs @@ -1,19 +1,11 @@ use crate::{ comp::{ - character_state::OutputEvents, - slot::{EquipSlot, Slot}, - tool::Stats, - CharacterState, InputAttr, InputKind, InventoryAction, MeleeConstructor, Stance, - StateUpdate, + character_state::OutputEvents, tool::Stats, CharacterState, MeleeConstructor, StateUpdate, }, - event::ServerEvent, states::{ behavior::{CharacterBehavior, JoinData}, - idle, utils::*, - wielding, }, - uid::Uid, }; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -82,12 +74,6 @@ pub struct StrikeMovement { pub struct StaticData { /// Data for each stage pub strikes: Vec>, - /// Whether or not combo melee should function as a stance (where it remains - /// in the character state after a strike has finished) - pub is_stance: bool, - /// If a stance is added, character state will attempt to enter that stance - /// if not already in it - pub stance: Option, /// The amount of energy consumed with each swing pub energy_cost_per_strike: f32, /// What key is used to press ability @@ -108,64 +94,24 @@ pub struct Data { pub timer: Duration, /// Checks what section a strike is in, if a strike is currently being /// performed - pub stage_section: Option, + pub stage_section: StageSection, /// Index of the strike that is currently in progress, or if not in a strike /// currently the next strike that will occur pub completed_strikes: usize, } -pub const STANCE_ENTER_TIME: Duration = Duration::from_millis(250); -pub const STANCE_LEAVE_TIME: Duration = Duration::from_secs(30); - impl CharacterBehavior for Data { - fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { + fn behavior(&self, data: &JoinData, _output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); - if let Some(stance) = self.static_data.stance { - if data.stance != Some(&stance) { - output_events.emit_server(ServerEvent::ChangeStance { - entity: data.entity, - stance, - }); - } - } - - // If is a stance, use M1 to control strikes, otherwise use the input that - // activated the ability - let ability_input = if self.static_data.is_stance { - InputKind::Primary - } else { - self.static_data - .ability_info - .input - .unwrap_or(InputKind::Primary) - }; - handle_orientation(data, &mut update, 1.0, None); - let move_eff = if self.stage_section.is_some() { - 0.7 - } else { - 1.0 - }; - handle_move(data, &mut update, move_eff); - let interrupted = handle_interrupts(data, &mut update); + handle_move(data, &mut update, 0.7); + handle_interrupts(data, &mut update); let strike_data = self.strike_data(); match self.stage_section { - Some(StageSection::Ready) => { - // Adds a small duration to entering a stance to discourage spam swapping - // stances for ability activation benefits of matching stance - if self.timer < STANCE_ENTER_TIME { - if let CharacterState::ComboMelee2(c) = &mut update.character { - c.timer = tick_attack_or_default(data, self.timer, None); - } - } else if let CharacterState::ComboMelee2(c) = &mut update.character { - c.timer = Duration::default(); - c.stage_section = None; - } - }, - Some(StageSection::Buildup) => { + StageSection::Buildup => { if let Some(movement) = strike_data.movement.buildup { handle_forced_movement(data, &mut update, movement); } @@ -178,15 +124,15 @@ impl CharacterBehavior for Data { // Transitions to swing section of stage if let CharacterState::ComboMelee2(c) = &mut update.character { c.timer = Duration::default(); - c.stage_section = Some(StageSection::Action); + c.stage_section = StageSection::Action; } } }, - Some(StageSection::Action) => { + StageSection::Action => { if let Some(movement) = strike_data.movement.swing { handle_forced_movement(data, &mut update, movement); } - if input_is_pressed(data, ability_input) { + if input_is_pressed(data, self.static_data.ability_info.input) { if let CharacterState::ComboMelee2(c) = &mut update.character { // Only have the next strike skip the recover period of this strike if not // every strike in the combo is complete yet @@ -221,16 +167,16 @@ impl CharacterBehavior for Data { if let CharacterState::ComboMelee2(c) = &mut update.character { c.completed_strikes += 1; } - next_strike(&mut update); + next_strike(data, &mut update); } else { // Transitions to recover section of stage if let CharacterState::ComboMelee2(c) = &mut update.character { c.timer = Duration::default(); - c.stage_section = Some(StageSection::Recover); + c.stage_section = StageSection::Recover; } } }, - Some(StageSection::Recover) => { + StageSection::Recover => { if let Some(movement) = strike_data.movement.recover { handle_forced_movement(data, &mut update, movement); } @@ -240,174 +186,18 @@ impl CharacterBehavior for Data { c.timer = tick_attack_or_default(data, self.timer, None); } } else { - // If is a stance, stay in combo melee, otherwise return to wielding - if self.static_data.is_stance { - if let CharacterState::ComboMelee2(c) = &mut update.character { - c.timer = Duration::default(); - c.stage_section = None; - c.completed_strikes = 0; - } - } else { - // Return to wielding - end_melee_ability(data, &mut update); - } + // Return to wielding + end_melee_ability(data, &mut update); } }, - Some(_) => { + _ => { // If it somehow ends up in an incorrect stage section end_melee_ability(data, &mut update); }, - None => { - if self.timer < STANCE_LEAVE_TIME { - if let CharacterState::ComboMelee2(c) = &mut update.character { - c.timer = tick_attack_or_default(data, self.timer, None); - } - } else { - // Done - end_melee_ability(data, &mut update); - } - - handle_climb(data, &mut update); - handle_jump(data, output_events, &mut update, 1.0); - - if input_is_pressed(data, ability_input) { - next_strike(&mut update) - } else if !self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - && !interrupted - { - attempt_input(data, output_events, &mut update); - } - }, } update } - - fn start_input( - &self, - data: &JoinData, - input: InputKind, - target_entity: Option, - select_pos: Option>, - ) -> StateUpdate { - let mut update = StateUpdate::from(data); - - if matches!(data.character, CharacterState::ComboMelee2(data) if data.static_data.ability_info.input == Some(input) && input != InputKind::Primary && data.stage_section.is_none()) - { - end_melee_ability(data, &mut update); - } else { - update.queued_inputs.insert(input, InputAttr { - select_pos, - target_entity, - }); - } - update - } - - fn swap_equipped_weapons(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { - let mut update = StateUpdate::from(data); - if let CharacterState::ComboMelee2(c) = data.character { - if c.stage_section.is_none() { - update.character = CharacterState::Wielding(wielding::Data { - is_sneaking: data.character.is_stealthy(), - }); - attempt_swap_equipped_weapons(data, &mut update); - } - } - update - } - - fn unwield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { - let mut update = StateUpdate::from(data); - if let CharacterState::ComboMelee2(c) = data.character { - if c.stage_section.is_none() { - update.character = CharacterState::Idle(idle::Data { - is_sneaking: data.character.is_stealthy(), - footwear: None, - }); - } - } - update - } - - fn manipulate_loadout( - &self, - data: &JoinData, - output_events: &mut OutputEvents, - inv_action: InventoryAction, - ) -> StateUpdate { - let mut update = StateUpdate::from(data); - if let CharacterState::ComboMelee2(c) = data.character { - if c.stage_section.is_none() { - let reset_to_idle = match inv_action { - InventoryAction::Drop(slot) - | InventoryAction::Swap(slot, _) - | InventoryAction::Swap(_, Slot::Equip(slot)) - if matches!(slot, EquipSlot::ActiveMainhand | EquipSlot::ActiveOffhand) => - { - true - }, - InventoryAction::Use(_) => true, - _ => false, - }; - if reset_to_idle { - update.character = CharacterState::Idle(idle::Data { - is_sneaking: data.character.is_stealthy(), - footwear: None, - }); - } - handle_manipulate_loadout(data, output_events, &mut update, inv_action); - } - } - update - } - - fn glide_wield(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { - let mut update = StateUpdate::from(data); - if let CharacterState::ComboMelee2(c) = data.character { - if c.stage_section.is_none() { - attempt_glide_wield(data, &mut update, output_events); - } - } - update - } - - fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { - let mut update = StateUpdate::from(data); - if let CharacterState::ComboMelee2(c) = data.character { - if c.stage_section.is_none() { - attempt_sit(data, &mut update); - } - } - update - } - - fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { - let mut update = StateUpdate::from(data); - if let CharacterState::ComboMelee2(c) = data.character { - if c.stage_section.is_none() { - attempt_dance(data, &mut update); - } - } - update - } - - fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { - let mut update = StateUpdate::from(data); - if let CharacterState::ComboMelee2(c) = data.character { - if c.stage_section.is_none() - && data.physics.on_ground.is_some() - && data.body.is_humanoid() - { - update.character = CharacterState::Wielding(wielding::Data { is_sneaking: true }); - } - } - update - } } impl Data { @@ -416,7 +206,7 @@ impl Data { } } -fn next_strike(update: &mut StateUpdate) { +fn next_strike(data: &JoinData, update: &mut StateUpdate) { let revert_to_wield = if let CharacterState::ComboMelee2(c) = &mut update.character { if update .energy @@ -426,7 +216,7 @@ fn next_strike(update: &mut StateUpdate) { c.exhausted = false; c.start_next_strike = false; c.timer = Duration::default(); - c.stage_section = Some(StageSection::Buildup); + c.stage_section = StageSection::Buildup; false } else { true @@ -435,6 +225,6 @@ fn next_strike(update: &mut StateUpdate) { false }; if revert_to_wield { - update.character = CharacterState::Wielding(wielding::Data { is_sneaking: false }); + end_melee_ability(data, update) } } diff --git a/common/src/states/dash_melee.rs b/common/src/states/dash_melee.rs index b4e7ed61cf..f3c292cb1a 100644 --- a/common/src/states/dash_melee.rs +++ b/common/src/states/dash_melee.rs @@ -81,11 +81,7 @@ impl CharacterBehavior for Data { } else { // Transitions to charge section of stage update.character = CharacterState::DashMelee(Data { - auto_charge: !self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)), + auto_charge: !input_is_pressed(data, self.static_data.ability_info.input), timer: Duration::default(), stage_section: StageSection::Charge, ..*self @@ -94,11 +90,7 @@ impl CharacterBehavior for Data { }, StageSection::Charge => { if self.timer < self.charge_end_timer - && (self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) + && (input_is_pressed(data, self.static_data.ability_info.input) || (self.auto_charge && self.timer < self.static_data.charge_duration)) && update.energy.current() > 0.0 { diff --git a/common/src/states/mod.rs b/common/src/states/mod.rs index 4a49159f19..a31d386d6e 100644 --- a/common/src/states/mod.rs +++ b/common/src/states/mod.rs @@ -3,6 +3,7 @@ pub mod basic_beam; pub mod basic_block; pub mod basic_melee; pub mod basic_ranged; +pub mod basic_stance; pub mod basic_summon; pub mod behavior; pub mod blink; diff --git a/common/src/states/music.rs b/common/src/states/music.rs index 9c081ccc82..fceedcc5bc 100644 --- a/common/src/states/music.rs +++ b/common/src/states/music.rs @@ -56,12 +56,7 @@ impl CharacterBehavior for Data { }); } else { // Done - if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - { + if input_is_pressed(data, self.static_data.ability_info.input) { reset_state(self, data, output_events, &mut update); } else { end_ability(data, &mut update); @@ -75,12 +70,7 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - if !self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) - { + if !input_is_pressed(data, self.static_data.ability_info.input) { handle_dodge_input(data, &mut update); } @@ -94,7 +84,10 @@ fn reset_state( output_events: &mut OutputEvents, update: &mut StateUpdate, ) { - if let Some(input) = data.static_data.ability_info.input { - handle_input(join, output_events, update, input); - } + handle_input( + join, + output_events, + update, + data.static_data.ability_info.input, + ); } diff --git a/common/src/states/repeater_ranged.rs b/common/src/states/repeater_ranged.rs index b4735748b4..e20362c339 100644 --- a/common/src/states/repeater_ranged.rs +++ b/common/src/states/repeater_ranged.rs @@ -87,11 +87,7 @@ impl CharacterBehavior for Data { .unwrap_or_default(), ..*self }); - } else if self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)) + } else if input_is_pressed(data, self.static_data.ability_info.input) && update.energy.current() >= self.static_data.energy_cost { // Fire if input is pressed still diff --git a/common/src/states/spin_melee.rs b/common/src/states/spin_melee.rs index 0a3da2d7f2..5eadcd2f9b 100644 --- a/common/src/states/spin_melee.rs +++ b/common/src/states/spin_melee.rs @@ -121,11 +121,7 @@ impl CharacterBehavior for Data { } else if update.energy.current() >= self.static_data.energy_cost && (self.consecutive_spins < self.static_data.num_spins || (self.static_data.is_infinite - && self - .static_data - .ability_info - .input - .map_or(false, |input| input_is_pressed(data, input)))) + && input_is_pressed(data, self.static_data.ability_info.input))) { update.character = CharacterState::SpinMelee(Data { timer: Duration::default(), diff --git a/common/src/states/sprite_interact.rs b/common/src/states/sprite_interact.rs index 78e7673b65..64e01e076b 100644 --- a/common/src/states/sprite_interact.rs +++ b/common/src/states/sprite_interact.rs @@ -39,8 +39,6 @@ pub struct StaticData { /// /// If third field is true, item should be consumed on collection pub required_item: Option<(ItemDefinitionIdOwned, InvSlotId, bool)>, - /// Miscellaneous information about the ability - pub ability_info: AbilityInfo, } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/common/src/states/stunned.rs b/common/src/states/stunned.rs index bdb3f0caf8..0f6d9eb65f 100644 --- a/common/src/states/stunned.rs +++ b/common/src/states/stunned.rs @@ -17,8 +17,6 @@ pub struct StaticData { pub movement_speed: f32, /// Poise state (used for determining animation in the client) pub poise_state: PoiseState, - /// Miscellaneous information about the ability - pub ability_info: AbilityInfo, } #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/common/src/states/use_item.rs b/common/src/states/use_item.rs index af2f1726a5..bd3297d319 100644 --- a/common/src/states/use_item.rs +++ b/common/src/states/use_item.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; /// Separated out to condense update portions of character state -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct StaticData { /// Buildup to item use pub buildup_duration: Duration, @@ -34,11 +34,9 @@ pub struct StaticData { pub was_wielded: bool, /// Was sneaking pub was_sneak: bool, - /// Miscellaneous information about the ability - pub ability_info: AbilityInfo, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Data { /// Struct containing data that does not change over the course of the /// character state diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index efd1e6f6ec..2d52c5de44 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -667,7 +667,9 @@ pub fn fly_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) /// Checks if an input related to an attack is held. If one is, moves entity /// into wielding state pub fn handle_wield(data: &JoinData<'_>, update: &mut StateUpdate) { - if data.controller.queued_inputs.keys().any(|i| i.is_ability()) { + if data.controller.queued_inputs.keys().any(|i| i.is_ability()) + || data.controller.held_inputs.keys().any(|i| i.is_ability()) + { attempt_wield(data, update); } } @@ -818,7 +820,6 @@ pub fn handle_manipulate_loadout( item_hash: item.item_hash(), was_wielded: data.character.is_wield(), was_sneak: data.character.is_stealthy(), - ability_info: AbilityInfo::from_forced_state_change(data.character), }, timer: Duration::default(), stage_section: StageSection::Buildup, @@ -950,9 +951,6 @@ pub fn handle_manipulate_loadout( was_wielded: data.character.is_wield(), was_sneak: data.character.is_stealthy(), required_item, - ability_info: AbilityInfo::from_forced_state_change( - data.character, - ), }, timer: Duration::default(), stage_section: StageSection::Buildup, @@ -1034,7 +1032,7 @@ pub fn handle_jump( } fn handle_ability(data: &JoinData<'_>, update: &mut StateUpdate, input: InputKind) -> bool { - let context = AbilityContext::try_from(data.stance); + let context = AbilityContext::from(data.stance); if let Some(ability_input) = input.into() { if let Some((ability, from_offhand)) = data .active_abilities @@ -1090,7 +1088,13 @@ pub fn attempt_input( update: &mut StateUpdate, ) { // TODO: look into using first() when it becomes stable - if let Some(input) = data.controller.queued_inputs.keys().next() { + if let Some(input) = data + .controller + .queued_inputs + .keys() + .next() + .or_else(|| data.controller.held_inputs.keys().next()) + { handle_input(data, output_events, update, *input); } } @@ -1134,11 +1138,7 @@ pub fn handle_dodge_input(data: &JoinData<'_>, update: &mut StateUpdate) -> bool update.used_inputs.push(InputKind::Roll); if let CharacterState::Roll(roll) = &mut update.character { if let CharacterState::ComboMelee(c) = data.character { - roll.was_combo = c - .static_data - .ability_info - .input - .map(|input| (input, c.stage)); + roll.was_combo = Some((c.static_data.ability_info.input, c.stage)); roll.was_wielded = true; } else { if data.character.is_wield() { @@ -1170,7 +1170,7 @@ pub fn handle_interrupts(data: &JoinData, update: &mut StateUpdate) -> bool { let interruptible = data .character .ability_info() - .and_then(|info| info.ability_meta) + .map(|info| info.ability_meta) .map_or(false, |meta| { meta.capabilities.contains(Capability::ROLL_INTERRUPT) }); @@ -1179,7 +1179,7 @@ pub fn handle_interrupts(data: &JoinData, update: &mut StateUpdate) -> bool { let can_block = data .character .ability_info() - .and_then(|info| info.ability_meta) + .map(|info| info.ability_meta) .map_or(false, |meta| { meta.capabilities.contains(Capability::BLOCK_INTERRUPT) }); @@ -1313,7 +1313,6 @@ pub enum StageSection { Charge, Movement, Action, - Ready, } #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] @@ -1359,11 +1358,10 @@ impl MovementDirection { pub struct AbilityInfo { pub tool: Option, pub hand: Option, - pub input: Option, + pub input: InputKind, pub input_attr: Option, - pub ability_meta: Option, + pub ability_meta: AbilityMeta, pub ability: Option, - pub return_ability: Option, } impl AbilityInfo { @@ -1388,78 +1386,32 @@ impl AbilityInfo { .zip(data.active_abilities) .map(|(i, a)| a.get_ability(i, data.inventory, Some(data.skill_set))); - let return_ability = if data.character.should_be_returned_to() { - data.character.ability_info().and_then(|info| info.input) - } else { - None - }; - Self { tool, hand, - input: Some(input), - input_attr: data.controller.queued_inputs.get(&input).copied(), - ability_meta: Some(ability_meta), + input, + input_attr: data + .controller + .queued_inputs + .get(&input) + .or_else(|| data.controller.held_inputs.get(&input)) + .copied(), + ability_meta, ability, - return_ability, - } - } - - pub fn from_forced_state_change(char_state: &CharacterState) -> Self { - let return_ability = if char_state.should_be_returned_to() { - char_state.ability_info().and_then(|info| info.input) - } else { - 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, - input: None, - input_attr: None, - ability_meta: None, - ability: None, - return_ability, } } } pub fn end_ability(data: &JoinData<'_>, update: &mut StateUpdate) { - // If an ability has a return ability specified, and is not itself an ability - // that should be returned to (to prevent bouncing between two abilities), - // attempt to return to the specified ability, otherwise return to wield or idle - // depending on whether or not leaving a wield state - let returned = if let Some(return_ability) = (!data.character.should_be_returned_to()) - .then_some( - data.character - .ability_info() - .and_then(|info| info.return_ability), - ) - .flatten() - { - handle_ability(data, update, return_ability) + if data.character.is_wield() || data.character.was_wielded() { + update.character = CharacterState::Wielding(wielding::Data { + is_sneaking: data.character.is_stealthy(), + }); } else { - false - }; - if !returned { - if data.character.is_wield() || data.character.was_wielded() { - update.character = CharacterState::Wielding(wielding::Data { - is_sneaking: data.character.is_stealthy(), - }); - } else { - update.character = CharacterState::Idle(idle::Data { - is_sneaking: data.character.is_stealthy(), - footwear: None, - }); - } + update.character = CharacterState::Idle(idle::Data { + is_sneaking: data.character.is_stealthy(), + footwear: None, + }); } } diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index 9b1c7aa79e..26580d7e0c 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -19,7 +19,7 @@ use common::{ resources::{DeltaTime, Time}, states::{ behavior::{JoinData, JoinStruct}, - idle, utils, + idle, }, terrain::TerrainGrid, uid::Uid, @@ -152,11 +152,10 @@ impl<'a> System<'a> for Sys { // Enter stunned state if poise damage is enough if let Some(mut poise) = poises.get_mut(entity) { let was_wielded = char_state.is_wield(); - let ability_info = utils::AbilityInfo::from_forced_state_change(&char_state); let poise_state = poise.poise_state(); let pos = pos.0; if let (Some((stunned_state, stunned_duration)), impulse_strength) = - poise_state.poise_effect(was_wielded, ability_info) + poise_state.poise_effect(was_wielded) { // Reset poise if there is some stunned state to apply poise.reset(*read_data.time, stunned_duration); diff --git a/common/systems/src/stats.rs b/common/systems/src/stats.rs index ae123ba5aa..ce52e21839 100644 --- a/common/systems/src/stats.rs +++ b/common/systems/src/stats.rs @@ -9,7 +9,6 @@ use common::{ }, event::{EventBus, ServerEvent}, resources::{DeltaTime, EntitiesDiedLastTick, Time}, - states, }; use common_ecs::{Job, Origin, Phase, System}; use specs::{ @@ -163,11 +162,7 @@ impl<'a> System<'a> for Sys { | CharacterState::GlideWield(_) | CharacterState::Wielding(_) | CharacterState::Equipping(_) - | CharacterState::Boost(_) - | CharacterState::ComboMelee2(states::combo_melee2::Data { - stage_section: None, - .. - }) => { + | CharacterState::Boost(_) => { if energy.needs_regen() { energy.regen(ENERGY_REGEN_ACCEL, dt); } @@ -199,7 +194,8 @@ impl<'a> System<'a> for Sys { | CharacterState::FinisherMelee(_) | CharacterState::DiveMelee(_) | CharacterState::RiposteMelee(_) - | CharacterState::RapidMelee(_) => { + | CharacterState::RapidMelee(_) + | CharacterState::BasicStance(_) => { if energy.needs_regen_rate_reset() { energy.reset_regen_rate(); } diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index fe2d7d1403..3027048df0 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -820,7 +820,7 @@ impl<'a> AgentData<'a> { && self .char_state .ability_info() - .and_then(|a| a.ability_meta) + .map(|a| a.ability_meta) .map(|m| m.capabilities) .map_or(false, |c| c.contains(Capability::BLOCK_INTERRUPT)) } else { @@ -843,7 +843,7 @@ impl<'a> AgentData<'a> { agent.action_state.conditions[CONDITION_HOLD] = false; agent.action_state.timers[TIMER_HOLD_TIMEOUT] = 0.0; } else if matches!( - self.char_state.ability_info().and_then(|info| info.input), + self.char_state.ability_info().map(|info| info.input), Some(InputKind::Ability(1)) ) { // If used defensive retreat, stand still for a little bit to bait people @@ -927,7 +927,7 @@ impl<'a> AgentData<'a> { && self .char_state .ability_info() - .and_then(|a| a.ability_meta) + .map(|a| a.ability_meta) .map(|m| m.capabilities) .map_or(false, |c| c.contains(Capability::ROLL_INTERRUPT)); if try_roll { @@ -1617,7 +1617,7 @@ impl<'a> AgentData<'a> { enum ActionStateConditions { ConditionStaffCanShockwave = 0, } - let context = AbilityContext::try_from(self.stance); + let context = AbilityContext::from(self.stance); let extract_ability = |input: AbilityInput| { self.active_abilities .activate_ability( diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 6676b4caed..bb90451f0e 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -27,7 +27,7 @@ use common::{ outcome::{HealthChangeInfo, Outcome}, resources::{Secs, Time}, rtsim::RtSimEntity, - states::utils::{AbilityInfo, StageSection}, + states::utils::StageSection, terrain::{Block, BlockKind, TerrainGrid}, uid::{Uid, UidAllocator}, util::Dir, @@ -1245,27 +1245,12 @@ pub fn handle_parry_hook(server: &Server, defender: EcsEntity, attacker: Option< .write_storage::() .get_mut(defender) { - let should_return = char_state - .ability_info() - .and_then(|info| info.return_ability) - .is_some(); - let return_to_wield = match &mut *char_state { CharacterState::RiposteMelee(c) => { c.stage_section = StageSection::Action; c.timer = Duration::default(); false }, - CharacterState::BasicBlock(c) if should_return => { - c.timer = c.static_data.recover_duration; - c.stage_section = StageSection::Recover; - // Refund half the energy of entering the block for a successful parry - server_eventbus.emit_now(ServerEvent::EnergyChange { - entity: defender, - change: c.static_data.energy_cost / 2.0, - }); - false - }, CharacterState::BasicBlock(c) => { // Refund half the energy of entering the block for a successful parry server_eventbus.emit_now(ServerEvent::EnergyChange { @@ -1280,7 +1265,7 @@ pub fn handle_parry_hook(server: &Server, defender: EcsEntity, attacker: Option< // defender if char_state .ability_info() - .and_then(|info| info.ability_meta) + .map(|info| info.ability_meta) .map_or(false, |meta| { meta.capabilities .contains(comp::ability::Capability::BUILDUP_PARRIES) @@ -1374,9 +1359,8 @@ pub fn handle_entity_attacked_hook(server: &Server, entity: EcsEntity) { ) { let poise_state = comp::poise::PoiseState::Interrupted; let was_wielded = char_state.is_wield(); - let ability_info = AbilityInfo::from_forced_state_change(&char_state); if let (Some((stunned_state, stunned_duration)), impulse_strength) = - poise_state.poise_effect(was_wielded, ability_info) + poise_state.poise_effect(was_wielded) { // Reset poise if there is some stunned state to apply poise.reset(*time, stunned_duration); diff --git a/voxygen/src/hud/diary.rs b/voxygen/src/hud/diary.rs index bc82e03b3b..aa9d685b5b 100644 --- a/voxygen/src/hud/diary.rs +++ b/voxygen/src/hud/diary.rs @@ -242,7 +242,7 @@ pub struct Diary<'a> { tooltip_manager: &'a mut TooltipManager, slot_manager: &'a mut SlotManager, pulse: f32, - context: Option, + context: AbilityContext, #[conrod(common_builder)] common: widget::CommonBuilder, @@ -288,7 +288,7 @@ impl<'a> Diary<'a> { tooltip_manager: &'a mut TooltipManager, slot_manager: &'a mut SlotManager, pulse: f32, - context: Option, + context: AbilityContext, ) -> Self { Self { show, @@ -1596,7 +1596,7 @@ impl<'a> Diary<'a> { position: TopLeftWithMarginsOn(state.ids.sword_bg, 489.0, 462.0), }, SkillIcon::Ability { - skill: Skill::Sword(SwordSkill::OffensiveCombo), + skill: Skill::Sword(SwordSkill::OffensiveStance), ability_id: "common.abilities.sword.offensive_combo", position: TopLeftWithMarginsOn(state.ids.sword_bg, 389.0, 313.0), }, @@ -1611,7 +1611,7 @@ impl<'a> Diary<'a> { position: TopLeftWithMarginsOn(state.ids.sword_bg, 489.0, 361.0), }, SkillIcon::Ability { - skill: Skill::Sword(SwordSkill::CripplingCombo), + skill: Skill::Sword(SwordSkill::CripplingStance), ability_id: "common.abilities.sword.crippling_combo", position: TopLeftWithMarginsOn(state.ids.sword_bg, 289.0, 164.0), }, @@ -1631,7 +1631,7 @@ impl<'a> Diary<'a> { position: TopLeftWithMarginsOn(state.ids.sword_bg, 2.0, 164.0), }, SkillIcon::Ability { - skill: Skill::Sword(SwordSkill::CleavingCombo), + skill: Skill::Sword(SwordSkill::CleavingStance), ability_id: "common.abilities.sword.cleaving_combo", position: TopLeftWithMarginsOn(state.ids.sword_bg, 289.0, 15.0), }, @@ -1651,7 +1651,7 @@ impl<'a> Diary<'a> { position: TopLeftWithMarginsOn(state.ids.sword_bg, 2.0, 15.0), }, SkillIcon::Ability { - skill: Skill::Sword(SwordSkill::DefensiveCombo), + skill: Skill::Sword(SwordSkill::DefensiveStance), ability_id: "common.abilities.sword.defensive_combo", position: TopLeftWithMarginsOn(state.ids.sword_bg, 389.0, 611.0), }, @@ -1666,7 +1666,7 @@ impl<'a> Diary<'a> { position: TopLeftWithMarginsOn(state.ids.sword_bg, 489.0, 563.0), }, SkillIcon::Ability { - skill: Skill::Sword(SwordSkill::ParryingCombo), + skill: Skill::Sword(SwordSkill::ParryingStance), ability_id: "common.abilities.sword.parrying_combo", position: TopLeftWithMarginsOn(state.ids.sword_bg, 289.0, 760.0), }, @@ -1686,7 +1686,7 @@ impl<'a> Diary<'a> { position: TopLeftWithMarginsOn(state.ids.sword_bg, 2.0, 760.0), }, SkillIcon::Ability { - skill: Skill::Sword(SwordSkill::HeavyCombo), + skill: Skill::Sword(SwordSkill::HeavyStance), ability_id: "common.abilities.sword.heavy_combo", position: TopLeftWithMarginsOn(state.ids.sword_bg, 289.0, 909.0), }, @@ -1706,7 +1706,7 @@ impl<'a> Diary<'a> { position: TopLeftWithMarginsOn(state.ids.sword_bg, 2.0, 909.0), }, SkillIcon::Ability { - skill: Skill::Sword(SwordSkill::MobilityCombo), + skill: Skill::Sword(SwordSkill::MobilityStance), ability_id: "common.abilities.sword.mobility_combo", position: TopLeftWithMarginsOn(state.ids.sword_bg, 289.0, 462.0), }, @@ -1721,7 +1721,7 @@ impl<'a> Diary<'a> { position: TopLeftWithMarginsOn(state.ids.sword_bg, 289.0, 611.0), }, SkillIcon::Ability { - skill: Skill::Sword(SwordSkill::ReachingCombo), + skill: Skill::Sword(SwordSkill::ReachingStance), ability_id: "common.abilities.sword.reaching_combo", position: TopLeftWithMarginsOn(state.ids.sword_bg, 141.0, 462.0), }, diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index bd8514e189..d5085a2b92 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -2995,7 +2995,7 @@ impl Hud { skillsets.get(entity), bodies.get(entity), ) { - let context = AbilityContext::try_from(stances.get(entity)); + let context = AbilityContext::from(stances.get(entity)); match Skillbar::new( client, &info, @@ -3466,7 +3466,7 @@ impl Hud { bodies.get(entity), poises.get(entity), ) { - let context = AbilityContext::try_from(stances.get(entity)); + let context = AbilityContext::from(stances.get(entity)); for event in Diary::new( &self.show, client, diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 72f909e0f7..20ae896017 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -310,7 +310,7 @@ pub struct Skillbar<'a> { common: widget::CommonBuilder, msm: &'a MaterialStatManifest, combo_floater: Option, - context: Option, + context: AbilityContext, combo: Option<&'a Combo>, } @@ -341,7 +341,7 @@ impl<'a> Skillbar<'a> { localized_strings: &'a Localization, msm: &'a MaterialStatManifest, combo_floater: Option, - context: Option, + context: AbilityContext, combo: Option<&'a Combo>, ) -> Self { Self { diff --git a/voxygen/src/hud/slots.rs b/voxygen/src/hud/slots.rs index 2e26f1e71c..c07c4dc9f6 100644 --- a/voxygen/src/hud/slots.rs +++ b/voxygen/src/hud/slots.rs @@ -128,7 +128,7 @@ type HotbarSource<'a> = ( &'a SkillSet, Option<&'a ActiveAbilities>, &'a Body, - Option, + AbilityContext, Option<&'a Combo>, ); type HotbarImageSource<'a> = (&'a ItemImgs, &'a img_ids::Imgs); @@ -219,7 +219,7 @@ type AbilitiesSource<'a> = ( &'a ActiveAbilities, &'a Inventory, &'a SkillSet, - Option, + AbilityContext, ); impl<'a> SlotKey, img_ids::Imgs> for AbilitySlot { diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index 0863a42d3b..3fdb476b35 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -346,31 +346,39 @@ pub fn ability_image(imgs: &img_ids::Imgs, ability_id: &str) -> image::Id { "common.abilities.sword.balanced_thrust" => imgs.sword_balanced_thrust, "common.abilities.sword.balanced_finisher" => imgs.sword_balanced_finisher, "common.abilities.sword.offensive_combo" => imgs.sword_offensive_combo, + "common.abilities.sword.offensive_stance" => imgs.sword_offensive_combo, "common.abilities.sword.offensive_finisher" => imgs.sword_offensive_finisher, "common.abilities.sword.offensive_advance" => imgs.sword_offensive_advance, "common.abilities.sword.crippling_combo" => imgs.sword_crippling_combo, + "common.abilities.sword.crippling_stance" => imgs.sword_crippling_combo, "common.abilities.sword.crippling_finisher" => imgs.sword_crippling_finisher, "common.abilities.sword.crippling_strike" => imgs.sword_crippling_strike, "common.abilities.sword.crippling_gouge" => imgs.sword_crippling_gouge, "common.abilities.sword.cleaving_combo" => imgs.sword_cleaving_combo, + "common.abilities.sword.cleaving_stance" => imgs.sword_cleaving_combo, "common.abilities.sword.cleaving_finisher" => imgs.sword_cleaving_finisher, "common.abilities.sword.cleaving_spin" => imgs.sword_cleaving_spin, "common.abilities.sword.cleaving_dive" => imgs.sword_cleaving_dive, "common.abilities.sword.defensive_combo" => imgs.sword_defensive_combo, + "common.abilities.sword.defensive_stance" => imgs.sword_defensive_combo, "common.abilities.sword.defensive_bulwark" => imgs.sword_defensive_bulwark, "common.abilities.sword.defensive_retreat" => imgs.sword_defensive_retreat, "common.abilities.sword.parrying_combo" => imgs.sword_parrying_combo, + "common.abilities.sword.parrying_stance" => imgs.sword_parrying_combo, "common.abilities.sword.parrying_parry" => imgs.sword_parrying_parry, "common.abilities.sword.parrying_riposte" => imgs.sword_parrying_riposte, "common.abilities.sword.parrying_counter" => imgs.sword_parrying_counter, "common.abilities.sword.heavy_combo" => imgs.sword_heavy_combo, + "common.abilities.sword.heavy_stance" => imgs.sword_heavy_combo, "common.abilities.sword.heavy_finisher" => imgs.sword_heavy_finisher, "common.abilities.sword.heavy_pommelstrike" => imgs.sword_heavy_pommelstrike, "common.abilities.sword.heavy_fortitude" => imgs.sword_heavy_fortitude, "common.abilities.sword.mobility_combo" => imgs.sword_mobility_combo, + "common.abilities.sword.mobility_stance" => imgs.sword_mobility_combo, "common.abilities.sword.mobility_feint" => imgs.sword_mobility_feint, "common.abilities.sword.mobility_agility" => imgs.sword_mobility_agility, "common.abilities.sword.reaching_combo" => imgs.sword_reaching_combo, + "common.abilities.sword.reaching_stance" => imgs.sword_reaching_combo, "common.abilities.sword.reaching_charge" => imgs.sword_reaching_charge, "common.abilities.sword.reaching_flurry" => imgs.sword_reaching_flurry, "common.abilities.sword.reaching_skewer" => imgs.sword_reaching_skewer, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 525ed2f280..f172233601 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -920,7 +920,7 @@ impl FigureMgr { let second_tool_spec = second_tool_spec.as_deref(); let hands = (active_tool_hand, second_tool_hand); - let context = AbilityContext::try_from(stance); + let context = AbilityContext::from(stance); let ability_id = character.and_then(|c| { c.ability_info() @@ -1759,45 +1759,38 @@ impl FigureMgr { } }, CharacterState::ComboMelee2(s) => { - if matches!( - s.stage_section, - Some( - StageSection::Buildup - | StageSection::Action - | StageSection::Recover - ) - ) { - let timer = s.timer.as_secs_f32(); - let current_strike = - s.completed_strikes % s.static_data.strikes.len(); - let strike_data = s.static_data.strikes[current_strike]; - let progress = match s.stage_section { - Some(StageSection::Buildup) => { - timer / strike_data.buildup_duration.as_secs_f32() - }, - Some(StageSection::Action) => { - timer / strike_data.swing_duration.as_secs_f32() - }, - Some(StageSection::Recover) => { - timer / strike_data.recover_duration.as_secs_f32() - }, - _ => 0.0, - }; + let timer = s.timer.as_secs_f32(); + let current_strike = s.completed_strikes % s.static_data.strikes.len(); + let strike_data = s.static_data.strikes[current_strike]; + let progress = match s.stage_section { + StageSection::Buildup => { + timer / strike_data.buildup_duration.as_secs_f32() + }, + StageSection::Action => { + timer / strike_data.swing_duration.as_secs_f32() + }, + StageSection::Recover => { + timer / strike_data.recover_duration.as_secs_f32() + }, + _ => 0.0, + }; - anim::character::ComboAnimation::update_skeleton( - &target_base, - ( - ability_id, - s.stage_section, - Some(s.static_data.ability_info), - current_strike, - move_dir, - ), - progress, - &mut state_animation_rate, - skeleton_attr, - ) - } else if physics.in_liquid().is_some() { + anim::character::ComboAnimation::update_skeleton( + &target_base, + ( + ability_id, + Some(s.stage_section), + Some(s.static_data.ability_info), + current_strike, + move_dir, + ), + progress, + &mut state_animation_rate, + skeleton_attr, + ) + }, + CharacterState::BasicStance(_) => { + if physics.in_liquid().is_some() { anim::character::SwimWieldAnimation::update_skeleton( &target_base, ( @@ -1811,25 +1804,6 @@ impl FigureMgr { &mut state_animation_rate, skeleton_attr, ) - } else if false { - // Check for sneaking here if we want combo melee 2 to be able to - // sneak when not actively swinging - anim::character::SneakWieldAnimation::update_skeleton( - &target_base, - ( - (active_tool_kind, active_tool_spec), - second_tool_kind, - hands, - rel_vel, - // TODO: Update to use the quaternion. - ori * anim::vek::Vec3::::unit_y(), - state.last_ori * anim::vek::Vec3::::unit_y(), - time, - ), - state.state_time, - &mut state_animation_rate, - skeleton_attr, - ) } else { anim::character::WieldAnimation::update_skeleton( &target_base,