Primary and secondary abilities can now be contextual. BasicStance character state added.

This commit is contained in:
Sam 2022-10-30 14:40:20 -04:00
parent 9875008efa
commit b376228d45
70 changed files with 673 additions and 953 deletions

View File

@ -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: [],
),
})

View File

@ -35,6 +35,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
energy_cost_per_strike: 0,
)

View File

@ -47,7 +47,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
stance: Some(Sword(Cleaving)),
energy_cost_per_strike: 5,
)

View File

@ -19,6 +19,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 20,
)

View File

@ -0,0 +1,4 @@
BasicStance(
buildup_duration: 0.25,
stance: Sword(Cleaving),
)

View File

@ -47,7 +47,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
stance: Some(Sword(Crippling)),
energy_cost_per_strike: 4,
)

View File

@ -24,6 +24,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 25,
)

View File

@ -0,0 +1,4 @@
BasicStance(
buildup_duration: 0.25,
stance: Sword(Crippling),
)

View File

@ -24,6 +24,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 25,
)

View File

@ -35,8 +35,6 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
stance: Some(Sword(Defensive)),
energy_cost_per_strike: 2,
meta: (
capabilities: (

View File

@ -23,6 +23,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 10,
)

View File

@ -0,0 +1,4 @@
BasicStance(
buildup_duration: 0.25,
stance: Sword(Defensive),
)

View File

@ -35,8 +35,6 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
stance: Some(Sword(Heavy)),
energy_cost_per_strike: 4,
meta: (
capabilities: (

View File

@ -18,6 +18,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 15,
)

View File

@ -0,0 +1,4 @@
BasicStance(
buildup_duration: 0.25,
stance: Sword(Heavy),
)

View File

@ -69,8 +69,6 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
stance: Some(Sword(Mobility)),
energy_cost_per_strike: 2,
meta: (
capabilities: (

View File

@ -23,6 +23,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 10,
)

View File

@ -0,0 +1,4 @@
BasicStance(
buildup_duration: 0.25,
stance: Sword(Mobility),
)

View File

@ -23,6 +23,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 10,
)

View File

@ -57,7 +57,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
stance: Some(Sword(Offensive)),
energy_cost_per_strike: 3,
)

View File

@ -0,0 +1,4 @@
BasicStance(
buildup_duration: 0.25,
stance: Sword(Offensive),
)

View File

@ -35,8 +35,6 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
stance: Some(Sword(Parrying)),
energy_cost_per_strike: 5,
meta: (
capabilities: (

View File

@ -24,6 +24,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 15,
)

View File

@ -0,0 +1,4 @@
BasicStance(
buildup_duration: 0.25,
stance: Sword(Parrying),
)

View File

@ -35,7 +35,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: true,
stance: Some(Sword(Reaching)),
energy_cost_per_strike: 4,
)

View File

@ -24,6 +24,5 @@ ComboMelee2(
ori_modifier: 0.6,
),
],
is_stance: false,
energy_cost_per_strike: 15,
)

View File

@ -0,0 +1,4 @@
BasicStance(
buildup_duration: 0.25,
stance: Sword(Reaching),
)

View File

@ -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},

View File

@ -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),

View File

@ -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)),
])

View File

@ -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)),
])

View File

@ -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)),

View File

@ -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)),

View File

@ -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),

View File

@ -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

View File

@ -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)
});

View File

@ -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<AbilityContext>,
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<AbilityContext>,
) -> 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<combo_melee2::Strike<f32>>,
is_stance: bool,
stance: Option<Stance>,
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(),
}),
}
}
}

View File

@ -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<Duration>,
pub movement: Option<Duration>,
pub charge: Option<Duration>,
pub ready: Option<Duration>,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq)]

View File

