mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Yeti AI
This commit is contained in:
parent
93f90d514c
commit
74b7039219
@ -1,11 +1,11 @@
|
|||||||
BasicBeam(
|
BasicBeam(
|
||||||
buildup_duration: 0.4,
|
buildup_duration: 0.4,
|
||||||
recover_duration: 0.25,
|
recover_duration: 0.25,
|
||||||
beam_duration: 0.5,
|
beam_duration: 0.25,
|
||||||
damage: 50,
|
damage: 50,
|
||||||
tick_rate: 1.0,
|
tick_rate: 1.0,
|
||||||
range: 15.0,
|
range: 15.0,
|
||||||
max_angle: 22.5,
|
max_angle: 30.0,
|
||||||
damage_effect: Some(Buff((
|
damage_effect: Some(Buff((
|
||||||
kind: Frozen,
|
kind: Frozen,
|
||||||
dur_secs: 3.0,
|
dur_secs: 3.0,
|
||||||
|
@ -3,15 +3,15 @@ Shockwave(
|
|||||||
buildup_duration: 0.6,
|
buildup_duration: 0.6,
|
||||||
swing_duration: 0.12,
|
swing_duration: 0.12,
|
||||||
recover_duration: 1.2,
|
recover_duration: 1.2,
|
||||||
damage: 300,
|
damage: 200,
|
||||||
poise_damage: 30,
|
poise_damage: 10,
|
||||||
knockback: (strength: 40.0, direction: Up),
|
knockback: (strength: 30.0, direction: Up),
|
||||||
shockwave_angle: 90.0,
|
shockwave_angle: 90.0,
|
||||||
shockwave_vertical_angle: 15.0,
|
shockwave_vertical_angle: 15.0,
|
||||||
shockwave_speed: 25.0,
|
shockwave_speed: 50.0,
|
||||||
shockwave_duration: 1.0,
|
shockwave_duration: 0.5,
|
||||||
requires_ground: false,
|
requires_ground: true,
|
||||||
move_efficiency: 0.0,
|
move_efficiency: 0.5,
|
||||||
damage_kind: Piercing,
|
damage_kind: Piercing,
|
||||||
specifier: IceSpikes,
|
specifier: IceSpikes,
|
||||||
)
|
)
|
@ -5,7 +5,7 @@ BasicMelee(
|
|||||||
recover_duration: 0.5,
|
recover_duration: 0.5,
|
||||||
base_damage: 150,
|
base_damage: 150,
|
||||||
base_poise_damage: 50,
|
base_poise_damage: 50,
|
||||||
knockback: ( strength: 100.0, direction: Away),
|
knockback: ( strength: 50.0, direction: Away),
|
||||||
range: 4.0,
|
range: 4.0,
|
||||||
max_angle: 20.0,
|
max_angle: 20.0,
|
||||||
damage_effect: None,
|
damage_effect: None,
|
||||||
|
@ -471,7 +471,7 @@ impl Body {
|
|||||||
biped_large::Species::Dullahan => 3000,
|
biped_large::Species::Dullahan => 3000,
|
||||||
biped_large::Species::Mindflayer => 12500,
|
biped_large::Species::Mindflayer => 12500,
|
||||||
biped_large::Species::Tidalwarrior => 16000,
|
biped_large::Species::Tidalwarrior => 16000,
|
||||||
biped_large::Species::Yeti => 4000,
|
biped_large::Species::Yeti => 12000,
|
||||||
biped_large::Species::Minotaur => 30000,
|
biped_large::Species::Minotaur => 30000,
|
||||||
biped_large::Species::Harvester => 3000,
|
biped_large::Species::Harvester => 3000,
|
||||||
biped_large::Species::Blueoni => 2400,
|
biped_large::Species::Blueoni => 2400,
|
||||||
@ -586,7 +586,7 @@ impl Body {
|
|||||||
biped_large::Species::Wendigo => 80,
|
biped_large::Species::Wendigo => 80,
|
||||||
biped_large::Species::Troll => 60,
|
biped_large::Species::Troll => 60,
|
||||||
biped_large::Species::Dullahan => 120,
|
biped_large::Species::Dullahan => 120,
|
||||||
biped_large::Species::Yeti => 80,
|
biped_large::Species::Yeti => 0,
|
||||||
biped_large::Species::Harvester => 80,
|
biped_large::Species::Harvester => 80,
|
||||||
// Boss enemies have their health set, not adjusted by level.
|
// Boss enemies have their health set, not adjusted by level.
|
||||||
biped_large::Species::Mindflayer => 0,
|
biped_large::Species::Mindflayer => 0,
|
||||||
@ -650,6 +650,7 @@ impl Body {
|
|||||||
biped_large::Species::Mindflayer => 4.8,
|
biped_large::Species::Mindflayer => 4.8,
|
||||||
biped_large::Species::Minotaur => 3.2,
|
biped_large::Species::Minotaur => 3.2,
|
||||||
biped_large::Species::Tidalwarrior => 2.25,
|
biped_large::Species::Tidalwarrior => 2.25,
|
||||||
|
biped_large::Species::Yeti => 2.0,
|
||||||
_ => 1.0,
|
_ => 1.0,
|
||||||
},
|
},
|
||||||
Body::Golem(g) => match g.species {
|
Body::Golem(g) => match g.species {
|
||||||
|
@ -119,6 +119,7 @@ pub enum Tactic {
|
|||||||
Minotaur,
|
Minotaur,
|
||||||
ClayGolem,
|
ClayGolem,
|
||||||
TidalWarrior,
|
TidalWarrior,
|
||||||
|
Yeti,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SystemData)]
|
#[derive(SystemData)]
|
||||||
@ -1609,6 +1610,7 @@ impl<'a> AgentData<'a> {
|
|||||||
"Clay Golem" => Tactic::ClayGolem,
|
"Clay Golem" => Tactic::ClayGolem,
|
||||||
"Tidal Warrior" => Tactic::TidalWarrior,
|
"Tidal Warrior" => Tactic::TidalWarrior,
|
||||||
"Tidal Totem" => Tactic::RadialTurret,
|
"Tidal Totem" => Tactic::RadialTurret,
|
||||||
|
"Yeti" => Tactic::Yeti,
|
||||||
_ => Tactic::Melee,
|
_ => Tactic::Melee,
|
||||||
},
|
},
|
||||||
AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind),
|
AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind),
|
||||||
@ -1697,6 +1699,18 @@ impl<'a> AgentData<'a> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
Tactic::Yeti if matches!(self.char_state, CharacterState::BasicRanged(_)) => {
|
||||||
|
const SNOWBALL_SPEED: f32 = 60.0;
|
||||||
|
aim_projectile(
|
||||||
|
SNOWBALL_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(
|
_ => Dir::from_unnormalized(
|
||||||
Vec3::new(
|
Vec3::new(
|
||||||
tgt_data.pos.0.x,
|
tgt_data.pos.0.x,
|
||||||
@ -1865,6 +1879,9 @@ impl<'a> AgentData<'a> {
|
|||||||
&tgt_data,
|
&tgt_data,
|
||||||
&read_data,
|
&read_data,
|
||||||
),
|
),
|
||||||
|
Tactic::Yeti => {
|
||||||
|
self.handle_yeti_attack(agent, controller, &attack_data, &tgt_data, &read_data)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3476,6 +3493,65 @@ impl<'a> AgentData<'a> {
|
|||||||
self.path_toward_target(agent, controller, tgt_data, read_data, false, None);
|
self.path_toward_target(agent, controller, tgt_data, read_data, false, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_yeti_attack(
|
||||||
|
&self,
|
||||||
|
agent: &mut Agent,
|
||||||
|
controller: &mut Controller,
|
||||||
|
attack_data: &AttackData,
|
||||||
|
tgt_data: &TargetData,
|
||||||
|
read_data: &ReadData,
|
||||||
|
) {
|
||||||
|
const ICE_SPIKES_RANGE: f32 = 20.0;
|
||||||
|
const ICE_BREATH_RANGE: f32 = 15.0;
|
||||||
|
const ICE_BREATH_TIMER: f32 = 5.0;
|
||||||
|
const SNOWBALL_MAX_RANGE: f32 = 50.0;
|
||||||
|
|
||||||
|
agent.action_state.counter += read_data.dt.0;
|
||||||
|
|
||||||
|
if attack_data.dist_sqrd < ICE_BREATH_RANGE.powi(2) && attack_data.angle < 60.0 {
|
||||||
|
if matches!(self.char_state, CharacterState::BasicBeam(c) if c.timer < Duration::from_secs(1))
|
||||||
|
{
|
||||||
|
// Keep using ice breath until a second has passed
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Ability(0)));
|
||||||
|
} else if agent.action_state.counter > ICE_BREATH_TIMER {
|
||||||
|
// Use ice breath if timer has gone for long enough
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Ability(0)));
|
||||||
|
|
||||||
|
if matches!(self.char_state, CharacterState::BasicBeam(_)) {
|
||||||
|
// Resets action counter when using beam
|
||||||
|
agent.action_state.counter = 0.0;
|
||||||
|
}
|
||||||
|
} else if attack_data.in_min_range() {
|
||||||
|
// Basic attack if on top of them
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Primary));
|
||||||
|
} else {
|
||||||
|
// Use ice spikes if too far for other abilities
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
|
}
|
||||||
|
} else if attack_data.dist_sqrd < ICE_SPIKES_RANGE.powi(2) && attack_data.angle < 60.0 {
|
||||||
|
// Use ice spikes if in range
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
|
} else if attack_data.dist_sqrd < SNOWBALL_MAX_RANGE.powi(2) && attack_data.angle < 60.0 {
|
||||||
|
// Otherwise, chuck all the snowballs
|
||||||
|
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(
|
fn follow(
|
||||||
&self,
|
&self,
|
||||||
agent: &mut Agent,
|
agent: &mut Agent,
|
||||||
|
Loading…
Reference in New Issue
Block a user