mirror of
https://github.com/s1lentq/ReGameDLL_CS.git
synced 2024-12-27 23:25:41 +03:00
363 lines
11 KiB
C++
363 lines
11 KiB
C++
/*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* In addition, as a special exception, the author gives permission to
|
|
* link the code of this program with the Half-Life Game Engine ("HL
|
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
* respects for all of the code used other than the HL Engine and MODs
|
|
* from Valve. If you modify this file, you may extend this exception
|
|
* to your version of the file, but you are not obligated to do so. If
|
|
* you do not wish to do so, delete this exception statement from your
|
|
* version.
|
|
*
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
|
|
cvar_t cv_bot_traceview = { "bot_traceview", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_stop = { "bot_stop", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_show_nav = { "bot_show_nav", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_show_danger = { "bot_show_danger", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_nav_edit = { "bot_nav_edit", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_nav_zdraw = { "bot_nav_zdraw", "4", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_walk = { "bot_walk", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_difficulty = { "bot_difficulty", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_debug = { "bot_debug", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_quicksave = { "bot_quicksave", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_quota = { "bot_quota", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_prefix = { "bot_prefix", "", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_rogues = { "bot_allow_rogues", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_pistols = { "bot_allow_pistols", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_shotguns = { "bot_allow_shotguns", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_sub_machine_guns = { "bot_allow_sub_machine_guns", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_rifles = { "bot_allow_rifles", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_machine_guns = { "bot_allow_machine_guns", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_grenades = { "bot_allow_grenades", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_snipers = { "bot_allow_snipers", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_allow_shield = { "bot_allow_shield", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_join_team = { "bot_join_team", "any", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_join_after_player = { "bot_join_after_player", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_auto_vacate = { "bot_auto_vacate", "1", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_zombie = { "bot_zombie", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_defer_to_human = { "bot_defer_to_human", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_chatter = { "bot_chatter", "normal", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_profile_db = { "bot_profile_db", "BotProfile.db", FCVAR_SERVER, 0.0f, nullptr };
|
|
|
|
#ifdef REGAMEDLL_ADD
|
|
cvar_t cv_bot_deathmatch = { "bot_deathmatch", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_quota_mode = { "bot_quota_mode", "normal", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_join_delay = { "bot_join_delay", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
cvar_t cv_bot_freeze = { "bot_freeze", "0", 0, 0.0f, nullptr };
|
|
cvar_t cv_bot_mimic = { "bot_mimic", "0", 0, 0.0f, nullptr };
|
|
cvar_t cv_bot_mimic_yaw_offset = { "bot_mimic_yaw_offset", "0", 0, 0.0f, nullptr };
|
|
#else
|
|
// Migrated to bot_quota_mode, use "match"
|
|
cvar_t cv_bot_quota_match = { "bot_quota_match", "0", FCVAR_SERVER, 0.0f, nullptr };
|
|
#endif
|
|
|
|
void InstallBotControl()
|
|
{
|
|
if (TheBots)
|
|
{
|
|
delete TheBots;
|
|
}
|
|
|
|
TheBots = new CCSBotManager;
|
|
}
|
|
|
|
// Engine callback for custom server commands
|
|
void Bot_ServerCommand()
|
|
{
|
|
if (TheBots)
|
|
{
|
|
const char *pcmd = CMD_ARGV(0);
|
|
TheBots->ServerCommand(pcmd);
|
|
}
|
|
}
|
|
|
|
void Bot_RegisterCVars()
|
|
{
|
|
if (!AreBotsAllowed())
|
|
return;
|
|
|
|
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);
|
|
|
|
#ifndef REGAMEDLL_ADD
|
|
CVAR_REGISTER(&cv_bot_quota_match);
|
|
#endif
|
|
|
|
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);
|
|
|
|
#ifdef REGAMEDLL_ADD
|
|
CVAR_REGISTER(&cv_bot_deathmatch);
|
|
CVAR_REGISTER(&cv_bot_quota_mode);
|
|
CVAR_REGISTER(&cv_bot_join_delay);
|
|
CVAR_REGISTER(&cv_bot_freeze);
|
|
CVAR_REGISTER(&cv_bot_mimic);
|
|
CVAR_REGISTER(&cv_bot_mimic_yaw_offset);
|
|
#endif
|
|
|
|
}
|
|
|
|
// Constructor
|
|
CCSBot::CCSBot() : m_gameState(this), m_chatter(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 = nullptr;
|
|
m_currentNode = nullptr;
|
|
|
|
// 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 = nullptr;
|
|
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 = nullptr;
|
|
m_lastKnownArea = nullptr;
|
|
|
|
m_avoidFriendTimer.Invalidate();
|
|
m_isFriendInTheWay = false;
|
|
m_isWaitingBehindFriend = false;
|
|
|
|
m_disposition = ENGAGE_AND_INVESTIGATE;
|
|
|
|
m_enemy = nullptr;
|
|
|
|
m_isWaitingToTossGrenade = false;
|
|
m_wasSafe = true;
|
|
|
|
m_nearbyEnemyCount = 0;
|
|
m_enemyPlace = 0;
|
|
m_nearbyFriendCount = 0;
|
|
m_closestVisibleFriend = nullptr;
|
|
m_closestVisibleHumanFriend = nullptr;
|
|
|
|
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 = nullptr;
|
|
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 = nullptr;
|
|
m_followTimestamp = 0.0f;
|
|
m_allowAutoFollowTime = 0.0f;
|
|
|
|
m_enemyQueueIndex = 0;
|
|
m_enemyQueueCount = 0;
|
|
m_enemyQueueAttendIndex = 0;
|
|
m_bomber = nullptr;
|
|
|
|
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 = nullptr;
|
|
m_spotCheckTimestamp = 0.0f;
|
|
m_peripheralTimestamp = 0.0f;
|
|
|
|
m_avgVelIndex = 0;
|
|
m_avgVelCount = 0;
|
|
|
|
m_lastOrigin = pev ? pev->origin : Vector(0, 0, 0);
|
|
|
|
m_lastRadioCommand = EVENT_INVALID;
|
|
m_lastRadioRecievedTimestamp = 0.0f;
|
|
m_lastRadioSentTimestamp = 0.0f;
|
|
m_radioSubject = nullptr;
|
|
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 = nullptr;
|
|
|
|
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 = nullptr;
|
|
|
|
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 = nullptr;
|
|
m_avoid = nullptr;
|
|
m_enemy = nullptr;
|
|
|
|
#ifdef REGAMEDLL_FIXES
|
|
for (int i = 0; i < MAX_ENEMY_QUEUE; i++)
|
|
{
|
|
m_enemyQueue[i].player = nullptr;
|
|
m_enemyQueue[i].isReloading = false;
|
|
m_enemyQueue[i].isProtectedByShield = false;
|
|
}
|
|
#endif
|
|
|
|
// 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()
|
|
{
|
|
TheCSBots()->ValidateMapData();
|
|
ResetValues();
|
|
|
|
Q_strcpy(m_name, STRING(pev->netname));
|
|
|
|
SetState(&m_buyState);
|
|
SetTouch(&CCSBot::BotTouch);
|
|
|
|
if (TheNavAreaList.empty() && !TheCSBots()->IsLearningMap())
|
|
{
|
|
TheCSBots()->SetLearningMapFlag();
|
|
StartLearnProcess();
|
|
}
|
|
}
|
|
|
|
void CCSBot::RoundRespawn()
|
|
{
|
|
// do the normal player spawn process
|
|
CBasePlayer::RoundRespawn();
|
|
EndVoiceFeedback();
|
|
}
|
|
|
|
void CCSBot::Disconnect()
|
|
{
|
|
EndVoiceFeedback();
|
|
|
|
if (m_processMode != PROCESS_NORMAL)
|
|
{
|
|
hideProgressMeter();
|
|
}
|
|
}
|