Files
DoomRTX/neo/doom3/game/bots/BotAI_Battle_Retreat.cpp
2026-05-19 19:43:23 -07:00

162 lines
3.9 KiB
C++

// BotAI_Battle_Retreat.cpp
//
#pragma hdrstop
#include "precompiled.h"
#include "../Game_local.h"
/*
=====================
rvmBot::state_Retreat
=====================
*/
stateResult_t rvmBot::state_Retreat(stateParms_t* parms)
{
bot_goal_t goal;
idPlayer* entinfo;
rvmBot* owner;
idVec3 target, dir;
float attack_skill, range;
// respawn if dead.
if( BotIsDead( &bs ) )
{
stateThread.SetState("state_Respawn");
return SRESULT_DONE_FRAME;
}
// if no enemy.
if( bs.enemy < 0 || bs.enemy >= gameLocal.num_entities || gameLocal.entities[bs.enemy] == NULL )
{
stateThread.SetState("state_SeekLTG");
return SRESULT_DONE_FRAME;
}
// Ensure the target is a player.
entinfo = gameLocal.entities[bs.enemy]->Cast<idPlayer>();
if( !entinfo )
{
stateThread.SetState("state_SeekLTG");
return SRESULT_DONE_FRAME;
}
owner = gameLocal.entities[bs.entitynum]->Cast<rvmBot>();
// If our enemy is dead, search for another LTG.
if( EntityIsDead( entinfo ) )
{
stateThread.SetState("state_SeekLTG");
return SRESULT_DONE_FRAME;
}
//if there is another better enemy
if( BotFindEnemy( &bs, bs.enemy ) )
{
common->DPrintf( "found new better enemy\n" );
}
//update the attack inventory values
BotUpdateBattleInventory( &bs, bs.enemy );
BotChooseWeapon( &bs );
// Before switching back to chase, opportunistically grab a nearby tactical
// pickup. This keeps the bot from running past a rocket launcher, shells, or
// health while it is already committed to a fight.
if( bs.check_time < Bot_Time() )
{
bs.check_time = Bot_Time() + 0.5f;
bot_goal_t pickupAnchor;
pickupAnchor.Reset();
pickupAnchor.entitynum = bs.enemy;
pickupAnchor.origin = entinfo->GetOrigin();
pickupAnchor.mins = idVec3( -8.0f, -8.0f, -8.0f );
pickupAnchor.maxs = idVec3( 8.0f, 8.0f, 8.0f );
if( BotNearbyGoal( &bs, 0, &pickupAnchor, 260.0f ) )
{
bs.nbg_time = Bot_Time() + 18.0f;
stateThread.SetState("state_BattleNBG");
return SRESULT_DONE_FRAME;
}
}
//if the bot doesn't want to retreat anymore... probably picked up some nice items
if( BotWantsToChase( &bs ) )
{
//empty the goal stack, when chasing, only the enemy is the goal
botGoalManager.BotEmptyGoalStack( bs.gs );
//go chase the enemy
//AIEnter_Battle_Chase(bs, "battle retreat: wants to chase");
stateThread.SetState("state_Chase");
return SRESULT_DONE_FRAME;
}
//update the last time the enemy was visible
if( BotEntityVisible( bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy ) )
{
bs.enemyvisible_time = Bot_Time();
target = entinfo->GetOrigin();
bs.lastenemyorigin = target;
bs.last_enemy_visible_position = target;
}
//if the enemy is NOT visible for 4 seconds
if( bs.enemyvisible_time < Bot_Time() - 4 )
{
stateThread.SetState("state_SeekLTG");
return SRESULT_DONE_FRAME;
}
//else if the enemy is NOT visible
else if( bs.enemyvisible_time < Bot_Time() )
{
//if there is another enemy
if( BotFindEnemy( &bs, -1 ) )
{
//AIEnter_Battle_Fight(bs, "battle retreat: another enemy");
stateThread.SetState("state_BattleFight");
return SRESULT_DONE_FRAME;
}
}
//use holdable items
BotBattleUseItems( &bs );
//get the current long term goal while retreating
if( !BotGetItemLongTermGoal( &bs, 0, &bs.currentGoal ) )
{
//AIEnter_Battle_SuicidalFight(bs, "battle retreat: no way out");
stateThread.SetState("state_BattleFight");
bs.flags |= BFL_FIGHTSUICIDAL;
return SRESULT_DONE_FRAME;
}
//check for nearby goals periodically while retreating along the long-term item path
if( bs.check_time < Bot_Time() )
{
bs.check_time = Bot_Time() + 0.5f;
range = 260.0f;
if( BotNearbyGoal( &bs, 0, &goal, range ) )
{
bs.nbg_time = Bot_Time() + 18.0f;
stateThread.SetState("state_BattleNBG");
return SRESULT_DONE_FRAME;
}
}
MoveToCoverPoint();
if (bot_skill.GetInteger() > 1)
{
bs.firethrottlewait_time = 0;
}
BotChooseWeapon( &bs );
BotAimAtEnemy( &bs );
//attack the enemy if possible
BotCheckAttack( &bs );
return SRESULT_WAIT;
}