Added support for abilities being cheaper if activated from the correct stance

This commit is contained in:
Sam 2022-02-17 00:07:04 -05:00
parent 0ff06edcdc
commit af39287331
10 changed files with 251 additions and 84 deletions

View File

@ -3,7 +3,7 @@
({
Tool(Sword): (
primary: "common.abilities.sword.balancedstance",
secondary: "common.abilities.sword.balancedstance",
secondary: "common.abilities.sword.lunge",
abilities: [],
),
Tool(Axe): (

View File

@ -54,5 +54,6 @@ ComboMelee2(
forward_movement: 0.0,
ori_modifier: 0.6,
),
]
],
meta: Some(Sword(Balanced)),
)

View File

@ -0,0 +1,18 @@
// TODO: Make actual ability, just for testing right now
BasicMelee(
energy_cost: 50,
buildup_duration: 0.3,
swing_duration: 0.1,
recover_duration: 0.2,
melee_constructor: (
kind: Stab(
damage: 10,
poise: 0,
knockback: 0,
energy_regen: 0,
),
range: 5.0,
angle: 10.0,
),
meta: Some(Sword(Balanced)),
)

View File

@ -419,6 +419,7 @@ pub enum CharacterAbility {
recover_duration: f32,
melee_constructor: MeleeConstructor,
ori_modifier: f32,
meta: Option<AbilityMeta>,
},
BasicRanged {
energy_cost: f32,
@ -430,6 +431,7 @@ pub enum CharacterAbility {
projectile_speed: f32,
num_projectiles: u32,
projectile_spread: f32,
meta: Option<AbilityMeta>,
},
RepeaterRanged {
energy_cost: f32,
@ -442,12 +444,14 @@ pub enum CharacterAbility {
projectile_body: Body,
projectile_light: Option<LightEmitter>,
projectile_speed: f32,
meta: Option<AbilityMeta>,
},
Boost {
movement_duration: f32,
only_up: bool,
speed: f32,
max_exit_velocity: f32,
meta: Option<AbilityMeta>,
},
DashMelee {
energy_cost: f32,
@ -461,6 +465,7 @@ pub enum CharacterAbility {
ori_modifier: f32,
charge_through: bool,
is_interruptible: bool,
meta: Option<AbilityMeta>,
},
BasicBlock {
buildup_duration: f32,
@ -468,6 +473,7 @@ pub enum CharacterAbility {
max_angle: f32,
block_strength: f32,
energy_cost: f32,
meta: Option<AbilityMeta>,
},
Roll {
energy_cost: f32,
@ -476,6 +482,7 @@ pub enum CharacterAbility {
recover_duration: f32,
roll_strength: f32,
immune_melee: bool,
meta: Option<AbilityMeta>,
},
ComboMelee {
stage_data: Vec<combo_melee::Stage<f32>>,
@ -487,9 +494,11 @@ pub enum CharacterAbility {
scales_from_combo: u32,
is_interruptible: bool,
ori_modifier: f32,
meta: Option<AbilityMeta>,
},
ComboMelee2 {
strikes: Vec<combo_melee2::Strike<f32>>,
meta: Option<AbilityMeta>,
},
LeapMelee {
energy_cost: f32,
@ -500,6 +509,7 @@ pub enum CharacterAbility {
melee_constructor: MeleeConstructor,
forward_leap_strength: f32,
vertical_leap_strength: f32,
meta: Option<AbilityMeta>,
},
SpinMelee {
buildup_duration: f32,
@ -513,6 +523,7 @@ pub enum CharacterAbility {
num_spins: u32,
specifier: Option<spin_melee::FrontendSpecifier>,
melee_constructor: MeleeConstructor,
meta: Option<AbilityMeta>,
},
ChargedMelee {
energy_cost: f32,
@ -523,6 +534,7 @@ pub enum CharacterAbility {
recover_duration: f32,
melee_constructor: MeleeConstructor,
specifier: Option<charged_melee::FrontendSpecifier>,
meta: Option<AbilityMeta>,
},
ChargedRanged {
energy_cost: f32,
@ -541,6 +553,7 @@ pub enum CharacterAbility {
initial_projectile_speed: f32,
scaled_projectile_speed: f32,
move_speed: f32,
meta: Option<AbilityMeta>,
},
Shockwave {
energy_cost: f32,
@ -559,6 +572,7 @@ pub enum CharacterAbility {
damage_kind: DamageKind,
specifier: comp::shockwave::FrontendSpecifier,
damage_effect: Option<CombatEffect>,
meta: Option<AbilityMeta>,
},
BasicBeam {
buildup_duration: f32,
@ -573,6 +587,7 @@ pub enum CharacterAbility {
energy_drain: f32,
ori_rate: f32,
specifier: beam::FrontendSpecifier,
meta: Option<AbilityMeta>,
},
BasicAura {
buildup_duration: f32,
@ -585,11 +600,13 @@ pub enum CharacterAbility {
energy_cost: f32,
scales_with_combo: bool,
specifier: Option<aura::Specifier>,
meta: Option<AbilityMeta>,
},
Blink {
buildup_duration: f32,
recover_duration: f32,
max_range: f32,
meta: Option<AbilityMeta>,
},
BasicSummon {
buildup_duration: f32,
@ -599,6 +616,7 @@ pub enum CharacterAbility {
summon_distance: (f32, f32),
summon_info: basic_summon::SummonInfo,
duration: Option<Duration>,
meta: Option<AbilityMeta>,
},
SelfBuff {
buildup_duration: f32,
@ -608,6 +626,7 @@ pub enum CharacterAbility {
buff_strength: f32,
buff_duration: Option<f32>,
energy_cost: f32,
meta: Option<AbilityMeta>,
},
SpriteSummon {
buildup_duration: f32,
@ -616,6 +635,7 @@ pub enum CharacterAbility {
sprite: SpriteKind,
summon_distance: (f32, f32),
sparseness: f64,
meta: Option<AbilityMeta>,
},
Music {
play_duration: f32,
@ -643,6 +663,7 @@ impl Default for CharacterAbility {
damage_effect: None,
},
ori_modifier: 1.0,
meta: None,
}
}
}
@ -709,6 +730,7 @@ impl CharacterAbility {
recover_duration: 0.125,
roll_strength: 2.0,
immune_melee: true,
meta: None,
}
}
@ -719,6 +741,7 @@ impl CharacterAbility {
max_angle: 60.0,
block_strength: 0.5,
energy_cost: 2.5,
meta: None,
}
}
@ -733,6 +756,7 @@ impl CharacterAbility {
ref mut recover_duration,
ref mut melee_constructor,
ori_modifier: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
*swing_duration /= stats.speed;
@ -750,6 +774,7 @@ impl CharacterAbility {
ref mut projectile_speed,
num_projectiles: _,
projectile_spread: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
*recover_duration /= stats.speed;
@ -768,6 +793,7 @@ impl CharacterAbility {
projectile_body: _,
projectile_light: _,
ref mut projectile_speed,
meta: _,
} => {
*buildup_duration /= stats.speed;
*shoot_duration /= stats.speed;
@ -781,6 +807,7 @@ impl CharacterAbility {
only_up: _,
speed: ref mut boost_speed,
max_exit_velocity: _,
meta: _,
} => {
*movement_duration /= stats.speed;
*boost_speed *= stats.power;
@ -797,6 +824,7 @@ impl CharacterAbility {
ori_modifier: _,
charge_through: _,
is_interruptible: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
*swing_duration /= stats.speed;
@ -813,6 +841,7 @@ impl CharacterAbility {
// Block strength explicitly not modified by power, that will be a separate stat
block_strength: _,
ref mut energy_cost,
meta: _,
} => {
*buildup_duration /= stats.speed;
*recover_duration /= stats.speed;
@ -825,6 +854,7 @@ impl CharacterAbility {
ref mut recover_duration,
roll_strength: _,
immune_melee: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
*movement_duration /= stats.speed;
@ -841,13 +871,17 @@ impl CharacterAbility {
scales_from_combo: _,
is_interruptible: _,
ori_modifier: _,
meta: _,
} => {
*stage_data = stage_data
.iter_mut()
.map(|s| s.adjusted_by_stats(stats))
.collect();
},
ComboMelee2 { ref mut strikes } => {
ComboMelee2 {
ref mut strikes,
meta: _,
} => {
*strikes = strikes
.iter_mut()
.map(|s| s.adjusted_by_stats(stats))
@ -862,6 +896,7 @@ impl CharacterAbility {
ref mut melee_constructor,
forward_leap_strength: _,
vertical_leap_strength: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
*swing_duration /= stats.speed;
@ -881,6 +916,7 @@ impl CharacterAbility {
forward_speed: _,
num_spins: _,
specifier: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
*swing_duration /= stats.speed;
@ -897,6 +933,7 @@ impl CharacterAbility {
ref mut recover_duration,
ref mut melee_constructor,
specifier: _,
meta: _,
} => {
*swing_duration /= stats.speed;
*recover_duration /= stats.speed;
@ -921,6 +958,7 @@ impl CharacterAbility {
ref mut initial_projectile_speed,
ref mut scaled_projectile_speed,
move_speed: _,
meta: _,
} => {
*initial_damage *= stats.power;
*scaled_damage *= stats.power;
@ -948,6 +986,7 @@ impl CharacterAbility {
damage_kind: _,
specifier: _,
ref mut damage_effect,
meta: _,
} => {
*buildup_duration /= stats.speed;
*swing_duration /= stats.speed;
@ -979,6 +1018,7 @@ impl CharacterAbility {
ref mut energy_drain,
ori_rate: _,
specifier: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
*recover_duration /= stats.speed;
@ -1009,6 +1049,7 @@ impl CharacterAbility {
ref mut energy_cost,
scales_with_combo: _,
specifier: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
*cast_duration /= stats.speed;
@ -1030,6 +1071,7 @@ impl CharacterAbility {
ref mut buildup_duration,
ref mut recover_duration,
ref mut max_range,
meta: _,
} => {
*buildup_duration /= stats.speed;
*recover_duration /= stats.speed;
@ -1043,6 +1085,7 @@ impl CharacterAbility {
summon_distance: (ref mut inner_dist, ref mut outer_dist),
summon_info: _,
duration: _,
meta: _,
} => {
// TODO: Figure out how/if power should affect this
*buildup_duration /= stats.speed;
@ -1059,6 +1102,7 @@ impl CharacterAbility {
ref mut buff_strength,
buff_duration: _,
ref mut energy_cost,
meta: _,
} => {
*buff_strength *= stats.diminished_buff_strength();
*buildup_duration /= stats.speed;
@ -1073,6 +1117,7 @@ impl CharacterAbility {
sprite: _,
summon_distance: (ref mut inner_dist, ref mut outer_dist),
sparseness: _,
meta: _,
} => {
// TODO: Figure out how/if power should affect this
*buildup_duration /= stats.speed;
@ -1124,6 +1169,53 @@ impl CharacterAbility {
}
}
// TODO: Maybe consider making CharacterAbility a struct at some point?
pub fn ability_meta(&self) -> Option<AbilityMeta> {
use CharacterAbility::*;
match self {
BasicMelee { meta, .. }
| BasicRanged { meta, .. }
| RepeaterRanged { meta, .. }
| DashMelee { meta, .. }
| Roll { meta, .. }
| LeapMelee { meta, .. }
| SpinMelee { meta, .. }
| ChargedMelee { meta, .. }
| ChargedRanged { meta, .. }
| Shockwave { meta, .. }
| BasicAura { meta, .. }
| BasicBlock { meta, .. }
| SelfBuff { meta, .. }
| BasicBeam { meta, .. }
| Boost { meta, .. }
| ComboMelee { meta, .. }
| ComboMelee2 { meta, .. }
| Blink { meta, .. }
| BasicSummon { meta, .. }
| SpriteSummon { meta, .. } => *meta,
}
}
#[must_use]
pub fn contextualize(mut self, data: &JoinData) -> Self {
if let Some(ability_info) = data.character.ability_info() {
if let Some(AbilityMeta::Sword(old_stance)) = ability_info.ability_meta {
if matches!(self.ability_meta(), Some(AbilityMeta::Sword(new_stance)) if old_stance == new_stance)
{
const ENERGY_REDUCTION: f32 = 0.75;
use CharacterAbility::*;
match &mut self {
BasicMelee { energy_cost, .. } => {
*energy_cost *= ENERGY_REDUCTION;
},
_ => {},
}
}
}
}
self
}
#[must_use = "method returns new ability and doesn't mutate the original value"]
pub fn adjusted_by_skills(mut self, skillset: &SkillSet, tool: Option<ToolKind>) -> Self {
match tool {
@ -1649,6 +1741,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
melee_constructor,
ori_modifier,
energy_cost: _,
meta: _,
} => CharacterState::BasicMelee(basic_melee::Data {
static_data: basic_melee::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1672,6 +1765,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
energy_cost: _,
num_projectiles,
projectile_spread,
meta: _,
} => CharacterState::BasicRanged(basic_ranged::Data {
static_data: basic_ranged::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1693,6 +1787,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
only_up,
speed,
max_exit_velocity,
meta: _,
} => CharacterState::Boost(boost::Data {
static_data: boost::StaticData {
movement_duration: Duration::from_secs_f32(*movement_duration),
@ -1715,6 +1810,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
ori_modifier,
charge_through,
is_interruptible,
meta: _,
} => CharacterState::DashMelee(dash_melee::Data {
static_data: dash_melee::StaticData {
energy_drain: *energy_drain,
@ -1741,6 +1837,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
max_angle,
block_strength,
energy_cost,
meta: _,
} => CharacterState::BasicBlock(basic_block::Data {
static_data: basic_block::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1760,6 +1857,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
recover_duration,
roll_strength,
immune_melee,
meta: _,
} => CharacterState::Roll(roll::Data {
static_data: roll::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1785,6 +1883,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
scales_from_combo,
is_interruptible,
ori_modifier,
meta: _,
} => CharacterState::ComboMelee(combo_melee::Data {
static_data: combo_melee::StaticData {
num_stages: stage_data.len() as u32,
@ -1804,7 +1903,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
timer: Duration::default(),
stage_section: StageSection::Buildup,
}),
CharacterAbility::ComboMelee2 { strikes } => {
CharacterAbility::ComboMelee2 { strikes, meta: _ } => {
CharacterState::ComboMelee2(combo_melee2::Data {
static_data: combo_melee2::StaticData {
strikes: strikes.iter().map(|s| s.to_duration()).collect(),
@ -1813,7 +1912,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
exhausted: false,
skip_recover: false,
timer: Duration::default(),
stage_section: None,
stage_section: Some(StageSection::Buildup),
completed_strikes: 0,
})
},
@ -1826,6 +1925,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
melee_constructor,
forward_leap_strength,
vertical_leap_strength,
meta: _,
} => CharacterState::LeapMelee(leap_melee::Data {
static_data: leap_melee::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1853,6 +1953,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
forward_speed,
num_spins,
specifier,
meta: _,
} => CharacterState::SpinMelee(spin_melee::Data {
static_data: spin_melee::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1882,6 +1983,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
recover_duration,
melee_constructor,
specifier,
meta: _,
} => CharacterState::ChargedMelee(charged_melee::Data {
static_data: charged_melee::StaticData {
energy_cost: *energy_cost,
@ -1916,6 +2018,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
initial_projectile_speed,
scaled_projectile_speed,
move_speed,
meta: _,
} => CharacterState::ChargedRanged(charged_ranged::Data {
static_data: charged_ranged::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1950,6 +2053,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
projectile_body,
projectile_light,
projectile_speed,
meta: _,
} => CharacterState::RepeaterRanged(repeater_ranged::Data {
static_data: repeater_ranged::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -1987,6 +2091,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
damage_kind,
specifier,
damage_effect,
meta: _,
} => CharacterState::Shockwave(shockwave::Data {
static_data: shockwave::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -2022,6 +2127,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
energy_drain,
ori_rate,
specifier,
meta: _,
} => CharacterState::BasicBeam(basic_beam::Data {
static_data: basic_beam::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -2052,6 +2158,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
energy_cost: _,
scales_with_combo,
specifier,
meta: _,
} => CharacterState::BasicAura(basic_aura::Data {
static_data: basic_aura::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -2073,6 +2180,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
buildup_duration,
recover_duration,
max_range,
meta: _,
} => CharacterState::Blink(blink::Data {
static_data: blink::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -2091,6 +2199,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
summon_distance,
summon_info,
duration,
meta: _,
} => CharacterState::BasicSummon(basic_summon::Data {
static_data: basic_summon::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -2114,6 +2223,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
buff_strength,
buff_duration,
energy_cost: _,
meta: _,
} => CharacterState::SelfBuff(self_buff::Data {
static_data: self_buff::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -2134,6 +2244,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
sprite,
summon_distance,
sparseness,
meta: _,
} => CharacterState::SpriteSummon(sprite_summon::Data {
static_data: sprite_summon::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration),
@ -2164,3 +2275,22 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum AbilityMeta {
Sword(SwordStance),
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum SwordStance {
Balanced,
Offensive,
Crippling,
Cleaving,
Defensive,
Parrying,
Heavy,
Mobility,
Reaching,
AirSlash,
}

View File

@ -7,7 +7,7 @@ use crate::{
states::{
self,
behavior::{CharacterBehavior, JoinData},
utils::StageSection,
utils::{AbilityInfo, StageSection},
*,
},
};
@ -413,6 +413,44 @@ impl CharacterState {
_ => None,
}
}
pub fn ability_info(&self) -> Option<AbilityInfo> {
match &self {
CharacterState::Idle(_) => None,
CharacterState::Talk => None,
CharacterState::Climb(_) => None,
CharacterState::Wallrun(_) => None,
CharacterState::Glide(_) => None,
CharacterState::GlideWield(_) => None,
CharacterState::Stunned(_) => None,
CharacterState::Sit => None,
CharacterState::Dance => None,
CharacterState::BasicBlock(data) => Some(data.static_data.ability_info),
CharacterState::Roll(data) => Some(data.static_data.ability_info),
CharacterState::Wielding(_) => None,
CharacterState::Equipping(_) => None,
CharacterState::ComboMelee(data) => Some(data.static_data.ability_info),
CharacterState::ComboMelee2(data) => Some(data.static_data.ability_info),
CharacterState::BasicMelee(data) => Some(data.static_data.ability_info),
CharacterState::BasicRanged(data) => Some(data.static_data.ability_info),
CharacterState::Boost(data) => Some(data.static_data.ability_info),
CharacterState::DashMelee(data) => Some(data.static_data.ability_info),
CharacterState::LeapMelee(data) => Some(data.static_data.ability_info),
CharacterState::SpinMelee(data) => Some(data.static_data.ability_info),
CharacterState::ChargedMelee(data) => Some(data.static_data.ability_info),
CharacterState::ChargedRanged(data) => Some(data.static_data.ability_info),
CharacterState::RepeaterRanged(data) => Some(data.static_data.ability_info),
CharacterState::Shockwave(data) => Some(data.static_data.ability_info),
CharacterState::BasicBeam(data) => Some(data.static_data.ability_info),
CharacterState::BasicAura(data) => Some(data.static_data.ability_info),
CharacterState::Blink(data) => Some(data.static_data.ability_info),
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(_) => None,
CharacterState::SpriteInteract(_) => None,
}
}
}
impl Default for CharacterState {

View File

@ -97,7 +97,9 @@ impl CharacterBehavior for Data {
handle_orientation(data, &mut update, 1.0, None);
handle_move(data, &mut update, 0.7);
handle_jump(data, output_events, &mut update, 1.0);
if !input_is_pressed(data, InputKind::Primary) {
handle_dodge_input(data, &mut update);
}
let strike_data =
self.static_data.strikes[self.completed_strikes % self.static_data.strikes.len()];
@ -106,41 +108,31 @@ impl CharacterBehavior for Data {
Some(StageSection::Buildup) => {
if self.timer < strike_data.buildup_duration {
// Build up
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
timer: tick_attack_or_default(data, self.timer, None),
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.timer = tick_attack_or_default(data, self.timer, None);
}
} else {
// Transitions to swing section of stage
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
timer: Duration::default(),
stage_section: Some(StageSection::Action),
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.timer = Duration::default();
c.stage_section = Some(StageSection::Action);
}
}
},
Some(StageSection::Action) => {
if input_is_pressed(data, InputKind::Primary) {
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
skip_recover: true,
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.skip_recover = true;
}
}
if self.timer.as_secs_f32()
> strike_data.hit_timing * strike_data.swing_duration.as_secs_f32()
&& !self.exhausted
{
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
timer: tick_attack_or_default(data, self.timer, None),
exhausted: true,
skip_recover: self.skip_recover
|| input_is_pressed(data, InputKind::Primary),
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.timer = tick_attack_or_default(data, self.timer, None);
c.exhausted = true;
}
let crit_data = get_crit_data(data, self.static_data.ability_info);
let buff_strength = get_buff_strength(data, self.static_data.ability_info);
@ -153,41 +145,31 @@ impl CharacterBehavior for Data {
);
} else if self.timer < strike_data.swing_duration {
// Swings
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
timer: tick_attack_or_default(data, self.timer, None),
skip_recover: self.skip_recover
|| input_is_pressed(data, InputKind::Primary),
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.timer = tick_attack_or_default(data, self.timer, None);
}
} else if self.skip_recover {
next_strike(&mut update)
} else {
// Transitions to recover section of stage
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
timer: Duration::default(),
stage_section: Some(StageSection::Recover),
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.timer = Duration::default();
c.stage_section = Some(StageSection::Recover);
}
}
},
Some(StageSection::Recover) => {
if self.timer < strike_data.recover_duration {
// Recovery
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
timer: tick_attack_or_default(data, self.timer, None),
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.timer = tick_attack_or_default(data, self.timer, None);
}
} else {
// Done
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
timer: Duration::default(),
stage_section: None,
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.timer = Duration::default();
c.stage_section = None;
}
}
},
Some(_) => {
@ -198,11 +180,9 @@ impl CharacterBehavior for Data {
},
None => {
if self.timer < STANCE_TIME {
update.character = CharacterState::ComboMelee2(Data {
static_data: self.static_data.clone(),
timer: tick_attack_or_default(data, self.timer, None),
..*self
});
if let CharacterState::ComboMelee2(c) = &mut update.character {
c.timer = tick_attack_or_default(data, self.timer, None);
}
} else {
// Done
update.character =
@ -210,17 +190,18 @@ impl CharacterBehavior for Data {
// Make sure melee component is removed
data.updater.remove::<Melee>(data.entity);
}
handle_climb(data, &mut update);
handle_jump(data, output_events, &mut update, 1.0);
if input_is_pressed(data, InputKind::Primary) {
next_strike(&mut update)
} else {
attempt_input(data, output_events, &mut update);
}
},
}
// At end of state logic so an interrupt isn't overwritten
if !input_is_pressed(data, InputKind::Primary) {
handle_dodge_input(data, &mut update);
}
update
}
}

View File

@ -2,6 +2,7 @@ use crate::{
astar::Astar,
combat,
comp::{
ability::AbilityMeta,
arthropod, biped_large, biped_small,
character_state::OutputEvents,
inventory::slot::{ArmorSlot, EquipSlot, Slot},
@ -952,28 +953,18 @@ fn handle_ability(data: &JoinData<'_>, update: &mut StateUpdate, input: InputKin
Some(data.body),
)
})
.map(|(ability, from_offhand)| (ability.contextualize(data), from_offhand))
.filter(|(ability, _)| ability.requirements_paid(data, update))
{
update.character = CharacterState::from((
&ability,
AbilityInfo::from_input(data, from_offhand, input),
AbilityInfo::from_input(data, from_offhand, input, ability.ability_meta()),
data,
));
}
}
}
pub fn handle_ability_input(data: &JoinData<'_>, update: &mut StateUpdate) {
if let Some(input) = data
.controller
.queued_inputs
.keys()
.find(|i| i.is_ability())
{
handle_ability(data, update, *input);
}
}
pub fn handle_input(
data: &JoinData<'_>,
output_events: &mut OutputEvents,
@ -1016,7 +1007,7 @@ pub fn handle_block_input(data: &JoinData<'_>, update: &mut StateUpdate) {
if ability.requirements_paid(data, update) {
update.character = CharacterState::from((
&ability,
AbilityInfo::from_input(data, false, InputKind::Roll),
AbilityInfo::from_input(data, false, InputKind::Block, None),
data,
));
}
@ -1031,7 +1022,7 @@ pub fn handle_dodge_input(data: &JoinData<'_>, update: &mut StateUpdate) {
if ability.requirements_paid(data, update) {
update.character = CharacterState::from((
&ability,
AbilityInfo::from_input(data, false, InputKind::Roll),
AbilityInfo::from_input(data, false, InputKind::Roll, None),
data,
));
if let CharacterState::Roll(roll) = &mut update.character {
@ -1218,10 +1209,16 @@ pub struct AbilityInfo {
pub hand: Option<HandInfo>,
pub input: InputKind,
pub input_attr: Option<InputAttr>,
pub ability_meta: Option<AbilityMeta>,
}
impl AbilityInfo {
pub fn from_input(data: &JoinData<'_>, from_offhand: bool, input: InputKind) -> Self {
pub fn from_input(
data: &JoinData<'_>,
from_offhand: bool,
input: InputKind,
ability_meta: Option<AbilityMeta>,
) -> Self {
let tool_data = if from_offhand {
unwrap_tool_data(data, EquipSlot::ActiveOffhand)
} else {
@ -1239,6 +1236,7 @@ impl AbilityInfo {
hand,
input,
input_attr: data.controller.queued_inputs.get(&input).copied(),
ability_meta,
}
}
}

View File

@ -241,5 +241,6 @@ fn empty_ability_info() -> states::utils::AbilityInfo {
hand: None,
input: InputKind::Primary,
input_attr: None,
ability_meta: None,
}
}

View File

@ -293,5 +293,6 @@ fn empty_ability_info() -> states::utils::AbilityInfo {
hand: None,
input: InputKind::Primary,
input_attr: None,
ability_meta: None,
}
}

View File

@ -1626,8 +1626,9 @@ impl FigureMgr {
CharacterState::ComboMelee2(s) => {
if let Some(stage_section) = s.stage_section {
let timer = s.timer.as_secs_f32();
let strike_data = s.static_data.strikes
[s.completed_strikes % s.static_data.strikes.len()];
let current_strike =
s.completed_strikes % s.static_data.strikes.len();
let strike_data = s.static_data.strikes[current_strike];
let progress = match stage_section {
StageSection::Buildup => {
timer / strike_data.buildup_duration.as_secs_f32()
@ -1640,8 +1641,6 @@ impl FigureMgr {
},
_ => 0.0,
};
let current_strike =
s.completed_strikes % s.static_data.strikes.len();
anim::character::ComboAnimation::update_skeleton(
&target_base,