Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
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

#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();
}
}