Harvester AI

This commit is contained in:
Sam 2021-06-20 12:04:06 -05:00
parent 0a32b676c8
commit c162827f97

View File

@ -122,6 +122,7 @@ pub enum Tactic {
TidalWarrior,
Yeti,
Tornado,
Harvester,
}
#[derive(SystemData)]
@ -1663,6 +1664,7 @@ impl<'a> AgentData<'a> {
"Tidal Warrior" => Tactic::TidalWarrior,
"Tidal Totem" => Tactic::RadialTurret,
"Yeti" => Tactic::Yeti,
"Harvester" => Tactic::Harvester,
_ => Tactic::Melee,
},
AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind),
@ -1763,6 +1765,18 @@ impl<'a> AgentData<'a> {
),
)
},
Tactic::Harvester if matches!(self.char_state, CharacterState::BasicRanged(_)) => {
const PUMPKIN_SPEED: f32 = 30.0;
aim_projectile(
PUMPKIN_SPEED,
Vec3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z + eye_offset),
Vec3::new(
tgt_data.pos.0.x,
tgt_data.pos.0.y,
tgt_data.pos.0.z + tgt_eye_offset,
),
)
},
_ => Dir::from_unnormalized(
Vec3::new(
tgt_data.pos.0.x,
@ -1942,6 +1956,9 @@ impl<'a> AgentData<'a> {
Tactic::Yeti => {
self.handle_yeti_attack(agent, controller, &attack_data, &tgt_data, &read_data)
},
Tactic::Harvester => {
self.handle_harvester_attack(agent, controller, &attack_data, &tgt_data, &read_data)
},
}
}
@ -3693,6 +3710,72 @@ impl<'a> AgentData<'a> {
self.path_toward_target(agent, controller, tgt_data, read_data, false, None);
}
fn handle_harvester_attack(
&self,
agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
) {
const VINE_CREATION_THRESHOLD: f32 = 0.50;
const FIRE_BREATH_RANGE: f32 = 20.0;
const MAX_PUMPKIN_RANGE: f32 = 50.0;
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
if health_fraction < VINE_CREATION_THRESHOLD && !agent.action_state.condition {
// Summon vines when reach threshold of health
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(0)));
if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.condition = true;
}
} else if attack_data.dist_sqrd < FIRE_BREATH_RANGE.powi(2) {
if matches!(self.char_state, CharacterState::BasicBeam(c) if c.timer < Duration::from_secs(10))
{
// Keep breathing fire if close enough and have not been breathing for more than
// 10 seconds
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
} else if attack_data.in_min_range() && attack_data.angle < 60.0 {
// Scythe them if they're in range and angle
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
} else if attack_data.angle < 30.0
&& can_see_tgt(
&*read_data.terrain,
self.pos,
tgt_data.pos,
attack_data.dist_sqrd,
)
{
// Start breathing fire at them if close enough, in angle, and can see target
controller
.actions
.push(ControlAction::basic_input(InputKind::Secondary));
}
} else if attack_data.dist_sqrd < MAX_PUMPKIN_RANGE.powi(2)
&& can_see_tgt(
&*read_data.terrain,
self.pos,
tgt_data.pos,
attack_data.dist_sqrd,
)
{
// Throw a pumpkin at them if close enough and can see them
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(1)));
}
// Always attempt to path towards target
self.path_toward_target(agent, controller, tgt_data, read_data, false, None);
}
fn follow(
&self,
agent: &mut Agent,