// 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 no enemy if( bs.enemy < 0 ) { 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 = idMath::CreateVector( -8, -8, -8 ); goal.maxs = idMath::CreateVector( 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, 0 ); 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() - 10 ) { //AIEnter_Seek_LTG(bs, "battle chase: time out"); stateThread.SetState("state_SeekLTG"); return SRESULT_DONE_FRAME; } //check for nearby goals periodicly if( bs.check_time < Bot_Time() ) { bs.check_time = Bot_Time() + 1; range = 150; // if( BotNearbyGoal( &bs, 0, &goal, range ) ) { //the bot gets 5 seconds to pick up the nearby goal item bs.nbg_time = Bot_Time() + 0.1 * range + 1; //BotResetLastAvoidReach(bs.ms); //AIEnter_Battle_NBG(bs, "battle chase: nbg"); stateThread.SetState("state_BattleNBG"); return SRESULT_DONE_FRAME; } } BotUpdateBattleInventory( &bs, bs.enemy ); ////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; }