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

217 lines
5.7 KiB
C++

// BotAI_Battle_Chase.cpp
//
#pragma hdrstop
#include "precompiled.h"
#include "../Game_local.h"
/*
=====================
rvmBot::state_Chase
=====================
*/
stateResult_t rvmBot::state_Chase(stateParms_t* parms)
{
bot_goal_t goal;
idVec3 target, dir;
//bot_moveresult_t moveresult;
float range;
//if (BotIsObserver(bs)) {
// AIEnter_Observer(bs, "battle chase: observer");
// return qfalse;
//}
//
////if in the intermission
//if (BotIntermission(bs)) {
// AIEnter_Intermission(bs, "battle chase: intermission");
// return qfalse;
//}
// respawn if dead.
if( BotIsDead( &bs ) )
{
stateThread.SetState("state_Respawn");
return SRESULT_DONE_FRAME;
}
if( parms->stage == 0 )
{
if( bs.chase_time <= Bot_Time() )
{
bs.chase_time = Bot_Time() + 10.0f;
}
parms->stage = 1;
}
//if no enemy
if( bs.enemy < 0 || bs.enemy >= gameLocal.num_entities || gameLocal.entities[bs.enemy] == NULL ||
bs.client < 0 || bs.client >= gameLocal.num_entities || gameLocal.entities[bs.client] == NULL )
{
stateThread.SetState("state_SeekLTG");
return SRESULT_DONE_FRAME;
}
//if the enemy is visible
if( BotEntityVisibleTest( bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy, false ) )
{
//AIEnter_Battle_Fight(bs, "battle chase");
stateThread.SetState("state_BattleFight");
return SRESULT_DONE_FRAME;
}
//if there is another enemy
if( BotFindEnemy( &bs, -1 ) )
{
//AIEnter_Battle_Fight(bs, "battle chase: better enemy");
//stateThread.SetState("state_BattleFight");
stateThread.SetState("state_BattleFight");
return SRESULT_DONE_FRAME;
}
////there is no last enemy area
//if (!bs.lastenemyareanum) {
// AIEnter_Seek_LTG(bs, "battle chase: no enemy area");
// return qfalse;
//}
// jmarshall
//
//bs.tfl = TFL_DEFAULT;
//if (bot_grapple.integer) bs.tfl |= TFL_GRAPPLEHOOK;
////if in lava or slime the bot should be able to get out
//if (BotInLavaOrSlime(bs)) bs.tfl |= TFL_LAVA | TFL_SLIME;
////
//if (BotCanAndWantsToRocketJump(bs)) {
// bs.tfl |= TFL_ROCKETJUMP;
//}
//map specific code
//BotMapScripts(bs);
// jmarshall end
//create the chase goal
goal.entitynum = bs.enemy;
// goal.areanum = bs.lastenemyareanum;
VectorCopy( bs.lastenemyorigin, goal.origin );
goal.mins = idVec3( -8, -8, -8 );
goal.maxs = idVec3( 8, 8, 8 );
// jmarshall - goal origin is last visible position
{
// Do a trace between the last_enemy_visible_position and the goal origin,
// if for some reason we don't have line of sight to it, switch to LTG.
trace_t trace;
gameLocal.Trace( trace, bs.last_enemy_visible_position, gameLocal.entities[bs.client]->GetOrigin(), CONTENTS_SOLID, bs.entitynum );
if( trace.fraction <= 0.9f )
{
//AIEnter_Seek_LTG(bs, "can't see last enemy position");
stateThread.SetState("state_SeekLTG");
return SRESULT_DONE_FRAME;
}
}
VectorCopy( bs.last_enemy_visible_position, goal.origin );
// jmarshall end
//if the last seen enemy spot is reached the enemy could not be found
if( botGoalManager.BotTouchingGoal( bs.origin, &goal ) )
{
bs.chase_time = 0;
}
//if there's no chase time left
if( !bs.chase_time || bs.chase_time < Bot_Time() )
{
//AIEnter_Seek_LTG(bs, "battle chase: time out");
stateThread.SetState("state_SeekLTG");
return SRESULT_DONE_FRAME;
}
//check for nearby goals periodically. Chasing should still route through a
// nearby weapon/ammo pickup instead of running past it, especially when the bot
// only has pistol/machinegun or is dry on ammo.
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;
}
}
BotUpdateBattleInventory( &bs, bs.enemy );
BotChooseWeapon( &bs );
////initialize the movement state
//BotSetupForMovement(bs);
//move towards the goal
//trap_BotMoveToGoal(&moveresult, bs.ms, &goal, bs.tfl);
if( idMath::FRandRange( 0.0f, 4.0f ) <= 2.0f )
{
BotMoveToGoal( &bs, &goal );
}
else
{
BotMoveInRandomDirection( &bs );
}
//if the movement failed
//if (moveresult.failure) {
// //reset the avoid reach, otherwise bot is stuck in current area
// trap_BotResetAvoidReach(bs.ms);
// //BotAI_Print(PRT_MESSAGE, "movement failure %d\n", moveresult.traveltype);
// bs.ltg_time = 0;
//}
////
//BotAIBlocked(bs, &moveresult, qfalse);
//
//if (moveresult.flags & (MOVERESULT_MOVEMENTVIEWSET | MOVERESULT_MOVEMENTVIEW | MOVERESULT_SWIMVIEW)) {
// VectorCopy(moveresult.ideal_viewangles, bs.ideal_viewangles);
//}
if( !( bs.flags & BFL_IDEALVIEWSET ) )
{
BotAimAtEnemy( &bs );
// jmarshall
//if (bs.chase_time > FloatTime() - 2) {
// BotAimAtEnemy(bs);
//}
//else {
// if (BotMovementViewTarget(bs.ms, &goal, bs.tfl, 300, target)) {
// VectorSubtract(target, bs.origin, dir);
// vectoangles(dir, bs.viewangles);
// }
// //else {
// // vectoangles(moveresult.movedir, bs.ideal_viewangles);
// //}
//}
// jmarshall end
// bs.ideal_viewangles[2] *= 0.5; // jmarshall <-- view angles!
}
if (BotEntityVisible(bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy))
{
//attack the enemy if possible
BotCheckAttack(&bs);
}
//if the weapon is used for the bot movement
//if (moveresult.flags & MOVERESULT_MOVEMENTWEAPON) bs.weaponnum = moveresult.weapon;
//if the bot is in the area the enemy was last seen in
//if (bs.areanum == bs.lastenemyareanum) bs.chase_time = 0;
//if the bot wants to retreat (the bot could have been damage during the chase)
if( BotWantsToRetreat( &bs ) )
{
//AIEnter_Battle_Retreat(bs, "battle chase: wants to retreat");
stateThread.SetState("state_Retreat");
return SRESULT_DONE_FRAME;
}
return SRESULT_WAIT;
}