Example #1
0
/*
==================
idBotAI::Bot_VehicleCanAttackEnemy
==================
*/
bool idBotAI::Bot_VehicleCanAttackEnemy( int clientNum ) {

	if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON ) {
		if ( !VehicleHasGunnerSeatOpen( botInfo->proxyInfo.entNum ) && botVehicleInfo->driverEntNum != botNum ) { 
			return false;
		}
	} else if ( botInfo->proxyInfo.weapon == PERSONAL_WEAPON ) { //mal: if we have our personal weapon, we can't control the vehicle in question, so can only attack if client is vis to us, and we have ammo to attack with.
		if ( !InFrontOfClient( botNum, botWorld->clientInfo[ clientNum ].origin ) && !VehicleHasGunnerSeatOpen( botInfo->proxyInfo.entNum ) ) {
			return false;
		}

		if ( !botInfo->weapInfo.hasNadeAmmo && !botInfo->weapInfo.sideArmHasAmmo && !botInfo->weapInfo.primaryWeapHasAmmo ) {
			return false;
		} //mal: dont have any ammo for the 3 weapons the bots can use while riding in a transport, so just sit there.
	} else if ( botVehicleInfo->type == MCP && botVehicleInfo->driverEntNum == botNum ) {
#ifdef _XENON
		return false;
#endif
		if ( !InFrontOfVehicle( botInfo->proxyInfo.entNum, botWorld->clientInfo[ clientNum ].origin ) ) {
			return false;
		} //mal: dont fight ppl if we're driving the mcp, and they're not in front of us - just get the MCP to the outpost!
	}

	return true;	
}
Example #2
0
/*
==================
idBotAI::Bot_PickBestVehicleWeapon

See what the best weapon is that we have at our disposal - we'll change our position in this vehicle if need be to get access to a ( better ) weapon.
==================
*/
void idBotAI::Bot_PickBestVehicleWeapon() {

	bool enemyInAirborneVehicle = false;
	bool enemyInGroundVehicle = false;
	bool needMovementUpdate = false;
	bool enemyOnFoot = false;
	bool hasGunnerSeatOpen;
	bool enemyReachable = false;

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

	if ( botVehicleInfo->type == ICARUS ) {
		return;
	}

	proxyInfo_t enemyVehicleInfo;

	idVec3 vec = botWorld->clientInfo[ enemy ].origin - botInfo->origin;

	float dist = vec.LengthSqr();

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

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

		if ( enemyVehicleInfo.isAirborneVehicle ) {
			enemyInAirborneVehicle = true;
		} else {
			enemyInGroundVehicle = true;
		}
	} else {
		enemyOnFoot = true;
	}

	Bot_SetupVehicleMove( vec3_zero, enemy, ACTION_NULL );

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

	switch( botVehicleInfo->type ) {

		case TITAN:
			if ( botVehicleInfo->driverEntNum == botNum ) {
				if ( enemyInAirborneVehicle && enemyInfo.enemyDist <= TANK_MINIGUN_RANGE && hasGunnerSeatOpen ) {
					botUcmd->botCmds.becomeGunner = true; 
					needMovementUpdate = true;
					break;
				}
			} else {
				if ( ( enemyInAirborneVehicle && enemyInfo.enemyDist > TANK_MINIGUN_RANGE && botVehicleInfo->driverEntNum == -1 ) || !enemyInAirborneVehicle ) {
					botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
					break;
				}
			}

			break;

		case TROJAN:
			if ( botInfo->proxyInfo.weapon == LAW ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					if ( ( !enemyInAirborneVehicle && !enemyInGroundVehicle ) || enemyInfo.enemyDist < 700.0f || enemyInfo.enemyDist > WEAPON_LOCK_DIST ) {
                        botUcmd->botCmds.becomeDriver = true; //mal: using the LAW to lock onto our vehicle enemy makes sense ( the drivers MG is a joke in this case ).
						needMovementUpdate = true;
						break;
					}
				}
			}

			if ( botVehicleInfo->driverEntNum == botNum ) {
				if ( ( enemyInAirborneVehicle || enemyInGroundVehicle ) && hasGunnerSeatOpen && dist < Square( WEAPON_LOCK_DIST ) ) {
					botUcmd->botCmds.becomeGunner = true; //mal: using the LAW to lock onto our airborne enemy makes sense ( the drivers MG is a joke in this case ).
					needMovementUpdate = true;
					break;
				}
			}

			if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
				} else if ( VehicleHasGunnerSeatOpen( botVehicleInfo->entNum ) ) {
					botUcmd->botCmds.becomeGunner = true;
					needMovementUpdate = true;
				}
				break;
			}//mal: if we're the driver, stay as the driver!

			break;

		case BADGER:
			if ( botVehicleInfo->driverEntNum == botNum ) { //mal: we're the driver, if the turret is available, we may jump into it to fight enemies.
				if ( hasGunnerSeatOpen && vehicleDriverTime < botWorld->gameLocalInfo.time && enemyReachable && enemyInfo.enemyDist > 700.0f && enemyVehicleInfo.type != HOG ) {
                    if ( botThreadData.random.RandomInt( 100 ) > 50 ) {
						vehicleDriverTime = botWorld->gameLocalInfo.time + 15000;
						break;
					}
					
					if ( ( enemyInAirborneVehicle || ( enemyInfo.enemyDist < 3000.0f && enemyInfo.enemyDist > 700.0f ) ) && vehicleGunnerTime + 30000 < botWorld->gameLocalInfo.time && enemyInfo.enemyVisible ) { //mal: dont do this if enemy too far away, or its been too soon since we last did this.
						botUcmd->botCmds.becomeGunner = true;
						vehicleGunnerTime = botWorld->gameLocalInfo.time + 15000;
						needMovementUpdate = true;
						break;
					}
				}
			}

			if ( botInfo->proxyInfo.weapon == PERSONAL_WEAPON ) {
				if ( hasGunnerSeatOpen && botVehicleInfo->driverEntNum != -1 ) {
					botUcmd->botCmds.becomeGunner = true;
					needMovementUpdate = true;
					break;
				} //mal: our gunner may have been killed, or maybe he jumped out some time ago - take his place.

				if ( botVehicleInfo->driverEntNum == -1 ) {
                    botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
					break;
				}
			}

			if ( botInfo->proxyInfo.weapon == MINIGUN ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					if ( vehicleGunnerTime < botWorld->gameLocalInfo.time || !enemyInfo.enemyVisible ) { //mal: even if we had a driver and he bailed, become the driver for a better shot, then can go back to the gun.
						botUcmd->botCmds.becomeDriver = true;
						needMovementUpdate = true;
						break;
					}
				}
			}

			if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON && botVehicleInfo->driverEntNum != botNum ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
				} else if ( VehicleHasGunnerSeatOpen( botVehicleInfo->entNum ) ) {
					botUcmd->botCmds.becomeGunner = true;
					needMovementUpdate = true;
				} else if ( botVehicleInfo->hasFreeSeat ) {
					needMovementUpdate = true;
					botUcmd->botCmds.activate = true; //mal: rotate to one of the back seats.
				}
			}//mal: if we're the driver, stay as the driver!

			break;

		case PLATYPUS:
			if ( botVehicleInfo->driverEntNum == botNum ) { //mal: we're the driver, if the turret is available, we may jump into it to fight enemies.
				if ( hasGunnerSeatOpen ) {
					if ( enemyInfo.enemyDist < 1500.0f && vehicleGunnerTime + 30000 < botWorld->gameLocalInfo.time && enemyInfo.enemyVisible ) { //mal: dont do this if enemy too far away, or its been too soon since we last did this.
						botUcmd->botCmds.becomeGunner = true;
						vehicleGunnerTime = botWorld->gameLocalInfo.time + 10000;
						needMovementUpdate = true;
					}
				} //mal: if we have a gunner, we'll try to get a better shot for him, so that he can cut down our enemies.
			}

			if ( botInfo->proxyInfo.weapon == MINIGUN ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					if ( vehicleGunnerTime < botWorld->gameLocalInfo.time || !enemyInfo.enemyVisible ) { //mal: even if we had a driver and he bailed, become the driver for a better shot, then can go back to the gun.
						botUcmd->botCmds.becomeDriver = true;
						needMovementUpdate = true;
					}
				}
			}

			break;

		case DESECRATOR:
			if ( botVehicleInfo->driverEntNum == botNum ) {
				if ( enemyInAirborneVehicle && enemyInfo.enemyDist <= TANK_MINIGUN_RANGE && hasGunnerSeatOpen ) {
					botUcmd->botCmds.becomeGunner = true; 
					needMovementUpdate = true;
					break;
				}
			} else {
				if ( ( enemyInAirborneVehicle && enemyInfo.enemyDist > TANK_MINIGUN_RANGE && botVehicleInfo->driverEntNum == -1 ) || !enemyInAirborneVehicle ) {
					botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
					break;
				}
			}

			break;

		case HOG:
			if ( botInfo->proxyInfo.weapon == MINIGUN ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					if ( vehicleGunnerTime < botWorld->gameLocalInfo.time || !enemyInfo.enemyVisible || botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE && !enemyInAirborneVehicle ) { //mal: even if we had a driver and he bailed, become the driver for a better shot, then can go back to the gun.
						botUcmd->botCmds.becomeDriver = true;
						needMovementUpdate = true;
					} //mal: we'll prefer to ram our enemies who are in vehicles
				}
			}

			if ( botVehicleInfo->driverEntNum == botNum && ( !Bot_VehicleCanRamClient( enemy ) || VEHICLE_COMBAT_MOVEMENT_STATE == NULL || combatMoveType != VEHICLE_RAM_ATTACK_MOVEMENT ) ) {
				if ( ( enemyInAirborneVehicle || ( enemyInfo.enemyDist < 3000.0f && enemyInfo.enemyDist > 700.0f ) ) && vehicleGunnerTime + 30000 < botWorld->gameLocalInfo.time && enemyInfo.enemyVisible ) {
					botUcmd->botCmds.becomeGunner = true;
					vehicleGunnerTime = botWorld->gameLocalInfo.time + 10000;
					needMovementUpdate = true;
				}
			}

			break;

		case ANANSI:
		case HORNET:
			if ( botInfo->proxyInfo.weapon == MINIGUN ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					botUcmd->botCmds.becomeDriver = true; //mal: our coward of a pilot bailed on us... take the controls!
					needMovementUpdate = true;
				}
			}

			if ( botVehicleInfo->driverEntNum == botNum ) {
				if ( botInfo->proxyInfo.weapon == LAW ) { //mal: law is better against other vehicles
					if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) {
						botUcmd->botCmds.switchVehicleWeap = true;
					} else {
						if ( botInfo->proxyInfo.weaponIsReady == false && rocketTime < botWorld->gameLocalInfo.time && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: use rockets if LAW outta charge
							rocketTime = botWorld->gameLocalInfo.time + 2000;
							botUcmd->botCmds.switchVehicleWeap = true;
						}
					}
				}

				if ( botInfo->proxyInfo.weapon == ROCKETS ) { //mal: rockets are nice against slow moving ground targets.
					if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE && rocketTime < botWorld->gameLocalInfo.time ) {
						botUcmd->botCmds.switchVehicleWeap = true;
					}
				}
			}

			break;		
	}

	if ( needMovementUpdate ) {
		COMBAT_MOVEMENT_STATE = NULL;
		VEHICLE_COMBAT_MOVEMENT_STATE = NULL;
		vehicleUpdateTime = botWorld->gameLocalInfo.time + 500;
	}

	weapSwitchTime = botWorld->gameLocalInfo.time + 1500;
}
Example #3
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;
}