@ -281,22 +281,22 @@ impl Tool {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AbilitySet<T> {
pub primary: T,
pub secondary: T,
pub abilities: Vec<AuxiliaryAbilityKind<T>>,
pub primary: AbilityKind<T>,
pub secondary: AbilityKind<T>,
pub abilities: Vec<AbilityKind<T>>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AuxiliaryAbilityKind<T> {
pub enum AbilityKind<T> {
Simple(Option<Skill>, T),
Contextualized(HashMap<AbilityContext, (Option<Skill>, T)>),
}
impl<T> AuxiliaryAbilityKind<T> {
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> AuxiliaryAbilityKind<U> {
impl<T> AbilityKind<T> {
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> AbilityKind<U> {
match self {
Self::Simple(s, x) => AuxiliaryAbilityKind::<U>::Simple(s, f(x)),
Self::Contextualized(abilities) => AuxiliaryAbilityKind::<U>::Contextualized(
Self::Simple(s, x) => AbilityKind::<U>::Simple(s, f(x)),
Self::Contextualized(abilities) => AbilityKind::<U>::Contextualized(
abilities
.into_iter()
.map(|(c, (s, x))| (c, (s, f(x))))
@ -305,10 +305,10 @@ impl<T> AuxiliaryAbilityKind<T> {
}
}
pub fn map_ref<U, F: FnMut(&T) -> U>(&self, mut f: F) -> AuxiliaryAbilityKind<U> {
pub fn map_ref<U, F: FnMut(&T) -> U>(&self, mut f: F) -> AbilityKind<U> {
match self {
Self::Simple(s, x) => AuxiliaryAbilityKind::<U>::Simple(*s, f(x)),
Self::Contextualized(abilities) => AuxiliaryAbilityKind::<U>::Contextualized(
Self::Simple(s, x) => AbilityKind::<U>::Simple(*s, f(x)),
Self::Contextualized(abilities) => AbilityKind::<U>::Contextualized(
abilities
.into_iter()
.map(|(c, (s, x))| (*c, (*s, f(x))))
@ -317,12 +317,10 @@ impl<T> AuxiliaryAbilityKind<T> {
}
}
pub fn ability(&self, context: Option<AbilityContext>) -> Option<(Option<Skill>, &T)> {
pub fn ability(&self, context: AbilityContext) -> Option<(Option<Skill>, &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<T> AuxiliaryAbilityKind<T> {
#[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<Self> {
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<AbilityItem> {
impl<T> AbilitySet<T> {
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> AbilitySet<U> {
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, F: FnMut(&T) -> U>(&self, mut f: F) -> AbilitySet<U> {
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<AbilityContext>,
) -> Option<(Option<Skill>, &T)> {
pub fn primary(&self, context: AbilityContext) -> Option<(Option<Skill>, &T)> {
self.primary.ability(context)
}
pub fn secondary(&self, context: AbilityContext) -> Option<(Option<Skill>, &T)> {
self.secondary.ability(context)
}
pub fn auxiliary(&self, index: usize, context: AbilityContext) -> Option<(Option<Skill>, &T)> {
self.abilities.get(index).and_then(|a| a.ability(context))
}
}
@ -377,14 +384,14 @@ impl<T> AbilitySet<T> {
impl Default for AbilitySet<AbilityItem> {
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(),
}
}

View File

@ -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<f32>) {
pub fn poise_effect(&self, was_wielded: bool) -> (Option<(CharacterState, f64)>, Option<f32>) {
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)
});

View File

@ -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,

View File

@ -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)
{

View File

@ -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 {

View File

@ -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,
);
}

View File

@ -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,
);
}

View File

@ -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
}
}

View File

@ -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,
);
}

View File

@ -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

View File

@ -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),

View File

@ -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;
}
}

View File

@ -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<Strike<Duration>>,
/// 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<Stance>,
/// 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<StageSection>,
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<Uid>,
select_pos: Option<Vec3<f32>>,
) -> 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)
}
}

View File

@ -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
{

View File

@ -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;

View File

@ -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,
);
}

View File

@ -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

View File

@ -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(),

View File

@ -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)]

View File

@ -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)]

View File

@ -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

View File

@ -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<ToolKind>,
pub hand: Option<HandInfo>,
pub input: Option<InputKind>,
pub input: InputKind,
pub input_attr: Option<InputAttr>,
pub ability_meta: Option<AbilityMeta>,
pub ability_meta: AbilityMeta,
pub ability: Option<Ability>,
pub return_ability: Option<InputKind>,
}
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,
});
}
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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(

View File

@ -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::<comp::CharacterState>()
.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);

View File

@ -242,7 +242,7 @@ pub struct Diary<'a> {
tooltip_manager: &'a mut TooltipManager,
slot_manager: &'a mut SlotManager,
pulse: f32,
context: Option<AbilityContext>,
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<AbilityContext>,
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),
},

View File

@ -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,

View File

@ -310,7 +310,7 @@ pub struct Skillbar<'a> {
common: widget::CommonBuilder,
msm: &'a MaterialStatManifest,
combo_floater: Option<ComboFloater>,
context: Option<AbilityContext>,
context: AbilityContext,
combo: Option<&'a Combo>,
}
@ -341,7 +341,7 @@ impl<'a> Skillbar<'a> {
localized_strings: &'a Localization,
msm: &'a MaterialStatManifest,
combo_floater: Option<ComboFloater>,
context: Option<AbilityContext>,
context: AbilityContext,
combo: Option<&'a Combo>,
) -> Self {
Self {

View File

@ -128,7 +128,7 @@ type HotbarSource<'a> = (
&'a SkillSet,
Option<&'a ActiveAbilities>,
&'a Body,
Option<AbilityContext>,
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>,
AbilityContext,
);
impl<'a> SlotKey<AbilitiesSource<'a>, img_ids::Imgs> for AbilitySlot {

View File

@ -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,

View File

@ -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::<f32>::unit_y(),
state.last_ori * anim::vek::Vec3::<f32>::unit_y(),
time,
),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
)
} else {
anim::character::WieldAnimation::update_skeleton(
&target_base,