etqw-sdk/source/game/botai/BotAI_VCombatNet.cpp

247 lines
6.4 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#include "../precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "BotThreadData.h"
#include "BotAI_Main.h"
/*
================
idBotAI::Enter_COMBAT_Vehicle_EvadeEnemy
Bot has a goal, or some other reason to not want to fight, so try to evade/avoid our enemy,
while still attacking them ( if we can ).
================
*/
bool idBotAI::Enter_COMBAT_Vehicle_EvadeEnemy() {
VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::COMBAT_Vehicle_EvadeEnemy;
combatMoveType = COMBAT_MOVE_NULL;
lastAINode = "Vehicle Evade Enemy";
return true;
}
/*
================
idBotAI::COMBAT_Vehicle_EvadeEnemy
================
*/
bool idBotAI::COMBAT_Vehicle_EvadeEnemy() {
bool bailOut = false;
idVec3 vec;
if ( !ClientIsValid( enemy, -1 ) ) {
Bot_ResetEnemy();
return false;
}
if ( botVehicleInfo->type == MCP ) {
assert( actionNum > -1 );
if ( Bot_CheckActionIsValid( actionNum ) ) {
vec = botThreadData.botActions[ actionNum ]->GetActionOrigin() - botVehicleInfo->origin;
if ( vec.LengthSqr() > Square( MCP_PARKED_DIST ) ) {
Bot_SetupVehicleMove( vec3_zero, -1, actionNum );
if ( MoveIsInvalid() ) { //mal: this should NEVER happen - but if it does, the bot is better off leaving.
Bot_ExitVehicleAINode( true );
Bot_ExitVehicle( false );
assert( false );
return false;
}
Bot_MoveToGoal( botAAS.path.moveGoal, vec3_zero, RUN, NULLMOVETYPE );
} else {
Bot_ExitVehicleAINode( true ); //mal: reached our goal, so just leave, and let the MCP deploy!
Bot_ExitVehicle( false );
return false;
}
}
} else {
if ( AIStack.stackActionNum != ACTION_NULL ) {
float evadeDist = 1200.0f;
vec = botThreadData.botActions[ AIStack.stackActionNum ]->origin - botInfo->origin;
if ( botVehicleInfo->type > ICARUS ) {
evadeDist = 550.0f;
bailOut = true;
vec.z = 0.0f;
}
if ( vec.LengthSqr() > Square( evadeDist ) ) {
Bot_SetupVehicleMove( vec3_zero, -1, AIStack.stackActionNum );
bailOut = false;
if ( MoveIsInvalid() ) {
VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::Enter_COMBAT_Vehicle_AttackEnemy; //mal: if theres a problem getting to our target, just fight our enemy normally.
return false;
}
Bot_MoveToGoal( botAAS.path.moveGoal, vec3_zero, RUN, NULLMOVETYPE );
}
if ( vec.LengthSqr() < Square( 800.0f ) && botVehicleInfo->type != MCP ) { //mal: get to the outpost if MCP, even to the bitter end!
VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::Enter_COMBAT_Vehicle_AttackEnemy; //mal: we're right at our target, so just fight our enemy normally.
return false;
}
} else {
// assert( false );
VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::Enter_COMBAT_Vehicle_AttackEnemy;
return false;
}
}
if ( bailOut ) {
Bot_ExitVehicle();
return false;
}
Bot_PickBestVehicleWeapon();
if ( !enemyInfo.enemyVisible && enemyInfo.enemyLastVisTime + 500 < botWorld->gameLocalInfo.time ) {
UpdateNonVisEnemyInfo();
if ( BotLeftEnemysSight() ) {
vec = bot_LS_Enemy_Pos;
} else {
vec = enemyInfo.enemy_LS_Pos;
}
Bot_LookAtLocation( vec, AIM_TURN );
} else {
if ( botVehicleInfo->type > ICARUS ) {
vec = botWorld->clientInfo[ enemy ].origin - botVehicleInfo->origin;
vec[ 2 ] = 0.0f;
if ( vec.LengthSqr() > Square( 2500.0f ) && InFrontOfVehicle( botVehicleInfo->entNum, botWorld->clientInfo[ enemy ].origin ) && botVehicleInfo->type != BUFFALO ) {
Bot_LookAtEntity( enemy, AIM_TURN );
Bot_CheckVehicleAttack();
} else {
Bot_LookAtLocation( botAAS.path.viewGoal, SMOOTH_TURN );
if ( botVehicleInfo->type != BUFFALO ) {
Bot_CheckVehicleAttack();
}
}
} else {
Bot_LookAtEntity( enemy, AIM_TURN );
Bot_CheckVehicleAttack();
}
}
return true;
}
/*
================
idBotAI::Enter_COMBAT_Vehicle_AttackEnemy
================
*/
bool idBotAI::Enter_COMBAT_Vehicle_AttackEnemy() {
VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::COMBAT_Vehicle_AttackEnemy;
combatMoveType = COMBAT_MOVE_NULL;
lastAINode = "Vehicle Attack Enemy";
return true;
}
/*
================
idBotAI::COMBAT_Vehicle_AttackEnemy
================
*/
bool idBotAI::COMBAT_Vehicle_AttackEnemy() {
bool keepEnemy = true;
if ( !enemyInfo.enemyVisible && enemyInfo.enemyLastVisTime + 5000 < botWorld->gameLocalInfo.time ) {
if ( !Bot_ShouldVehicleChaseHiddenEnemy() ) {
Bot_ResetEnemy();
return false;
}
Bot_PickVehicleChaseType();
return false;
}
Bot_PickBestVehicleWeapon();
if ( vehicleUpdateTime < botWorld->gameLocalInfo.time ) {
if ( VEHICLE_COMBAT_MOVEMENT_STATE == NULL ) {
keepEnemy = Bot_FindBestVehicleCombatMovement();
}
}
if ( !keepEnemy ) { //mal: make sure enemy is reachable by our current move state/abilities/limitations. If not, we have to forget them.
Bot_IgnoreEnemy( enemy, 3000 ); //mal: perhaps in 3 seconds, we will have moved to a better position for a kill...
Bot_ResetEnemy();
return false;
}
if ( VEHICLE_COMBAT_MOVEMENT_STATE != NULL ) {
CallFuncPtr( VEHICLE_COMBAT_MOVEMENT_STATE );
}
if ( ClientIsValid( enemy, enemySpawnID ) && enemyInfo.enemyVisible ) {
if ( botVehicleInfo->type <= ICARUS || botInfo->proxyInfo.weapon == MINIGUN ) {
Bot_LookAtEntity( enemy, AIM_TURN ); //mal: aim at the enemy - but let the game side code handle it.
Bot_CheckVehicleAttack();
}
}
return false;
}
/*
================
idBotAI::Enter_COMBAT_Vehicle_ChaseEnemy
Bot has an enemy he wants to chase.
================
*/
bool idBotAI::Enter_COMBAT_Vehicle_ChaseEnemy() {
VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::COMBAT_Vehicle_ChaseEnemy;
combatMoveType = COMBAT_MOVE_NULL;
lastAINode = "Vehicle Chase Enemy";
return true;
}
/*
================
idBotAI::COMBAT_Vehicle_ChaseEnemy
================
*/
bool idBotAI::COMBAT_Vehicle_ChaseEnemy() {
if ( enemyInfo.enemyVisible ) {
VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::Enter_COMBAT_Vehicle_AttackEnemy;
return false;
}
if ( chaseEnemyTime < botWorld->gameLocalInfo.time ) {
Bot_ResetEnemy();
return false;
}
Bot_SetupVehicleMove( vec3_zero, enemy, ACTION_NULL );
if ( MoveIsInvalid() ) {
Bot_ResetEnemy();
return false;
}
Bot_MoveToGoal( botAAS.path.moveGoal, vec3_zero, RUN, NULLMOVETYPE );
Bot_LookAtEntity( enemy, SMOOTH_TURN );
return true;
}