mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 16:21:04 +02:00
177 lines
4.0 KiB
C++
177 lines
4.0 KiB
C++
// BotAI_Battle_Fight.cpp
|
|
//
|
|
|
|
#pragma hdrstop
|
|
#include "precompiled.h"
|
|
#include "../Game_local.h"
|
|
|
|
/*
|
|
=====================
|
|
rvmBot::state_BattleFight
|
|
=====================
|
|
*/
|
|
stateResult_t rvmBot::state_BattleFight(stateParms_t* parms)
|
|
{
|
|
idVec3 target;
|
|
idPlayer* entinfo;
|
|
|
|
// respawn if dead.
|
|
if( BotIsDead( &bs ) )
|
|
{
|
|
stateThread.SetState("state_Respawn");
|
|
return SRESULT_DONE_FRAME;
|
|
}
|
|
|
|
//if there is another better enemy
|
|
if( BotFindEnemy( &bs, bs.enemy ) )
|
|
{
|
|
common->DPrintf( "found new better enemy\n" );
|
|
}
|
|
|
|
//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;
|
|
}
|
|
|
|
entinfo = gameLocal.entities[bs.enemy]->Cast<idPlayer>();
|
|
if( entinfo == NULL )
|
|
{
|
|
stateThread.SetState("state_SeekLTG");
|
|
return SRESULT_DONE_FRAME;
|
|
}
|
|
|
|
//if the enemy is dead
|
|
if( bs.enemydeath_time )
|
|
{
|
|
if( bs.enemydeath_time < Bot_Time() - 1.0 )
|
|
{
|
|
bs.enemydeath_time = 0;
|
|
bs.ltg_time = 0;
|
|
stateThread.SetState("state_SeekLTG");
|
|
return SRESULT_DONE_FRAME;
|
|
}
|
|
}
|
|
else if( EntityIsDead( entinfo ) )
|
|
{
|
|
bs.enemydeath_time = Bot_Time();
|
|
}
|
|
|
|
target = entinfo->GetOrigin();
|
|
|
|
//update the attack inventory values
|
|
BotUpdateBattleInventory( &bs, bs.enemy );
|
|
|
|
//if the enemy is not visible
|
|
if( !BotEntityVisible( bs.entitynum, bs.eye, bs.viewangles, 360, bs.enemy ) )
|
|
{
|
|
if( BotWantsToChase( &bs ) )
|
|
{
|
|
bs.chase_time = Bot_Time() + 10.0f;
|
|
stateThread.SetState("state_Chase");
|
|
return SRESULT_DONE_FRAME;
|
|
}
|
|
else
|
|
{
|
|
stateThread.SetState("state_SeekLTG");
|
|
return SRESULT_DONE_FRAME;
|
|
}
|
|
}
|
|
|
|
bs.enemyvisible_time = Bot_Time();
|
|
bs.lastenemyorigin = target;
|
|
bs.last_enemy_visible_position = target;
|
|
|
|
//use holdable items
|
|
BotBattleUseItems( &bs );
|
|
|
|
//choose the best weapon to fight with
|
|
BotChooseWeapon( &bs );
|
|
|
|
// Opportunistic combat pickup: keep fighting, but route through a nearby item
|
|
// instead of throwing the current goal away and random-strafing forever. The
|
|
// NBG selector itself expands this range when the bot is stuck on pistol/dry
|
|
// ammo, and otherwise keeps the detour short.
|
|
if( bs.check_time < Bot_Time() )
|
|
{
|
|
bs.check_time = Bot_Time() + 0.45f;
|
|
|
|
bot_goal_t pickupAnchor;
|
|
pickupAnchor.Reset();
|
|
pickupAnchor.entitynum = bs.enemy;
|
|
pickupAnchor.origin = target;
|
|
pickupAnchor.mins = idVec3( -8.0f, -8.0f, -8.0f );
|
|
pickupAnchor.maxs = idVec3( 8.0f, 8.0f, 8.0f );
|
|
|
|
const float pickupRange = 260.0f;
|
|
if( BotNearbyGoal( &bs, 0, &pickupAnchor, pickupRange ) )
|
|
{
|
|
bs.nbg_time = Bot_Time() + 18.0f;
|
|
stateThread.SetState("state_BattleNBG");
|
|
return SRESULT_DONE_FRAME;
|
|
}
|
|
}
|
|
|
|
// Fight like a deathmatch bot: keep pressure on the enemy while changing
|
|
// strafe direction often enough to be hard to track.
|
|
if( bs.attackstrafe_time < Bot_Time() )
|
|
{
|
|
bs.attackstrafe_time = Bot_Time() + idMath::FRandRange( 0.65f, 1.35f );
|
|
if( rvmBotUtil::random() < 0.5f )
|
|
{
|
|
bs.flags ^= BFL_STRAFERIGHT;
|
|
}
|
|
}
|
|
|
|
idVec3 toEnemy = target - bs.origin;
|
|
toEnemy[2] = 0.0f;
|
|
const float enemyDist = toEnemy.Length();
|
|
if( enemyDist > 1.0f )
|
|
{
|
|
toEnemy /= enemyDist;
|
|
idVec3 strafeDir = ( bs.flags & BFL_STRAFERIGHT ) ? idVec3( -toEnemy[1], toEnemy[0], 0.0f ) : idVec3( toEnemy[1], -toEnemy[0], 0.0f );
|
|
idVec3 moveDir = strafeDir;
|
|
|
|
if( enemyDist > 520.0f )
|
|
{
|
|
moveDir += toEnemy * 0.65f;
|
|
}
|
|
else if( enemyDist < 170.0f )
|
|
{
|
|
moveDir -= toEnemy * 0.75f;
|
|
}
|
|
|
|
moveDir.Normalize();
|
|
bs.botinput.dir = moveDir;
|
|
bs.botinput.speed = pm_runspeed.GetInteger();
|
|
|
|
if( enemyDist < 420.0f && rvmBotUtil::random() < 0.025f )
|
|
{
|
|
bs.botinput.actionflags |= ACTION_JUMP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BotMoveInRandomDirection(&bs);
|
|
}
|
|
|
|
//aim at the enemy
|
|
BotAimAtEnemy( &bs );
|
|
|
|
//attack the enemy if possible
|
|
BotCheckAttack( &bs );
|
|
|
|
//if the bot wants to retreat
|
|
if( !( bs.flags & BFL_FIGHTSUICIDAL ) )
|
|
{
|
|
if( BotWantsToRetreat( &bs ) )
|
|
{
|
|
stateThread.SetState("state_Retreat");
|
|
return SRESULT_DONE_FRAME;
|
|
}
|
|
}
|
|
|
|
return SRESULT_WAIT;
|
|
}
|