Maneater AI

Rebase fixes and maneater AI
This commit is contained in:
jiminycrick 2020-11-12 22:13:37 -08:00 committed by Sam
parent e3e513cc11
commit 793d6095b3
6 changed files with 147 additions and 88 deletions

View File

@ -1,18 +1,10 @@
BasicRanged( BasicMelee(
energy_cost: 0, energy_cost: 0,
buildup_duration: 800, buildup_duration: 250,
recover_duration: 350, swing_duration: 250,
projectile: Fireball( recover_duration: 250,
damage: 100.0, base_damage: 200,
radius: 5.0, knockback: 25.0,
energy_regen: 50, range: 2.0,
), max_angle: 120.0,
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(),
..Default::default()
}),*/
projectile_gravity: Some(Gravity(0.9)),
projectile_speed: 60.0,
can_continue: true,
) )

View File

@ -0,0 +1,18 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 800,
recover_duration: 350,
projectile: Fireball(
damage: 100.0,
radius: 5.0,
energy_regen: 0,
),
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(),
..Default::default()
}),*/
projectile_gravity: Some(Gravity(5.0)),
projectile_speed: 60.0,
can_continue: true,
)

View File

@ -7,7 +7,7 @@ ItemDef(
stats: ( stats: (
equip_time_millis: 500, equip_time_millis: 500,
power: 1.00, power: 1.00,
speed: 1.0 speed: 1.0,
), ),
) )
), ),

View File

@ -6,7 +6,9 @@ ItemDef(
kind: Unique(GenericQuadMed), kind: Unique(GenericQuadMed),
stats: ( stats: (
equip_time_millis: 10, equip_time_millis: 10,
power: 1.00), power: 1.00,
speed: 1.0,
),
) )
), ),
quality: Low, quality: Low,

View File

@ -6,7 +6,9 @@ ItemDef(
kind: Unique(QuadLowRanged), kind: Unique(QuadLowRanged),
stats: ( stats: (
equip_time_millis: 10, equip_time_millis: 10,
power: 1.00), power: 1.00,
speed: 1.00,
),
) )
), ),
quality: Low, quality: Low,

View File

