/* ================ idBotAI::CheckBotStuckState ================ */ void idBotAI::CheckBotStuckState() { if ( !botInfo->hasGroundContact && botInfo->invulnerableEndTime > botWorld->gameLocalInfo.time ) { framesStuck = 0; framesFlipped = 0; vehicleFramesStuck = 0; overallFramesStuck = 0; return; //mal: if we're spawning in, dont count a lack of a valid AAS area against us } if ( stuckRandomMoveTime > botWorld->gameLocalInfo.time ) { BotAI_ResetUcmd(); Bot_MoveToGoal( vec3_zero, vec3_zero, SPRINT, RANDOM_DIR_JUMP ); return; } if ( !botAAS.triedToMoveThisFrame ) { botAAS.blockedByObstacleCounterOnFoot = 0; } if ( botInfo->areaNum == 0 ) { noAASCounter++; if ( noAASCounter >= 100 ) { if ( botVehicleInfo == NULL ) { botUcmd->botCmds.suicide = true; noAASCounter = 0; } else { Bot_ExitVehicle(); } } return; } else { noAASCounter = 0; } if ( moveErrorCounter.moveErrorTime < botWorld->gameLocalInfo.time ) { moveErrorCounter.moveErrorTime = botWorld->gameLocalInfo.time + 5000; if ( moveErrorCounter.moveErrorCount >= MAX_MOVE_ERRORS ) { moveErrorCounter.moveErrorCount = 0; botUcmd->botCmds.suicide = true; } else { moveErrorCounter.moveErrorCount = 0; } } if ( botVehicleInfo == NULL ) { idVec3 vec = botInfo->origin - botInfo->oldOrigin; if ( vec.LengthSqr() < Square( 10.0f ) && botInfo->isTryingToMove ) { framesStuck++; // if ( framesStuck > MAX_FRAMES_BLOCKED_BY_OBSTACLE_ON_FOOT ) { // botAAS.blockedByObstacleCounterOnFoot = MAX_FRAMES_BLOCKED_BY_OBSTACLE_ON_FOOT + 1; // framesStuck = 0; // stuckRandomMoveTime = botWorld->gameLocalInfo.time + 500; // overallFramesStuck++; // } if ( framesStuck >= 300 ) { stuckRandomMoveTime = botWorld->gameLocalInfo.time + 500; framesStuck = 0; overallFramesStuck++; } if ( overallFramesStuck > 6 && botWorld->gameLocalInfo.botsCanSuicide ) { botUcmd->botCmds.suicide = true; } return; } } framesStuck = 0; overallFramesStuck = 0; if ( botVehicleInfo != NULL ) { if ( botVehicleInfo->isFlipped ) { framesFlipped++; if ( framesFlipped >= 100 ) { //mal: give us time to recover, just in case we can. Bot_ExitVehicle( false); } return; } if ( botVehicleInfo->isCareening && botVehicleInfo->isAirborneVehicle ) { //mal: out NOW! This thing is lost! Bot_ExitVehicle(); } if ( botVehicleInfo->inWater && !( botVehicleInfo->flags & WATER ) ) { Bot_ExitVehicle( false ); } } framesFlipped = 0; /* if ( botVehicleInfo != NULL ) { //mal: this sucks. idVec3 vec = botInfo->origin - botInfo->oldOrigin; vec.z = 0.0f; if ( vec.LengthSqr() < Square( 10.0f ) && botInfo->isTryingToMove ) { vehicleFramesStuck++; if ( vehicleFramesStuck >= 300 ) { vehicleReverseTime = botWorld->gameLocalInfo.time + 900; botUcmd->specialMoveType = REVERSEMOVE; vehicleFramesStuck = 0; } } else { vehicleFramesStuck = 0; } } */ }
/* ================ 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; }