fixed crash on escaping from bomb on really small maps (de_iceworld ie)
reworked how yb_quota works fixed engine is not notified about bot cvar is beeing changed
This commit is contained in:
parent
8a9ccfd083
commit
db79df8d38
9 changed files with 127 additions and 145 deletions
|
|
@ -636,6 +636,7 @@ struct ExperienceSave
|
||||||
// bot creation tab
|
// bot creation tab
|
||||||
struct CreateQueue
|
struct CreateQueue
|
||||||
{
|
{
|
||||||
|
bool console;
|
||||||
int difficulty;
|
int difficulty;
|
||||||
int team;
|
int team;
|
||||||
int member;
|
int member;
|
||||||
|
|
@ -1203,9 +1204,8 @@ public:
|
||||||
void TryHeadTowardRadioEntity (void);
|
void TryHeadTowardRadioEntity (void);
|
||||||
|
|
||||||
void Kill (void);
|
void Kill (void);
|
||||||
void Kick (void);
|
void Kick (bool keepQuota = false);
|
||||||
void ResetDoubleJumpState (void);
|
void ResetDoubleJumpState (void);
|
||||||
void MoveToVector (const Vector &to);
|
|
||||||
int FindPlantedBomb(void);
|
int FindPlantedBomb(void);
|
||||||
|
|
||||||
bool HasHostage (void);
|
bool HasHostage (void);
|
||||||
|
|
@ -1248,7 +1248,7 @@ private:
|
||||||
edict_t *m_killerEntity; // killer entity for bots
|
edict_t *m_killerEntity; // killer entity for bots
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int CreateBot (const String &name, int difficulty, int personality, int team, int member);
|
int CreateBot (const String &name, int difficulty, int personality, int team, int member, bool isConsoleCmd);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BotManager (void);
|
BotManager (void);
|
||||||
|
|
@ -1280,13 +1280,13 @@ public:
|
||||||
void Free (void);
|
void Free (void);
|
||||||
void Free (int index);
|
void Free (int index);
|
||||||
|
|
||||||
void AddRandom (void) { AddBot ("", -1, -1, -1, -1); }
|
void AddRandom (bool isConsoleCmd = true) { AddBot ("", -1, -1, -1, -1, isConsoleCmd); }
|
||||||
void AddBot (const String &name, int difficulty, int personality, int team, int member);
|
void AddBot (const String &name, int difficulty, int personality, int team, int member, bool isConsoleCmd = true);
|
||||||
void AddBot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member);
|
void AddBot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member, bool isConsoleCmd = true);
|
||||||
void FillServer (int selection, int personality = PERSONALITY_NORMAL, int difficulty = -1, int numToAdd = -1);
|
void FillServer (int selection, int personality = PERSONALITY_NORMAL, int difficulty = -1, int numToAdd = -1);
|
||||||
|
|
||||||
void RemoveAll (bool zeroQuota = true);
|
void RemoveAll (void);
|
||||||
void RemoveRandom (void);
|
void RemoveRandom (bool keepQuota = false);
|
||||||
void RemoveFromTeam (Team team, bool removeAll = false);
|
void RemoveFromTeam (Team team, bool removeAll = false);
|
||||||
void RemoveMenu (edict_t *ent, int selection);
|
void RemoveMenu (edict_t *ent, int selection);
|
||||||
void KillAll (int team = -1);
|
void KillAll (int team = -1);
|
||||||
|
|
|
||||||
|
|
@ -318,7 +318,7 @@ public:
|
||||||
FORCEINLINE int GetInt (void) { return static_cast <int> (m_eptr->value); }
|
FORCEINLINE int GetInt (void) { return static_cast <int> (m_eptr->value); }
|
||||||
FORCEINLINE float GetFloat (void) { return m_eptr->value; }
|
FORCEINLINE float GetFloat (void) { return m_eptr->value; }
|
||||||
FORCEINLINE const char *GetString (void) { return m_eptr->string; }
|
FORCEINLINE const char *GetString (void) { return m_eptr->string; }
|
||||||
FORCEINLINE void SetFloat (float val) { m_eptr->value = val; }
|
FORCEINLINE void SetFloat (float val) { g_engfuncs.pfnCVarSetFloat (m_eptr->name, val); }
|
||||||
FORCEINLINE void SetInt (int val) { SetFloat (static_cast <float> (val)); }
|
FORCEINLINE void SetInt (int val) { SetFloat (static_cast <float> (val)); }
|
||||||
FORCEINLINE void SetString (const char *val) { g_engfuncs.pfnCvar_DirectSet (m_eptr, const_cast <char *> (val)); }
|
FORCEINLINE void SetString (const char *val) { g_engfuncs.pfnCvar_DirectSet (m_eptr, const_cast <char *> (val)); }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ extern bool g_autoWaypoint;
|
||||||
extern bool g_botsCanPause;
|
extern bool g_botsCanPause;
|
||||||
extern bool g_editNoclip;
|
extern bool g_editNoclip;
|
||||||
extern bool g_isMetamod;
|
extern bool g_isMetamod;
|
||||||
extern bool g_sendAudioFinished;
|
|
||||||
extern bool g_isCommencing;
|
extern bool g_isCommencing;
|
||||||
extern bool g_leaderChoosen[2];
|
extern bool g_leaderChoosen[2];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseOfMfc>false</UseOfMfc>
|
<UseOfMfc>false</UseOfMfc>
|
||||||
<PlatformToolset>v140_xp</PlatformToolset>
|
<PlatformToolset>v120_xp</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
|
|
||||||
|
|
@ -984,7 +984,7 @@ void Bot::InstantChatterMessage (int type)
|
||||||
{
|
{
|
||||||
// this function sends instant chatter messages.
|
// this function sends instant chatter messages.
|
||||||
|
|
||||||
if (yb_communication_type.GetInt () != 2 || g_chatterFactory[type].IsEmpty () || (g_gameFlags & GAME_LEGACY) || !g_sendAudioFinished)
|
if (yb_communication_type.GetInt () != 2 || g_chatterFactory[type].IsEmpty () || (g_gameFlags & GAME_LEGACY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_notKilled)
|
if (m_notKilled)
|
||||||
|
|
@ -1009,8 +1009,6 @@ void Bot::InstantChatterMessage (int type)
|
||||||
if (!IsValidPlayer (ent) || IsValidBot (ent) || engine.GetTeam (ent) != m_team)
|
if (!IsValidPlayer (ent) || IsValidBot (ent) || engine.GetTeam (ent) != m_team)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
g_sendAudioFinished = false;
|
|
||||||
|
|
||||||
MESSAGE_BEGIN (MSG_ONE, engine.FindMessageId (NETMSG_SENDAUDIO), NULL, ent); // begin message
|
MESSAGE_BEGIN (MSG_ONE, engine.FindMessageId (NETMSG_SENDAUDIO), NULL, ent); // begin message
|
||||||
WRITE_BYTE (GetIndex ());
|
WRITE_BYTE (GetIndex ());
|
||||||
|
|
||||||
|
|
@ -1021,8 +1019,6 @@ void Bot::InstantChatterMessage (int type)
|
||||||
|
|
||||||
WRITE_SHORT (m_voicePitch);
|
WRITE_SHORT (m_voicePitch);
|
||||||
MESSAGE_END ();
|
MESSAGE_END ();
|
||||||
|
|
||||||
g_sendAudioFinished = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1597,7 +1593,7 @@ void Bot::PurchaseWeapons (void)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BUYSTATE_SECONDARY_WEAPON: // if bot has still some money, buy a better secondary weapon
|
case BUYSTATE_SECONDARY_WEAPON: // if bot has still some money, buy a better secondary weapon
|
||||||
if (isPistolMode || (HasPrimaryWeapon () && (pev->weapons & ((1 << WEAPON_USP) | (1 << WEAPON_GLOCK))) && m_moneyAmount > Random.Long (7500, 9000)))
|
if (false || isPistolMode || (HasPrimaryWeapon () && (pev->weapons & ((1 << WEAPON_USP) | (1 << WEAPON_GLOCK))) && m_moneyAmount > Random.Long (7500, 9000)))
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
@ -2511,7 +2507,9 @@ void Bot::CheckRadioCommands (void)
|
||||||
SelectWeaponByName ("weapon_knife");
|
SelectWeaponByName ("weapon_knife");
|
||||||
|
|
||||||
DeleteSearchNodes ();
|
DeleteSearchNodes ();
|
||||||
MoveToVector (waypoints.GetBombPosition ());
|
|
||||||
|
m_position = waypoints.GetBombPosition ();
|
||||||
|
PushTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, -1, 0.0f, true);
|
||||||
|
|
||||||
RadioMessage (Radio_Affirmative);
|
RadioMessage (Radio_Affirmative);
|
||||||
}
|
}
|
||||||
|
|
@ -2961,9 +2959,45 @@ void Bot::ThinkFrame (void)
|
||||||
engine.IssueBotCommand (GetEntity (), "votemap %d", m_voteMap);
|
engine.IssueBotCommand (GetEntity (), "votemap %d", m_voteMap);
|
||||||
m_voteMap = 0;
|
m_voteMap = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (m_notKilled && m_buyingFinished && !(pev->maxspeed < 10.0f && GetTaskId () != TASK_PLANTBOMB && GetTaskId () != TASK_DEFUSEBOMB) && !yb_freeze_bots.GetBool ())
|
||||||
|
botMovement = true;
|
||||||
|
|
||||||
|
#ifdef XASH_CSDM
|
||||||
|
if (m_notKilled)
|
||||||
|
botMovement = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CheckMessageQueue (); // check for pending messages
|
||||||
|
|
||||||
|
// remove voice icon
|
||||||
|
if (!(g_gameFlags & GAME_LEGACY) && g_lastRadioTime[g_clients[GetIndex () - 1].team2] + Random.Float (0.8f, 2.1f) < engine.Time ())
|
||||||
|
SwitchChatterIcon (false); // hide icon
|
||||||
|
|
||||||
|
if (botMovement)
|
||||||
|
BotAI (); // execute main code
|
||||||
|
|
||||||
|
RunPlayerMovement (); // run the player movement
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bot::PeriodicThink (void)
|
||||||
|
{
|
||||||
|
if (m_timePeriodicUpdate > engine.Time ())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// this function is called from main think function
|
||||||
|
|
||||||
|
m_numFriendsLeft = GetNearbyFriendsNearPosition (pev->origin, 99999.0f);
|
||||||
|
m_numEnemiesLeft = GetNearbyEnemiesNearPosition (pev->origin, 99999.0f);
|
||||||
|
|
||||||
|
if (g_bombPlanted && m_team == CT && (pev->origin - waypoints.GetBombPosition ()).GetLength () < 700 && !IsBombDefusing (waypoints.GetBombPosition ()) && !m_hasProgressBar && GetTaskId () != TASK_ESCAPEFROMBOMB)
|
||||||
|
ResetTasks ();
|
||||||
|
|
||||||
|
CheckSpawnTimeConditions ();
|
||||||
|
|
||||||
extern ConVar yb_chat;
|
extern ConVar yb_chat;
|
||||||
|
|
||||||
if (yb_chat.GetBool () && !RepliesToPlayer () && m_lastChatTime + 10.0 < engine.Time () && g_lastChatTime + 5.0f < engine.Time ()) // bot chatting turned on?
|
if (m_notKilled && yb_chat.GetBool () && m_lastChatTime + 10.0 < engine.Time () && g_lastChatTime + 5.0f < engine.Time () && !RepliesToPlayer ()) // bot chatting turned on?
|
||||||
{
|
{
|
||||||
// say a text every now and then
|
// say a text every now and then
|
||||||
if (Random.Long (1, 1500) < 2)
|
if (Random.Long (1, 1500) < 2)
|
||||||
|
|
@ -2995,41 +3029,6 @@ void Bot::ThinkFrame (void)
|
||||||
m_sayTextBuffer.lastUsedSentences.RemoveAll ();
|
m_sayTextBuffer.lastUsedSentences.RemoveAll ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (m_notKilled && m_buyingFinished && !(pev->maxspeed < 10.0f && GetTaskId () != TASK_PLANTBOMB && GetTaskId () != TASK_DEFUSEBOMB) && !yb_freeze_bots.GetBool ())
|
|
||||||
botMovement = true;
|
|
||||||
|
|
||||||
#ifdef XASH_CSDM
|
|
||||||
if (m_notKilled)
|
|
||||||
botMovement = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CheckMessageQueue (); // check for pending messages
|
|
||||||
|
|
||||||
// remove voice icon
|
|
||||||
if (g_lastRadioTime[g_clients[engine.IndexOfEntity (GetEntity ()) - 1].team2] + Random.Float (0.8f, 2.1f) < engine.Time ())
|
|
||||||
SwitchChatterIcon (false); // hide icon
|
|
||||||
|
|
||||||
if (botMovement)
|
|
||||||
BotAI (); // execute main code
|
|
||||||
|
|
||||||
RunPlayerMovement (); // run the player movement
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bot::PeriodicThink (void)
|
|
||||||
{
|
|
||||||
if (m_timePeriodicUpdate > engine.Time ())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// this function is called from main think function
|
|
||||||
|
|
||||||
m_numFriendsLeft = GetNearbyFriendsNearPosition (pev->origin, 99999.0f);
|
|
||||||
m_numEnemiesLeft = GetNearbyEnemiesNearPosition (pev->origin, 99999.0f);
|
|
||||||
|
|
||||||
if (g_bombPlanted && m_team == CT && (pev->origin - waypoints.GetBombPosition ()).GetLength () < 700 && !IsBombDefusing (waypoints.GetBombPosition ()) && !m_hasProgressBar && GetTaskId () != TASK_ESCAPEFROMBOMB)
|
|
||||||
ResetTasks ();
|
|
||||||
|
|
||||||
CheckSpawnTimeConditions ();
|
|
||||||
|
|
||||||
// clear enemy far away
|
// clear enemy far away
|
||||||
if (!m_lastEnemyOrigin.IsZero () && !engine.IsNullEntity (m_lastEnemy) && (pev->origin - m_lastEnemyOrigin).GetLength () >= 1600.0f)
|
if (!m_lastEnemyOrigin.IsZero () && !engine.IsNullEntity (m_lastEnemy) && (pev->origin - m_lastEnemyOrigin).GetLength () >= 1600.0f)
|
||||||
|
|
@ -4374,6 +4373,15 @@ void Bot::RunTask_EscapeFromBomb (void)
|
||||||
if (lastSelectedGoal < 0)
|
if (lastSelectedGoal < 0)
|
||||||
lastSelectedGoal = waypoints.FindFarest (pev->origin, safeRadius);
|
lastSelectedGoal = waypoints.FindFarest (pev->origin, safeRadius);
|
||||||
|
|
||||||
|
// still no luck?
|
||||||
|
if (lastSelectedGoal < 0)
|
||||||
|
{
|
||||||
|
TaskComplete (); // we're done
|
||||||
|
|
||||||
|
// we have no destination point, so just sit down and camp
|
||||||
|
PushTask (TASK_CAMP, TASKPRI_CAMP, -1, engine.Time () + 10.0f, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_prevGoalIndex = lastSelectedGoal;
|
m_prevGoalIndex = lastSelectedGoal;
|
||||||
GetTask ()->data = lastSelectedGoal;
|
GetTask ()->data = lastSelectedGoal;
|
||||||
|
|
||||||
|
|
@ -4984,7 +4992,7 @@ void Bot::DisplayDebugOverlay (void)
|
||||||
{
|
{
|
||||||
bool displayDebugOverlay = false;
|
bool displayDebugOverlay = false;
|
||||||
|
|
||||||
if (g_hostEntity->v.iuser2 == engine.IndexOfEntity (GetEntity ()))
|
if (g_hostEntity->v.iuser2 == GetIndex ())
|
||||||
displayDebugOverlay = true;
|
displayDebugOverlay = true;
|
||||||
|
|
||||||
if (!displayDebugOverlay && yb_debug.GetInt () >= 2)
|
if (!displayDebugOverlay && yb_debug.GetInt () >= 2)
|
||||||
|
|
@ -5590,7 +5598,7 @@ void Bot::DebugMsg (const char *format, ...)
|
||||||
|
|
||||||
bool playMessage = false;
|
bool playMessage = false;
|
||||||
|
|
||||||
if (level == 3 && !engine.IsNullEntity (g_hostEntity) && g_hostEntity->v.iuser2 == engine.IndexOfEntity (GetEntity ()))
|
if (level == 3 && !engine.IsNullEntity (g_hostEntity) && g_hostEntity->v.iuser2 == GetIndex ())
|
||||||
playMessage = true;
|
playMessage = true;
|
||||||
else if (level != 3)
|
else if (level != 3)
|
||||||
playMessage = true;
|
playMessage = true;
|
||||||
|
|
@ -5731,14 +5739,6 @@ Vector Bot::CheckBombAudible (void)
|
||||||
return Vector::GetZero ();
|
return Vector::GetZero ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::MoveToVector (const Vector &to)
|
|
||||||
{
|
|
||||||
if (to.IsZero ())
|
|
||||||
return;
|
|
||||||
|
|
||||||
FindPath (m_currentWaypointIndex, waypoints.FindNearest (to), SEARCH_PATH_FASTEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte Bot::ThrottledMsec (void)
|
byte Bot::ThrottledMsec (void)
|
||||||
{
|
{
|
||||||
// estimate msec to use for this command based on time passed from the previous command
|
// estimate msec to use for this command based on time passed from the previous command
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,11 @@
|
||||||
|
|
||||||
#include <core.h>
|
#include <core.h>
|
||||||
|
|
||||||
// forward for super-globals
|
|
||||||
//NetworkMsg netmsg;
|
|
||||||
//Localizer locale;
|
|
||||||
//Waypoint waypoints;
|
|
||||||
//BotManager bots;
|
|
||||||
//Engine engine;
|
|
||||||
|
|
||||||
bool g_canSayBombPlanted = true;
|
bool g_canSayBombPlanted = true;
|
||||||
bool g_isMetamod = false;
|
bool g_isMetamod = false;
|
||||||
bool g_radioInsteadVoice = false;
|
bool g_radioInsteadVoice = false;
|
||||||
bool g_roundEnded = true;
|
bool g_roundEnded = true;
|
||||||
bool g_botsCanPause = false;
|
bool g_botsCanPause = false;
|
||||||
bool g_sendAudioFinished = true;
|
|
||||||
bool g_bombPlanted = false;
|
bool g_bombPlanted = false;
|
||||||
bool g_bombSayString = false;
|
bool g_bombSayString = false;
|
||||||
bool g_isCommencing = false;
|
bool g_isCommencing = false;
|
||||||
|
|
|
||||||
|
|
@ -1103,7 +1103,7 @@ void UpdateClientData (const struct edict_s *ent, int sendweapons, struct client
|
||||||
{
|
{
|
||||||
extern ConVar yb_latency_display;
|
extern ConVar yb_latency_display;
|
||||||
|
|
||||||
if (yb_latency_display.GetInt () == 2)
|
if (!(g_gameFlags & GAME_LEGACY) && yb_latency_display.GetInt () == 2)
|
||||||
bots.SendPingDataOffsets (const_cast <edict_t *> (ent));
|
bots.SendPingDataOffsets (const_cast <edict_t *> (ent));
|
||||||
|
|
||||||
if (g_isMetamod)
|
if (g_isMetamod)
|
||||||
|
|
@ -2452,7 +2452,6 @@ void pfnMessageBegin (int msgDest, int msgType, const float *origin, edict_t *ed
|
||||||
// is this message for a bot?
|
// is this message for a bot?
|
||||||
if (index != -1 && !(ed->v.flags & FL_DORMANT))
|
if (index != -1 && !(ed->v.flags & FL_DORMANT))
|
||||||
{
|
{
|
||||||
engine.ResetMessageCapture ();
|
|
||||||
engine.SetOngoingMessageReceiver (index);
|
engine.SetOngoingMessageReceiver (index);
|
||||||
|
|
||||||
// message handling is done in usermsg.cpp
|
// message handling is done in usermsg.cpp
|
||||||
|
|
@ -2471,8 +2470,6 @@ void pfnMessageBegin (int msgDest, int msgType, const float *origin, edict_t *ed
|
||||||
}
|
}
|
||||||
else if (msgDest == MSG_ALL)
|
else if (msgDest == MSG_ALL)
|
||||||
{
|
{
|
||||||
engine.ResetMessageCapture ();
|
|
||||||
|
|
||||||
engine.TryCaptureMessage (msgType, NETMSG_SCOREINFO);
|
engine.TryCaptureMessage (msgType, NETMSG_SCOREINFO);
|
||||||
engine.TryCaptureMessage (msgType, NETMSG_DEATH);
|
engine.TryCaptureMessage (msgType, NETMSG_DEATH);
|
||||||
engine.TryCaptureMessage (msgType, NETMSG_TEXTMSG);
|
engine.TryCaptureMessage (msgType, NETMSG_TEXTMSG);
|
||||||
|
|
@ -2786,8 +2783,10 @@ void pfnAlertMessage (ALERT_TYPE alertType, char *format, ...)
|
||||||
|
|
||||||
if (bot != NULL && bot->m_team == TERRORIST && bot->m_notKilled)
|
if (bot != NULL && bot->m_team == TERRORIST && bot->m_notKilled)
|
||||||
{
|
{
|
||||||
bot->ResetTasks ();
|
bot->DeleteSearchNodes ();
|
||||||
bot->MoveToVector (waypoints.GetBombPosition ());
|
|
||||||
|
bot->m_position = waypoints.GetBombPosition ();
|
||||||
|
bot->PushTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, -1, 0.0f, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#include <core.h>
|
#include <core.h>
|
||||||
|
|
||||||
ConVar yb_autovacate ("yb_autovacate", "0");
|
ConVar yb_autovacate ("yb_autovacate", "0");
|
||||||
ConVar yb_autovacate_smart_kick ("yb_autovacate_smart_kick", "1");
|
ConVar yb_autovacate_smart_kick ("yb_autovacate_smart_kick", "0");
|
||||||
|
|
||||||
ConVar yb_quota ("yb_quota", "0", VT_NORMAL);
|
ConVar yb_quota ("yb_quota", "0", VT_NORMAL);
|
||||||
ConVar yb_quota_mode ("yb_quota_mode", "normal");
|
ConVar yb_quota_mode ("yb_quota_mode", "normal");
|
||||||
|
|
@ -108,12 +108,11 @@ void BotManager::CallGameEntity (entvars_t *vars)
|
||||||
player (vars);
|
player (vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
int BotManager::CreateBot (const String &name, int difficulty, int personality, int team, int member)
|
int BotManager::CreateBot (const String &name, int difficulty, int personality, int team, int member, bool isConsoleCmd)
|
||||||
{
|
{
|
||||||
// this function completely prepares bot entity (edict) for creation, creates team, difficulty, sets name etc, and
|
// this function completely prepares bot entity (edict) for creation, creates team, difficulty, sets name etc, and
|
||||||
// then sends result to bot constructor
|
// then sends result to bot constructor
|
||||||
|
|
||||||
|
|
||||||
edict_t *bot = NULL;
|
edict_t *bot = NULL;
|
||||||
char outputName[33];
|
char outputName[33];
|
||||||
|
|
||||||
|
|
@ -195,8 +194,9 @@ int BotManager::CreateBot (const String &name, int difficulty, int personality,
|
||||||
if (!IsNullString (prefixedName))
|
if (!IsNullString (prefixedName))
|
||||||
strcpy (outputName, prefixedName);
|
strcpy (outputName, prefixedName);
|
||||||
}
|
}
|
||||||
|
bot = g_engfuncs.pfnCreateFakeClient (outputName);
|
||||||
|
|
||||||
if (engine.IsNullEntity ((bot = (*g_engfuncs.pfnCreateFakeClient) (outputName))))
|
if (engine.IsNullEntity (bot))
|
||||||
{
|
{
|
||||||
engine.CenterPrintf ("Maximum players reached (%d/%d). Unable to create Bot.", engine.MaxClients (), engine.MaxClients ());
|
engine.CenterPrintf ("Maximum players reached (%d/%d). Unable to create Bot.", engine.MaxClients (), engine.MaxClients ());
|
||||||
return 2;
|
return 2;
|
||||||
|
|
@ -213,6 +213,9 @@ int BotManager::CreateBot (const String &name, int difficulty, int personality,
|
||||||
|
|
||||||
engine.Printf ("Connecting Bot...");
|
engine.Printf ("Connecting Bot...");
|
||||||
|
|
||||||
|
if (isConsoleCmd)
|
||||||
|
yb_quota.SetInt (yb_quota.GetInt () + 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -296,7 +299,7 @@ void BotManager::PeriodicThink (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotManager::AddBot (const String &name, int difficulty, int personality, int team, int member)
|
void BotManager::AddBot (const String &name, int difficulty, int personality, int team, int member, bool isConsoleCmd)
|
||||||
{
|
{
|
||||||
// this function putting bot creation process to queue to prevent engine crashes
|
// this function putting bot creation process to queue to prevent engine crashes
|
||||||
|
|
||||||
|
|
@ -308,12 +311,13 @@ void BotManager::AddBot (const String &name, int difficulty, int personality, in
|
||||||
bot.personality = personality;
|
bot.personality = personality;
|
||||||
bot.team = team;
|
bot.team = team;
|
||||||
bot.member = member;
|
bot.member = member;
|
||||||
|
bot.console = isConsoleCmd;
|
||||||
|
|
||||||
// put to queue
|
// put to queue
|
||||||
m_creationTab.Push (bot);
|
m_creationTab.Push (bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotManager::AddBot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member)
|
void BotManager::AddBot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member, bool isConsoleCmd)
|
||||||
{
|
{
|
||||||
// this function is same as the function above, but accept as parameters string instead of integers
|
// this function is same as the function above, but accept as parameters string instead of integers
|
||||||
|
|
||||||
|
|
@ -380,8 +384,9 @@ void BotManager::VerifyPlayersHasJoinedTeam (int &desiredCount)
|
||||||
{
|
{
|
||||||
Client &cl = g_clients[i];
|
Client &cl = g_clients[i];
|
||||||
|
|
||||||
if ((cl.flags & CF_USED) && cl.team != SPECTATOR && !IsValidBot (cl.ent))
|
if (!(cl.flags & CF_USED) || cl.team == SPECTATOR || IsValidBot (cl.ent))
|
||||||
{
|
continue;
|
||||||
|
|
||||||
FOR_EACH_AE (m_trackedPlayers, it)
|
FOR_EACH_AE (m_trackedPlayers, it)
|
||||||
{
|
{
|
||||||
if (cl.ent != m_trackedPlayers[it])
|
if (cl.ent != m_trackedPlayers[it])
|
||||||
|
|
@ -395,7 +400,6 @@ void BotManager::VerifyPlayersHasJoinedTeam (int &desiredCount)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotManager::MaintainBotQuota (void)
|
void BotManager::MaintainBotQuota (void)
|
||||||
|
|
@ -410,7 +414,7 @@ void BotManager::MaintainBotQuota (void)
|
||||||
if (!m_creationTab.IsEmpty () && m_maintainTime < engine.Time ())
|
if (!m_creationTab.IsEmpty () && m_maintainTime < engine.Time ())
|
||||||
{
|
{
|
||||||
CreateQueue last = m_creationTab.Pop ();
|
CreateQueue last = m_creationTab.Pop ();
|
||||||
int resultOfCall = CreateBot (last.name, last.difficulty, last.personality, last.team, last.member);
|
int resultOfCall = CreateBot (last.name, last.difficulty, last.personality, last.team, last.member, last.console);
|
||||||
|
|
||||||
// check the result of creation
|
// check the result of creation
|
||||||
if (resultOfCall == 0)
|
if (resultOfCall == 0)
|
||||||
|
|
@ -429,15 +433,20 @@ void BotManager::MaintainBotQuota (void)
|
||||||
// now keep bot number up to date
|
// now keep bot number up to date
|
||||||
if (m_quotaMaintainTime < engine.Time ())
|
if (m_quotaMaintainTime < engine.Time ())
|
||||||
{
|
{
|
||||||
// don't allow that quota is below zero
|
// keep the quota number in valid ranges
|
||||||
|
{
|
||||||
if (yb_quota.GetInt () < 0)
|
if (yb_quota.GetInt () < 0)
|
||||||
yb_quota.SetInt (0);
|
yb_quota.SetInt (0);
|
||||||
|
|
||||||
|
if (yb_quota.GetInt () > engine.MaxClients ())
|
||||||
|
yb_quota.SetInt (engine.MaxClients ());
|
||||||
|
}
|
||||||
|
|
||||||
int numBots = GetBotsNum ();
|
int numBots = GetBotsNum ();
|
||||||
int numHumans = GetHumansJoinedTeam ();
|
int numHumans = yb_autovacate_smart_kick.GetBool () ? GetHumansNum () : GetHumansJoinedTeam ();
|
||||||
int desiredCount = yb_quota.GetInt ();
|
int desiredCount = yb_quota.GetInt ();
|
||||||
|
|
||||||
if (yb_join_after_player.GetInt () > 0 && !numHumans)
|
if (yb_join_after_player.GetBool () && !numHumans)
|
||||||
desiredCount = 0;
|
desiredCount = 0;
|
||||||
|
|
||||||
// quota mode
|
// quota mode
|
||||||
|
|
@ -448,20 +457,17 @@ void BotManager::MaintainBotQuota (void)
|
||||||
else if (mode == 'm') // match
|
else if (mode == 'm') // match
|
||||||
desiredCount = max (0, yb_quota.GetInt () * numHumans);
|
desiredCount = max (0, yb_quota.GetInt () * numHumans);
|
||||||
|
|
||||||
if (yb_autovacate.GetBool ())
|
desiredCount = min (desiredCount, engine.MaxClients () - (numHumans + (yb_autovacate.GetBool () ? 1 : 0)));
|
||||||
desiredCount = min (desiredCount, engine.MaxClients () - (numHumans + 1));
|
|
||||||
else
|
|
||||||
desiredCount = min (desiredCount, engine.MaxClients () - numHumans);
|
|
||||||
|
|
||||||
if (yb_autovacate_smart_kick.GetBool () && numBots > 1 && desiredCount > 1)
|
if (yb_autovacate_smart_kick.GetBool () && numBots > 1 && desiredCount > 1)
|
||||||
VerifyPlayersHasJoinedTeam (desiredCount);
|
VerifyPlayersHasJoinedTeam (desiredCount);
|
||||||
|
|
||||||
if (desiredCount > numBots)
|
if (desiredCount > numBots)
|
||||||
AddRandom ();
|
AddRandom (false);
|
||||||
else if (desiredCount < numBots)
|
else if (desiredCount < numBots)
|
||||||
RemoveRandom ();
|
RemoveRandom (true);
|
||||||
|
|
||||||
m_quotaMaintainTime = engine.Time () + 0.90f;
|
m_quotaMaintainTime = engine.Time () + 0.40f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -506,30 +512,17 @@ void BotManager::FillServer (int selection, int personality, int difficulty, int
|
||||||
for (int i = 0; i <= toAdd; i++)
|
for (int i = 0; i <= toAdd; i++)
|
||||||
AddBot ("", difficulty, personality, selection, -1);
|
AddBot ("", difficulty, personality, selection, -1);
|
||||||
|
|
||||||
yb_quota.SetInt (toAdd);
|
|
||||||
engine.CenterPrintf ("Fill Server with %s bots...", &teamDesc[selection][0]);
|
engine.CenterPrintf ("Fill Server with %s bots...", &teamDesc[selection][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotManager::RemoveAll (bool zeroQuota)
|
void BotManager::RemoveAll (void)
|
||||||
{
|
{
|
||||||
// this function drops all bot clients from server (this function removes only yapb's)`q
|
// this function drops all bot clients from server (this function removes only yapb's)`q
|
||||||
|
|
||||||
if (zeroQuota)
|
|
||||||
engine.CenterPrintf ("Bots are removed from server.");
|
engine.CenterPrintf ("Bots are removed from server.");
|
||||||
|
|
||||||
for (int i = 0; i < engine.MaxClients (); i++)
|
|
||||||
{
|
|
||||||
if (m_bots[i] != NULL) // is this slot used?
|
|
||||||
m_bots[i]->Kick ();
|
|
||||||
}
|
|
||||||
m_creationTab.RemoveAll ();
|
m_creationTab.RemoveAll ();
|
||||||
|
|
||||||
// reset cvars
|
|
||||||
if (zeroQuota)
|
|
||||||
{
|
|
||||||
yb_quota.SetInt (0);
|
yb_quota.SetInt (0);
|
||||||
yb_autovacate.SetInt (0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotManager::RemoveFromTeam (Team team, bool removeAll)
|
void BotManager::RemoveFromTeam (Team team, bool removeAll)
|
||||||
|
|
@ -625,19 +618,18 @@ void BotManager::KillAll (int team)
|
||||||
engine.CenterPrintf ("All Bots died !");
|
engine.CenterPrintf ("All Bots died !");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotManager::RemoveRandom (void)
|
void BotManager::RemoveRandom (bool keepQuota)
|
||||||
{
|
{
|
||||||
// this function removes random bot from server (only yapb's)
|
// this function removes random bot from server (only yapb's)
|
||||||
|
|
||||||
bool deadBotFound = false;
|
bool deadBotFound = false;
|
||||||
|
|
||||||
|
|
||||||
// first try to kick the bot that is currently dead
|
// first try to kick the bot that is currently dead
|
||||||
for (int i = 0; i < engine.MaxClients (); i++)
|
for (int i = 0; i < engine.MaxClients (); i++)
|
||||||
{
|
{
|
||||||
if (m_bots[i] != NULL && !m_bots[i]->m_notKilled) // is this slot used?
|
if (m_bots[i] != NULL && !m_bots[i]->m_notKilled) // is this slot used?
|
||||||
{
|
{
|
||||||
m_bots[i]->Kick ();
|
m_bots[i]->Kick (keepQuota);
|
||||||
deadBotFound = true;
|
deadBotFound = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -666,7 +658,7 @@ void BotManager::RemoveRandom (void)
|
||||||
// if found some bots
|
// if found some bots
|
||||||
if (index != 0)
|
if (index != 0)
|
||||||
{
|
{
|
||||||
m_bots[index]->Kick ();
|
m_bots[index]->Kick (keepQuota);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -675,7 +667,7 @@ void BotManager::RemoveRandom (void)
|
||||||
{
|
{
|
||||||
if (m_bots[i] != NULL) // is this slot used?
|
if (m_bots[i] != NULL) // is this slot used?
|
||||||
{
|
{
|
||||||
m_bots[i]->Kick ();
|
m_bots[i]->Kick (keepQuota);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -887,6 +879,7 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member, c
|
||||||
engine.IssueCmd ("kick \"%s\"", STRING (bot->v.netname)); // kick the bot player if the server refused it
|
engine.IssueCmd ("kick \"%s\"", STRING (bot->v.netname)); // kick the bot player if the server refused it
|
||||||
|
|
||||||
bot->v.flags |= FL_KILLME;
|
bot->v.flags |= FL_KILLME;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MDLL_ClientPutInServer (bot);
|
MDLL_ClientPutInServer (bot);
|
||||||
|
|
@ -957,12 +950,6 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member, c
|
||||||
m_wantedTeam = team;
|
m_wantedTeam = team;
|
||||||
m_wantedClass = member;
|
m_wantedClass = member;
|
||||||
|
|
||||||
int newBotsNum = bots.GetBotsNum () + 1;
|
|
||||||
|
|
||||||
// keep quota number up to date
|
|
||||||
if (newBotsNum < engine.MaxClients () && newBotsNum > yb_quota.GetInt ())
|
|
||||||
yb_quota.SetInt (newBotsNum);
|
|
||||||
|
|
||||||
NewRound ();
|
NewRound ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1246,12 +1233,7 @@ void Bot::NewRound (void)
|
||||||
if (Random.Long (0, 100) < 50)
|
if (Random.Long (0, 100) < 50)
|
||||||
ChatterMessage (Chatter_NewRound);
|
ChatterMessage (Chatter_NewRound);
|
||||||
|
|
||||||
const float interval = (1.0f / 30.0f) * Random.Float (0.95f, 1.05f);
|
m_thinkInterval = (g_gameFlags & GAME_LEGACY) ? 0.0f : (1.0f / 30.0f) * Random.Float (0.95f, 1.05f);
|
||||||
|
|
||||||
if (g_gameFlags & GAME_LEGACY)
|
|
||||||
m_thinkInterval = 0.0f;
|
|
||||||
else
|
|
||||||
m_thinkInterval = interval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::Kill (void)
|
void Bot::Kill (void)
|
||||||
|
|
@ -1262,18 +1244,16 @@ void Bot::Kill (void)
|
||||||
bots.TouchWithKillerEntity (this);
|
bots.TouchWithKillerEntity (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::Kick (void)
|
void Bot::Kick (bool keepQuota)
|
||||||
{
|
{
|
||||||
// this function kick off one bot from the server.
|
// this function kick off one bot from the server.
|
||||||
|
|
||||||
engine.IssueCmd ("kick \"%s\"", STRING (pev->netname));
|
engine.IssueCmd ("kick \"%s\"", STRING (pev->netname));
|
||||||
engine.CenterPrintf ("Bot '%s' kicked", STRING (pev->netname));
|
engine.CenterPrintf ("Bot '%s' kicked", STRING (pev->netname));
|
||||||
|
|
||||||
int newBotsNum = bots.GetBotsNum () - 1;
|
|
||||||
|
|
||||||
// keep quota number up to date
|
// keep quota number up to date
|
||||||
if (newBotsNum < engine.MaxClients () && newBotsNum < yb_quota.GetInt ())
|
if (!keepQuota)
|
||||||
yb_quota.SetInt (newBotsNum);
|
yb_quota.SetInt (Clamp <int> (yb_quota.GetInt () - 1, 0, yb_quota.GetInt ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::StartGame (void)
|
void Bot::StartGame (void)
|
||||||
|
|
|
||||||
|
|
@ -1264,6 +1264,18 @@ void Bot::FindShortestPath (int srcIndex, int destIndex)
|
||||||
{
|
{
|
||||||
// this function finds the shortest path from source index to destination index
|
// this function finds the shortest path from source index to destination index
|
||||||
|
|
||||||
|
if (srcIndex > g_numWaypoints - 1 || srcIndex < 0)
|
||||||
|
{
|
||||||
|
AddLogEntry (true, LL_ERROR, "Pathfinder source path index not valid (%d)", srcIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destIndex > g_numWaypoints - 1 || destIndex < 0)
|
||||||
|
{
|
||||||
|
AddLogEntry (true, LL_ERROR, "Pathfinder destination path index not valid (%d)", destIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DeleteSearchNodes ();
|
DeleteSearchNodes ();
|
||||||
|
|
||||||
m_chosenGoalIndex = srcIndex;
|
m_chosenGoalIndex = srcIndex;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue