// BotAI_Battle_Attacked.cpp // #pragma hdrstop #include "precompiled.h" #include "../Game_local.h" /* ================== rvmBot::state_Attacked ================== */ stateResult_t rvmBot::state_Attacked(stateParms_t* parms) { // respawn if dead. if (BotIsDead(&bs)) { stateThread.SetState("state_Respawn"); return SRESULT_DONE_FRAME; } if( bs.enemy < 0 || bs.enemy >= gameLocal.num_entities || gameLocal.entities[bs.enemy] == NULL ) { stateThread.SetState("state_SeekLTG"); return SRESULT_DONE_FRAME; } // Update combat distance before weapon selection so the bot can pick // shotgun/rocket/plasma appropriately instead of using stale inventory // values from the previous state. BotUpdateBattleInventory( &bs, bs.enemy ); BotChooseWeapon( &bs ); // If we were ambushed while under-armed, do not stand and trade pistol shots. // Use the existing BattleNBG state so the bot can keep aiming/firing while it // moves through a nearby weapon, ammo, health, or armor pickup. if( bs.check_time < Bot_Time() ) { bs.check_time = Bot_Time() + 0.35f; bot_goal_t pickupAnchor; pickupAnchor.Reset(); pickupAnchor.entitynum = bs.enemy; pickupAnchor.origin = bs.lastenemyorigin; pickupAnchor.mins = idVec3( -8.0f, -8.0f, -8.0f ); pickupAnchor.maxs = idVec3( 8.0f, 8.0f, 8.0f ); if( BotNearbyGoal( &bs, 0, &pickupAnchor, 300.0f ) ) { bs.nbg_time = Bot_Time() + 18.0f; stateThread.SetState("state_BattleNBG"); return SRESULT_DONE_FRAME; } } if (gameLocal.SysScriptTime() > bs.aggressiveAttackTime || bs.weaponnum == 0) { stateThread.SetState("state_Retreat"); return SRESULT_DONE; } // Ensure the target is a player. idPlayer *entinfo = gameLocal.entities[bs.enemy]->Cast(); if (!entinfo) { stateThread.SetState("state_SeekLTG"); return SRESULT_DONE_FRAME; } // If our enemy is dead, search for another LTG. if (EntityIsDead(entinfo)) { stateThread.SetState("state_SeekLTG"); return SRESULT_DONE_FRAME; } bs.currentGoal.origin = bs.lastenemyorigin; //aim at the enemy BotAimAtEnemy(&bs); //attack the enemy if possible BotCheckAttack(&bs); return SRESULT_WAIT; }