Ran Cargo fmt

This commit is contained in:
Timothy Finnegan 2022-10-24 19:52:37 -07:00
parent cd5ae96424
commit 1922d69154
5 changed files with 341 additions and 181 deletions

View File

@ -21,20 +21,22 @@ pub const TRADE_INTERACTION_TIME: f32 = 300.0;
const AWARENESS_DECREMENT_CONSTANT: f32 = 2.1;
const SECONDS_BEFORE_FORGET_SOUNDS: f64 = 180.0;
//intentionally very few concurrent action state variables are allowed. This is to keep the
//complexity of our AI from getting too large, too quickly. Originally I was
//going to provide 30 of these, but if we decide later that this is too many
//and somebody is already using 30 in one of their AI, it will be difficult
//to go back.
//intentionally very few concurrent action state variables are allowed. This is
// to keep the complexity of our AI from getting too large, too quickly.
// Originally I was going to provide 30 of these, but if we decide later that
// this is too many and somebody is already using 30 in one of their AI, it will
// be difficult to go back.
/// The number of timers that a single Action node can track concurrently
/// Define constants within a given action node to index between them.
const ACTIONSTATE_NUMBER_OF_CONCURRENT_TIMERS: usize = 5;
/// The number of float counters that a single Action node can track concurrently
/// Define constants within a given action node to index between them.
/// The number of float counters that a single Action node can track
/// concurrently Define constants within a given action node to index between
/// them.
const ACTIONSTATE_NUMBER_OF_CONCURRENT_COUNTERS: usize = 5;
/// The number of integer counters that a single Action node can track concurrently
/// Define constants within a given action node to index between them.
/// The number of integer counters that a single Action node can track
/// concurrently Define constants within a given action node to index between
/// them.
const ACTIONSTATE_NUMBER_OF_CONCURRENT_INT_COUNTERS: usize = 5;
/// The number of booleans that a single Action node can track concurrently
/// Define constants within a given action node to index between them.
@ -531,8 +533,9 @@ pub struct Agent {
}
/// State persistence object for the behavior tree
/// Allows for state to be stored between subsequent, sequential calls of a single action node.
/// If the executed action node changes between ticks, then the state should be considered lost.
/// Allows for state to be stored between subsequent, sequential calls of a
/// single action node. If the executed action node changes between ticks, then
/// the state should be considered lost.
#[derive(Clone, Debug, Default)]
pub struct ActionState {
pub timers: [f32; ACTIONSTATE_NUMBER_OF_CONCURRENT_TIMERS],

View File

@ -1,4 +1,3 @@
use crate::{
consts::{
AVG_FOLLOW_DIST, DEFAULT_ATTACK_RANGE, IDLE_HEALING_ITEM_THRESHOLD, PARTIAL_PATH_DIST,
@ -44,9 +43,6 @@ use vek::*;
#[cfg(feature = "use-dyn-lib")]
use {crate::LIB, std::ffi::CStr};
impl<'a> AgentData<'a> {
////////////////////////////////////////
// Action Nodes

View File

@ -213,8 +213,7 @@ impl<'a> AgentData<'a> {
read_data: &ReadData,
rng: &mut impl Rng,
) {
enum ActionStateTimers
{
enum ActionStateTimers {
TimerHandleAxeAttack = 0,
}
let has_leap = || self.skill_set.has_skill(Skill::Axe(AxeSkill::UnlockLeap));
@ -228,15 +227,21 @@ impl<'a> AgentData<'a> {
if agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] > 5.0 {
controller.push_cancel_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] = 0.0;
} else if agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] > 2.5 && has_energy(10.0) {
} else if agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize]
> 2.5
&& has_energy(10.0)
{
controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] +=
read_data.dt.0;
} else if has_leap() && has_energy(45.0) && rng.gen_bool(0.5) {
controller.push_basic_input(InputKind::Ability(0));
agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] +=
read_data.dt.0;
} else {
controller.push_basic_input(InputKind::Primary);
agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerHandleAxeAttack as usize] +=
read_data.dt.0;
}
} else {
self.path_toward_target(
@ -279,8 +284,7 @@ impl<'a> AgentData<'a> {
read_data: &ReadData,
rng: &mut impl Rng,
) {
enum ActionStateTimers
{
enum ActionStateTimers {
TimerHandleHammerAttack = 0,
}
let has_leap = || {
@ -296,18 +300,25 @@ impl<'a> AgentData<'a> {
if attack_data.in_min_range() && attack_data.angle < 45.0 {
controller.inputs.move_dir = Vec2::zero();
if agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] > 4.0 {
if agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] > 4.0
{
controller.push_cancel_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] = 0.0;
} else if agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] > 3.0 {
agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] =
0.0;
} else if agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize]
> 3.0
{
controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] +=
read_data.dt.0;
} else if has_leap() && has_energy(50.0) && rng.gen_bool(0.9) {
use_leap(controller);
agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] +=
read_data.dt.0;
} else {
controller.push_basic_input(InputKind::Primary);
agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerHandleHammerAttack as usize] +=
read_data.dt.0;
}
} else {
self.path_toward_target(
@ -358,16 +369,21 @@ impl<'a> AgentData<'a> {
if self
.skill_set
.has_skill(Skill::Sword(SwordSkill::UnlockSpin))
&& agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] < 2.0
&& agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize]
< 2.0
&& self.energy.current() > 60.0
{
controller.push_basic_input(InputKind::Ability(0));
agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] += read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] > 2.0 {
agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] +=
read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize]
> 2.0
{
agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] = 0.0;
} else {
controller.push_basic_input(InputKind::Primary);
agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] +=
read_data.dt.0;
}
} else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) {
if self.path_toward_target(
@ -384,11 +400,16 @@ impl<'a> AgentData<'a> {
tgt_data.body,
read_data,
) {
if agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] > 4.0 && attack_data.angle < 45.0 {
if agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize]
> 4.0
&& attack_data.angle < 45.0
{
controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] = 0.0;
agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] =
0.0;
} else {
agent.action_state.timers[ActionStateTimers::TimerHandleSwordAttack as usize] += read_data.dt.0;
agent.action_state.timers
[ActionStateTimers::TimerHandleSwordAttack as usize] += read_data.dt.0;
}
}
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
@ -594,8 +615,10 @@ impl<'a> AgentData<'a> {
// emergency roll
controller.push_basic_input(InputKind::Roll);
} else if matches!(self.char_state, CharacterState::Shockwave(_)) {
agent.action_state.conditions[ActionStateConditions::ConditionStaffCanShockwave as usize] = false;
} else if agent.action_state.conditions[ActionStateConditions::ConditionStaffCanShockwave as usize]
agent.action_state.conditions
[ActionStateConditions::ConditionStaffCanShockwave as usize] = false;
} else if agent.action_state.conditions
[ActionStateConditions::ConditionStaffCanShockwave as usize]
&& matches!(self.char_state, CharacterState::Wielding(_))
{
controller.push_basic_input(InputKind::Ability(0));
@ -618,7 +641,8 @@ impl<'a> AgentData<'a> {
if matches!(self.char_state, CharacterState::Wielding(_)) {
controller.push_basic_input(InputKind::Ability(0));
} else {
agent.action_state.conditions[ActionStateConditions::ConditionStaffCanShockwave as usize] = true;
agent.action_state.conditions
[ActionStateConditions::ConditionStaffCanShockwave as usize] = true;
}
} else if self.energy.current()
> shockwave_cost + CharacterAbility::default_roll().get_energy_cost()
@ -868,11 +892,16 @@ impl<'a> AgentData<'a> {
read_data,
) && attack_data.angle < 90.0
{
if agent.action_state.timers[ActionStateTimers::TimerHandleStoneGolemAttack as usize] > 5.0 {
if agent.action_state.timers
[ActionStateTimers::TimerHandleStoneGolemAttack as usize]
> 5.0
{
controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerHandleStoneGolemAttack as usize] = 0.0;
agent.action_state.timers
[ActionStateTimers::TimerHandleStoneGolemAttack as usize] = 0.0;
} else {
agent.action_state.timers[ActionStateTimers::TimerHandleStoneGolemAttack as usize] += read_data.dt.0;
agent.action_state.timers
[ActionStateTimers::TimerHandleStoneGolemAttack as usize] += read_data.dt.0;
}
}
} else {
@ -907,15 +936,23 @@ impl<'a> AgentData<'a> {
CounterIHandleCircleChargeAttack = 0,
}
if agent.action_state.counters[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] >= circle_time as f32 {
if agent.action_state.counters
[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize]
>= circle_time as f32
{
// if circle charge is in progress and time hasn't expired, continue charging
controller.push_basic_input(InputKind::Secondary);
}
if attack_data.in_min_range() {
if agent.action_state.counters[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] > 0.0 {
if agent.action_state.counters
[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize]
> 0.0
{
// set timer and rotation counter to zero if in minimum range
agent.action_state.counters[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] = 0.0;
agent.action_state.int_counters[ActionStateCountersI::CounterIHandleCircleChargeAttack as usize] = 0;
agent.action_state.counters
[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] = 0.0;
agent.action_state.int_counters
[ActionStateCountersI::CounterIHandleCircleChargeAttack as usize] = 0;
} else {
// melee attack
controller.push_basic_input(InputKind::Primary);
@ -923,13 +960,23 @@ impl<'a> AgentData<'a> {
}
} else if attack_data.dist_sqrd < (radius as f32 + attack_data.min_attack_dist).powi(2) {
// if in range to charge, circle, then charge
if agent.action_state.int_counters[ActionStateCountersI::CounterIHandleCircleChargeAttack as usize] == 0 {
if agent.action_state.int_counters
[ActionStateCountersI::CounterIHandleCircleChargeAttack as usize]
== 0
{
// if you haven't chosen a direction to go in, choose now
agent.action_state.int_counters[ActionStateCountersI::CounterIHandleCircleChargeAttack as usize] = 1 + rng.gen_bool(0.5) as u8;
agent.action_state.int_counters
[ActionStateCountersI::CounterIHandleCircleChargeAttack as usize] =
1 + rng.gen_bool(0.5) as u8;
}
if agent.action_state.counters[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] < circle_time as f32 {
if agent.action_state.counters
[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize]
< circle_time as f32
{
// circle if circle timer not ready
let move_dir = match agent.action_state.int_counters[ActionStateCountersI::CounterIHandleCircleChargeAttack as usize] {
let move_dir = match agent.action_state.int_counters
[ActionStateCountersI::CounterIHandleCircleChargeAttack as usize]
{
1 =>
// circle left if counter is 1
{
@ -966,11 +1013,15 @@ impl<'a> AgentData<'a> {
.map_or(true, |b| b.is_some());
if obstacle {
// if obstacle detected, stop circling
agent.action_state.counters[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] = circle_time as f32;
agent.action_state.counters
[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] =
circle_time as f32;
}
controller.inputs.move_dir = move_dir;
// use counter as timer since timer may be modified in other parts of the code
agent.action_state.counters[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] += read_data.dt.0;
agent.action_state.counters
[ActionStateCountersF::CounterFHandleCircleChargeAttack as usize] +=
read_data.dt.0;
}
// activating charge once circle timer expires is handled above
} else {
@ -1024,16 +1075,25 @@ impl<'a> AgentData<'a> {
read_data,
)
{
if agent.action_state.timers[ActionStateTimers::TimerHandleQuadLowRanged as usize] > 5.0 {
agent.action_state.timers[ActionStateTimers::TimerHandleQuadLowRanged as usize] = 0.0;
} else if agent.action_state.timers[ActionStateTimers::TimerHandleQuadLowRanged as usize] > 2.5 {
if agent.action_state.timers
[ActionStateTimers::TimerHandleQuadLowRanged as usize]
> 5.0
{
agent.action_state.timers
[ActionStateTimers::TimerHandleQuadLowRanged as usize] = 0.0;
} else if agent.action_state.timers
[ActionStateTimers::TimerHandleQuadLowRanged as usize]
> 2.5
{
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
.xy()
.rotated_z(1.75 * PI)
.try_normalized()
.unwrap_or_else(Vec2::zero)
* speed;
agent.action_state.timers[ActionStateTimers::TimerHandleQuadLowRanged as usize] += read_data.dt.0;
agent.action_state.timers
[ActionStateTimers::TimerHandleQuadLowRanged as usize] +=
read_data.dt.0;
} else {
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
.xy()
@ -1041,7 +1101,9 @@ impl<'a> AgentData<'a> {
.try_normalized()
.unwrap_or_else(Vec2::zero)
* speed;
agent.action_state.timers[ActionStateTimers::TimerHandleQuadLowRanged as usize] += read_data.dt.0;
agent.action_state.timers
[ActionStateTimers::TimerHandleQuadLowRanged as usize] +=
read_data.dt.0;
}
controller.push_basic_input(InputKind::Secondary);
self.jump_if(bearing.z > 1.5, controller);
@ -1087,10 +1149,12 @@ impl<'a> AgentData<'a> {
agent.action_state.timers[ActionStateTimers::TimerTailSlap as usize] = 0.0;
} else if agent.action_state.timers[ActionStateTimers::TimerTailSlap as usize] > 1.0 {
controller.push_basic_input(InputKind::Primary);
agent.action_state.timers[ActionStateTimers::TimerTailSlap as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerTailSlap as usize] +=
read_data.dt.0;
} else {
controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerTailSlap as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerTailSlap as usize] +=
read_data.dt.0;
}
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
.xy()
@ -1180,12 +1244,15 @@ impl<'a> AgentData<'a> {
controller.inputs.move_dir = Vec2::zero();
if agent.action_state.timers[ActionStateTimers::TimerQuadLowBasic as usize] > 5.0 {
agent.action_state.timers[ActionStateTimers::TimerQuadLowBasic as usize] = 0.0;
} else if agent.action_state.timers[ActionStateTimers::TimerQuadLowBasic as usize] > 2.0 {
} else if agent.action_state.timers[ActionStateTimers::TimerQuadLowBasic as usize] > 2.0
{
controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerQuadLowBasic as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerQuadLowBasic as usize] +=
read_data.dt.0;
} else {
controller.push_basic_input(InputKind::Primary);
agent.action_state.timers[ActionStateTimers::TimerQuadLowBasic as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerQuadLowBasic as usize] +=
read_data.dt.0;
}
} else {
let path = if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) {
@ -1261,10 +1328,13 @@ impl<'a> AgentData<'a> {
controller.inputs.move_dir = Vec2::zero();
if agent.action_state.timers[ActionStateTimers::TimerQuadMedBasic as usize] < 2.0 {
controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerQuadMedBasic as usize] += read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerQuadMedBasic as usize] < 3.0 {
agent.action_state.timers[ActionStateTimers::TimerQuadMedBasic as usize] +=
read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerQuadMedBasic as usize] < 3.0
{
controller.push_basic_input(InputKind::Primary);
agent.action_state.timers[ActionStateTimers::TimerQuadMedBasic as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerQuadMedBasic as usize] +=
read_data.dt.0;
} else {
agent.action_state.timers[ActionStateTimers::TimerQuadMedBasic as usize] = 0.0;
}
@ -1297,8 +1367,7 @@ impl<'a> AgentData<'a> {
tgt_data: &TargetData,
read_data: &ReadData,
) {
enum ActionStateTimers
{
enum ActionStateTimers {
TimerQuadLowBeam = 0,
}
if attack_data.angle < 90.0
@ -1316,18 +1385,25 @@ impl<'a> AgentData<'a> {
.try_normalized()
.unwrap_or_else(Vec2::unit_y);
controller.push_basic_input(InputKind::Primary);
agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] += read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] < 4.0 && attack_data.angle < 15.0 {
agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] +=
read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] < 4.0
&& attack_data.angle < 15.0
{
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
.xy()
.rotated_z(-0.47 * PI)
.try_normalized()
.unwrap_or_else(Vec2::unit_y);
controller.push_basic_input(InputKind::Primary);
agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] += read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] < 6.0 && attack_data.angle < 15.0 {
agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] +=
read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] < 6.0
&& attack_data.angle < 15.0
{
controller.push_basic_input(InputKind::Ability(0));
agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] +=
read_data.dt.0;
} else {
agent.action_state.timers[ActionStateTimers::TimerQuadLowBeam as usize] = 0.0;
}
@ -1366,15 +1442,19 @@ impl<'a> AgentData<'a> {
const ORGAN_AURA_DURATION: f32 = 34.75;
if attack_data.dist_sqrd < (7.0 * attack_data.min_attack_dist).powi(2) {
if agent.action_state.timers[ActionStateTimers::TimerOrganAura as usize] > ORGAN_AURA_DURATION {
if agent.action_state.timers[ActionStateTimers::TimerOrganAura as usize]
> ORGAN_AURA_DURATION
{
agent.action_state.timers[ActionStateTimers::TimerOrganAura as usize] = 0.0;
} else if agent.action_state.timers[ActionStateTimers::TimerOrganAura as usize] < 1.0 {
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
agent.action_state.timers[ActionStateTimers::TimerOrganAura as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerOrganAura as usize] +=
read_data.dt.0;
} else {
agent.action_state.timers[ActionStateTimers::TimerOrganAura as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerOrganAura as usize] +=
read_data.dt.0;
}
} else {
agent.target = None;
@ -1495,24 +1575,29 @@ impl<'a> AgentData<'a> {
ConditionCounterInit = 0,
}
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());
// Sets counter at start of combat, using `condition` to keep track of whether
// it was already initialized
if !agent.action_state.conditions[ActionStateConditions::ConditionCounterInit as usize] {
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] = 1.0 - MINION_SUMMON_THRESHOLD;
agent.action_state.conditions[ActionStateConditions::ConditionCounterInit as usize] = true;
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] =
1.0 - MINION_SUMMON_THRESHOLD;
agent.action_state.conditions[ActionStateConditions::ConditionCounterInit as usize] =
true;
}
if agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] > health_fraction {
if agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize]
> health_fraction
{
// Summon minions at particular thresholds of health
controller.push_basic_input(InputKind::Ability(2));
if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] -= MINION_SUMMON_THRESHOLD;
agent.action_state.counters
[ActionStateFCounters::FCounterHealthThreshold as usize] -=
MINION_SUMMON_THRESHOLD;
}
} else if attack_data.dist_sqrd < MINDFLAYER_ATTACK_DIST.powi(2) {
if entities_have_line_of_sight(
@ -1552,7 +1637,8 @@ impl<'a> AgentData<'a> {
} else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) {
// If too far from target, throw a random number of necrotic spheres at them and
// then blink to them.
let num_fireballs = &mut agent.action_state.int_counters[ActionStateICounters::ICounterNumFireballs as usize];
let num_fireballs = &mut agent.action_state.int_counters
[ActionStateICounters::ICounterNumFireballs as usize];
if *num_fireballs == 0 {
controller.push_action(ControlAction::StartInput {
input: InputKind::Ability(0),
@ -1830,14 +1916,16 @@ impl<'a> AgentData<'a> {
Path::Separate,
Some(0.5),
);
agent.action_state.timers[ActionStateTimers::TimerBirdLargeBreathe as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerBirdLargeBreathe as usize] +=
read_data.dt.0;
} else if agent.action_state.timers[ActionStateTimers::TimerBirdLargeBreathe as usize] < 6.0
&& attack_data.angle < 90.0
&& attack_data.in_min_range()
{
// Triple strike
controller.push_basic_input(InputKind::Secondary);
agent.action_state.timers[ActionStateTimers::TimerBirdLargeBreathe as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerBirdLargeBreathe as usize] +=
read_data.dt.0;
} else {
// Reset timer
agent.action_state.timers[ActionStateTimers::TimerBirdLargeBreathe as usize] = 0.0;
@ -1866,14 +1954,16 @@ impl<'a> AgentData<'a> {
}
enum ActionStateConditions {
ConditionBirdLargeBasic = 0, //FIXME: Not sure what this represents. This name should be reflective of the condition...
ConditionBirdLargeBasic = 0, /* FIXME: Not sure what this represents. This name
* should be reflective of the condition... */
}
const BIRD_ATTACK_RANGE: f32 = 4.0;
const BIRD_CHARGE_DISTANCE: f32 = 15.0;
let bird_attack_distance = self.body.map_or(0.0, |b| b.max_radius()) + BIRD_ATTACK_RANGE;
// Increase action timer
agent.action_state.timers[ActionStateTimers::TimerBirdLargeBasic as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerBirdLargeBasic as usize] +=
read_data.dt.0;
// If higher than 2 blocks
if !read_data
.terrain
@ -1913,7 +2003,8 @@ impl<'a> AgentData<'a> {
} else if attack_data.dist_sqrd < bird_attack_distance.powi(2) {
// Combo melee target
controller.push_basic_input(InputKind::Primary);
agent.action_state.conditions[ActionStateConditions::ConditionBirdLargeBasic as usize] = true;
agent.action_state.conditions
[ActionStateConditions::ConditionBirdLargeBasic as usize] = true;
}
// Make bird move towards target
self.path_toward_target(
@ -1934,12 +2025,12 @@ impl<'a> AgentData<'a> {
tgt_data: &TargetData,
read_data: &ReadData,
) {
enum ActionStateTimers
{
enum ActionStateTimers {
TimerArthropodRanged = 0,
}
agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize] +=
read_data.dt.0;
if agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize] > 6.0
&& attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2)
{
@ -1981,16 +2072,23 @@ impl<'a> AgentData<'a> {
read_data,
)
{
if agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize] > 5.0 {
agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize] = 0.0;
} else if agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize] > 2.5 {
if agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize]
> 5.0
{
agent.action_state.timers
[ActionStateTimers::TimerArthropodRanged as usize] = 0.0;
} else if agent.action_state.timers
[ActionStateTimers::TimerArthropodRanged as usize]
> 2.5
{
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
.xy()
.rotated_z(1.75 * PI)
.try_normalized()
.unwrap_or_else(Vec2::zero)
* speed;
agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize] += read_data.dt.0;
agent.action_state.timers
[ActionStateTimers::TimerArthropodRanged as usize] += read_data.dt.0;
} else {
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
.xy()
@ -1998,7 +2096,8 @@ impl<'a> AgentData<'a> {
.try_normalized()
.unwrap_or_else(Vec2::zero)
* speed;
agent.action_state.timers[ActionStateTimers::TimerArthropodRanged as usize] += read_data.dt.0;
agent.action_state.timers
[ActionStateTimers::TimerArthropodRanged as usize] += read_data.dt.0;
}
controller.push_basic_input(InputKind::Ability(0));
self.jump_if(bearing.z > 1.5, controller);
@ -2037,7 +2136,8 @@ impl<'a> AgentData<'a> {
TimersArthropodAmbush = 0,
}
agent.action_state.timers[ActionStateTimers::TimersArthropodAmbush as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimersArthropodAmbush as usize] +=
read_data.dt.0;
if agent.action_state.timers[ActionStateTimers::TimersArthropodAmbush as usize] > 12.0
&& attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2)
{
@ -2084,7 +2184,8 @@ impl<'a> AgentData<'a> {
enum ActionStateTimers {
TimersArthropodMelee = 0,
}
agent.action_state.timers[ActionStateTimers::TimersArthropodMelee as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimersArthropodMelee as usize] +=
read_data.dt.0;
if matches!(self.char_state, CharacterState::DashMelee(c) if !matches!(c.stage_section, StageSection::Recover))
{
// If already charging, keep charging if not in recover
@ -2135,17 +2236,22 @@ impl<'a> AgentData<'a> {
self.body.map_or(0.0, |b| b.max_radius()) + MINOTAUR_ATTACK_RANGE;
let health_fraction = self.health.map_or(1.0, |h| h.fraction());
// Sets action counter at start of combat
if agent.action_state.counters[ActionStateFCounters::FCounterMinotaurAttack as usize] < MINOTAUR_FRENZY_THRESHOLD
if agent.action_state.counters[ActionStateFCounters::FCounterMinotaurAttack as usize]
< MINOTAUR_FRENZY_THRESHOLD
&& health_fraction > MINOTAUR_FRENZY_THRESHOLD
{
agent.action_state.counters[ActionStateFCounters::FCounterMinotaurAttack as usize] = MINOTAUR_FRENZY_THRESHOLD;
agent.action_state.counters[ActionStateFCounters::FCounterMinotaurAttack as usize] =
MINOTAUR_FRENZY_THRESHOLD;
}
if health_fraction < agent.action_state.counters[ActionStateFCounters::FCounterMinotaurAttack as usize] {
if health_fraction
< agent.action_state.counters[ActionStateFCounters::FCounterMinotaurAttack as usize]
{
// Makes minotaur buff itself with frenzy
controller.push_basic_input(InputKind::Ability(1));
if matches!(self.char_state, CharacterState::SelfBuff(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.counters[ActionStateFCounters::FCounterMinotaurAttack as usize] = 0.0;
agent.action_state.counters
[ActionStateFCounters::FCounterMinotaurAttack as usize] = 0.0;
}
} else if matches!(self.char_state, CharacterState::DashMelee(c) if !matches!(c.stage_section, StageSection::Recover))
{
@ -2161,14 +2267,19 @@ impl<'a> AgentData<'a> {
controller.push_basic_input(InputKind::Ability(0));
}
} else if attack_data.dist_sqrd < minotaur_attack_distance.powi(2) {
if agent.action_state.conditions[ActionStateConditions::ConditionJustCrippledOrCleaved as usize] && !self.char_state.is_attack() {
if agent.action_state.conditions
[ActionStateConditions::ConditionJustCrippledOrCleaved as usize]
&& !self.char_state.is_attack()
{
// Cripple target if not just used cripple
controller.push_basic_input(InputKind::Secondary);
agent.action_state.conditions[ActionStateConditions::ConditionJustCrippledOrCleaved as usize] = false;
agent.action_state.conditions
[ActionStateConditions::ConditionJustCrippledOrCleaved as usize] = false;
} else if !self.char_state.is_attack() {
// Cleave target if not just used cleave
controller.push_basic_input(InputKind::Primary);
agent.action_state.conditions[ActionStateConditions::ConditionJustCrippledOrCleaved as usize] = true;
agent.action_state.conditions
[ActionStateConditions::ConditionJustCrippledOrCleaved as usize] = true;
}
}
// Make minotaur move towards target
@ -2215,16 +2326,20 @@ impl<'a> AgentData<'a> {
};
if attack_data.dist_sqrd < golem_melee_range.powi(2) {
if agent.action_state.counters[ActionStateFCounters::FCounterGlayGolemAttack as usize] < 7.5 {
if agent.action_state.counters[ActionStateFCounters::FCounterGlayGolemAttack as usize]
< 7.5
{
// If target is close, whack them
controller.push_basic_input(InputKind::Primary);
agent.action_state.counters[ActionStateFCounters::FCounterGlayGolemAttack as usize] += read_data.dt.0;
agent.action_state.counters
[ActionStateFCounters::FCounterGlayGolemAttack as usize] += read_data.dt.0;
} else {
// If whacked for too long, nuke them
controller.push_basic_input(InputKind::Ability(1));
if matches!(self.char_state, CharacterState::BasicRanged(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.counters[ActionStateFCounters::FCounterGlayGolemAttack as usize] = 0.0;
agent.action_state.counters
[ActionStateFCounters::FCounterGlayGolemAttack as usize] = 0.0;
}
}
} else if attack_data.dist_sqrd < GOLEM_LASER_RANGE.powi(2) {
@ -2274,13 +2389,11 @@ impl<'a> AgentData<'a> {
const BUBBLE_RANGE: f32 = 20.0;
const MINION_SUMMON_THRESHOLD: f32 = 0.20;
enum ActionStateConditions
{
enum ActionStateConditions {
ConditionCounterInitialized = 0,
}
enum ActionStateFCounters
{
enum ActionStateFCounters {
FCounterMinionSummonThreshold = 0,
}
@ -2291,18 +2404,27 @@ impl<'a> AgentData<'a> {
// Sets counter at start of combat, using `condition` to keep track of whether
// it was already initialized
if !agent.action_state.conditions[ActionStateConditions::ConditionCounterInitialized as usize] {
agent.action_state.counters[ActionStateFCounters::FCounterMinionSummonThreshold as usize] = 1.0 - MINION_SUMMON_THRESHOLD;
agent.action_state.conditions[ActionStateConditions::ConditionCounterInitialized as usize] = true;
if !agent.action_state.conditions
[ActionStateConditions::ConditionCounterInitialized as usize]
{
agent.action_state.counters
[ActionStateFCounters::FCounterMinionSummonThreshold as usize] =
1.0 - MINION_SUMMON_THRESHOLD;
agent.action_state.conditions
[ActionStateConditions::ConditionCounterInitialized as usize] = true;
}
if agent.action_state.counters[ActionStateFCounters::FCounterMinionSummonThreshold as usize] > health_fraction {
if agent.action_state.counters[ActionStateFCounters::FCounterMinionSummonThreshold as usize]
> health_fraction
{
// Summon minions at particular thresholds of health
controller.push_basic_input(InputKind::Ability(1));
if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.counters[ActionStateFCounters::FCounterMinionSummonThreshold as usize] -= MINION_SUMMON_THRESHOLD;
agent.action_state.counters
[ActionStateFCounters::FCounterMinionSummonThreshold as usize] -=
MINION_SUMMON_THRESHOLD;
}
} else if attack_data.dist_sqrd < SCUTTLE_RANGE.powi(2) {
if matches!(self.char_state, CharacterState::DashMelee(c) if !matches!(c.stage_section, StageSection::Recover))
@ -2353,25 +2475,28 @@ impl<'a> AgentData<'a> {
const ICE_BREATH_TIMER: f32 = 10.0;
const SNOWBALL_MAX_RANGE: f32 = 50.0;
enum ActionStateFCounters
{
enum ActionStateFCounters {
FCounterYetiAttack = 0,
}
agent.action_state.counters[ActionStateFCounters::FCounterYetiAttack as usize] += read_data.dt.0;
agent.action_state.counters[ActionStateFCounters::FCounterYetiAttack as usize] +=
read_data.dt.0;
if attack_data.dist_sqrd < ICE_BREATH_RANGE.powi(2) {
if matches!(self.char_state, CharacterState::BasicBeam(c) if c.timer < Duration::from_secs(2))
{
// Keep using ice breath for 2 second
controller.push_basic_input(InputKind::Ability(0));
} else if agent.action_state.counters[ActionStateFCounters::FCounterYetiAttack as usize] > ICE_BREATH_TIMER {
} else if agent.action_state.counters[ActionStateFCounters::FCounterYetiAttack as usize]
> ICE_BREATH_TIMER
{
// Use ice breath if timer has gone for long enough
controller.push_basic_input(InputKind::Ability(0));
if matches!(self.char_state, CharacterState::BasicBeam(_)) {
// Resets action counter when using beam
agent.action_state.counters[ActionStateFCounters::FCounterYetiAttack as usize] = 0.0;
agent.action_state.counters
[ActionStateFCounters::FCounterYetiAttack as usize] = 0.0;
}
} else if attack_data.in_min_range() {
// Basic attack if on top of them
@ -2420,13 +2545,17 @@ impl<'a> AgentData<'a> {
entities_have_line_of_sight(self.pos, self.body, tgt_data.pos, tgt_data.body, read_data)
};
if health_fraction < VINE_CREATION_THRESHOLD && !agent.action_state.conditions[ActionStateConditions::ConditionHasSummonedVines as usize] {
if health_fraction < VINE_CREATION_THRESHOLD
&& !agent.action_state.conditions
[ActionStateConditions::ConditionHasSummonedVines as usize]
{
// Summon vines when reach threshold of health
controller.push_basic_input(InputKind::Ability(0));
if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.conditions[ActionStateConditions::ConditionHasSummonedVines as usize] = true;
agent.action_state.conditions
[ActionStateConditions::ConditionHasSummonedVines as usize] = 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(5))
@ -2474,26 +2603,33 @@ impl<'a> AgentData<'a> {
ConditionCounterInitialized = 0,
}
enum ActionStateFCounters
{
enum ActionStateFCounters {
FCounterHealthThreshold = 0,
}
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
// Sets counter at start of combat, using `condition` to keep track of whether
// it was already intitialized
if !agent.action_state.conditions[ActionStateConditions::ConditionCounterInitialized as usize] {
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] = 1.0 - MINION_SUMMON_THRESHOLD;
agent.action_state.conditions[ActionStateConditions::ConditionCounterInitialized as usize] = true;
if !agent.action_state.conditions
[ActionStateConditions::ConditionCounterInitialized as usize]
{
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] =
1.0 - MINION_SUMMON_THRESHOLD;
agent.action_state.conditions
[ActionStateConditions::ConditionCounterInitialized as usize] = true;
}
if agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] > health_fraction {
if agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize]
> health_fraction
{
// Summon minions at particular thresholds of health
controller.push_basic_input(InputKind::Ability(1));
if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] -= MINION_SUMMON_THRESHOLD;
agent.action_state.counters
[ActionStateFCounters::FCounterHealthThreshold as usize] -=
MINION_SUMMON_THRESHOLD;
}
}
// Logic to use abilities
@ -2632,14 +2768,10 @@ impl<'a> AgentData<'a> {
tgt_data: &TargetData,
read_data: &ReadData,
) {
enum ActionStateTimers
{
enum ActionStateTimers {
TimerDagon = 0,
}
if agent.action_state.timers[ActionStateTimers::TimerDagon as usize] > 2.5 {
agent.action_state.timers[ActionStateTimers::TimerDagon as usize] = 0.0;
}
@ -2742,30 +2874,31 @@ impl<'a> AgentData<'a> {
) {
const SCREAM_RANGE: f32 = 10.0;
enum ActionStateFCounters
{
enum ActionStateFCounters {
FCounterHealthThreshold = 0,
}
enum ActionStateConditions
{
enum ActionStateConditions {
ConditionHasScreamed = 0,
}
if !agent.action_state.initialized {
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] = self.health.map_or(0.0, |h| h.maximum());
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] =
self.health.map_or(0.0, |h| h.maximum());
agent.action_state.initialized = true;
}
if !agent.action_state.conditions[ActionStateConditions::ConditionHasScreamed as usize] {
// If mandragora is still "sleeping" and hasn't screamed yet, do nothing until
// target in range or until it's taken damage
if self
.health
.map_or(false, |h| h.current() < agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize])
|| attack_data.dist_sqrd < SCREAM_RANGE.powi(2)
if self.health.map_or(false, |h| {
h.current()
< agent.action_state.counters
[ActionStateFCounters::FCounterHealthThreshold as usize]
}) || attack_data.dist_sqrd < SCREAM_RANGE.powi(2)
{
agent.action_state.conditions[ActionStateConditions::ConditionHasScreamed as usize] = true;
agent.action_state.conditions
[ActionStateConditions::ConditionHasScreamed as usize] = true;
controller.push_basic_input(InputKind::Secondary);
}
} else {
@ -2792,8 +2925,11 @@ impl<'a> AgentData<'a> {
);
} else {
// Otherwise, go back to sleep
agent.action_state.conditions[ActionStateConditions::ConditionHasScreamed as usize] = false;
agent.action_state.counters[ActionStateFCounters::FCounterHealthThreshold as usize] = self.health.map_or(0.0, |h| h.maximum());
agent.action_state.conditions
[ActionStateConditions::ConditionHasScreamed as usize] = false;
agent.action_state.counters
[ActionStateFCounters::FCounterHealthThreshold as usize] =
self.health.map_or(0.0, |h| h.maximum());
}
}
}
@ -2810,8 +2946,7 @@ impl<'a> AgentData<'a> {
const SHOCKWAVE_WAIT_TIME: f32 = 7.5;
const SPIN_WAIT_TIME: f32 = 3.0;
enum ActionStateTimers
{
enum ActionStateTimers {
TimerSpinWait = 0,
TimerShockwaveWait,
}
@ -2824,7 +2959,8 @@ impl<'a> AgentData<'a> {
if attack_data.in_min_range() {
// If in minimum range
if agent.action_state.timers[ActionStateTimers::TimerSpinWait as usize] > SPIN_WAIT_TIME {
if agent.action_state.timers[ActionStateTimers::TimerSpinWait as usize] > SPIN_WAIT_TIME
{
// If it's been too long since able to hit target, spin
controller.push_basic_input(InputKind::Secondary);
} else if attack_data.angle < 30.0 {
@ -2832,7 +2968,8 @@ impl<'a> AgentData<'a> {
controller.push_basic_input(InputKind::Primary);
} else {
// Else increment spin timer
agent.action_state.timers[ActionStateTimers::TimerSpinWait as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerSpinWait as usize] +=
read_data.dt.0;
// If not in angle, apply slight movement so golem orients itself correctly
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
.xy()
@ -2844,13 +2981,16 @@ impl<'a> AgentData<'a> {
// Else if too far for melee
if attack_data.dist_sqrd < SHOCKWAVE_RANGE.powi(2) && attack_data.angle < 45.0 {
// Shockwave if close enough and haven't shockwaved too recently
if agent.action_state.timers[ActionStateTimers::TimerSpinWait as usize] > SHOCKWAVE_WAIT_TIME {
if agent.action_state.timers[ActionStateTimers::TimerSpinWait as usize]
> SHOCKWAVE_WAIT_TIME
{
controller.push_basic_input(InputKind::Ability(0));
}
if matches!(self.char_state, CharacterState::Shockwave(_)) {
agent.action_state.timers[ActionStateTimers::TimerShockwaveWait as usize] = 0.0;
} else {
agent.action_state.timers[ActionStateTimers::TimerShockwaveWait as usize] += read_data.dt.0;
agent.action_state.timers[ActionStateTimers::TimerShockwaveWait as usize] +=
read_data.dt.0;
}
}
// And always try to path towards target
@ -2884,7 +3024,9 @@ impl<'a> AgentData<'a> {
// Handle timers
agent.action_state.timers[ActionStateTimers::TimerSummonTotem as usize] += read_data.dt.0;
match self.char_state {
CharacterState::BasicSummon(_) => agent.action_state.timers[ActionStateTimers::TimerSummonTotem as usize] = 0.0,
CharacterState::BasicSummon(_) => {
agent.action_state.timers[ActionStateTimers::TimerSummonTotem as usize] = 0.0
},
CharacterState::Shockwave(_) | CharacterState::BasicRanged(_) => {
agent.action_state.counters[ActionStateTimers::TimerShockwave as usize] = 0.0
},
@ -2898,7 +3040,9 @@ impl<'a> AgentData<'a> {
{
agent.action_state.initialized = true;
}
} else if agent.action_state.timers[ActionStateTimers::TimerSummonTotem as usize] > TOTEM_TIMER {
} else if agent.action_state.timers[ActionStateTimers::TimerSummonTotem as usize]
> TOTEM_TIMER
{
// If time to summon a totem, do it
let input = rng.gen_range(1..=3);
let buff_kind = match input {
@ -2916,7 +3060,9 @@ impl<'a> AgentData<'a> {
} else {
controller.push_basic_input(InputKind::Ability(input));
}
} else if agent.action_state.counters[ActionStateTimers::TimerShockwave as usize] > HEAVY_ATTACK_WAIT_TIME {
} else if agent.action_state.counters[ActionStateTimers::TimerShockwave as usize]
> HEAVY_ATTACK_WAIT_TIME
{
// Else if time for a heavy attack
if attack_data.in_min_range() {
// If in range, shockwave
@ -2935,14 +3081,17 @@ impl<'a> AgentData<'a> {
// Else if not time to use anything fancy, if in range and angle, strike them
if attack_data.angle < 20.0 {
controller.push_basic_input(InputKind::Primary);
agent.action_state.counters[ActionStateTimers::TimerShockwave as usize] += read_data.dt.0;
agent.action_state.counters[ActionStateTimers::TimerShockwave as usize] +=
read_data.dt.0;
} else {
// If not in angle, charge heavy attack faster
agent.action_state.counters[ActionStateTimers::TimerShockwave as usize] += read_data.dt.0 * 5.0;
agent.action_state.counters[ActionStateTimers::TimerShockwave as usize] +=
read_data.dt.0 * 5.0;
}
} else {
// If not in range, charge heavy attack faster
agent.action_state.counters[ActionStateTimers::TimerShockwave as usize] += read_data.dt.0 * 3.3;
agent.action_state.counters[ActionStateTimers::TimerShockwave as usize] +=
read_data.dt.0 * 3.3;
}
self.path_toward_target(

View File

@ -59,15 +59,17 @@ pub struct BehaviorTree {
}
/// Enumeration of the timers used by the behavior tree.
// FIXME: We shouldnt have a global timer enumeration for the whole behavior tree.
// It isnt entirely clear where a lot of the agents in some of the bdata objects in
// behavior tree functions come from, so it's hard to granularly define these timers per action
// node. As such, the behavior tree currently has one global enumeration for mapping timers
// in all functions, regardless as to use case or action node currently executed -- even if the
// agent might be different between calls. This doesn't break anything as each agent has its own
// instance of timers, but it is much less clear than I would like.
// FIXME: We shouldnt have a global timer enumeration for the whole behavior
// tree. It isnt entirely clear where a lot of the agents in some of the bdata
// objects in behavior tree functions come from, so it's hard to granularly
// define these timers per action node. As such, the behavior tree currently has
// one global enumeration for mapping timers in all functions, regardless as to
// use case or action node currently executed -- even if the agent might be
// different between calls. This doesn't break anything as each agent has its
// own instance of timers, but it is much less clear than I would like.
//
// This may require some refactoring to fix, and I don't feel confident doing so.
// This may require some refactoring to fix, and I don't feel confident doing
// so.
enum ActionStateBehaviorTreeTimers {
TimerBehaviorTree = 0,
}
@ -488,13 +490,13 @@ fn handle_timed_events(bdata: &mut BehaviorData) -> bool {
/// Try to heal self if our damage went below a certain threshold
fn heal_self_if_hurt(bdata: &mut BehaviorData) -> bool {
if bdata.agent_data.damage < HEALING_ITEM_THRESHOLD
&& bdata
.agent_data
.heal_self(bdata.agent, bdata.controller, false)
{
bdata.agent.action_state.timers[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] = 0.01;
bdata.agent.action_state.timers
[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] = 0.01;
return true;
}
false
@ -558,18 +560,27 @@ fn do_combat(bdata: &mut BehaviorData) -> bool {
let aggro_on = *aggro_on;
if agent_data.below_flee_health(agent) {
let has_opportunity_to_flee = agent.action_state.timers[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] < FLEE_DURATION;
let has_opportunity_to_flee = agent.action_state.timers
[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize]
< FLEE_DURATION;
let within_flee_distance = dist_sqrd < MAX_FLEE_DIST.powi(2);
// FIXME: Using action state timer to see if allowed to speak is a hack.
if agent.action_state.timers[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] == 0.0 {
if agent.action_state.timers
[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize]
== 0.0
{
agent_data.cry_out(agent, event_emitter, read_data);
agent.action_state.timers[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] = 0.01;
agent.action_state.timers
[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] = 0.01;
} else if within_flee_distance && has_opportunity_to_flee {
agent_data.flee(agent, controller, tgt_pos, &read_data.terrain);
agent.action_state.timers[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] += read_data.dt.0;
agent.action_state.timers
[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] +=
read_data.dt.0;
} else {
agent.action_state.timers[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] = 0.0;
agent.action_state.timers
[ActionStateBehaviorTreeTimers::TimerBehaviorTree as usize] = 0.0;
agent.target = None;
agent_data.idle(agent, controller, read_data, rng);
}

View File

@ -26,7 +26,6 @@ enum ActionStateInteractionTimers {
TimerInteraction = 0,
}
/// Interact if incoming messages
pub fn process_inbox_sound_and_hurt(bdata: &mut BehaviorData) -> bool {
if !bdata.agent.inbox.is_empty() {
@ -49,7 +48,8 @@ pub fn process_inbox_sound_and_hurt(bdata: &mut BehaviorData) -> bool {
Some(_) | None => {},
}
} else {
bdata.agent.action_state.timers[ActionStateInteractionTimers::TimerInteraction as usize] = 0.1;
bdata.agent.action_state.timers
[ActionStateInteractionTimers::TimerInteraction as usize] = 0.1;
}
}
false
@ -68,7 +68,8 @@ pub fn process_inbox_interaction(bdata: &mut BehaviorData) -> bool {
/// Increment agent's action_state timer
pub fn increment_timer_deltatime(bdata: &mut BehaviorData) -> bool {
bdata.agent.action_state.timers[ActionStateInteractionTimers::TimerInteraction as usize] += bdata.read_data.dt.0;
bdata.agent.action_state.timers[ActionStateInteractionTimers::TimerInteraction as usize] +=
bdata.read_data.dt.0;
false
}