mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Axe AI
This commit is contained in:
parent
dd616f85a9
commit
9fa556b165
@ -306,9 +306,9 @@ common-abilities-axe-bloodfeast = Bloodfeast
|
|||||||
common-abilities-axe-fierce_raze = Fierce Raze
|
common-abilities-axe-fierce_raze = Fierce Raze
|
||||||
.desc =
|
.desc =
|
||||||
A rapid flurry of strikes on your foe
|
A rapid flurry of strikes on your foe
|
||||||
common-abilities-axe-dueal_fierce_raze = Fierce Raze
|
common-abilities-axe-dual_fierce_raze = Fierce Raze
|
||||||
.desc =
|
.desc =
|
||||||
A rapid flurry of strikes on yoru foe using both of your axes
|
A rapid flurry of strikes on your foe using both of your axes
|
||||||
common-abilities-axe-furor = Furor
|
common-abilities-axe-furor = Furor
|
||||||
.desc =
|
.desc =
|
||||||
As your fury rises, your movement and attacks quicken
|
As your fury rises, your movement and attacks quicken
|
||||||
|
@ -8,7 +8,7 @@ use common::{
|
|||||||
ability::{ActiveAbilities, AuxiliaryAbility, Stance, SwordStance, MAX_ABILITIES},
|
ability::{ActiveAbilities, AuxiliaryAbility, Stance, SwordStance, MAX_ABILITIES},
|
||||||
buff::BuffKind,
|
buff::BuffKind,
|
||||||
item::tool::AbilityContext,
|
item::tool::AbilityContext,
|
||||||
skills::{BowSkill, HammerSkill, SceptreSkill, Skill, StaffSkill, SwordSkill},
|
skills::{AxeSkill, BowSkill, HammerSkill, SceptreSkill, Skill, StaffSkill, SwordSkill},
|
||||||
AbilityInput, Agent, CharacterAbility, CharacterState, ControlAction, ControlEvent,
|
AbilityInput, Agent, CharacterAbility, CharacterState, ControlAction, ControlEvent,
|
||||||
Controller, InputKind,
|
Controller, InputKind,
|
||||||
},
|
},
|
||||||
@ -327,18 +327,6 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_axe_attack(
|
|
||||||
&self,
|
|
||||||
_agent: &mut Agent,
|
|
||||||
_controller: &mut Controller,
|
|
||||||
_attack_data: &AttackData,
|
|
||||||
_tgt_data: &TargetData,
|
|
||||||
_read_data: &ReadData,
|
|
||||||
_rng: &mut impl Rng,
|
|
||||||
) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_hammer_attack(
|
pub fn handle_hammer_attack(
|
||||||
&self,
|
&self,
|
||||||
agent: &mut Agent,
|
agent: &mut Agent,
|
||||||
@ -738,7 +726,10 @@ impl<'a> AgentData<'a> {
|
|||||||
agent.action_state.int_counters[IntCounters::Tactics as usize],
|
agent.action_state.int_counters[IntCounters::Tactics as usize],
|
||||||
) {
|
) {
|
||||||
SwordTactics::Unskilled => {
|
SwordTactics::Unskilled => {
|
||||||
let desired_energy = 15.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 15.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -749,7 +740,7 @@ impl<'a> AgentData<'a> {
|
|||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -760,14 +751,17 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::Basic => {
|
SwordTactics::Basic => {
|
||||||
let desired_energy = 25.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 25.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
continue_current_input(input, &mut next_input);
|
continue_current_input(input, &mut next_input);
|
||||||
} else {
|
} else {
|
||||||
let attempt_ability = InputKind::Ability(rng.gen_range(0..5));
|
let attempt_ability = InputKind::Ability(rng.gen_range(0..5));
|
||||||
if could_use_input(attempt_ability, desired_energy) {
|
if could_use_input(attempt_ability, ability_preferences) {
|
||||||
next_input = Some(attempt_ability);
|
next_input = Some(attempt_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -776,7 +770,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -787,7 +781,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::HeavySimple => {
|
SwordTactics::HeavySimple => {
|
||||||
let desired_energy = 35.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 35.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -796,16 +793,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Heavy))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Heavy))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -814,7 +811,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -825,7 +822,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::AgileSimple => {
|
SwordTactics::AgileSimple => {
|
||||||
let desired_energy = 35.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 35.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -834,16 +834,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Agile))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Agile))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -852,7 +852,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -863,7 +863,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::DefensiveSimple => {
|
SwordTactics::DefensiveSimple => {
|
||||||
let desired_energy = 35.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 35.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -872,18 +875,18 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Defensive))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Defensive))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(InputKind::Ability(3), desired_energy) {
|
} else if could_use_input(InputKind::Ability(3), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(3));
|
next_input = Some(InputKind::Ability(3));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -892,7 +895,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -903,7 +906,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::CripplingSimple => {
|
SwordTactics::CripplingSimple => {
|
||||||
let desired_energy = 35.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 35.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -912,16 +918,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Crippling))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Crippling))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -930,7 +936,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -941,7 +947,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::CleavingSimple => {
|
SwordTactics::CleavingSimple => {
|
||||||
let desired_energy = 35.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 35.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -950,16 +959,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
let stance_ability = InputKind::Ability(rng.gen_range(3..5));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Cleaving))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Cleaving))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -968,7 +977,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -979,7 +988,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::HeavyAdvanced => {
|
SwordTactics::HeavyAdvanced => {
|
||||||
let desired_energy = 50.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 50.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -988,16 +1000,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Heavy))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Heavy))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -1006,7 +1018,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -1017,7 +1029,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::AgileAdvanced => {
|
SwordTactics::AgileAdvanced => {
|
||||||
let desired_energy = 50.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 50.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -1026,16 +1041,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Agile))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Agile))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -1044,7 +1059,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -1055,7 +1070,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::DefensiveAdvanced => {
|
SwordTactics::DefensiveAdvanced => {
|
||||||
let desired_energy = 50.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 50.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -1064,18 +1082,18 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..4));
|
let random_ability = InputKind::Ability(rng.gen_range(1..4));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Defensive))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Defensive))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if could_use_input(InputKind::Ability(4), desired_energy)
|
} else if could_use_input(InputKind::Ability(4), ability_preferences)
|
||||||
&& rng.gen_bool(2.0 * read_data.dt.0 as f64)
|
&& rng.gen_bool(2.0 * read_data.dt.0 as f64)
|
||||||
{
|
{
|
||||||
next_input = Some(InputKind::Ability(4));
|
next_input = Some(InputKind::Ability(4));
|
||||||
@ -1086,7 +1104,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -1097,7 +1115,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::CripplingAdvanced => {
|
SwordTactics::CripplingAdvanced => {
|
||||||
let desired_energy = 50.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 50.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -1106,16 +1127,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Crippling))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Crippling))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -1124,7 +1145,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -1135,7 +1156,10 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordTactics::CleavingAdvanced => {
|
SwordTactics::CleavingAdvanced => {
|
||||||
let desired_energy = 50.0;
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 50.0,
|
||||||
|
combo_scaling_buildup: 0,
|
||||||
|
};
|
||||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
let mut next_input = None;
|
let mut next_input = None;
|
||||||
if let Some(input) = current_input {
|
if let Some(input) = current_input {
|
||||||
@ -1144,16 +1168,16 @@ impl<'a> AgentData<'a> {
|
|||||||
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
let stance_ability = InputKind::Ability(rng.gen_range(1..3));
|
||||||
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
let random_ability = InputKind::Ability(rng.gen_range(1..5));
|
||||||
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Cleaving))) {
|
if !matches!(self.stance, Some(Stance::Sword(SwordStance::Cleaving))) {
|
||||||
if could_use_input(stance_ability, desired_energy) {
|
if could_use_input(stance_ability, ability_preferences) {
|
||||||
next_input = Some(stance_ability);
|
next_input = Some(stance_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
} else {
|
} else {
|
||||||
next_input = Some(InputKind::Secondary);
|
next_input = Some(InputKind::Secondary);
|
||||||
}
|
}
|
||||||
} else if could_use_input(InputKind::Ability(0), desired_energy) {
|
} else if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
next_input = Some(InputKind::Ability(0));
|
next_input = Some(InputKind::Ability(0));
|
||||||
} else if could_use_input(random_ability, desired_energy) {
|
} else if could_use_input(random_ability, ability_preferences) {
|
||||||
next_input = Some(random_ability);
|
next_input = Some(random_ability);
|
||||||
} else if rng.gen_bool(0.5) {
|
} else if rng.gen_bool(0.5) {
|
||||||
next_input = Some(InputKind::Primary);
|
next_input = Some(InputKind::Primary);
|
||||||
@ -1162,7 +1186,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(input) = next_input {
|
if let Some(input) = next_input {
|
||||||
if could_use_input(input, desired_energy) {
|
if could_use_input(input, ability_preferences) {
|
||||||
controller.push_basic_input(input);
|
controller.push_basic_input(input);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -1189,6 +1213,322 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_axe_attack(
|
||||||
|
&self,
|
||||||
|
agent: &mut Agent,
|
||||||
|
controller: &mut Controller,
|
||||||
|
attack_data: &AttackData,
|
||||||
|
tgt_data: &TargetData,
|
||||||
|
read_data: &ReadData,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
) {
|
||||||
|
if !agent.action_state.initialized {
|
||||||
|
agent.action_state.initialized = true;
|
||||||
|
let available_tactics = {
|
||||||
|
let mut tactics = Vec::new();
|
||||||
|
let try_tactic = |skill, tactic, tactics: &mut Vec<AxeTactics>| {
|
||||||
|
if self.skill_set.has_skill(Skill::Axe(skill)) {
|
||||||
|
tactics.push(tactic);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try_tactic(AxeSkill::Execute, AxeTactics::SavageAdvanced, &mut tactics);
|
||||||
|
try_tactic(
|
||||||
|
AxeSkill::Lacerate,
|
||||||
|
AxeTactics::MercilessAdvanced,
|
||||||
|
&mut tactics,
|
||||||
|
);
|
||||||
|
try_tactic(AxeSkill::Bulkhead, AxeTactics::RivingAdvanced, &mut tactics);
|
||||||
|
if tactics.is_empty() {
|
||||||
|
try_tactic(
|
||||||
|
AxeSkill::RisingTide,
|
||||||
|
AxeTactics::SavageIntermediate,
|
||||||
|
&mut tactics,
|
||||||
|
);
|
||||||
|
try_tactic(
|
||||||
|
AxeSkill::FierceRaze,
|
||||||
|
AxeTactics::MercilessIntermediate,
|
||||||
|
&mut tactics,
|
||||||
|
);
|
||||||
|
try_tactic(
|
||||||
|
AxeSkill::Plunder,
|
||||||
|
AxeTactics::RivingIntermediate,
|
||||||
|
&mut tactics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if tactics.is_empty() {
|
||||||
|
try_tactic(
|
||||||
|
AxeSkill::BrutalSwing,
|
||||||
|
AxeTactics::SavageSimple,
|
||||||
|
&mut tactics,
|
||||||
|
);
|
||||||
|
try_tactic(AxeSkill::Rake, AxeTactics::MercilessSimple, &mut tactics);
|
||||||
|
try_tactic(AxeSkill::SkullBash, AxeTactics::RivingSimple, &mut tactics);
|
||||||
|
}
|
||||||
|
if tactics.is_empty() {
|
||||||
|
tactics.push(AxeTactics::Unskilled);
|
||||||
|
}
|
||||||
|
tactics
|
||||||
|
};
|
||||||
|
|
||||||
|
let tactic = available_tactics
|
||||||
|
.choose(rng)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(AxeTactics::Unskilled);
|
||||||
|
|
||||||
|
agent.action_state.int_counters[IntCounters::Tactic as usize] = tactic as u8;
|
||||||
|
|
||||||
|
let auxiliary_key = ActiveAbilities::active_auxiliary_key(Some(self.inventory));
|
||||||
|
let set_axe_ability = |controller: &mut Controller, slot, skill| {
|
||||||
|
controller.push_event(ControlEvent::ChangeAbility {
|
||||||
|
slot,
|
||||||
|
auxiliary_key,
|
||||||
|
new_ability: AuxiliaryAbility::MainWeapon(skill),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
match tactic {
|
||||||
|
AxeTactics::Unskilled => {},
|
||||||
|
AxeTactics::SavageSimple => {
|
||||||
|
// Brutal swing
|
||||||
|
set_axe_ability(controller, 0, 0);
|
||||||
|
},
|
||||||
|
AxeTactics::MercilessSimple => {
|
||||||
|
// Rake
|
||||||
|
set_axe_ability(controller, 0, 6);
|
||||||
|
},
|
||||||
|
AxeTactics::RivingSimple => {
|
||||||
|
// Skull bash
|
||||||
|
set_axe_ability(controller, 0, 12);
|
||||||
|
},
|
||||||
|
AxeTactics::SavageIntermediate => {
|
||||||
|
// Brutal swing
|
||||||
|
set_axe_ability(controller, 0, 0);
|
||||||
|
// Berserk
|
||||||
|
set_axe_ability(controller, 1, 1);
|
||||||
|
// Rising tide
|
||||||
|
set_axe_ability(controller, 2, 2);
|
||||||
|
},
|
||||||
|
AxeTactics::MercilessIntermediate => {
|
||||||
|
// Rake
|
||||||
|
set_axe_ability(controller, 0, 6);
|
||||||
|
// Bloodfeast
|
||||||
|
set_axe_ability(controller, 1, 7);
|
||||||
|
// Fierce raze
|
||||||
|
set_axe_ability(controller, 2, 8);
|
||||||
|
},
|
||||||
|
AxeTactics::RivingIntermediate => {
|
||||||
|
// Skull bash
|
||||||
|
set_axe_ability(controller, 0, 12);
|
||||||
|
// Sunder
|
||||||
|
set_axe_ability(controller, 1, 13);
|
||||||
|
// Plunder
|
||||||
|
set_axe_ability(controller, 2, 14);
|
||||||
|
},
|
||||||
|
AxeTactics::SavageAdvanced => {
|
||||||
|
// Berserk
|
||||||
|
set_axe_ability(controller, 0, 1);
|
||||||
|
// Rising tide
|
||||||
|
set_axe_ability(controller, 1, 2);
|
||||||
|
// Savage sense
|
||||||
|
set_axe_ability(controller, 2, 3);
|
||||||
|
// Adrenaline rush
|
||||||
|
set_axe_ability(controller, 3, 4);
|
||||||
|
// Execute/maelstrom
|
||||||
|
set_axe_ability(controller, 4, 5);
|
||||||
|
},
|
||||||
|
AxeTactics::MercilessAdvanced => {
|
||||||
|
// Bloodfeast
|
||||||
|
set_axe_ability(controller, 0, 7);
|
||||||
|
// Fierce raze
|
||||||
|
set_axe_ability(controller, 1, 8);
|
||||||
|
// Furor
|
||||||
|
set_axe_ability(controller, 2, 9);
|
||||||
|
// Fracture
|
||||||
|
set_axe_ability(controller, 3, 10);
|
||||||
|
// Lacerate/riptide
|
||||||
|
set_axe_ability(controller, 4, 11);
|
||||||
|
},
|
||||||
|
AxeTactics::RivingAdvanced => {
|
||||||
|
// Sunder
|
||||||
|
set_axe_ability(controller, 0, 13);
|
||||||
|
// Plunder
|
||||||
|
set_axe_ability(controller, 1, 14);
|
||||||
|
// Defiance
|
||||||
|
set_axe_ability(controller, 2, 15);
|
||||||
|
// Keelhaul
|
||||||
|
set_axe_ability(controller, 3, 16);
|
||||||
|
// Bulkhead/capsize
|
||||||
|
set_axe_ability(controller, 4, 17);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
agent.action_state.int_counters[IntCounters::ActionMode as usize] =
|
||||||
|
ActionMode::Reckless as u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum IntCounters {
|
||||||
|
Tactic = 0,
|
||||||
|
ActionMode = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Timers {
|
||||||
|
GuardedCycle = 0,
|
||||||
|
PosTimeOut = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Conditions {
|
||||||
|
GuardedDefend = 0,
|
||||||
|
RollingBreakThrough = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FloatCounters {
|
||||||
|
GuardedTimer = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Positions {
|
||||||
|
GuardedCover = 0,
|
||||||
|
Flee = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
let attempt_attack = handle_attack_aggression(
|
||||||
|
self,
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
attack_data,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
rng,
|
||||||
|
Timers::PosTimeOut as usize,
|
||||||
|
Timers::GuardedCycle as usize,
|
||||||
|
FloatCounters::GuardedTimer as usize,
|
||||||
|
IntCounters::ActionMode as usize,
|
||||||
|
Conditions::GuardedDefend as usize,
|
||||||
|
Conditions::RollingBreakThrough as usize,
|
||||||
|
Positions::GuardedCover as usize,
|
||||||
|
Positions::Flee as usize,
|
||||||
|
);
|
||||||
|
|
||||||
|
let attack_failed = if attempt_attack {
|
||||||
|
let primary = self.extract_ability(AbilityInput::Primary);
|
||||||
|
let secondary = self.extract_ability(AbilityInput::Secondary);
|
||||||
|
let abilities = [
|
||||||
|
self.extract_ability(AbilityInput::Auxiliary(0)),
|
||||||
|
self.extract_ability(AbilityInput::Auxiliary(1)),
|
||||||
|
self.extract_ability(AbilityInput::Auxiliary(2)),
|
||||||
|
self.extract_ability(AbilityInput::Auxiliary(3)),
|
||||||
|
self.extract_ability(AbilityInput::Auxiliary(4)),
|
||||||
|
];
|
||||||
|
let could_use_input = |input, desired_energy| match input {
|
||||||
|
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
||||||
|
p.could_use(attack_data, self, tgt_data, read_data, desired_energy)
|
||||||
|
}),
|
||||||
|
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
||||||
|
s.could_use(attack_data, self, tgt_data, read_data, desired_energy)
|
||||||
|
}),
|
||||||
|
InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| {
|
||||||
|
a.could_use(attack_data, self, tgt_data, read_data, desired_energy)
|
||||||
|
}),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
let continue_current_input = |current_input, next_input: &mut Option<InputKind>| {
|
||||||
|
if matches!(current_input, InputKind::Secondary) {
|
||||||
|
let charging =
|
||||||
|
matches!(self.char_state.stage_section(), Some(StageSection::Charge));
|
||||||
|
let charged = self
|
||||||
|
.char_state
|
||||||
|
.durations()
|
||||||
|
.and_then(|durs| durs.charge)
|
||||||
|
.zip(self.char_state.timer())
|
||||||
|
.map_or(false, |(dur, timer)| timer > dur);
|
||||||
|
if !(charging && charged) {
|
||||||
|
*next_input = Some(InputKind::Secondary);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*next_input = Some(current_input);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||||
|
let ability_preferences = AbilityPreferences {
|
||||||
|
desired_energy: 40.0,
|
||||||
|
combo_scaling_buildup: 15,
|
||||||
|
};
|
||||||
|
let mut next_input = None;
|
||||||
|
if let Some(input) = current_input {
|
||||||
|
continue_current_input(input, &mut next_input);
|
||||||
|
} else {
|
||||||
|
match AxeTactics::from_u8(
|
||||||
|
agent.action_state.int_counters[IntCounters::Tactic as usize],
|
||||||
|
) {
|
||||||
|
AxeTactics::Unskilled => {
|
||||||
|
if rng.gen_bool(0.5) {
|
||||||
|
next_input = Some(InputKind::Primary);
|
||||||
|
} else {
|
||||||
|
next_input = Some(InputKind::Secondary);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AxeTactics::SavageSimple
|
||||||
|
| AxeTactics::MercilessSimple
|
||||||
|
| AxeTactics::RivingSimple => {
|
||||||
|
if could_use_input(InputKind::Ability(0), ability_preferences) {
|
||||||
|
next_input = Some(InputKind::Ability(0));
|
||||||
|
} else if rng.gen_bool(0.5) {
|
||||||
|
next_input = Some(InputKind::Primary);
|
||||||
|
} else {
|
||||||
|
next_input = Some(InputKind::Secondary);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AxeTactics::SavageIntermediate
|
||||||
|
| AxeTactics::MercilessIntermediate
|
||||||
|
| AxeTactics::RivingIntermediate => {
|
||||||
|
let random_ability = InputKind::Ability(rng.gen_range(0..3));
|
||||||
|
if could_use_input(random_ability, ability_preferences) {
|
||||||
|
next_input = Some(random_ability);
|
||||||
|
} else if rng.gen_bool(0.5) {
|
||||||
|
next_input = Some(InputKind::Primary);
|
||||||
|
} else {
|
||||||
|
next_input = Some(InputKind::Secondary);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AxeTactics::SavageAdvanced
|
||||||
|
| AxeTactics::MercilessAdvanced
|
||||||
|
| AxeTactics::RivingAdvanced => {
|
||||||
|
let random_ability = InputKind::Ability(rng.gen_range(0..5));
|
||||||
|
if could_use_input(random_ability, ability_preferences) {
|
||||||
|
next_input = Some(random_ability);
|
||||||
|
} else if rng.gen_bool(0.5) {
|
||||||
|
next_input = Some(InputKind::Primary);
|
||||||
|
} else {
|
||||||
|
next_input = Some(InputKind::Secondary);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(input) = next_input {
|
||||||
|
if could_use_input(input, ability_preferences) {
|
||||||
|
controller.push_basic_input(input);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if attack_failed && attack_data.dist_sqrd > 1.5_f32.powi(2) {
|
||||||
|
self.path_toward_target(
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
tgt_data.pos.0,
|
||||||
|
read_data,
|
||||||
|
Path::Separate,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_bow_attack(
|
pub fn handle_bow_attack(
|
||||||
&self,
|
&self,
|
||||||
agent: &mut Agent,
|
agent: &mut Agent,
|
||||||
@ -4767,10 +5107,22 @@ impl<'a> AgentData<'a> {
|
|||||||
let secondary = self.extract_ability(AbilityInput::Secondary);
|
let secondary = self.extract_ability(AbilityInput::Secondary);
|
||||||
let could_use_input = |input| match input {
|
let could_use_input = |input| match input {
|
||||||
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
||||||
p.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
p.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
||||||
s.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
s.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
@ -4823,10 +5175,22 @@ impl<'a> AgentData<'a> {
|
|||||||
let secondary = self.extract_ability(AbilityInput::Secondary);
|
let secondary = self.extract_ability(AbilityInput::Secondary);
|
||||||
let could_use_input = |input| match input {
|
let could_use_input = |input| match input {
|
||||||
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
||||||
p.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
p.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
||||||
s.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
s.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
@ -4868,7 +5232,13 @@ impl<'a> AgentData<'a> {
|
|||||||
let primary = self.extract_ability(AbilityInput::Primary);
|
let primary = self.extract_ability(AbilityInput::Primary);
|
||||||
let could_use_input = |input| match input {
|
let could_use_input = |input| match input {
|
||||||
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
||||||
p.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
p.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
@ -4916,13 +5286,31 @@ impl<'a> AgentData<'a> {
|
|||||||
];
|
];
|
||||||
let could_use_input = |input| match input {
|
let could_use_input = |input| match input {
|
||||||
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
||||||
p.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
p.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
||||||
s.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
s.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| {
|
InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| {
|
||||||
a.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
a.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
@ -4984,13 +5372,31 @@ impl<'a> AgentData<'a> {
|
|||||||
];
|
];
|
||||||
let could_use_input = |input| match input {
|
let could_use_input = |input| match input {
|
||||||
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
||||||
p.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
p.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
||||||
s.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
s.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| {
|
InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| {
|
||||||
a.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
a.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
@ -5077,13 +5483,31 @@ impl<'a> AgentData<'a> {
|
|||||||
];
|
];
|
||||||
let could_use_input = |input| match input {
|
let could_use_input = |input| match input {
|
||||||
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
InputKind::Primary => primary.as_ref().map_or(false, |p| {
|
||||||
p.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
p.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
|
||||||
s.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
s.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| {
|
InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| {
|
||||||
a.could_use(attack_data, self, tgt_data, read_data, 0.0)
|
a.could_use(
|
||||||
|
attack_data,
|
||||||
|
self,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
AbilityPreferences::default(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,10 @@ use common::{
|
|||||||
character_state::AttackFilters,
|
character_state::AttackFilters,
|
||||||
group,
|
group,
|
||||||
inventory::{
|
inventory::{
|
||||||
item::{tool::ToolKind, ItemKind, MaterialStatManifest},
|
item::{
|
||||||
|
tool::{AbilityMap, ToolKind},
|
||||||
|
ItemKind, MaterialStatManifest,
|
||||||
|
},
|
||||||
slot::EquipSlot,
|
slot::EquipSlot,
|
||||||
},
|
},
|
||||||
ActiveAbilities, Alignment, Body, CharacterState, Combo, Energy, Health, Inventory,
|
ActiveAbilities, Alignment, Body, CharacterState, Combo, Energy, Health, Inventory,
|
||||||
@ -246,7 +249,7 @@ pub enum Tactic {
|
|||||||
AdletElder,
|
AdletElder,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum SwordTactics {
|
pub enum SwordTactics {
|
||||||
Unskilled = 0,
|
Unskilled = 0,
|
||||||
Basic = 1,
|
Basic = 1,
|
||||||
@ -283,6 +286,39 @@ impl SwordTactics {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum AxeTactics {
|
||||||
|
Unskilled = 0,
|
||||||
|
SavageSimple = 1,
|
||||||
|
MercilessSimple = 2,
|
||||||
|
RivingSimple = 3,
|
||||||
|
SavageIntermediate = 4,
|
||||||
|
MercilessIntermediate = 5,
|
||||||
|
RivingIntermediate = 6,
|
||||||
|
SavageAdvanced = 7,
|
||||||
|
MercilessAdvanced = 8,
|
||||||
|
RivingAdvanced = 9,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AxeTactics {
|
||||||
|
pub fn from_u8(x: u8) -> Self {
|
||||||
|
use AxeTactics::*;
|
||||||
|
match x {
|
||||||
|
0 => Unskilled,
|
||||||
|
1 => SavageSimple,
|
||||||
|
2 => MercilessSimple,
|
||||||
|
3 => RivingSimple,
|
||||||
|
4 => SavageIntermediate,
|
||||||
|
5 => MercilessIntermediate,
|
||||||
|
6 => RivingIntermediate,
|
||||||
|
7 => SavageAdvanced,
|
||||||
|
8 => MercilessAdvanced,
|
||||||
|
9 => RivingAdvanced,
|
||||||
|
_ => Unskilled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(SystemData)]
|
#[derive(SystemData)]
|
||||||
pub struct ReadData<'a> {
|
pub struct ReadData<'a> {
|
||||||
pub entities: Entities<'a>,
|
pub entities: Entities<'a>,
|
||||||
@ -323,6 +359,7 @@ pub struct ReadData<'a> {
|
|||||||
pub poises: ReadStorage<'a, Poise>,
|
pub poises: ReadStorage<'a, Poise>,
|
||||||
pub stances: ReadStorage<'a, Stance>,
|
pub stances: ReadStorage<'a, Stance>,
|
||||||
pub presences: ReadStorage<'a, Presence>,
|
pub presences: ReadStorage<'a, Presence>,
|
||||||
|
pub ability_map: ReadExpect<'a, AbilityMap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ReadData<'a> {
|
impl<'a> ReadData<'a> {
|
||||||
@ -353,10 +390,13 @@ pub enum AbilityData {
|
|||||||
angle: f32,
|
angle: f32,
|
||||||
energy: f32,
|
energy: f32,
|
||||||
combo: u32,
|
combo: u32,
|
||||||
|
combo_scales: bool,
|
||||||
},
|
},
|
||||||
SelfBuff {
|
SelfBuff {
|
||||||
buff: BuffKind,
|
buff: BuffKind,
|
||||||
energy: f32,
|
energy: f32,
|
||||||
|
combo: u32,
|
||||||
|
combo_scales: bool,
|
||||||
},
|
},
|
||||||
DiveMelee {
|
DiveMelee {
|
||||||
range: f32,
|
range: f32,
|
||||||
@ -420,6 +460,12 @@ pub enum AbilityData {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
pub struct AbilityPreferences {
|
||||||
|
pub desired_energy: f32,
|
||||||
|
pub combo_scaling_buildup: u32,
|
||||||
|
}
|
||||||
|
|
||||||
impl AbilityData {
|
impl AbilityData {
|
||||||
pub fn from_ability(ability: &CharacterAbility) -> Option<Self> {
|
pub fn from_ability(ability: &CharacterAbility) -> Option<Self> {
|
||||||
use CharacterAbility::*;
|
use CharacterAbility::*;
|
||||||
@ -456,20 +502,26 @@ impl AbilityData {
|
|||||||
energy_cost,
|
energy_cost,
|
||||||
melee_constructor,
|
melee_constructor,
|
||||||
minimum_combo,
|
minimum_combo,
|
||||||
|
scaling,
|
||||||
..
|
..
|
||||||
} => Self::FinisherMelee {
|
} => Self::FinisherMelee {
|
||||||
energy: *energy_cost,
|
energy: *energy_cost,
|
||||||
range: melee_constructor.range,
|
range: melee_constructor.range,
|
||||||
angle: melee_constructor.angle,
|
angle: melee_constructor.angle,
|
||||||
combo: *minimum_combo,
|
combo: *minimum_combo,
|
||||||
|
combo_scales: scaling.is_some(),
|
||||||
},
|
},
|
||||||
SelfBuff {
|
SelfBuff {
|
||||||
buff_kind,
|
buff_kind,
|
||||||
energy_cost,
|
energy_cost,
|
||||||
|
combo_cost,
|
||||||
|
combo_scaling,
|
||||||
..
|
..
|
||||||
} => Self::SelfBuff {
|
} => Self::SelfBuff {
|
||||||
buff: *buff_kind,
|
buff: *buff_kind,
|
||||||
energy: *energy_cost,
|
energy: *energy_cost,
|
||||||
|
combo: *combo_cost,
|
||||||
|
combo_scales: combo_scaling.is_some(),
|
||||||
},
|
},
|
||||||
DiveMelee {
|
DiveMelee {
|
||||||
energy_cost,
|
energy_cost,
|
||||||
@ -595,7 +647,7 @@ impl AbilityData {
|
|||||||
agent_data: &AgentData,
|
agent_data: &AgentData,
|
||||||
tgt_data: &TargetData,
|
tgt_data: &TargetData,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
desired_energy: f32,
|
ability_preferences: AbilityPreferences,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let melee_check = |range: f32, angle, forced_movement: Option<ForcedMovement>| {
|
let melee_check = |range: f32, angle, forced_movement: Option<ForcedMovement>| {
|
||||||
let (range_inc, min_mult) = forced_movement.map_or((0.0, 0.0), |fm| match fm {
|
let (range_inc, min_mult) = forced_movement.map_or((0.0, 0.0), |fm| match fm {
|
||||||
@ -621,9 +673,19 @@ impl AbilityData {
|
|||||||
};
|
};
|
||||||
let energy_check = |energy: f32| {
|
let energy_check = |energy: f32| {
|
||||||
agent_data.energy.current() >= energy
|
agent_data.energy.current() >= energy
|
||||||
&& (energy < f32::EPSILON || agent_data.energy.current() >= desired_energy)
|
&& (energy < f32::EPSILON
|
||||||
|
|| agent_data.energy.current() >= ability_preferences.desired_energy)
|
||||||
|
};
|
||||||
|
let combo_check = |combo, scales| {
|
||||||
|
let additional_combo = if scales {
|
||||||
|
ability_preferences.combo_scaling_buildup
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
agent_data
|
||||||
|
.combo
|
||||||
|
.map_or(false, |c| c.counter() >= combo + additional_combo)
|
||||||
};
|
};
|
||||||
let combo_check = |combo| agent_data.combo.map_or(false, |c| c.counter() >= combo);
|
|
||||||
let attack_kind_check = |attacks: AttackFilters| {
|
let attack_kind_check = |attacks: AttackFilters| {
|
||||||
tgt_data
|
tgt_data
|
||||||
.char_state
|
.char_state
|
||||||
@ -673,9 +735,20 @@ impl AbilityData {
|
|||||||
angle,
|
angle,
|
||||||
energy,
|
energy,
|
||||||
combo,
|
combo,
|
||||||
} => melee_check(*range, *angle, None) && energy_check(*energy) && combo_check(*combo),
|
combo_scales,
|
||||||
SelfBuff { buff, energy } => {
|
} => {
|
||||||
|
melee_check(*range, *angle, None)
|
||||||
|
&& energy_check(*energy)
|
||||||
|
&& combo_check(*combo, *combo_scales)
|
||||||
|
},
|
||||||
|
SelfBuff {
|
||||||
|
buff,
|
||||||
|
energy,
|
||||||
|
combo,
|
||||||
|
combo_scales,
|
||||||
|
} => {
|
||||||
energy_check(*energy)
|
energy_check(*energy)
|
||||||
|
&& combo_check(*combo, *combo_scales)
|
||||||
&& agent_data
|
&& agent_data
|
||||||
.buffs
|
.buffs
|
||||||
.map_or(false, |buffs| !buffs.contains(*buff))
|
.map_or(false, |buffs| !buffs.contains(*buff))
|
||||||
@ -716,7 +789,7 @@ impl AbilityData {
|
|||||||
} => {
|
} => {
|
||||||
melee_check(*range, *angle, None)
|
melee_check(*range, *angle, None)
|
||||||
&& energy_check(*energy_per_strike * *strikes as f32)
|
&& energy_check(*energy_per_strike * *strikes as f32)
|
||||||
&& combo_check(*combo)
|
&& combo_check(*combo, false)
|
||||||
},
|
},
|
||||||
ChargedMelee {
|
ChargedMelee {
|
||||||
range,
|
range,
|
||||||
|
@ -1061,43 +1061,6 @@ impl Animation for ComboAnimation {
|
|||||||
next.belt.orientation.rotate_z(move2 * -0.6);
|
next.belt.orientation.rotate_z(move2 * -0.6);
|
||||||
next.control.position += Vec3::new(move2 * -6.0, move2 * -20.0, move2 * -4.0);
|
next.control.position += Vec3::new(move2 * -6.0, move2 * -20.0, move2 * -4.0);
|
||||||
},
|
},
|
||||||
Some("common.abilities.axe.fracture") => {
|
|
||||||
let (move1, move2) = match stage_section {
|
|
||||||
Some(StageSection::Buildup) => (anim_time, 0.0),
|
|
||||||
Some(StageSection::Action) => (1.0, anim_time),
|
|
||||||
Some(StageSection::Recover) => (1.0, 1.0),
|
|
||||||
_ => (0.0, 0.0),
|
|
||||||
};
|
|
||||||
let move1 = move1 * multi_strike_pullback;
|
|
||||||
let move2 = move2 * multi_strike_pullback;
|
|
||||||
|
|
||||||
next.hand_l.position = Vec3::new(s_a.ahl.0, s_a.ahl.1, s_a.ahl.2);
|
|
||||||
next.hand_l.orientation =
|
|
||||||
Quaternion::rotation_x(s_a.ahl.3) * Quaternion::rotation_y(s_a.ahl.4);
|
|
||||||
next.hand_r.position = Vec3::new(s_a.ahr.0, s_a.ahr.1, s_a.ahr.2);
|
|
||||||
next.hand_r.orientation =
|
|
||||||
Quaternion::rotation_x(s_a.ahr.3) * Quaternion::rotation_z(s_a.ahr.5);
|
|
||||||
|
|
||||||
next.control.position = Vec3::new(s_a.ac.0, s_a.ac.1, s_a.ac.2);
|
|
||||||
next.control.orientation = Quaternion::rotation_x(s_a.ac.3)
|
|
||||||
* Quaternion::rotation_y(s_a.ac.4)
|
|
||||||
* Quaternion::rotation_z(s_a.ac.5 + move1 * -PI / 2.0 + move2 * -0.5);
|
|
||||||
|
|
||||||
next.control.orientation.rotate_x(move1 * 0.0);
|
|
||||||
next.chest.orientation.rotate_x(move1 * -0.5);
|
|
||||||
next.chest.orientation.rotate_z(move1 * 0.7);
|
|
||||||
next.head.orientation.rotate_z(move1 * -0.3);
|
|
||||||
next.belt.orientation.rotate_z(move1 * -0.1);
|
|
||||||
next.shorts.orientation.rotate_z(move1 * -0.4);
|
|
||||||
|
|
||||||
next.chest.orientation.rotate_z(move2 * -1.8);
|
|
||||||
next.head.orientation.rotate_z(move2 * 0.9);
|
|
||||||
next.shorts.orientation.rotate_z(move2 * 1.3);
|
|
||||||
next.belt.orientation.rotate_z(move2 * 0.6);
|
|
||||||
next.control.orientation.rotate_x(move2 * -0.9);
|
|
||||||
next.control.orientation.rotate_z(move2 * -3.5);
|
|
||||||
next.control.position += Vec3::new(move2 * 14.0, move2 * 6.0, 0.0);
|
|
||||||
},
|
|
||||||
Some("common.abilities.axe.skull_bash") => {
|
Some("common.abilities.axe.skull_bash") => {
|
||||||
let (move1, move2) = match stage_section {
|
let (move1, move2) = match stage_section {
|
||||||
Some(StageSection::Buildup) => (anim_time, 0.0),
|
Some(StageSection::Buildup) => (anim_time, 0.0),
|
||||||
|
@ -402,6 +402,44 @@ impl Animation for FinisherMeleeAnimation {
|
|||||||
next.control.position += Vec3::new(move2 * 12.0, move2 * -6.0, 0.0);
|
next.control.position += Vec3::new(move2 * 12.0, move2 * -6.0, 0.0);
|
||||||
next.torso.orientation.rotate_z(move2_raw * -TAU);
|
next.torso.orientation.rotate_z(move2_raw * -TAU);
|
||||||
},
|
},
|
||||||
|
Some("common.abilities.axe.fracture") => {
|
||||||
|
let (move1, move2, move3) = match stage_section {
|
||||||
|
Some(StageSection::Buildup) => (anim_time, 0.0, 0.0),
|
||||||
|
Some(StageSection::Action) => (1.0, anim_time, 0.0),
|
||||||
|
Some(StageSection::Recover) => (1.0, 1.0, anim_time),
|
||||||
|
_ => (0.0, 0.0, 0.0),
|
||||||
|
};
|
||||||
|
let pullback = 1.0 - move3;
|
||||||
|
let move1 = move1 * pullback;
|
||||||
|
let move2 = move2 * pullback;
|
||||||
|
|
||||||
|
next.hand_l.position = Vec3::new(s_a.ahl.0, s_a.ahl.1, s_a.ahl.2);
|
||||||
|
next.hand_l.orientation =
|
||||||
|
Quaternion::rotation_x(s_a.ahl.3) * Quaternion::rotation_y(s_a.ahl.4);
|
||||||
|
next.hand_r.position = Vec3::new(s_a.ahr.0, s_a.ahr.1, s_a.ahr.2);
|
||||||
|
next.hand_r.orientation =
|
||||||
|
Quaternion::rotation_x(s_a.ahr.3) * Quaternion::rotation_z(s_a.ahr.5);
|
||||||
|
|
||||||
|
next.control.position = Vec3::new(s_a.ac.0, s_a.ac.1, s_a.ac.2);
|
||||||
|
next.control.orientation = Quaternion::rotation_x(s_a.ac.3)
|
||||||
|
* Quaternion::rotation_y(s_a.ac.4)
|
||||||
|
* Quaternion::rotation_z(s_a.ac.5 + move1 * -PI / 2.0 + move2 * -0.5);
|
||||||
|
|
||||||
|
next.control.orientation.rotate_x(move1 * 0.0);
|
||||||
|
next.chest.orientation.rotate_x(move1 * -0.5);
|
||||||
|
next.chest.orientation.rotate_z(move1 * 0.7);
|
||||||
|
next.head.orientation.rotate_z(move1 * -0.3);
|
||||||
|
next.belt.orientation.rotate_z(move1 * -0.1);
|
||||||
|
next.shorts.orientation.rotate_z(move1 * -0.4);
|
||||||
|
|
||||||
|
next.chest.orientation.rotate_z(move2 * -1.8);
|
||||||
|
next.head.orientation.rotate_z(move2 * 0.9);
|
||||||
|
next.shorts.orientation.rotate_z(move2 * 1.3);
|
||||||
|
next.belt.orientation.rotate_z(move2 * 0.6);
|
||||||
|
next.control.orientation.rotate_x(move2 * -0.9);
|
||||||
|
next.control.orientation.rotate_z(move2 * -3.5);
|
||||||
|
next.control.position += Vec3::new(move2 * 14.0, move2 * 6.0, 0.0);
|
||||||
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user