@ -8,9 +8,9 @@ use crate::{
tool::{ToolKind, UniqueKind}, tool::{ToolKind, UniqueKind},
ItemKind, ItemKind,
}, },
Agent, Alignment, Body, CharacterState, ControlAction, ControlEvent, Controller, Energy, quadruped_low, Agent, Alignment, Body, CharacterState, ControlAction, ControlEvent,
GroupManip, Health, LightEmitter, Loadout, MountState, Ori, PhysicsState, Pos, Scale, Controller, Energy, GroupManip, Health, LightEmitter, Loadout, MountState, Ori,
UnresolvedChatMsg, Vel, PhysicsState, Pos, Scale, UnresolvedChatMsg, Vel,
}, },
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
metrics::SysMetrics, metrics::SysMetrics,
@ -334,6 +334,7 @@ impl<'a> System<'a> for Sys {
Staff, Staff,
StoneGolemBoss, StoneGolemBoss,
Wolf, Wolf,
Maneater,
} }
let tactic = match loadout.active_item.as_ref().and_then(|ic| { let tactic = match loadout.active_item.as_ref().and_then(|ic| {
@ -352,7 +353,7 @@ impl<'a> System<'a> for Sys {
Tactic::StoneGolemBoss Tactic::StoneGolemBoss
}, },
Some(ToolKind::Unique(UniqueKind::GenericQuadMed)) => Tactic::Wolf, Some(ToolKind::Unique(UniqueKind::GenericQuadMed)) => Tactic::Wolf,
Some(ToolKind::Unique(UniqueKind::QuadLowRanged)) => Tactic::Staff, Some(ToolKind::Unique(UniqueKind::QuadLowRanged)) => Tactic::Maneater,
_ => Tactic::Melee, _ => Tactic::Melee,
}; };
@ -377,6 +378,7 @@ impl<'a> System<'a> for Sys {
let distance_offset = match tactic { let distance_offset = match tactic {
Tactic::Bow => 0.0004 * pos.0.distance_squared(tgt_pos.0), Tactic::Bow => 0.0004 * pos.0.distance_squared(tgt_pos.0),
Tactic::Staff => 0.0015 * pos.0.distance_squared(tgt_pos.0), Tactic::Staff => 0.0015 * pos.0.distance_squared(tgt_pos.0),
Tactic::Maneater => 0.05 * pos.0.distance_squared(tgt_pos.0),
_ => 0.0, _ => 0.0,
}; };
@ -390,10 +392,6 @@ impl<'a> System<'a> for Sys {
inputs.look_dir = dir; inputs.look_dir = dir;
} }
//if let Some(dir) = Dir::from_unnormalized(tgt_pos.0 - pos.0) {
// inputs.look_dir = dir;
//}
// Don't attack entities we are passive towards // Don't attack entities we are passive towards
// TODO: This is here, it's a bit of a hack // TODO: This is here, it's a bit of a hack
if let Some(alignment) = alignment { if let Some(alignment) = alignment {
@ -444,11 +442,14 @@ impl<'a> System<'a> for Sys {
} }
} else if (tactic == Tactic::Staff } else if (tactic == Tactic::Staff
&& dist_sqrd < (5.0 * MIN_ATTACK_DIST * scale).powf(2.0)) && dist_sqrd < (5.0 * MIN_ATTACK_DIST * scale).powf(2.0))
|| (tactic == Tactic::Maneater
&& dist_sqrd < (4.0 * MIN_ATTACK_DIST * scale).powf(2.0))
|| (tactic == Tactic::Wolf || (tactic == Tactic::Wolf
&& dist_sqrd < (3.0 * MIN_ATTACK_DIST * scale).powf(2.0)) && dist_sqrd < (3.0 * MIN_ATTACK_DIST * scale).powf(2.0))
|| dist_sqrd < (MIN_ATTACK_DIST * scale).powf(2.0) || dist_sqrd < (MIN_ATTACK_DIST * scale).powf(2.0)
{ {
controller.actions.push(ControlAction::Wield); controller.actions.push(ControlAction::Wield);
// Movement
match tactic { match tactic {
Tactic::Wolf => { Tactic::Wolf => {
// Run away from target to get clear // Run away from target to get clear
@ -458,13 +459,20 @@ impl<'a> System<'a> for Sys {
.try_normalized() .try_normalized()
.unwrap_or(Vec2::unit_y()); .unwrap_or(Vec2::unit_y());
}, },
Tactic::Maneater => {
inputs.move_dir = (tgt_pos.0 - pos.0)
.xy()
.try_normalized()
.unwrap_or(Vec2::unit_y());
},
_ => { _ => {
// Close-range attack
inputs.move_dir = (tgt_pos.0 - pos.0) inputs.move_dir = (tgt_pos.0 - pos.0)
.xy() .xy()
.try_normalized() .try_normalized()
.unwrap_or(Vec2::unit_y()) .unwrap_or(Vec2::unit_y())
* 0.1; * 0.1;
},
}
match tactic { match tactic {
Tactic::Hammer => { Tactic::Hammer => {
@ -484,8 +492,7 @@ impl<'a> System<'a> for Sys {
}, },
Tactic::Staff => { Tactic::Staff => {
// Kind of arbitrary values, but feel right in game // Kind of arbitrary values, but feel right in game
if energy.current() > 800 if energy.current() > 800 && thread_rng().gen::<f32>() > 0.8
&& thread_rng().gen::<f32>() > 0.8
{ {
inputs.ability3.set_state(true) inputs.ability3.set_state(true)
} else if energy.current() > 10 { } else if energy.current() > 10 {
@ -517,10 +524,10 @@ impl<'a> System<'a> for Sys {
*powerup += dt.0; *powerup += dt.0;
} }
}, },
Tactic::Maneater => inputs.secondary.set_state(true),
Tactic::Bow => inputs.roll.set_state(true), Tactic::Bow => inputs.roll.set_state(true),
_ => inputs.primary.set_state(true), Tactic::Melee => inputs.primary.set_state(true),
} _ => {},
},
} }
} else if matches!(tactic, Tactic::Wolf) } else if matches!(tactic, Tactic::Wolf)
&& dist_sqrd < (4.0 * MIN_ATTACK_DIST * scale).powf(2.0) && dist_sqrd < (4.0 * MIN_ATTACK_DIST * scale).powf(2.0)
@ -557,13 +564,27 @@ impl<'a> System<'a> for Sys {
|| (dist_sqrd < SIGHT_DIST.powf(2.0) || (dist_sqrd < SIGHT_DIST.powf(2.0)
&& (!*been_close || !matches!(tactic, Tactic::Melee))) && (!*been_close || !matches!(tactic, Tactic::Melee)))
{ {
let can_see_tgt = terrain let can_see_tgt = match tactic {
Tactic::Maneater => {
terrain
.ray(pos.0 + Vec3::unit_z(), tgt_pos.0 + Vec3::unit_z()) .ray(pos.0 + Vec3::unit_z(), tgt_pos.0 + Vec3::unit_z())
.until(Block::is_opaque) .until(Block::is_opaque)
.cast() .cast()
.0 .0
.powf(2.0) .powf(2.0)
>= dist_sqrd; >= dist_sqrd
&& dist_sqrd < (1.2 * MAX_CHASE_DIST).powf(2.0)
},
_ => {
terrain
.ray(pos.0 + Vec3::unit_z(), tgt_pos.0 + Vec3::unit_z())
.until(Block::is_opaque)
.cast()
.0
.powf(2.0)
>= dist_sqrd
},
};
if can_see_tgt { if can_see_tgt {
match tactic { match tactic {
@ -613,6 +634,9 @@ impl<'a> System<'a> for Sys {
*powerup += dt.0; *powerup += dt.0;
} }
}, },
Tactic::Maneater => {
inputs.primary.set_state(true);
},
_ => {}, _ => {},
} }
} }
@ -650,6 +674,27 @@ impl<'a> System<'a> for Sys {
.unwrap_or(Vec2::zero()) .unwrap_or(Vec2::zero())
* speed; * speed;
}, },
Tactic::Maneater => {
if *powerup > 5.0 {
*powerup = 0.0;
} else if *powerup > 2.5 {
inputs.move_dir = bearing
.xy()
.rotated_z(-0.25 * PI)
.try_normalized()
.unwrap_or(Vec2::zero())
* speed;
*powerup += dt.0;
} else {
inputs.move_dir = bearing
.xy()
.rotated_z(0.25 * PI)
.try_normalized()
.unwrap_or(Vec2::zero())
* speed;
*powerup += dt.0;
}
},
_ => { _ => {
inputs.move_dir = bearing inputs.move_dir = bearing
.xy() .xy()