diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index da4f06e26c..570b80cfbc 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -2807,7 +2807,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { meta: _, } => CharacterState::DiveMelee(dive_melee::Data { static_data: dive_melee::StaticData { - buildup_duration: buildup_duration.map(|b| Duration::from_secs_f32(b)), + buildup_duration: buildup_duration.map(Duration::from_secs_f32), movement_duration: Duration::from_secs_f32(*movement_duration), swing_duration: Duration::from_secs_f32(*swing_duration), recover_duration: Duration::from_secs_f32(*recover_duration), diff --git a/common/src/states/charged_melee.rs b/common/src/states/charged_melee.rs index 936ab78afc..2e29ce7fa1 100644 --- a/common/src/states/charged_melee.rs +++ b/common/src/states/charged_melee.rs @@ -80,11 +80,9 @@ impl CharacterBehavior for Data { c.timer = Duration::default(); } } - } else { - if let CharacterState::ChargedMelee(c) = &mut update.character { - c.stage_section = StageSection::Charge; - c.timer = Duration::default(); - } + } else if let CharacterState::ChargedMelee(c) = &mut update.character { + c.stage_section = StageSection::Charge; + c.timer = Duration::default(); } }, StageSection::Charge => { diff --git a/common/src/states/dive_melee.rs b/common/src/states/dive_melee.rs index 2982f1ad85..43c951bd42 100644 --- a/common/src/states/dive_melee.rs +++ b/common/src/states/dive_melee.rs @@ -62,17 +62,13 @@ impl CharacterBehavior for Data { if let CharacterState::DiveMelee(c) = &mut update.character { c.timer = tick_attack_or_default(data, self.timer, None); } - } else { - if let CharacterState::DiveMelee(c) = &mut update.character { - c.timer = Duration::default(); - c.stage_section = StageSection::Action; - } - } - } else { - if let CharacterState::DiveMelee(c) = &mut update.character { + } else if let CharacterState::DiveMelee(c) = &mut update.character { c.timer = Duration::default(); c.stage_section = StageSection::Action; } + } else if let CharacterState::DiveMelee(c) = &mut update.character { + c.timer = Duration::default(); + c.stage_section = StageSection::Action; } }, StageSection::Movement => { diff --git a/common/src/states/music.rs b/common/src/states/music.rs index 2f4cc96564..4310b0a7e4 100644 --- a/common/src/states/music.rs +++ b/common/src/states/music.rs @@ -70,10 +70,8 @@ impl CharacterBehavior for Data { } // At end of state logic so an interrupt isn't overwritten - if !input_is_pressed(data, self.static_data.ability_info.input) { - if input_is_pressed(data, InputKind::Roll) { - handle_input(data, output_events, &mut update, InputKind::Roll); - } + if !input_is_pressed(data, self.static_data.ability_info.input) && input_is_pressed(data, InputKind::Roll) { + handle_input(data, output_events, &mut update, InputKind::Roll); } update diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index f03ae35044..c3aa4cc151 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -512,6 +512,7 @@ impl<'a> AgentData<'a> { enum IntCounters { Tactics = 0, + ActionMode = 1, } if !agent.action_state.initialized { @@ -589,28 +590,212 @@ impl<'a> AgentData<'a> { .unwrap_or(SwordTactics::Unskilled); agent.action_state.int_counters[IntCounters::Tactics as usize] = tactic as u8; + + let auxiliary_key = ActiveAbilities::active_auxiliary_key(Some(self.inventory)); + let mut set_sword_ability = |slot, skill| { + controller.push_event(ControlEvent::ChangeAbility { + slot, + auxiliary_key, + new_ability: AuxiliaryAbility::MainWeapon(skill), + }) + }; + + match tactic { + SwordTactics::Unskilled => {}, + SwordTactics::Basic => { + // Crescent slash + set_sword_ability(0, 0); + // Fell strike + set_sword_ability(1, 1); + // Skewer + set_sword_ability(2, 2); + // Cascade + set_sword_ability(3, 3); + // Cross cut + set_sword_ability(4, 4); + }, + SwordTactics::HeavySimple => { + // Finisher + set_sword_ability(0, 5); + // Crescent slash + set_sword_ability(1, 0); + // Cascade + set_sword_ability(2, 3); + // Windmill slash + set_sword_ability(3, 6); + // Pommel strike + set_sword_ability(4, 7); + }, + SwordTactics::AgileSimple => { + // Finisher + set_sword_ability(0, 5); + // Skewer + set_sword_ability(1, 2); + // Cross cut + set_sword_ability(2, 4); + // Quick draw + set_sword_ability(3, 8); + // Feint + set_sword_ability(4, 9); + }, + SwordTactics::DefensiveSimple => { + // Finisher + set_sword_ability(0, 5); + // Crescent slash + set_sword_ability(1, 0); + // Fell strike + set_sword_ability(2, 1); + // Riposte + set_sword_ability(3, 10); + // Disengage + set_sword_ability(4, 11); + }, + SwordTactics::CripplingSimple => { + // Finisher + set_sword_ability(0, 5); + // Fell strike + set_sword_ability(1, 1); + // Skewer + set_sword_ability(2, 2); + // Gouge + set_sword_ability(3, 12); + // Hamstring + set_sword_ability(4, 13); + }, + SwordTactics::CleavingSimple => { + // Finisher + set_sword_ability(0, 5); + // Cascade + set_sword_ability(1, 3); + // Cross cut + set_sword_ability(2, 4); + // Whirlwind slice + set_sword_ability(3, 14); + // Earth splitter + set_sword_ability(4, 15); + }, + SwordTactics::HeavyAdvanced => { + // Finisher + set_sword_ability(0, 5); + // Windmill slash + set_sword_ability(1, 6); + // Pommel strike + set_sword_ability(2, 7); + // Fortitude + set_sword_ability(3, 16); + // Pillar Thrust + set_sword_ability(4, 17); + }, + SwordTactics::AgileAdvanced => { + // Finisher + set_sword_ability(0, 5); + // Quick draw + set_sword_ability(1, 8); + // Feint + set_sword_ability(2, 9); + // Dancing edge + set_sword_ability(3, 18); + // Flurry + set_sword_ability(4, 19); + }, + SwordTactics::DefensiveAdvanced => { + // Finisher + set_sword_ability(0, 5); + // Riposte + set_sword_ability(1, 10); + // Disengage + set_sword_ability(2, 11); + // Stalwart sword + set_sword_ability(3, 20); + // Deflect + set_sword_ability(4, 21); + }, + SwordTactics::CripplingAdvanced => { + // Finisher + set_sword_ability(0, 5); + // Gouge + set_sword_ability(1, 12); + // Hamstring + set_sword_ability(2, 13); + // Eviscerate + set_sword_ability(3, 22); + // Bloody gash + set_sword_ability(4, 23); + }, + SwordTactics::CleavingAdvanced => { + // Finisher + set_sword_ability(0, 5); + // Whirlwind slice + set_sword_ability(1, 14); + // Earth splitter + set_sword_ability(2, 15); + // Blade fever + set_sword_ability(3, 24); + // Sky splitter + set_sword_ability(4, 25); + }, + } + + agent.action_state.int_counters[IntCounters::ActionMode as usize] = + ActionMode::Guarded as u8; } - // Action modes - const RECKLESS: usize = 0; - const GUARDED: usize = 1; - const RETREAT: usize = 2; + enum ActionMode { + Reckless = 0, + Guarded = 1, + Fleeing = 2, + } - match SwordTactics::from_u8(agent.action_state.int_counters[IntCounters::Tactics as usize]) - { - SwordTactics::Unskilled => {}, - SwordTactics::Basic => {}, - SwordTactics::HeavySimple => {}, - SwordTactics::AgileSimple => {}, - SwordTactics::DefensiveSimple => {}, - SwordTactics::CripplingSimple => {}, - SwordTactics::CleavingSimple => {}, - SwordTactics::HeavyAdvanced => {}, - SwordTactics::AgileAdvanced => {}, - SwordTactics::DefensiveAdvanced => {}, - SwordTactics::CripplingAdvanced => {}, - SwordTactics::CleavingAdvanced => {}, - _ => {}, + impl ActionMode { + fn from_u8(x: u8) -> Self { + match x { + 0 => ActionMode::Reckless, + 1 => ActionMode::Guarded, + 2 => ActionMode::Fleeing, + _ => ActionMode::Guarded, + } + } + } + + let attempt_attack = match ActionMode::from_u8( + agent.action_state.int_counters[IntCounters::ActionMode as usize], + ) { + ActionMode::Reckless => true, + ActionMode::Guarded => true, + ActionMode::Fleeing => false, + }; + + let attack_failed = if attempt_attack { + match SwordTactics::from_u8( + agent.action_state.int_counters[IntCounters::Tactics as usize], + ) { + SwordTactics::Unskilled => {}, + SwordTactics::Basic => {}, + SwordTactics::HeavySimple => {}, + SwordTactics::AgileSimple => {}, + SwordTactics::DefensiveSimple => {}, + SwordTactics::CripplingSimple => {}, + SwordTactics::CleavingSimple => {}, + SwordTactics::HeavyAdvanced => {}, + SwordTactics::AgileAdvanced => {}, + SwordTactics::DefensiveAdvanced => {}, + SwordTactics::CripplingAdvanced => {}, + SwordTactics::CleavingAdvanced => {}, + } + true + } else { + false + }; + + if attack_failed { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Separate, + None, + ); } }