You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
8.4 KiB
318 lines
8.4 KiB
#include "bot_common.h" |
|
|
|
/* |
|
* Globals initialization |
|
*/ |
|
cvar_t cv_bot_traceview = { "bot_traceview", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_stop = { "bot_stop", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_show_nav = { "bot_show_nav", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_show_danger = { "bot_show_danger", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_nav_edit = { "bot_nav_edit", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_nav_zdraw = { "bot_nav_zdraw", "4", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_walk = { "bot_walk", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_difficulty = { "bot_difficulty", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_debug = { "bot_debug", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_quicksave = { "bot_quicksave", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_quota = { "bot_quota", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_quota_match = { "bot_quota_match", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_prefix = { "bot_prefix", "", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_rogues = { "bot_allow_rogues", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_pistols = { "bot_allow_pistols", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_shotguns = { "bot_allow_shotguns", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_sub_machine_guns = { "bot_allow_sub_machine_guns", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_rifles = { "bot_allow_rifles", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_machine_guns = { "bot_allow_machine_guns", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_grenades = { "bot_allow_grenades", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_snipers = { "bot_allow_snipers", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_allow_shield = { "bot_allow_shield", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_join_team = { "bot_join_team", "any", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_join_after_player = { "bot_join_after_player", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_auto_vacate = { "bot_auto_vacate", "1", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_zombie = { "bot_zombie", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_defer_to_human = { "bot_defer_to_human", "0", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_chatter = { "bot_chatter", "normal", FCVAR_SERVER, 0.0f, NULL }; |
|
cvar_t cv_bot_profile_db = { "bot_profile_db", "BotProfile.db", FCVAR_SERVER, 0.0f, NULL }; |
|
|
|
void InstallBotControl() |
|
{ |
|
if (TheBots != NULL) |
|
{ |
|
delete TheBots; |
|
TheBots = NULL; |
|
} |
|
|
|
TheBots = new CCSBotManager; |
|
} |
|
|
|
// Engine callback for custom server commands |
|
|
|
void Bot_ServerCommand() |
|
{ |
|
if (TheBots != NULL) |
|
{ |
|
const char *pcmd = CMD_ARGV(0); |
|
TheBots->ServerCommand(pcmd); |
|
} |
|
} |
|
|
|
void Bot_RegisterCvars() |
|
{ |
|
if (true) |
|
{ |
|
CVAR_REGISTER (&cv_bot_traceview); |
|
CVAR_REGISTER (&cv_bot_stop); |
|
CVAR_REGISTER (&cv_bot_show_nav); |
|
CVAR_REGISTER (&cv_bot_show_danger); |
|
CVAR_REGISTER (&cv_bot_nav_edit); |
|
CVAR_REGISTER (&cv_bot_nav_zdraw); |
|
CVAR_REGISTER (&cv_bot_walk); |
|
CVAR_REGISTER (&cv_bot_difficulty); |
|
CVAR_REGISTER (&cv_bot_debug); |
|
CVAR_REGISTER (&cv_bot_quicksave); |
|
CVAR_REGISTER (&cv_bot_quota); |
|
CVAR_REGISTER (&cv_bot_quota_match); |
|
CVAR_REGISTER (&cv_bot_prefix); |
|
CVAR_REGISTER (&cv_bot_allow_rogues); |
|
CVAR_REGISTER (&cv_bot_allow_pistols); |
|
CVAR_REGISTER (&cv_bot_allow_shotguns); |
|
CVAR_REGISTER (&cv_bot_allow_sub_machine_guns); |
|
CVAR_REGISTER (&cv_bot_allow_rifles); |
|
CVAR_REGISTER (&cv_bot_allow_machine_guns); |
|
CVAR_REGISTER (&cv_bot_allow_grenades); |
|
CVAR_REGISTER (&cv_bot_allow_snipers); |
|
CVAR_REGISTER (&cv_bot_allow_shield); |
|
CVAR_REGISTER (&cv_bot_join_team); |
|
CVAR_REGISTER (&cv_bot_join_after_player); |
|
CVAR_REGISTER (&cv_bot_auto_vacate); |
|
CVAR_REGISTER (&cv_bot_zombie); |
|
CVAR_REGISTER (&cv_bot_defer_to_human); |
|
CVAR_REGISTER (&cv_bot_chatter); |
|
CVAR_REGISTER (&cv_bot_profile_db); |
|
} |
|
} |
|
|
|
// Constructor |
|
|
|
CCSBot::CCSBot() : m_chatter(this), m_gameState(this) |
|
{ |
|
; |
|
} |
|
|
|
// Prepare bot for action |
|
|
|
bool CCSBot::Initialize(const BotProfile *profile) |
|
{ |
|
// extend |
|
CBot::Initialize(profile); |
|
|
|
// CS bot initialization |
|
m_diedLastRound = false; |
|
m_morale = POSITIVE; // starting a new round makes everyone a little happy |
|
|
|
m_combatRange = RANDOM_FLOAT(325, 425); |
|
|
|
m_navNodeList = NULL; |
|
m_currentNode = NULL; |
|
|
|
// set initial safe time guess for this map |
|
m_safeTime = 15.0f + 5.0f * GetProfile()->GetAggression(); |
|
|
|
m_name[0] = '\0'; |
|
|
|
ResetValues(); |
|
StartNormalProcess(); |
|
|
|
return true; |
|
} |
|
|
|
// Reset internal data to initial state |
|
|
|
void CCSBot::ResetValues() |
|
{ |
|
m_chatter.Reset(); |
|
m_gameState.Reset(); |
|
|
|
m_avoid = NULL; |
|
m_avoidTimestamp = 0.0f; |
|
|
|
m_hurryTimer.Invalidate(); |
|
|
|
m_isStuck = false; |
|
m_stuckTimestamp = 0.0f; |
|
m_wiggleTimestamp = 0.0f; |
|
m_stuckJumpTimestamp = 0.0f; |
|
|
|
m_pathLength = 0; |
|
m_pathIndex = 0; |
|
m_areaEnteredTimestamp = 0.0f; |
|
m_currentArea = NULL; |
|
m_lastKnownArea = NULL; |
|
|
|
m_avoidFriendTimer.Invalidate(); |
|
m_isFriendInTheWay = false; |
|
m_isWaitingBehindFriend = false; |
|
|
|
m_disposition = ENGAGE_AND_INVESTIGATE; |
|
|
|
m_enemy = NULL; |
|
|
|
m_isWaitingToTossGrenade = false; |
|
m_wasSafe = true; |
|
|
|
m_nearbyEnemyCount = 0; |
|
m_enemyPlace = 0; |
|
m_nearbyFriendCount = 0; |
|
m_closestVisibleFriend = NULL; |
|
m_closestVisibleHumanFriend = NULL; |
|
|
|
for (int w = 0; w < ARRAYSIZE(m_watchInfo); ++w) |
|
{ |
|
m_watchInfo[w].timestamp = 0.0f; |
|
m_watchInfo[w].isEnemy = false; |
|
} |
|
|
|
m_isEnemyVisible = false; |
|
m_visibleEnemyParts = NONE; |
|
m_lastSawEnemyTimestamp = 0.0f; |
|
m_firstSawEnemyTimestamp = 0.0f; |
|
m_currentEnemyAcquireTimestamp = 0.0f; |
|
m_isLastEnemyDead = true; |
|
m_attacker = NULL; |
|
m_attackedTimestamp = 0.0f; |
|
m_enemyDeathTimestamp = 0.0f; |
|
m_lastVictimID = 0; |
|
m_isAimingAtEnemy = false; |
|
m_fireWeaponTimestamp = 0.0f; |
|
m_equipTimer.Invalidate(); |
|
|
|
m_isFollowing = false; |
|
m_leader = NULL; |
|
m_followTimestamp = 0.0f; |
|
m_allowAutoFollowTime = 0.0f; |
|
|
|
m_enemyQueueIndex = 0; |
|
m_enemyQueueCount = 0; |
|
m_enemyQueueAttendIndex = 0; |
|
m_bomber = NULL; |
|
|
|
m_lookAroundStateTimestamp = 0.0f; |
|
m_inhibitLookAroundTimestamp = 0.0f; |
|
|
|
m_lookPitch = 0.0f; |
|
m_lookPitchVel = 0.0f; |
|
m_lookYaw = 0.0f; |
|
m_lookYawVel = 0.0f; |
|
|
|
m_aimOffsetTimestamp = 0.0f; |
|
m_aimSpreadTimestamp = 0.0f; |
|
m_lookAtSpotState = NOT_LOOKING_AT_SPOT; |
|
|
|
m_spotEncounter = NULL; |
|
m_spotCheckTimestamp = 0.0f; |
|
m_peripheralTimestamp = 0.0f; |
|
|
|
m_avgVelIndex = 0; |
|
m_avgVelCount = 0; |
|
|
|
m_lastOrigin = (pev != NULL) ? pev->origin : Vector(0, 0, 0); |
|
|
|
m_lastRadioCommand = EVENT_INVALID; |
|
m_lastRadioRecievedTimestamp = 0.0f; |
|
m_lastRadioSentTimestamp = 0.0f; |
|
m_radioSubject = NULL; |
|
m_voiceFeedbackEndTimestamp = 0.0f; |
|
|
|
m_hostageEscortCount = 0; |
|
m_hostageEscortCountTimestamp = 0.0f; |
|
|
|
m_noisePosition = Vector(0, 0, 0); |
|
m_noiseTimestamp = 0.0f; |
|
m_noiseCheckTimestamp = 0.0f; |
|
m_isNoiseTravelRangeChecked = false; |
|
|
|
m_stateTimestamp = 0.0f; |
|
m_task = SEEK_AND_DESTROY; |
|
m_taskEntity = NULL; |
|
|
|
m_approachPointCount = 0; |
|
m_approachPointViewPosition = Vector(0, 0, 0); |
|
|
|
m_checkedHidingSpotCount = 0; |
|
m_isJumpCrouching = false; |
|
|
|
StandUp(); |
|
Run(); |
|
m_mustRunTimer.Invalidate(); |
|
m_repathTimer.Invalidate(); |
|
m_pathLadder = NULL; |
|
|
|
m_huntState.ClearHuntArea(); |
|
|
|
// adjust morale - if we died, our morale decreased, |
|
// but if we live, no adjustement (round win/loss also adjusts morale |
|
if (m_diedLastRound) |
|
DecreaseMorale(); |
|
|
|
m_diedLastRound = false; |
|
|
|
// IsRogue() randomly changes this |
|
m_isRogue = false; |
|
|
|
m_surpriseDelay = 0.0f; |
|
m_surpriseTimestamp = 0.0f; |
|
|
|
// even though these are EHANDLEs, they need to be NULL-ed |
|
m_goalEntity = NULL; |
|
m_avoid = NULL; |
|
m_enemy = NULL; |
|
|
|
for (int i = 0; i < MAX_ENEMY_QUEUE; ++i) |
|
{ |
|
m_enemyQueue[i].player = NULL; |
|
m_enemyQueue[i].isReloading = false; |
|
m_enemyQueue[i].isProtectedByShield = false; |
|
} |
|
|
|
// start in idle state |
|
StopAttacking(); |
|
Idle(); |
|
} |
|
|
|
// Called when bot is placed in map, and when bots are reset after a round ends. |
|
// NOTE: For some reason, this can be called twice when a bot is added. |
|
|
|
void CCSBot::SpawnBot() |
|
{ |
|
CCSBotManager *ctrl = TheCSBots(); |
|
|
|
ctrl->ValidateMapData(); |
|
ResetValues(); |
|
|
|
Q_strcpy(m_name, STRING(pev->netname)); |
|
|
|
SetState(&m_huntState); |
|
SetTouch(&CCSBot::BotTouch); |
|
|
|
if (!TheNavAreaList.Count () && !ctrl->IsLearningMap()) |
|
{ |
|
ctrl->SetLearningMapFlag(); |
|
StartLearnProcess(); |
|
} |
|
} |
|
|
|
void CCSBot::RoundRespawn() |
|
{ |
|
// do the normal player spawn process |
|
//CBasePlayer::RoundRespawn(); |
|
// EndVoiceFeedback(); |
|
} |
|
|
|
void CCSBot::Disconnect() |
|
{ |
|
// EndVoiceFeedback(); |
|
|
|
if (m_processMode != PROCESS_NORMAL) |
|
{ |
|
hideProgressMeter(); |
|
} |
|
}
|
|
|