Пример #1
0
/*
================
idBotAI::Bot_ShouldVehicleChaseHiddenEnemy
================
*/
bool idBotAI::Bot_ShouldVehicleChaseHiddenEnemy() {

	proxyInfo_t enemyVehicleInfo;
	idVec3 vec;
	chasingEnemy = false;

	if ( ClientHasObj( botNum ) || Client_IsCriticalForCurrentObj( botNum, -1.0f ) ) { //mal: never chase if we are important!
		return false;
	}

	if ( botVehicleInfo->driverEntNum != botNum ) { //mal: we dont get the choice to chase someone if we're not the driver!
		return false;
	}

	if ( botVehicleInfo->health <= ( botVehicleInfo->maxHealth / 4 ) && !ClientHasObj( enemy ) ) { //mal: if we're in pretty bad shape, randomly decide to sometimes give up the fight....
		if ( botThreadData.random.RandomInt( 100 ) > 50 ) {
            return false;
		}
	}

	if ( ( botVehicleInfo->flags & PERSONAL ) || botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON && !ClientHasObj( enemy ) ) {
		return false;
	} //mal: if we dont have a vehicle weapon to fight with, or we're in a personal transport, dont go chasing ppl.

	if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) {

		GetVehicleInfo( botWorld->clientInfo[ enemy ].proxyInfo.entNum, enemyVehicleInfo );

		if ( enemyVehicleInfo.inWater && !botVehicleInfo->isAirborneVehicle || !( botVehicleInfo->flags & WATER ) ) {
			return false;
		} //mal: hes in the water, but we can't chase him, so forget him!

		if ( !ClientHasObj( enemy ) && !Client_IsCriticalForCurrentObj( enemy, 2000.0f ) ) {
            if ( botThreadData.random.RandomInt( 100 ) > 50 ) {
				return false;
			}
		}
	}

	if ( AIStack.STACK_AI_NODE != NULL && AIStack.isPriority != false && !ClientHasObj( enemy ) ) {
		return false;
	} // we have something important on our mind, and cant chase ATM - UNLESS they have the obj! Always chase them!

	vec = enemyInfo.enemy_LS_Pos - botInfo->origin;
	
	if ( vec.LengthSqr() > Square( ENEMY_CHASE_DIST ) ) {
		return false;
	} // too far away to chase

	vec = enemyInfo.enemy_LS_Pos - botWorld->clientInfo[ enemy ].origin;

	if ( vec.LengthSqr() > Square( 900.0f ) && !ClientHasObj( enemy ) && !Client_IsCriticalForCurrentObj( enemy, 1500.0f ) ) { // unless he's REALLY close or a threat, sometimes we'll stop the chase, just because....
		if ( botThreadData.random.RandomInt( 100 ) > 50 ) {
            return false;
		}
	}

	chasingEnemy = true;

	if ( ClientHasObj( enemy ) ) {
		chaseEnemyTime = botWorld->gameLocalInfo.time + 30000;
	} else if ( Client_IsCriticalForCurrentObj( enemy, 1500.0f ) ) {
		chaseEnemyTime = botWorld->gameLocalInfo.time + 15000;
	} else {
		chaseEnemyTime = botWorld->gameLocalInfo.time + 7000;
	}

	return true;
}
Пример #2
0
/*
================
idBotAI::Bot_VehicleFindBetterEnemy
================
*/
bool idBotAI::Bot_VehicleFindBetterEnemy() {
	int i;
	int entClientNum = enemy;
	float dist;
	float entDist;
	proxyInfo_t vehicleInfo;
	proxyInfo_t enemyVehicleInfo;
	idVec3 vec;

	if ( enemy == -1 ) { //mal: we lost our enemy for some reason, so just skip finding a new one til next frame.
		return false;
	}

	if ( ignoreNewEnemiesWhileInVehicleTime > botWorld->gameLocalInfo.time ) {
		return false;
	}

	if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { //mal: if we're attacking the MCP, its the priority.
		if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum == botWorld->botGoalInfo.botGoal_MCP_VehicleNum ) {
			return false;
		}
	}

	GetVehicleInfo( botWorld->clientInfo[ enemy ].proxyInfo.entNum, enemyVehicleInfo );

	if ( enemyVehicleInfo.entNum > 0 && ( enemyVehicleInfo.type == ANANSI || enemyVehicleInfo.type == HORNET ) ) { //mal: stay in dogfights!
		return false;
	}

	const clientInfo_t& enemyPlayerInfo = botWorld->clientInfo[ enemy ];

    vec = enemyPlayerInfo.origin - botInfo->origin;
	entDist = vec.LengthSqr();

	if ( !enemyInfo.enemyVisible ) { //mal: if we can't see our current enemy, more likely to attack a visible enemy.
		entDist = idMath::INFINITY;
	}

	if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_DEMO && !botWorld->botGoalInfo.gameIsOnFinalObjective && ( !enemyPlayerInfo.isBot || enemyPlayerInfo.isActor ) ) { //mal: dont worry about keeping our human target in training mode, unless its the final obj...
		entDist += Square( TRAINING_MODE_RANGE_ADDITION );
	}

	bool curEnemyNotInVehicle = false;

	if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && !ClientIsDefusingOurTeamCharge( enemy ) && !vehicleEnemyWasInheritedFromFootCombat ) { //mal: if our current enemy is on foot, more likely to pick a better target. Unless they're defusing our charge, or an enemy we jumped in this vehicle for, then we artificially raise their importance.
		curEnemyNotInVehicle = true;
	}
	
	numVisEnemies = 1; //mal: our current enemy is always visible to us

	for ( i = 0; i < MAX_CLIENTS; i++ ) {

		if ( !ClientIsValid( i, -1 ) ) {
			continue; //mal: no valid client in this client slot!
		}

		if ( i == botNum ) {
			continue; //mal: dont try to fight ourselves!
		}

		if ( i == enemy ) { //mal: ignore an enemy we already have
			continue;
		}

		if ( EnemyIsIgnored( i ) ) {
			continue; //mal: dont try to fight someone we've flagged to ignore for whatever reason!
		}

//mal: if we're in the middle of a critical obj, dont go looking for trouble, unless they're shooting us!
		if ( Client_IsCriticalForCurrentObj( botNum, -1.0f ) && ( botInfo->lastAttacker != i || botInfo->lastAttackerTime + 3000 < botWorld->gameLocalInfo.time ) && !ClientIsDefusingOurTeamCharge( i ) ) {
			continue;
		}

		const clientInfo_t& playerInfo = botWorld->clientInfo[ i ];

		if ( playerInfo.isNoTarget ) {
			continue;
		} //mal: dont target clients that have notarget set - this is useful for debugging, etc.

		if ( playerInfo.isDisguised && playerInfo.disguisedClient != botNum ) {
			continue; //mal: won't "see" disguised clients, unless they look like us!
		}

		if ( playerInfo.inLimbo ) {
			continue;
		}

		if ( playerInfo.isActor ) {
			continue;
		}

		if ( playerInfo.invulnerableEndTime > botWorld->gameLocalInfo.time ) {
			continue; //mal: ignore revived/just spawned in clients - get the ppl around them!
		}

		if ( playerInfo.health <= 0 ) {
			continue;
		}

		if ( playerInfo.team == botInfo->team ) {
			continue;
		}

		if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_DEMO && !botWorld->botGoalInfo.gameIsOnFinalObjective && !playerInfo.isBot && enemyPlayerInfo.isBot ) { //mal: dont worry about human targets in training mode if we have a bot one, unless its the final obj...
			continue;
		}

		if ( botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: st00pid bot - your not smart enough to pick your targets wisely
			if ( enemyVehicleInfo.entNum > 0 && enemyInfo.enemyVisible ) {

				if ( !( enemyVehicleInfo.flags & PERSONAL ) && !( enemyVehicleInfo.flags & WATER ) && ( enemyVehicleInfo.isAirborneVehicle && enemyVehicleInfo.xyspeed > 900.0f && entDist > Square( 2000.0f ) ) ) {
                    if ( playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && !Client_IsCriticalForCurrentObj( i, 1500.0f ) && !ClientHasObj( i ) ) {
						continue;
					} //mal: dont worry about an enemy in a vehicle if the vehicle is far away, moving too fast, is not a real threat
				}
			}
		} //mal: if our current enemy is in a vehicle, and this guy isn't, and this guy doesn't have an obj, or isn't important, hes not worth fighting.

		bool enemyIsInAirAttackVehicle = false;

		if ( playerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { //mal: pick the driver of a vehicle as the target, NOT passengers, unless there is no driver - then kill whoever.
			
			GetVehicleInfo( playerInfo.proxyInfo.entNum, vehicleInfo );

			if ( vehicleInfo.driverEntNum != i && vehicleInfo.driverEntNum != -1 ) {
				continue;
			}

			if ( vehicleInfo.type == ANANSI || vehicleInfo.type == HORNET ) {
				enemyIsInAirAttackVehicle = true;
			} else {
				vec = vehicleInfo.origin - botInfo->origin;				

				if ( vehicleInfo.xyspeed > 600.0f && vec.LengthSqr() > Square( 1900.0f ) && !InFrontOfVehicle( vehicleInfo.entNum, botInfo->origin ) ) { //mal: if they're in a mad dash away from us, forget about them!
					continue;
				}
			}
		}

		vec = playerInfo.origin - botInfo->origin;
		dist = vec.LengthSqr();

		if ( !enemyIsInAirAttackVehicle ) {
			if ( dist > Square( ENEMY_SIGHT_BUSY_DIST * 2.0f ) ) {
				continue;
			}
		}

		float tempDist = entDist;

		if ( curEnemyNotInVehicle && playerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) {
			tempDist += Square( 3000.0f );
		}

		if ( !enemyIsInAirAttackVehicle ) {
			if ( dist > tempDist ) {
				continue;
			}
		} else {
			if ( dist > Square( AIRCRAFT_ATTACK_DIST ) ) {
				continue;
			}
		}

		if ( !ClientIsVisibleToBot ( i, true, false ) ) {
			continue;
		}

		if ( Client_IsCriticalForCurrentObj( i, 1500.0f ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: if a critical class, get high priority
			dist = Square( 600.0f );
			ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
		}

		if ( ClientHasObj( i ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: if have docs, get HIGHER priority.
			dist = Square( 500.0f );
			ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
		}

		if ( ClientIsDefusingOurTeamCharge( i ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: if defusing our charge, get HIGHER priority.
			dist = Square( 100.0f );
			ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
		}

		if ( botWorld->botGoalInfo.mapHasMCPGoal && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
			if ( playerInfo.proxyInfo.entNum == botWorld->botGoalInfo.botGoal_MCP_VehicleNum ) {
				dist = Square( 400.0f );
				ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
			}
		}

		if ( enemyIsInAirAttackVehicle && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: dont ignore a chance to dogfight!
			dist = Square( 100.0f );
			ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
		}

		numVisEnemies++;
		entClientNum = i;
		entDist = dist;
	}

	if ( entClientNum != enemy ) {
		enemy = entClientNum;
		enemySpawnID = botWorld->clientInfo[ entClientNum ].spawnID;

		enemyInfo.enemy_FS_Pos = botWorld->clientInfo[ entClientNum ].origin;
		enemyInfo.enemy_LS_Pos = enemyInfo.enemy_FS_Pos;

		enemyInfo.enemyLastVisTime = botWorld->gameLocalInfo.time;

		enemyAcquireTime = botWorld->gameLocalInfo.time;

		bot_FS_Enemy_Pos = botInfo->origin;
		bot_LS_Enemy_Pos = bot_FS_Enemy_Pos;

		VEHICLE_COMBAT_AI_SUB_NODE = NULL; //mal: reset the bot's combat AI node and movement state.
		COMBAT_MOVEMENT_STATE = NULL;
		return true;
	}

	return false;
}
Пример #3
0
/*
================
idBotAI::Bot_CheckCurrentStateForVehicleCombat

Check to see if we're doing an important goal that we need to avoid combat for, or if we can just jump into the fray.
================
*/
void idBotAI::Bot_CheckCurrentStateForVehicleCombat() {
	if ( botVehicleInfo->driverEntNum == botNum && ( Client_IsCriticalForCurrentObj( botNum, 4500.0f ) || ClientHasObj( botNum ) || ( AIStack.STACK_AI_NODE != NULL && AIStack.isPriority ) || botVehicleInfo->type == MCP || botVehicleInfo->type == BUFFALO ) ) {
        VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::Enter_COMBAT_Vehicle_EvadeEnemy; //mal: if bot has a priority target, and its close, try to avoid combat as much as possible.
		return;
	} //mal: if we're not the driver of this vehicle, we'll always attack ( really, what else can we do? ).

    
	VEHICLE_COMBAT_AI_SUB_NODE = &idBotAI::Enter_COMBAT_Vehicle_AttackEnemy; 
}
Пример #4
0
/*
================
idBotAI::Bot_VehicleFindEnemy

We'll sort thru the clients, and ignore certain clients if we're too busy
to be buggered (carrying obj, planting/hacking, etc) or they're not valid enemies
(in disguise, hidden by smoke, etc).
================
*/
bool idBotAI::Bot_VehicleFindEnemy() {
	bool hasAttackedMate;
	bool hasAttackedCriticalMate;
	bool hasObj;
	bool isDefusingOurBomb;
	bool inFront;
	bool botGotShotRecently;
	bool botIsBigShot;
	bool audible;
	bool isVisible;
	bool isFacingUs;
	bool isFiringWeapon;
	bool isNearOurObj;
	bool isAttackingDeployable = false;
	bool inAttackAirCraft = false;
	int i;
	int entClientNum = -1;
	float dist;
	float botSightDist;
	float tempSightDist;
	float entDist = idMath::INFINITY;
	proxyInfo_t enemyVehicleInfo;
	enemyVehicleInfo.entNum = 0;
	idVec3 vec;

	numVisEnemies = 0;

	vehicleEnemyWasInheritedFromFootCombat = false;

	botSightDist = Square( ENEMY_VEHICLE_SIGHT_DIST ); //mal_FIXME: break this out into a script cmd!

/*
	if ( botSightDist > Square( 8000.0f ) ) {
		botSightDist = Square( 8000.0f );
	} else if ( botSightDist < Square( 3000.0f ) ) {
		botSightDist = Square( 3000.0f );
	}
*/

//mal: some debugging stuff....
	if ( botWorld->gameLocalInfo.botIgnoreEnemies == 1 ) {
			return false;
	} else if ( botWorld->gameLocalInfo.botIgnoreEnemies == 2 ) {
			if ( botInfo->team == GDF ) {
				return false;
			}
	} else if ( botWorld->gameLocalInfo.botIgnoreEnemies == 3 ) {
			if ( botInfo->team == STROGG ) {
				return false;
			}
		}

	if ( botVehicleInfo->type != BUFFALO && Bot_VehicleIsUnderAVTAttack() != -1 && ( ( botVehicleInfo->flags & ARMOR ) || botVehicleInfo->type > ICARUS ) ) {
		return false;
	}

	if ( botVehicleInfo->type > ICARUS ) {
		botSightDist = Square( 6000.0f );
	}

	if ( botVehicleInfo->type == BUFFALO ) {
		botSightDist = Square( 3500.0f );
	}

	if ( botVehicleInfo->type == GOLIATH || botVehicleInfo->type == DESECRATOR ) { //mal: these 2 are really limited
		botSightDist = Square( PLASMA_CANNON_RANGE - 1000.0f );
	}

	if ( botVehicleInfo->type == HUSKY ) { //mal: we're no match for anybody!
		return false;
	}

#ifdef _XENON
	if ( botVehicleInfo->type == MCP && botVehicleInfo->driverEntNum == botNum ) {
		return false;
	}

	if ( botVehicleInfo->type == PLATYPUS && botVehicleInfo->driverEntNum == botNum ) {
		return false;
	}
#endif

	if ( botVehicleInfo->type > ICARUS && Client_IsCriticalForCurrentObj( botNum, -1.0f ) ) {
		return false;
	}

	botIsBigShot = Client_IsCriticalForCurrentObj( botNum, 3500.0f );

	if ( aiState == VLTG && vLTGType == V_DESTROY_DEPLOYABLE ) {
		deployableInfo_t deployable;
		if ( GetDeployableInfo( false, vLTGTarget, deployable ) ) {
			if ( deployable.type == APT || deployable.type == AVT || deployable.type == AIT ) { //mal: these are the priorities
				isAttackingDeployable = true;
			}
		}
	}

	for ( i = 0; i < MAX_CLIENTS; i++ ) {

		if ( !ClientIsValid( i, -1 ) ) {
			continue; //mal: no valid client in this client slot!
		}

		if ( i == botNum ) {
			continue; //mal: dont try to fight ourselves!
		}

		if ( EnemyIsIgnored( i ) ) {
			continue; //mal: dont try to fight someone we've flagged to ignore for whatever reason!
		}

		if ( !Bot_VehicleCanAttackEnemy( i ) ) { //mal: check if the bot has access to a weapon in the vehicle, that can hit this client.
			continue;
		}

		const clientInfo_t& playerInfo = botWorld->clientInfo[ i ];

		if ( playerInfo.isNoTarget ) {
			continue;
		} //mal: dont target clients that have notarget set - this is useful for debugging, etc.

		bool enemyIsBigShot = Client_IsCriticalForCurrentObj( i, 2500.0f );

		if ( playerInfo.inLimbo ) {
			continue;
		}

		if ( playerInfo.invulnerableEndTime > botWorld->gameLocalInfo.time ) {
			continue; //mal: ignore revived/just spawned in clients - get the ppl around them!
		}

		if ( playerInfo.isActor ) {
			continue;
		}

		if ( playerInfo.health <= 0 ) {
			continue;
		}

		if ( playerInfo.team == botInfo->team ) {
			continue;
		}

		if ( botVehicleInfo->type == MCP && botVehicleInfo->driverEntNum == botNum ) {
			if ( !InFrontOfVehicle( botInfo->proxyInfo.entNum, playerInfo.origin ) ) {
				continue;
			}
		}

		if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_DEMO && botVehicleInfo->type > ICARUS && !playerInfo.isBot ) { //mal: don't attack human players in training mode when we're in flyers.
			continue;
		}

		hasAttackedCriticalMate = ClientHasAttackedTeammate( i, true, 3000 );
		hasAttackedMate = ClientHasAttackedTeammate( i, false, 3000 );
		hasObj = ClientHasObj( i );
		isDefusingOurBomb = ClientIsDefusingOurTeamCharge( i );
		inFront = ( botInfo->proxyInfo.weapon == PERSONAL_WEAPON ) ? InFrontOfClient( botNum, playerInfo.origin) : InFrontOfVehicle( botInfo->proxyInfo.entNum, playerInfo.origin );
		isFacingUs = ( playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) ? InFrontOfClient( i, botInfo->origin ) : InFrontOfVehicle( playerInfo.proxyInfo.entNum, botInfo->origin );
		botGotShotRecently = ( botInfo->lastAttackerTime + 3000 < botWorld->gameLocalInfo.time ) ? false : true;
		isFiringWeapon = playerInfo.weapInfo.isFiringWeap;
		isNearOurObj = ( LocationDistFromCurrentObj( botInfo->team, playerInfo.origin ) < 2500.0f ) ? true : false;
		bool isCriticalEnemy = Client_IsCriticalForCurrentObj( i, 2500.0f );

		if ( playerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { 
			GetVehicleInfo( playerInfo.proxyInfo.entNum, enemyVehicleInfo );
		}

		if ( isAttackingDeployable ) {
			if ( botInfo->team == botWorld->botGoalInfo.attackingTeam ) {
				if ( playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) {
					if ( playerInfo.weapInfo.weapon != ROCKET && !isDefusingOurBomb ) {
						continue;
					}
				} else {
					if ( !( enemyVehicleInfo.flags & ARMOR ) && enemyVehicleInfo.type != ANANSI && enemyVehicleInfo.type != HORNET ) {
			continue;
		}
				}
			} else {
				if ( !isDefusingOurBomb && playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && !hasObj && playerInfo.weapInfo.weapon != ROCKET && ( !isCriticalEnemy || !isNearOurObj ) ) {
					continue;
				}
			}
		}

		if ( botIsBigShot && !isFacingUs && ( !botGotShotRecently || botInfo->lastAttacker != i ) && !isFiringWeapon && !hasObj && !isNearOurObj ) {
			continue;
		} //mal: if we're trying to do an important obj, dont get into a fight with everyone.

		vec = playerInfo.origin - botInfo->origin;

		if ( botVehicleInfo->isAirborneVehicle ) {
			vec.z = 0.0f;
		}

		dist = vec.LengthSqr();

		if ( botIsBigShot && !inFront && dist > Square( 2500.0f ) && ( !botGotShotRecently || botInfo->lastAttacker != i ) && botVehicleInfo->driverEntNum == botNum ) {
			continue;
		}

		if ( playerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { //mal: pick the driver of a vehicle as the target, NOT passengers, unless there is no driver - then kill whoever.
			if ( enemyVehicleInfo.type == ANANSI || enemyVehicleInfo.type == HORNET ) {
				inAttackAirCraft = true;
			}

			if ( botIsBigShot && enemyVehicleInfo.type <= ICARUS ) {
				continue;
			}

			if ( enemyVehicleInfo.type == BUFFALO && botVehicleInfo->flags & ARMOR && playerInfo.isBot ) {
				continue;
			}

			if ( enemyVehicleInfo.type == MCP && enemyVehicleInfo.isImmobilized && enemyVehicleInfo.driverEntNum == i ) {
				continue;
			}

			if ( botVehicleInfo->type == ANANSI && enemyVehicleInfo.type == ICARUS ) { //mal: this is funny to watch, but is a waste of time. :-)
				continue;
			}

			if ( isAttackingDeployable ) {
				if ( botVehicleInfo->isAirborneVehicle && ( enemyVehicleInfo.type <= ICARUS || enemyVehicleInfo.type == BUFFALO ) ) { //mal: if attacking from the air, only worry about air vehicles.
					continue;
				}
			}

			if ( enemyVehicleInfo.driverEntNum != i && enemyVehicleInfo.driverEntNum != -1 ) {
				continue;
			}

			if ( inAttackAirCraft && enemyVehicleInfo.xyspeed > 500.0f && dist > Square( TANK_MINIGUN_RANGE ) && botVehicleInfo->flags & ARMOR ) { //mal: tanks won't attack fast moving aircraft that are too far away for their MGs
				continue;
			}

			if ( botVehicleInfo->type == BADGER ) {
				if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON && enemyVehicleInfo.flags & ARMOR || enemyVehicleInfo.inWater || ( enemyVehicleInfo.isAirborneVehicle && dist > Square( 3000.0f ) || enemyVehicleInfo.type == HOG ) ) {
                    continue;
				}
			}

			if ( botVehicleInfo->inWater && botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON ) {
				continue;
			}

			if ( botVehicleInfo->type != ANANSI && botVehicleInfo->type != HORNET ) {
                if ( enemyVehicleInfo.xyspeed > 600.0f && dist > Square( 1900.0f ) && !InFrontOfVehicle( enemyVehicleInfo.entNum, botInfo->origin ) && !ClientHasObj( i ) && !enemyIsBigShot ) { //mal: if they're in a mad dash away from us, forget about them!
					continue;
				}
			}
		}

		if ( botVehicleInfo->type == BUFFALO && !inAttackAirCraft ) { //mal_TODO: need to make the buffalo a more effective fighting platform!
			continue;
		}

		tempSightDist = botSightDist;

		if ( !ClientHasObj( i ) && !enemyIsBigShot && playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && !playerInfo.isCamper && playerInfo.killsSinceSpawn < KILLING_SPREE && botVehicleInfo->driverEntNum == botNum && !isDefusingOurBomb ) { //mal: vehicles will prefer to fight other vehicles, not some guy on foot a mile away....
			tempSightDist = Square( 3500.0f );
		}

		if ( inAttackAirCraft && ( botVehicleInfo->type == ANANSI || botVehicleInfo->type == HORNET ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
			tempSightDist = Square( AIRCRAFT_ATTACK_DIST );
		}

		if ( dist > tempSightDist ) {
            continue;
		}

		if ( playerInfo.isDisguised ) { //mal: when in a vehicle, bots are much less likely to notice or worry about coverts
			if ( botThreadData.GetBotSkill() == BOT_SKILL_EASY ) {
				continue;
			} else {
				if ( ( playerInfo.disguisedClient != botNum && !hasAttackedMate ) || dist > Square( 2500.0f ) ) {
                    continue;
				}
			}
		} 

 		if ( !ClientHasObj( i ) ) {
            audible = ClientIsAudibleToVehicle( i ); //mal: if we can hear you, we'll skip the FOV test in the vis check below
		} else {
            audible = true;
			dist = Square( 500.0f ); //mal: if you've got the docs, your our priority target, unless someone else is right on top of us!
		}

		isVisible = ClientIsVisibleToBot( i, !audible, false );

		if ( !isVisible && !ClientHasObj( i ) ) {
			continue;
		}

		if ( botWorld->gameLocalInfo.botSkill != BOT_SKILL_DEMO || botWorld->botGoalInfo.gameIsOnFinalObjective || botWorld->botGoalInfo.attackingTeam == botInfo->team ) {
			if ( isDefusingOurBomb ) {
				dist = Square( 100.0f );
			}

			if ( hasAttackedCriticalMate && inFront && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
				dist = Square( 600.0f ); //mal: will give higher priority to someone attacking a critical mate, if we can see it happening.
			}

			if ( botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
				if ( Client_IsCriticalForCurrentObj( i, 6000.0f ) ) {
					dist = Square( 700.0f ); //mal: if your a critical client, we're more likely to kill you.
				}
			}

			if ( botWorld->botGoalInfo.mapHasMCPGoal ) {
				if ( playerInfo.proxyInfo.entNum == botWorld->botGoalInfo.botGoal_MCP_VehicleNum ) {
					dist = 400.0f;
				}
			} //mal: if your in MCP, you get higher priority then a normal enemy. Especially when we're in a vehicle!

			if ( botVehicleInfo->type > ICARUS && botVehicleInfo->type != BUFFALO && ( playerInfo.isCamper || playerInfo.killsSinceSpawn >= KILLING_SPREE ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY && !playerInfo.isBot ) {
				dist = Square( 600.0f );
			} //mal: target trouble making humans!
		} else {
			if ( !playerInfo.isBot || playerInfo.isActor ) {
				dist += Square( TRAINING_MODE_RANGE_ADDITION );
			}
		}

		numVisEnemies++;

		if ( dist < entDist ) {
			entClientNum = i;
			entDist = dist;
		}
	}

	if ( entClientNum != -1 ) {
		enemy = entClientNum;
		enemySpawnID = botWorld->clientInfo[ entClientNum ].spawnID;

		enemyInfo.enemy_FS_Pos = botWorld->clientInfo[ entClientNum ].origin;
		enemyInfo.enemy_LS_Pos = enemyInfo.enemy_FS_Pos;

		bot_FS_Enemy_Pos = botInfo->origin;
		bot_LS_Enemy_Pos = bot_FS_Enemy_Pos;
		enemyInfo.enemyLastVisTime = botWorld->gameLocalInfo.time;
		enemyAcquireTime = botWorld->gameLocalInfo.time;

		Bot_SetAttackTimeDelay( inFront ); //mal: this sets a delay on how long the bot should take to see enemy, based on bot's state.

		VEHICLE_COMBAT_AI_SUB_NODE = NULL; //mal: reset the bot's combat AI node
		COMBAT_MOVEMENT_STATE = NULL;
		return true;
	}

	return false;
}
Пример #5
0
/*
================
idBotAI::ClientIsAudibleToVehicle

Cheaply tells us if the client is question is making enough noise for this vehicle
to "notice" them and possibly consider them an enemy.
================
*/
bool idBotAI::ClientIsAudibleToVehicle( int clientNum ) {
	heardClient = -1; // reset this every frame.

	if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_EASY ) { // stupid bot - you can't hear anyone!
		return false;
	}

	if ( botWorld->botGoalInfo.teamRetreatInfo[ botInfo->team ].retreatTime > botWorld->gameLocalInfo.time ) {
		return false;
	}

	const clientInfo_t& client = botWorld->clientInfo[ clientNum ];

	if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_DEMO && !botWorld->botGoalInfo.gameIsOnFinalObjective && !client.isBot ) { //mal: dont worry about hearing human targets in training mode, unless its the final obj...
		return false;
	}

	float hearingRange = ( client.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) ? PLAYER_HEARING_DIST : VEHICLE_HEARING_DIST;

	idVec3 vec = client.origin - botInfo->origin;
	float dist = vec.LengthSqr();

	float distTemp = vec.LengthFast();

	if ( client.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && client.weapInfo.weapon == SNIPERRIFLE && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
		hearingRange = SNIPER_HEARING_DIST;
	}

	if ( client.weapInfo.isFiringWeap && dist < Square( hearingRange ) ) {
		heardClient = clientNum;
		return true;
	}

	if ( dist < Square( FOOTSTEP_DIST )  ) {
		heardClient = clientNum;
		return true;
	}

	if ( ClientHasObj( clientNum ) && ( botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY || client.isInRadar ) ) {
		return true;
	}

	if ( client.isInRadar && dist < Square( 1500.0f ) && ( client.abilities.gdfStealthToRadar == false || client.classType != COVERTOPS ) ) { //mal_TODO: test me!!!
		return true;
	}

	if ( ClientIsMarkedForDeath( clientNum, false ) ) {
		return true;
	}

	if ( ClientIsDangerous( clientNum ) ) { //mal: we're "aware" of campers, and will kill them if they're vis to us.
		heardClient = clientNum;
		return true;
	}

	if ( botInfo->lastAttacker == clientNum && botInfo->lastAttackerTime + 3000 > botWorld->gameLocalInfo.time ) {
		return true;
	}

	if ( ( client.targetLockEntNum == botNum || client.targetLockEntNum == botInfo->proxyInfo.entNum ) && client.targetLockTime + 3000 < botWorld->gameLocalInfo.time ) {
		return true;
	}

	return false;
}
Пример #6
0
/*
================
idBotAI::Bot_FindBestVehicleCombatMovement

Finds the best combat movement for the bot while in a vehicle.
================
*/
bool idBotAI::Bot_FindBestVehicleCombatMovement() {
	bool vehicleCanRamClient; //mal: sounds a bit... dirty, doesn't it?
	bool vehicleGunnerSeatOpen;
	bool hasAttackedCriticalMate = false;
	bool enemyReachable = false;
	bool enemyHasVehicle = false;
	proxyInfo_t enemyVehicleInfo;

	const clientInfo_t& enemyPlayerInfo = botWorld->clientInfo[ enemy ];

	if ( enemyPlayerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) {
		GetVehicleInfo( enemyPlayerInfo.proxyInfo.entNum, enemyVehicleInfo );
		enemyHasVehicle = true;
	}

	combatMoveFailedCount = 0;
	combatMoveTime = -1;

	if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON && botVehicleInfo->driverEntNum != botNum ) {
		return false;
	} //mal: this shouldn't really ever happen, but may if the bot is moving between positions in a vehicle. Or if a human entered/exited a vehicle at just the right/wrong time.

	if ( ( botInfo->proxyInfo.weapon == MINIGUN || botInfo->proxyInfo.weapon == LAW || botInfo->proxyInfo.weapon == PERSONAL_WEAPON ) && botVehicleInfo->driverEntNum != botNum ) {
		VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_NULL_Movement; //mal: just sit there, and shoot the enemy.
		return true;
	}

	if ( botVehicleInfo->type > ICARUS ) {
		VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Air_Movement;
		return true;
	}

	//mal: this more often then not causes issues
/*
	if ( enemyHasVehicle ) {
		if ( enemyVehicleInfo.type == HOG && enemyInfo.enemyDist < 3000.0f && botVehicleInfo->driverEntNum == botNum ) { //mal: never stand around if a hog has us in his sights.
			VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Random_Movement;
			return true;
		}
	}
*/

	vehicleGunnerSeatOpen = VehicleHasGunnerSeatOpen( botInfo->proxyInfo.entNum );

	if ( enemyPlayerInfo.lastAttackClient > - 1 && enemyPlayerInfo.lastAttackClient < MAX_CLIENTS ) {
		if ( botWorld->clientInfo[ enemyPlayerInfo.lastAttackClient ].team == botInfo->team && enemyPlayerInfo.lastAttackClientTime + 3000 > botWorld->gameLocalInfo.time ) {
			if ( Client_IsCriticalForCurrentObj( enemyPlayerInfo.lastAttackClient, 2000.0f ) || ClientHasObj( enemyPlayerInfo.lastAttackClient ) ) {
				hasAttackedCriticalMate = true;
			}
		}
	}

	Bot_SetupVehicleMove( vec3_zero, enemy, ACTION_NULL );

    if ( botAAS.hasPath && botAAS.path.travelTime < Bot_ApproxTravelTimeToLocation( botInfo->origin, enemyPlayerInfo.origin, true ) * TRAVEL_TIME_MULTIPLY ) {
		enemyReachable = true;
	}

	if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON && botVehicleInfo->driverEntNum == botNum ) {

		vehicleCanRamClient = Bot_VehicleCanRamClient( enemy );

		if ( botVehicleInfo->type == HOG ) {
			if ( vehicleCanRamClient && InFrontOfVehicle( botVehicleInfo->entNum, enemyPlayerInfo.origin, true ) ) {
				VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Ram_Attack_Movement; //mal: ram them! Thats our only weapon.
				return true;
			}

			if ( enemyReachable && enemyHasVehicle ) {
				if ( enemyVehicleInfo.type != HUSKY ) {
					VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Chase_Movement; //mal: move in for a closer kill, THEN ram them.
					return true;
				}
			}
		}

		if ( botVehicleInfo->type == BADGER && enemyInfo.enemyDist < 1500.0f && vehicleCanRamClient && enemyPlayerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && botVehicleInfo->driverEntNum == botNum ) {
			VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Ram_Attack_Movement; //mal: 10 points! Fun for the whole family.
			return true;
		}

		if ( !vehicleGunnerSeatOpen ) {
			if ( enemyInfo.enemyDist < 2500.0f ) {
				VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Stand_Ground_Movement; //mal: just sit there, let our gunner get a chance to kill the enemy.
			} else {
				if ( enemyReachable || enemyInfo.enemyDist > 1500.0f ) {
                    VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Chase_Movement; //mal: move in for a closer kill.
				} else {
					VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Stand_Ground_Movement; //mal: just sit there, let our gunner get a chance to kill the enemy.
				}
			}

			return true;
		} else {
			if ( enemyPlayerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) {
				if ( enemyInfo.enemyDist < 6000.0f && ( vehicleCanRamClient || hasAttackedCriticalMate ) ) { //mal: if an important mate is under attack, we'll fight to the end, even if its just to draw the enemies fire.
					VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Ram_Attack_Movement; //mal: ram them! Thats our only weapon.
					return true;
				}
			} else {
				Bot_IgnoreEnemy( enemy, 15000 );
				return false;
			} //mal: if all else fails, we have no choice but to ignore this enemy.
		}
	}

	if ( ( botInfo->proxyInfo.weapon == MINIGUN || botInfo->proxyInfo.weapon == LAW || botInfo->proxyInfo.weapon == PERSONAL_WEAPON ) && botVehicleInfo->driverEntNum != botNum ) {
		VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_NULL_Movement; //mal: just sit there, and shoot the enemy.
		return true;
	}

	if ( ( botInfo->proxyInfo.weapon == MINIGUN || botInfo->proxyInfo.weapon == LAW || botInfo->proxyInfo.weapon == PERSONAL_WEAPON ) && botVehicleInfo->driverEntNum == botNum ) {

		if ( botThreadData.random.RandomInt( 100 ) > 50 && enemyInfo.enemyDist < 1500.0f ) {
   			VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Stand_Ground_Movement; 
		} else {
			VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Chase_Movement; //mal: move around a bit to make ourselves harder to hit.
		}
		return true;
	}

	if ( botVehicleInfo->type == GOLIATH && botVehicleInfo->driverEntNum == botNum ) {
		VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Stand_Ground_Movement;
		return true;
	}

	if ( botInfo->proxyInfo.weapon == TANK_GUN && botVehicleInfo->driverEntNum == botNum ) {
		if ( !enemyReachable && enemyInfo.enemyDist < 3000.0f ) { //mal: dont do chase movement of our enemy, if we cant reach him.
           VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Stand_Ground_Movement; 
		} else {
			if ( enemyAcquireTime + 10000 < botWorld->gameLocalInfo.time && botInfo->lastAttackClientTime + 10000 < botWorld->gameLocalInfo.time ) {
				proxyInfo_t enemyVehicleInfo;
				GetVehicleInfo( enemyPlayerInfo.proxyInfo.entNum, enemyVehicleInfo );

				if ( enemyVehicleInfo.entNum != 0 && enemyVehicleInfo.type >= ICARUS ) { //mal: dont chase air vehicles around - this looks retarded.
					VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Stand_Ground_Movement;
				} else {
					VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Chase_Movement; //mal: haven't had much success hitting our enemy - so chase him for a better shot.
				}
			} else {
//				if ( botThreadData.random.RandomInt( 100 ) > 40 ) {
					VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Stand_Ground_Movement;
//				} else {
//					VEHICLE_COMBAT_MOVEMENT_STATE = &idBotAI::Enter_Vehicle_Chase_Movement;  //mal: move around a bit to make ourselves harder to hit.
//				}
			}
		}

		return true;
	}


	//mal_TODO: add support for air vehicles too......

	botThreadData.Warning( "Can't find a move that suits bot %i and his vehicle!", botNum );

	return false;
}