Gave minotaur AI.

This commit is contained in:
Sam 2021-04-27 22:33:24 -04:00
parent 811f1fadb2
commit 2290a22a15
5 changed files with 80 additions and 4 deletions

View File

@ -10,7 +10,7 @@ ChargedMelee(
range: 5.0,
max_angle: 45.0,
speed: 1.0,
charge_duration: 2.0,
charge_duration: 1.5,
swing_duration: 0.1,
hit_timing: 0.8,
recover_duration: 0.5,

View File

@ -40,6 +40,7 @@ pub enum Tactic {
Mindflayer,
BirdLargeBreathe,
BirdLargeFire,
Minotaur,
}
#[derive(Copy, Clone, Debug, PartialEq)]

View File

@ -52,6 +52,7 @@ impl CharacterBehavior for Data {
fn behavior(&self, data: &JoinData) -> StateUpdate {
let mut update = StateUpdate::from(data);
handle_orientation(data, &mut update, 1.0);
handle_move(data, &mut update, 0.7);
handle_jump(data, &mut update, 1.0);
handle_orientation(data, &mut update, 0.35);

View File

@ -76,6 +76,7 @@ impl CharacterBehavior for Data {
match self.stage_section {
StageSection::Buildup => {
if self.timer < self.static_data.buildup_duration {
handle_orientation(data, &mut update, 1.0);
// Build up
update.character = CharacterState::DashMelee(Data {
timer: self
@ -105,6 +106,7 @@ impl CharacterBehavior for Data {
/ self.static_data.charge_duration.as_secs_f32())
.min(1.0);
handle_orientation(data, &mut update, 0.6);
handle_forced_movement(
data,
&mut update,

View File

@ -1542,6 +1542,7 @@ impl<'a> AgentData<'a> {
"Bird Large Breathe" => Tactic::BirdLargeBreathe,
"Bird Large Fire" => Tactic::BirdLargeFire,
"Mindflayer" => Tactic::Mindflayer,
"Minotaur" => Tactic::Minotaur,
_ => Tactic::Melee,
},
AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind),
@ -2569,11 +2570,11 @@ impl<'a> AgentData<'a> {
const MINDFLAYER_ATTACK_DIST: f32 = 16.0;
const MINION_SUMMON_THRESHOLD: f32 = 0.20;
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
// Extreme hack to set action_timer at start of combat
// Sets action_float at start of combat
if agent.action_state.action_float < MINION_SUMMON_THRESHOLD
&& health_fraction > MINION_SUMMON_THRESHOLD
{
agent.action_state.action_float = 0.8;
agent.action_state.action_float = 1.0 - MINION_SUMMON_THRESHOLD;
}
let mindflayer_is_far = dist_sqrd > MINDFLAYER_ATTACK_DIST.powi(2);
if agent.action_state.action_float > health_fraction {
@ -2611,7 +2612,7 @@ impl<'a> AgentData<'a> {
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
} else if thread_rng().gen_bool(health_fraction.into()) && angle < 30.0 {
} else if thread_rng().gen_bool(health_fraction.into()) {
// Else if at high health, use primary
controller
.actions
@ -2889,6 +2890,77 @@ impl<'a> AgentData<'a> {
agent.action_state.action_timer = 0.0;
}
},
Tactic::Minotaur => {
const MINOTAUR_FRENZY_THRESHOLD: f32 = 0.5;
const MINOTAUR_ATTACK_RANGE: f32 = 5.0;
const MINOTAUR_CHARGE_DISTANCE: f32 = 15.0;
let minotaur_attack_distance =
self.body.map_or(0.0, |b| b.radius()) + MINOTAUR_ATTACK_RANGE;
let health_fraction = self.health.map_or(1.0, |h| h.fraction());
// Sets action float at start of combat
if agent.action_state.action_float < MINOTAUR_FRENZY_THRESHOLD
&& health_fraction > MINOTAUR_FRENZY_THRESHOLD
{
agent.action_state.action_float = MINOTAUR_FRENZY_THRESHOLD;
}
if health_fraction < agent.action_state.action_float {
// Makes minotaur buff itself with frenzy
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(1)));
if matches!(self.char_state, CharacterState::SelfBuff(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.action_float = 0.0;
}
} else if matches!(self.char_state, CharacterState::DashMelee(c) if !matches!(c.stage_section, StageSection::Recover))
{
// If already charging, keep charging if not in recover
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(0)));
} else if matches!(self.char_state, CharacterState::ChargedMelee(c) if matches!(c.stage_section, StageSection::Charge) && c.timer < c.static_data.charge_duration)
{
// If already charging a melee attack, keep charging it if charging
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
} else if dist_sqrd > MINOTAUR_CHARGE_DISTANCE.powi(2) {
// Charges at target if they are far enough away
if angle < 60.0 {
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(0)));
}
} else if dist_sqrd < minotaur_attack_distance.powi(2) {
if agent.action_state.action_bool && !self.char_state.is_attack() {
// Cripple target if not just used cripple
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
agent.action_state.action_bool = false;
} else if !self.char_state.is_attack() {
// Cleave target if not just used cleave
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
agent.action_state.action_bool = true;
}
}
// Make minotaur move towards target
if let Some((bearing, speed)) = agent.chaser.chase(
&*terrain,
self.pos.0,
self.vel.0,
tgt_pos.0,
TraversalConfig {
min_tgt_dist: 1.25,
..self.traversal_config
},
) {
controller.inputs.move_dir =
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
}
},
}
}