mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Maneater AI
Rebase fixes and maneater AI
This commit is contained in:
parent
e3e513cc11
commit
793d6095b3
@ -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,
|
|
||||||
)
|
)
|
18
assets/common/abilities/unique/quadlowranged/firebomb.ron
Normal file
18
assets/common/abilities/unique/quadlowranged/firebomb.ron
Normal 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,
|
||||||
|
)
|
@ -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,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,69 +459,75 @@ 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 => {
|
||||||
if *powerup > 4.0 {
|
if *powerup > 4.0 {
|
||||||
inputs.secondary.set_state(false);
|
inputs.secondary.set_state(false);
|
||||||
*powerup = 0.0;
|
*powerup = 0.0;
|
||||||
} else if *powerup > 2.0 {
|
} else if *powerup > 2.0 {
|
||||||
inputs.secondary.set_state(true);
|
inputs.secondary.set_state(true);
|
||||||
*powerup += dt.0;
|
*powerup += dt.0;
|
||||||
} else if energy.current() > 700 {
|
} else if energy.current() > 700 {
|
||||||
inputs.ability3.set_state(true);
|
inputs.ability3.set_state(true);
|
||||||
*powerup += dt.0;
|
*powerup += dt.0;
|
||||||
} else {
|
} else {
|
||||||
inputs.primary.set_state(true);
|
inputs.primary.set_state(true);
|
||||||
*powerup += dt.0;
|
*powerup += dt.0;
|
||||||
}
|
|
||||||
},
|
|
||||||
Tactic::Staff => {
|
|
||||||
// Kind of arbitrary values, but feel right in game
|
|
||||||
if energy.current() > 800
|
|
||||||
&& thread_rng().gen::<f32>() > 0.8
|
|
||||||
{
|
|
||||||
inputs.ability3.set_state(true)
|
|
||||||
} else if energy.current() > 10 {
|
|
||||||
inputs.secondary.set_state(true)
|
|
||||||
} else {
|
|
||||||
inputs.primary.set_state(true)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Tactic::Sword => {
|
|
||||||
if *powerup < 2.0 && energy.current() > 500 {
|
|
||||||
inputs.ability3.set_state(true);
|
|
||||||
*powerup += dt.0;
|
|
||||||
} else if *powerup > 2.0 {
|
|
||||||
*powerup = 0.0;
|
|
||||||
} else {
|
|
||||||
inputs.primary.set_state(true);
|
|
||||||
*powerup += dt.0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Tactic::Axe => {
|
|
||||||
if *powerup > 6.0 {
|
|
||||||
inputs.secondary.set_state(false);
|
|
||||||
*powerup = 0.0;
|
|
||||||
} else if *powerup > 4.0 && energy.current() > 10 {
|
|
||||||
inputs.secondary.set_state(true);
|
|
||||||
*powerup += dt.0;
|
|
||||||
} else {
|
|
||||||
inputs.primary.set_state(true);
|
|
||||||
*powerup += dt.0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Tactic::Bow => inputs.roll.set_state(true),
|
|
||||||
_ => inputs.primary.set_state(true),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Tactic::Staff => {
|
||||||
|
// Kind of arbitrary values, but feel right in game
|
||||||
|
if energy.current() > 800 && thread_rng().gen::<f32>() > 0.8
|
||||||
|
{
|
||||||
|
inputs.ability3.set_state(true)
|
||||||
|
} else if energy.current() > 10 {
|
||||||
|
inputs.secondary.set_state(true)
|
||||||
|
} else {
|
||||||
|
inputs.primary.set_state(true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Tactic::Sword => {
|
||||||
|
if *powerup < 2.0 && energy.current() > 500 {
|
||||||
|
inputs.ability3.set_state(true);
|
||||||
|
*powerup += dt.0;
|
||||||
|
} else if *powerup > 2.0 {
|
||||||
|
*powerup = 0.0;
|
||||||
|
} else {
|
||||||
|
inputs.primary.set_state(true);
|
||||||
|
*powerup += dt.0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Tactic::Axe => {
|
||||||
|
if *powerup > 6.0 {
|
||||||
|
inputs.secondary.set_state(false);
|
||||||
|
*powerup = 0.0;
|
||||||
|
} else if *powerup > 4.0 && energy.current() > 10 {
|
||||||
|
inputs.secondary.set_state(true);
|
||||||
|
*powerup += dt.0;
|
||||||
|
} else {
|
||||||
|
inputs.primary.set_state(true);
|
||||||
|
*powerup += dt.0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Tactic::Maneater => inputs.secondary.set_state(true),
|
||||||
|
Tactic::Bow => inputs.roll.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 {
|
||||||
.ray(pos.0 + Vec3::unit_z(), tgt_pos.0 + Vec3::unit_z())
|
Tactic::Maneater => {
|
||||||
.until(Block::is_opaque)
|
terrain
|
||||||
.cast()
|
.ray(pos.0 + Vec3::unit_z(), tgt_pos.0 + Vec3::unit_z())
|
||||||
.0
|
.until(Block::is_opaque)
|
||||||
.powf(2.0)
|
.cast()
|
||||||
>= dist_sqrd;
|
.0
|
||||||
|
.powf(2.0)
|
||||||
|
>= 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()
|
||||||
|
Loading…
Reference in New Issue
Block a user