fixed crashes on door open on xash3d

workaround bug with svc_bad after adding bots
reworked a little how bot menus works
some more source cleanup
This commit is contained in:
jeefo 2016-09-13 19:09:20 +03:00
commit 0f97db33db
11 changed files with 304 additions and 257 deletions

View file

@ -66,6 +66,34 @@ enum GameFlags
GAME_METAMOD = (1 << 6) GAME_METAMOD = (1 << 6)
}; };
// bot menu ids
enum MenuId
{
BOT_MENU_IVALID = -1,
BOT_MENU_MAIN,
BOT_MENU_FEATURES,
BOT_MENU_CONTROL,
BOT_MENU_WEAPON_MODE,
BOT_MENU_PERSONALITY,
BOT_MENU_DIFFICULTY,
BOT_MENU_TEAM_SELECT,
BOT_MENU_TERRORIST_SELECT,
BOT_MENU_CT_SELECT,
BOT_MENU_COMMANDS,
BOT_MENU_WAYPOINT_MAIN_PAGE1,
BOT_MENU_WAYPOINT_MAIN_PAGE2,
BOT_MENU_WAYPOINT_RADIUS,
BOT_MENU_WAYPOINT_TYPE,
BOT_MENU_WAYPOINT_FLAG,
BOT_MENU_WAYPOINT_AUTOPATH,
BOT_MENU_WAYPOINT_PATH,
BOT_MENU_KICK_PAGE_1,
BOT_MENU_KICK_PAGE_2,
BOT_MENU_KICK_PAGE_3,
BOT_MENU_KICK_PAGE_4,
BOT_MENU_TOTAL_MENUS
};
// log levels // log levels
enum LogLevel enum LogLevel
{ {
@ -601,14 +629,15 @@ struct WeaponSelect
// struct for menus // struct for menus
struct MenuText struct MenuText
{ {
int validSlots; // ored together bits for valid keys MenuId id; // actual menu id
const char *menuText; // ptr to actual string int slots; // together bits for valid keys
String text; // ptr to actual string
}; };
// array of clients struct // array of clients struct
struct Client struct Client
{ {
MenuText *menu; // pointer to opened bot menu MenuId menu; // id to opened bot menu
edict_t *ent; // pointer to actual edict edict_t *ent; // pointer to actual edict
Vector origin; // position in the world Vector origin; // position in the world
Vector soundPosition; // position sound was played Vector soundPosition; // position sound was played
@ -619,6 +648,8 @@ struct Client
float hearingDistance; // distance this sound is heared float hearingDistance; // distance this sound is heared
float timeSoundLasting; // time sound is played/heared float timeSoundLasting; // time sound is played/heared
Client (void) : menu (BOT_MENU_IVALID) { }
}; };
// experience data hold in memory while playing // experience data hold in memory while playing
@ -1184,7 +1215,7 @@ public:
bool FindWaypoint (void); bool FindWaypoint (void);
bool EntityIsVisible (const Vector &dest, bool fromBody = false); bool EntityIsVisible (const Vector &dest, bool fromBody = false);
void SwitchChatterIcon (bool show); void EnableChatterIcon (bool show);
void DeleteSearchNodes (void); void DeleteSearchNodes (void);
void VerifyBreakable (edict_t *touch); void VerifyBreakable (edict_t *touch);
@ -1455,6 +1486,11 @@ public:
WaypointDownloadError RequestWaypoint (void); WaypointDownloadError RequestWaypoint (void);
}; };
class BotMenu
{
};
#include <engine.h> #include <engine.h>
// expose bot super-globals // expose bot super-globals
@ -1482,7 +1518,7 @@ extern void FreeLibraryMemory (void);
extern void RoundInit (void); extern void RoundInit (void);
extern void CheckWelcomeMessage (void); extern void CheckWelcomeMessage (void);
extern void AddLogEntry (bool outputToConsole, int logLevel, const char *format, ...); extern void AddLogEntry (bool outputToConsole, int logLevel, const char *format, ...);
extern void DisplayMenuToClient (edict_t *ent, MenuText *menu); extern void DisplayMenuToClient (edict_t *ent, MenuId menu);
extern void DecalTrace (entvars_t *pev, TraceResult *trace, int logotypeIndex); extern void DecalTrace (entvars_t *pev, TraceResult *trace, int logotypeIndex);
extern void SoundAttachToClients (edict_t *ent, const char *sample, float volume); extern void SoundAttachToClients (edict_t *ent, const char *sample, float volume);
extern void SoundSimulateUpdate (int playerIndex); extern void SoundSimulateUpdate (int playerIndex);

View file

@ -2429,7 +2429,7 @@ public:
// Returns: // Returns:
// Length of string, 0 in case of error. // Length of string, 0 in case of error.
// //
int GetLength (void) int GetLength (void) const
{ {
if (m_bufferPtr == NULL) if (m_bufferPtr == NULL)
return 0; return 0;

View file

@ -17,7 +17,7 @@ extern bool g_waypointOn;
extern bool g_autoWaypoint; extern bool g_autoWaypoint;
extern bool g_botsCanPause; extern bool g_botsCanPause;
extern bool g_editNoclip; extern bool g_editNoclip;
extern bool g_isCommencing; extern bool g_gameWelcomeSent;
extern float g_autoPathDistance; extern float g_autoPathDistance;
extern float g_timeBombPlanted; extern float g_timeBombPlanted;
@ -57,7 +57,7 @@ extern WeaponSelect g_weaponSelect[NUM_WEAPONS + 1];
extern WeaponProperty g_weaponDefs[MAX_WEAPONS + 1]; extern WeaponProperty g_weaponDefs[MAX_WEAPONS + 1];
extern Client g_clients[MAX_ENGINE_PLAYERS]; extern Client g_clients[MAX_ENGINE_PLAYERS];
extern MenuText g_menus[21]; extern MenuText g_menus[BOT_MENU_TOTAL_MENUS];
extern TaskItem g_taskFilters[]; extern TaskItem g_taskFilters[];
extern Experience *g_experienceData; extern Experience *g_experienceData;

View file

@ -52,7 +52,7 @@ endif
LINK += -m32 -lm -ldl LINK += -m32 -lm -ldl
CFLAGS += -std=c++11 -DHAVE_STDINT_H -D__extern_always_inline=inline -D_strdup=strdup -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -fno-strict-aliasing -m32 -Wall -Werror -Wextra CFLAGS += -msse2 -std=c++11 -DHAVE_STDINT_H -D__extern_always_inline=inline -D_strdup=strdup -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -fno-strict-aliasing -m32 -Wall -Werror -Wextra
CPPFLAGS += -fno-exceptions -fno-rtti -fno-builtin CPPFLAGS += -fno-exceptions -fno-rtti -fno-builtin
BINARY = $(PROJECT).$(LIB_EXT) BINARY = $(PROJECT).$(LIB_EXT)

View file

@ -963,7 +963,7 @@ void Bot::GetCampDirection (Vector *dest)
} }
} }
void Bot::SwitchChatterIcon (bool show) void Bot::EnableChatterIcon (bool show)
{ {
// this function depending on show boolen, shows/remove chatter, icon, on the head of bot. // this function depending on show boolen, shows/remove chatter, icon, on the head of bot.
@ -988,11 +988,11 @@ 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)) if ((g_gameFlags & GAME_LEGACY) || yb_communication_type.GetInt () != 2 || g_chatterFactory[type].IsEmpty ())
return; return;
if (m_notKilled) if (m_notKilled)
SwitchChatterIcon (true); EnableChatterIcon (true);
// delay only reportteam // delay only reportteam
if (type == Radio_ReportTeam) if (type == Radio_ReportTeam)
@ -1003,17 +1003,17 @@ void Bot::InstantChatterMessage (int type)
m_timeRepotingInDelay = engine.Time () + Random.Float (30.0f, 60.0f); m_timeRepotingInDelay = engine.Time () + Random.Float (30.0f, 60.0f);
} }
String defaultSound = g_chatterFactory[type].GetRandomElement ().name; const String &defaultSound = g_chatterFactory[type].GetRandomElement ().name;
String painSound = g_chatterFactory[Chatter_DiePain].GetRandomElement ().name; const String &painSound = g_chatterFactory[Chatter_DiePain].GetRandomElement ().name;
for (int i = 0; i < engine.MaxClients (); i++) for (int i = 0; i < engine.MaxClients (); i++)
{ {
edict_t *ent = engine.EntityOfIndex (i); const Client &client = g_clients[i];
if (!IsValidPlayer (ent) || IsValidBot (ent) || engine.GetTeam (ent) != m_team) if (!(client.flags & CF_USED) || (client.ent->v.flags & FL_FAKECLIENT) || client.team != m_team)
continue; continue;
MESSAGE_BEGIN (MSG_ONE, engine.FindMessageId (NETMSG_SENDAUDIO), nullptr, ent); // begin message MESSAGE_BEGIN (MSG_ONE, engine.FindMessageId (NETMSG_SENDAUDIO), nullptr, client.ent); // begin message
WRITE_BYTE (GetIndex ()); WRITE_BYTE (GetIndex ());
if (pev->deadflag & DEAD_DYING) if (pev->deadflag & DEAD_DYING)
@ -1033,7 +1033,7 @@ void Bot::RadioMessage (int message)
if (yb_communication_type.GetInt () == 0 || m_numFriendsLeft == 0) if (yb_communication_type.GetInt () == 0 || m_numFriendsLeft == 0)
return; return;
if (g_chatterFactory[message].IsEmpty () || (g_gameFlags & GAME_LEGACY) || yb_communication_type.GetInt () != 2) if ((g_gameFlags & GAME_LEGACY) || g_chatterFactory[message].IsEmpty () || yb_communication_type.GetInt () != 2)
m_forceRadio = true; // use radio instead voice m_forceRadio = true; // use radio instead voice
else else
m_forceRadio = false; m_forceRadio = false;
@ -2922,7 +2922,7 @@ void Bot::ThinkFrame (void)
// remove voice icon // remove voice icon
if (!(g_gameFlags & GAME_LEGACY) && g_lastRadioTime[g_clients[GetIndex () - 1].team2] + Random.Float (0.8f, 2.1f) < engine.Time ()) if (!(g_gameFlags & GAME_LEGACY) && g_lastRadioTime[g_clients[GetIndex () - 1].team2] + Random.Float (0.8f, 2.1f) < engine.Time ())
SwitchChatterIcon (false); // hide icon EnableChatterIcon (false); // hide icon
if (botMovement) if (botMovement)
BotAI (); // execute main code BotAI (); // execute main code

View file

@ -948,7 +948,7 @@ void Engine::ProcessMessageCapture (void *ptr)
g_roundEnded = true; g_roundEnded = true;
if (FStrEq (strVal, "#Game_Commencing")) if (FStrEq (strVal, "#Game_Commencing"))
g_isCommencing = true; g_gameWelcomeSent = true;
if (FStrEq (strVal, "#CTs_Win")) if (FStrEq (strVal, "#CTs_Win"))
{ {

View file

@ -9,37 +9,12 @@
#include <core.h> #include <core.h>
class Chat
{
public:
};
class Globals
{
public:
};
class Practice
{
public:
};
class GameState
{
public:
};
class MenuManager
{
public:
};
bool g_canSayBombPlanted = true; bool g_canSayBombPlanted = true;
bool g_roundEnded = true; bool g_roundEnded = true;
bool g_botsCanPause = false; bool g_botsCanPause = false;
bool g_bombPlanted = false; bool g_bombPlanted = false;
bool g_bombSayString = false; bool g_bombSayString = false;
bool g_isCommencing = false; bool g_gameWelcomeSent = false;
bool g_editNoclip = false; bool g_editNoclip = false;
bool g_waypointOn = false; bool g_waypointOn = false;
@ -183,10 +158,11 @@ WeaponSelect g_weaponSelect[NUM_WEAPONS + 1] =
}; };
// bot menus // bot menus
MenuText g_menus[21] = MenuText g_menus[BOT_MENU_TOTAL_MENUS] =
{ {
// main menu // main menu
{ {
BOT_MENU_MAIN,
0x2ff, 0x2ff,
"\\yMain Menu\\w\v\v" "\\yMain Menu\\w\v\v"
"1. Control Bots\v" "1. Control Bots\v"
@ -198,6 +174,7 @@ MenuText g_menus[21] =
// bot features menu // bot features menu
{ {
BOT_MENU_FEATURES,
0x25f, 0x25f,
"\\yBots Features\\w\v\v" "\\yBots Features\\w\v\v"
"1. Weapon Mode Menu\v" "1. Weapon Mode Menu\v"
@ -210,6 +187,7 @@ MenuText g_menus[21] =
// bot control menu // bot control menu
{ {
BOT_MENU_CONTROL,
0x2ff, 0x2ff,
"\\yBots Control Menu\\w\v\v" "\\yBots Control Menu\\w\v\v"
"1. Add a Bot, Quick\v" "1. Add a Bot, Quick\v"
@ -222,6 +200,7 @@ MenuText g_menus[21] =
// weapon mode select menu // weapon mode select menu
{ {
BOT_MENU_WEAPON_MODE,
0x27f, 0x27f,
"\\yBots Weapon Mode\\w\v\v" "\\yBots Weapon Mode\\w\v\v"
"1. Knives only\v" "1. Knives only\v"
@ -236,6 +215,7 @@ MenuText g_menus[21] =
// personality select menu // personality select menu
{ {
BOT_MENU_PERSONALITY,
0x20f, 0x20f,
"\\yBots Personality\\w\v\v" "\\yBots Personality\\w\v\v"
"1. Random\v" "1. Random\v"
@ -247,6 +227,7 @@ MenuText g_menus[21] =
// difficulty select menu // difficulty select menu
{ {
BOT_MENU_DIFFICULTY,
0x23f, 0x23f,
"\\yBots Difficulty Level\\w\v\v" "\\yBots Difficulty Level\\w\v\v"
"1. Newbie\v" "1. Newbie\v"
@ -259,6 +240,7 @@ MenuText g_menus[21] =
// team select menu // team select menu
{ {
BOT_MENU_TEAM_SELECT,
0x213, 0x213,
"\\ySelect a team\\w\v\v" "\\ySelect a team\\w\v\v"
"1. Terrorist Force\v" "1. Terrorist Force\v"
@ -269,6 +251,7 @@ MenuText g_menus[21] =
// terrorist model select menu // terrorist model select menu
{ {
BOT_MENU_TERRORIST_SELECT,
0x21f, 0x21f,
"\\ySelect an appearance\\w\v\v" "\\ySelect an appearance\\w\v\v"
"1. Phoenix Connexion\v" "1. Phoenix Connexion\v"
@ -279,8 +262,9 @@ MenuText g_menus[21] =
"0. Exit" "0. Exit"
}, },
// counter-terrirust model select menu // counter-terrorist model select menu
{ {
BOT_MENU_CT_SELECT,
0x21f, 0x21f,
"\\ySelect an appearance\\w\v\v" "\\ySelect an appearance\\w\v\v"
"1. Seal Team 6 (DEVGRU)\v" "1. Seal Team 6 (DEVGRU)\v"
@ -291,8 +275,21 @@ MenuText g_menus[21] =
"0. Exit" "0. Exit"
}, },
// command menu
{
BOT_MENU_COMMANDS,
0x23f,
"\\yBot Command Menu\\w\v\v"
"1. Make Double Jump\v"
"2. Finish Double Jump\v\v"
"3. Drop the C4 Bomb\v"
"4. Drop the Weapon\v\v"
"0. Exit"
},
// main waypoint menu // main waypoint menu
{ {
BOT_MENU_WAYPOINT_MAIN_PAGE1,
0x3ff, 0x3ff,
"\\yWaypoint Operations (Page 1)\\w\v\v" "\\yWaypoint Operations (Page 1)\\w\v\v"
"1. Show/Hide waypoints\v" "1. Show/Hide waypoints\v"
@ -309,6 +306,7 @@ MenuText g_menus[21] =
// main waypoint menu (page 2) // main waypoint menu (page 2)
{ {
BOT_MENU_WAYPOINT_MAIN_PAGE2,
0x3ff, 0x3ff,
"\\yWaypoint Operations (Page 2)\\w\v\v" "\\yWaypoint Operations (Page 2)\\w\v\v"
"1. Waypoint stats\v" "1. Waypoint stats\v"
@ -325,6 +323,7 @@ MenuText g_menus[21] =
// select waypoint radius menu // select waypoint radius menu
{ {
BOT_MENU_WAYPOINT_RADIUS,
0x3ff, 0x3ff,
"\\yWaypoint Radius\\w\v\v" "\\yWaypoint Radius\\w\v\v"
"1. SetRadius 0\v" "1. SetRadius 0\v"
@ -341,6 +340,7 @@ MenuText g_menus[21] =
// waypoint add menu // waypoint add menu
{ {
BOT_MENU_WAYPOINT_TYPE,
0x3ff, 0x3ff,
"\\yWaypoint Type\\w\v\v" "\\yWaypoint Type\\w\v\v"
"1. Normal\v" "1. Normal\v"
@ -357,6 +357,7 @@ MenuText g_menus[21] =
// set waypoint flag menu // set waypoint flag menu
{ {
BOT_MENU_WAYPOINT_FLAG,
0x2ff, 0x2ff,
"\\yToggle Waypoint Flags\\w\v\v" "\\yToggle Waypoint Flags\\w\v\v"
"1. Block with Hostage\v" "1. Block with Hostage\v"
@ -367,43 +368,9 @@ MenuText g_menus[21] =
"0. Exit" "0. Exit"
}, },
// kickmenu #1
{
0x0,
nullptr,
},
// kickmenu #2
{
0x0,
nullptr,
},
// kickmenu #3
{
0x0,
nullptr,
},
// kickmenu #4
{
0x0,
nullptr,
},
// command menu
{
0x23f,
"\\yBot Command Menu\\w\v\v"
"1. Make Double Jump\v"
"2. Finish Double Jump\v\v"
"3. Drop the C4 Bomb\v"
"4. Drop the Weapon\v\v"
"0. Exit"
},
// auto-path max distance // auto-path max distance
{ {
BOT_MENU_WAYPOINT_AUTOPATH,
0x27f, 0x27f,
"\\yAutoPath Distance\\w\v\v" "\\yAutoPath Distance\\w\v\v"
"1. Distance 0\v" "1. Distance 0\v"
@ -418,11 +385,40 @@ MenuText g_menus[21] =
// path connections // path connections
{ {
BOT_MENU_WAYPOINT_PATH,
0x207, 0x207,
"\\yCreate Path (Choose Direction)\\w\v\v" "\\yCreate Path (Choose Direction)\\w\v\v"
"1. Outgoing Path\v" "1. Outgoing Path\v"
"2. Incoming Path\v" "2. Incoming Path\v"
"3. Bidirectional (Both Ways)\v\v" "3. Bidirectional (Both Ways)\v\v"
"0. Exit" "0. Exit"
},
// kickmenu #1
{
BOT_MENU_KICK_PAGE_1,
0x0,
nullptr,
},
// kickmenu #2
{
BOT_MENU_KICK_PAGE_2,
0x0,
nullptr,
},
// kickmenu #3
{
BOT_MENU_KICK_PAGE_3,
0x0,
nullptr,
},
// kickmenu #4
{
BOT_MENU_KICK_PAGE_4,
0x0,
nullptr,
} }
}; };

View file

@ -188,16 +188,16 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
// displays main bot menu // displays main bot menu
else if (stricmp (arg0, "botmenu") == 0 || stricmp (arg0, "menu") == 0) else if (stricmp (arg0, "botmenu") == 0 || stricmp (arg0, "menu") == 0)
DisplayMenuToClient (ent, &g_menus[0]); DisplayMenuToClient (ent, BOT_MENU_MAIN);
// display command menu // display command menu
else if (stricmp (arg0, "cmdmenu") == 0 || stricmp (arg0, "cmenu") == 0) else if (stricmp (arg0, "cmdmenu") == 0 || stricmp (arg0, "cmenu") == 0)
{ {
if (IsAlive (ent)) if (IsAlive (ent))
DisplayMenuToClient (ent, &g_menus[18]); DisplayMenuToClient (ent, BOT_MENU_COMMANDS);
else else
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
engine.CenterPrintf ("You're dead, and have no access to this menu"); engine.CenterPrintf ("You're dead, and have no access to this menu");
} }
} }
@ -280,7 +280,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
else if (stricmp (arg1, "add") == 0) else if (stricmp (arg1, "add") == 0)
{ {
g_waypointOn = true; // turn waypoints on g_waypointOn = true; // turn waypoints on
DisplayMenuToClient (g_hostEntity, &g_menus[12]); DisplayMenuToClient (g_hostEntity, BOT_MENU_WAYPOINT_TYPE);
} }
// creates basic waypoints on the map (ladder/spawn points/goals) // creates basic waypoints on the map (ladder/spawn points/goals)
@ -334,7 +334,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
// opens menu for setting (removing) waypoint flags // opens menu for setting (removing) waypoint flags
else if (stricmp (arg1, "flags") == 0) else if (stricmp (arg1, "flags") == 0)
DisplayMenuToClient (g_hostEntity, &g_menus[13]); DisplayMenuToClient (g_hostEntity, BOT_MENU_WAYPOINT_FLAG);
// setting waypoint radius // setting waypoint radius
else if (stricmp (arg1, "setradius") == 0) else if (stricmp (arg1, "setradius") == 0)
@ -363,7 +363,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
// displays waypoint menu // displays waypoint menu
else if (stricmp (arg1, "menu") == 0) else if (stricmp (arg1, "menu") == 0)
DisplayMenuToClient (g_hostEntity, &g_menus[9]); DisplayMenuToClient (g_hostEntity, BOT_MENU_WAYPOINT_MAIN_PAGE1);
// otherwise display waypoint current status // otherwise display waypoint current status
else else
@ -378,7 +378,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
// opens path creation menu // opens path creation menu
if (stricmp (arg1, "create") == 0) if (stricmp (arg1, "create") == 0)
DisplayMenuToClient (g_hostEntity, &g_menus[20]); DisplayMenuToClient (g_hostEntity, BOT_MENU_WAYPOINT_PATH);
// creates incoming path from the cached waypoint // creates incoming path from the cached waypoint
else if (stricmp (arg1, "create_in") == 0) else if (stricmp (arg1, "create_in") == 0)
@ -398,7 +398,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
// sets auto path maximum distance // sets auto path maximum distance
else if (stricmp (arg1, "autodistance") == 0) else if (stricmp (arg1, "autodistance") == 0)
DisplayMenuToClient (g_hostEntity, &g_menus[19]); DisplayMenuToClient (g_hostEntity, BOT_MENU_WAYPOINT_AUTOPATH);
} }
// automatic waypoint handling (supported only on listen server) // automatic waypoint handling (supported only on listen server)
@ -905,19 +905,6 @@ void InitConfig (void)
g_timePerSecondUpdate = 0.0f; g_timePerSecondUpdate = 0.0f;
} }
void CommandHandler_NotMM (void)
{
// this function is the dedicated server command handler for the new yapb server command we
// registered at game start. It will be called by the engine each time a server command that
// starts with "meta" is entered in the server console. It works exactly the same way as
// ClientCommand() does, using the CmdArgc() and CmdArgv() facilities of the engine. Argv(0)
// is the server command itself (here "meta") and the next ones are its arguments. Just like
// the stdio command-line parsing in C when you write "long main (long argc, char **argv)".
// this function is handler for non-metamod launch of yapb, it's just print error message.
}
void GameDLLInit (void) void GameDLLInit (void)
{ {
// this function is a one-time call, and appears to be the second function called in the // this function is a one-time call, and appears to be the second function called in the
@ -1151,7 +1138,7 @@ void ClientDisconnect (edict_t *ent)
{ {
if (bot->pev == &ent->v) if (bot->pev == &ent->v)
{ {
bot->SwitchChatterIcon (false); bot->EnableChatterIcon (false);
bot->ReleaseUsedName (); bot->ReleaseUsedName ();
bots.Free (i); bots.Free (i);
@ -1237,14 +1224,14 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (stricmp (command, "menuselect") == 0 && !IsNullString (arg1) && g_clients[issuerPlayerIndex].menu != nullptr) else if (stricmp (command, "menuselect") == 0 && !IsNullString (arg1) && g_clients[issuerPlayerIndex].menu != BOT_MENU_IVALID)
{ {
Client *client = &g_clients[issuerPlayerIndex]; Client *client = &g_clients[issuerPlayerIndex];
int selection = atoi (arg1); int selection = atoi (arg1);
if (client->menu == &g_menus[12]) if (client->menu == BOT_MENU_WAYPOINT_TYPE)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1267,7 +1254,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1275,9 +1262,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[13]) else if (client->menu == BOT_MENU_WAYPOINT_FLAG)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1306,9 +1293,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[9]) else if (client->menu == BOT_MENU_WAYPOINT_MAIN_PAGE1)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1326,7 +1313,7 @@ void ClientCommand (edict_t *ent)
case 3: case 3:
g_waypointOn = true; g_waypointOn = true;
DisplayMenuToClient (ent, &g_menus[20]); DisplayMenuToClient (ent, BOT_MENU_WAYPOINT_PATH);
break; break;
case 4: case 4:
@ -1336,7 +1323,7 @@ void ClientCommand (edict_t *ent)
case 5: case 5:
g_waypointOn = true; g_waypointOn = true;
DisplayMenuToClient (ent, &g_menus[12]); DisplayMenuToClient (ent, BOT_MENU_WAYPOINT_TYPE);
break; break;
case 6: case 6:
@ -1346,20 +1333,20 @@ void ClientCommand (edict_t *ent)
case 7: case 7:
g_waypointOn = true; g_waypointOn = true;
DisplayMenuToClient (ent, &g_menus[19]); DisplayMenuToClient (ent, BOT_MENU_WAYPOINT_AUTOPATH);
break; break;
case 8: case 8:
g_waypointOn = true; g_waypointOn = true;
DisplayMenuToClient (ent, &g_menus[11]); DisplayMenuToClient (ent, BOT_MENU_WAYPOINT_RADIUS);
break; break;
case 9: case 9:
DisplayMenuToClient (ent, &g_menus[10]); DisplayMenuToClient (ent, BOT_MENU_WAYPOINT_MAIN_PAGE2);
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1367,9 +1354,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[10]) else if (client->menu == BOT_MENU_WAYPOINT_MAIN_PAGE2)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1425,7 +1412,7 @@ void ClientCommand (edict_t *ent)
case 3: case 3:
g_waypointOn = true; g_waypointOn = true;
DisplayMenuToClient (ent, &g_menus[13]); DisplayMenuToClient (ent, BOT_MENU_WAYPOINT_FLAG);
break; break;
case 4: case 4:
@ -1455,7 +1442,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 9: case 9:
DisplayMenuToClient (ent, &g_menus[9]); DisplayMenuToClient (ent, BOT_MENU_WAYPOINT_MAIN_PAGE1);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1463,9 +1450,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[11]) else if (client->menu == BOT_MENU_WAYPOINT_RADIUS)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
g_waypointOn = true; // turn waypoints on in case g_waypointOn = true; // turn waypoints on in case
@ -1479,24 +1466,24 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[0]) else if (client->menu == BOT_MENU_MAIN)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
case 1: case 1:
fillCommand = false; fillCommand = false;
DisplayMenuToClient (ent, &g_menus[2]); DisplayMenuToClient (ent, BOT_MENU_CONTROL);
break; break;
case 2: case 2:
DisplayMenuToClient (ent, &g_menus[1]); DisplayMenuToClient (ent, BOT_MENU_FEATURES);
break; break;
case 3: case 3:
fillCommand = true; fillCommand = true;
DisplayMenuToClient (ent, &g_menus[6]); DisplayMenuToClient (ent, BOT_MENU_TEAM_SELECT);
break; break;
case 4: case 4:
@ -1504,7 +1491,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
@ -1513,9 +1500,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[2]) else if (client->menu == BOT_MENU_CONTROL)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1524,7 +1511,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 2: case 2:
DisplayMenuToClient (ent, &g_menus[5]); DisplayMenuToClient (ent, BOT_MENU_DIFFICULTY);
break; break;
case 3: case 3:
@ -1540,7 +1527,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1548,22 +1535,22 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[1]) else if (client->menu == BOT_MENU_FEATURES)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
case 1: case 1:
DisplayMenuToClient (ent, &g_menus[3]); DisplayMenuToClient (ent, BOT_MENU_WEAPON_MODE);
break; break;
case 2: case 2:
DisplayMenuToClient (ent, &g_menus[9]); DisplayMenuToClient (ent, BOT_MENU_WAYPOINT_MAIN_PAGE1);
break; break;
case 3: case 3:
DisplayMenuToClient (ent, &g_menus[4]); DisplayMenuToClient (ent, BOT_MENU_PERSONALITY);
break; break;
case 4: case 4:
@ -1574,16 +1561,16 @@ void ClientCommand (edict_t *ent)
case 5: case 5:
if (IsAlive (ent)) if (IsAlive (ent))
DisplayMenuToClient (ent, &g_menus[18]); DisplayMenuToClient (ent, BOT_MENU_COMMANDS);
else else
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
engine.CenterPrintf ("You're dead, and have no access to this menu"); engine.CenterPrintf ("You're dead, and have no access to this menu");
} }
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1591,9 +1578,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[18]) else if (client->menu == BOT_MENU_COMMANDS)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
Bot *bot = nullptr; Bot *bot = nullptr;
switch (selection) switch (selection)
@ -1616,6 +1603,7 @@ void ClientCommand (edict_t *ent)
} }
else if (selection == 2) else if (selection == 2)
bot->ResetDoubleJumpState (); bot->ResetDoubleJumpState ();
break; break;
} }
} }
@ -1628,7 +1616,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
@ -1637,9 +1625,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[19]) else if (client->menu ==BOT_MENU_WAYPOINT_AUTOPATH)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
const float autoDistanceValue[] = {0.0f, 100.0f, 130.0f, 160.0f, 190.0f, 220.0f, 250.0f }; const float autoDistanceValue[] = {0.0f, 100.0f, 130.0f, 160.0f, 190.0f, 220.0f, 250.0f };
@ -1656,9 +1644,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[20]) else if (client->menu == BOT_MENU_WAYPOINT_PATH)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1675,7 +1663,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
@ -1684,11 +1672,11 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[5]) else if (client->menu == BOT_MENU_DIFFICULTY)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
client->menu = &g_menus[4]; client->menu = BOT_MENU_PERSONALITY;
switch (selection) switch (selection)
{ {
@ -1713,21 +1701,21 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (client->menu == &g_menus[4]) if (client->menu == BOT_MENU_PERSONALITY)
DisplayMenuToClient (ent, &g_menus[4]); DisplayMenuToClient (ent, BOT_MENU_PERSONALITY);
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
RETURN_META (MRES_SUPERCEDE); RETURN_META (MRES_SUPERCEDE);
return; return;
} }
else if (client->menu == &g_menus[6] && fillCommand) else if (client->menu == BOT_MENU_TEAM_SELECT && fillCommand)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1739,11 +1727,11 @@ void ClientCommand (edict_t *ent)
case 5: case 5:
fillServerTeam = selection; fillServerTeam = selection;
DisplayMenuToClient (ent, &g_menus[5]); DisplayMenuToClient (ent, BOT_MENU_DIFFICULTY);
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1751,9 +1739,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[4] && fillCommand) else if (client->menu == BOT_MENU_PERSONALITY && fillCommand)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1764,7 +1752,7 @@ void ClientCommand (edict_t *ent)
bots.FillServer (fillServerTeam, selection - 2, g_storeAddbotVars[0]); bots.FillServer (fillServerTeam, selection - 2, g_storeAddbotVars[0]);
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1772,9 +1760,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[6]) else if (client->menu == BOT_MENU_TEAM_SELECT)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1790,14 +1778,14 @@ void ClientCommand (edict_t *ent)
else else
{ {
if (selection == 1) if (selection == 1)
DisplayMenuToClient (ent, &g_menus[7]); DisplayMenuToClient (ent, BOT_MENU_TERRORIST_SELECT);
else else
DisplayMenuToClient (ent, &g_menus[8]); DisplayMenuToClient (ent, BOT_MENU_CT_SELECT);
} }
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1805,9 +1793,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[4]) else if (client->menu == BOT_MENU_PERSONALITY)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1816,11 +1804,11 @@ void ClientCommand (edict_t *ent)
case 3: case 3:
case 4: case 4:
g_storeAddbotVars[3] = selection - 2; g_storeAddbotVars[3] = selection - 2;
DisplayMenuToClient (ent, &g_menus[6]); DisplayMenuToClient (ent, BOT_MENU_TEAM_SELECT);
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1828,9 +1816,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[7] || client->menu == &g_menus[8]) else if (client->menu == BOT_MENU_TERRORIST_SELECT || client->menu == BOT_MENU_CT_SELECT)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1844,7 +1832,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1852,9 +1840,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[3]) else if (client->menu == BOT_MENU_WEAPON_MODE)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1869,7 +1857,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, nullptr); DisplayMenuToClient (ent, BOT_MENU_IVALID);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1877,9 +1865,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[14]) else if (client->menu == BOT_MENU_KICK_PAGE_1)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1899,7 +1887,7 @@ void ClientCommand (edict_t *ent)
break; break;
case 10: case 10:
DisplayMenuToClient (ent, &g_menus[2]); DisplayMenuToClient (ent, BOT_MENU_CONTROL);
break; break;
} }
if (g_gameFlags & GAME_METAMOD) if (g_gameFlags & GAME_METAMOD)
@ -1907,9 +1895,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[15]) else if (client->menu == BOT_MENU_KICK_PAGE_2)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1937,9 +1925,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[16]) else if (client->menu == BOT_MENU_KICK_PAGE_3)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {
@ -1967,9 +1955,9 @@ void ClientCommand (edict_t *ent)
return; return;
} }
else if (client->menu == &g_menus[17]) else if (client->menu == BOT_MENU_KICK_PAGE_4)
{ {
DisplayMenuToClient (ent, nullptr); // reset menu display DisplayMenuToClient (ent, BOT_MENU_IVALID); // reset menu display
switch (selection) switch (selection)
{ {

View file

@ -9,7 +9,7 @@
#include <core.h> #include <core.h>
ConVar yb_autovacate ("yb_autovacate", "0"); ConVar yb_autovacate ("yb_autovacate", "1");
ConVar yb_autovacate_smart_kick ("yb_autovacate_smart_kick", "0"); 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);
@ -439,8 +439,11 @@ void BotManager::MaintainBotQuota (void)
if (yb_quota.GetInt () < 0) if (yb_quota.GetInt () < 0)
yb_quota.SetInt (0); yb_quota.SetInt (0);
if (yb_quota.GetInt () > engine.MaxClients ()) // always keep one slot
yb_quota.SetInt (engine.MaxClients ()); int maxClients = yb_autovacate.GetBool () ? engine.MaxClients () - 1 - GetHumansNum () : engine.MaxClients ();
if (yb_quota.GetInt () > maxClients)
yb_quota.SetInt (maxClients);
} }
int numBots = GetBotsNum (); int numBots = GetBotsNum ();
@ -487,7 +490,10 @@ void BotManager::FillServer (int selection, int personality, int difficulty, int
{ {
// this function fill server with bots, with specified team & personality // this function fill server with bots, with specified team & personality
if (GetBotsNum () >= engine.MaxClients () - GetHumansNum ()) // always keep one slot
int maxClients = yb_autovacate.GetBool () ? engine.MaxClients () - 1 - GetHumansNum () : engine.MaxClients ();
if (GetBotsNum () >= maxClients - GetHumansNum ())
return; return;
if (selection == 1 || selection == 2) if (selection == 1 || selection == 2)
@ -498,7 +504,7 @@ void BotManager::FillServer (int selection, int personality, int difficulty, int
else else
selection = 5; selection = 5;
char teamDesc[6][12] = char teams[6][12] =
{ {
"", "",
{"Terrorists"}, {"Terrorists"},
@ -508,12 +514,12 @@ void BotManager::FillServer (int selection, int personality, int difficulty, int
{"Random"}, {"Random"},
}; };
int toAdd = numToAdd == -1 ? engine.MaxClients () - (GetHumansNum () + GetBotsNum ()) : numToAdd; int toAdd = numToAdd == -1 ? maxClients - (GetHumansNum () + GetBotsNum ()) : numToAdd;
for (int i = 0; i <= toAdd; i++) for (int i = 0; i <= toAdd; i++)
AddBot ("", difficulty, personality, selection, -1); AddBot ("", difficulty, personality, selection, -1);
engine.CenterPrintf ("Fill Server with %s bots...", &teamDesc[selection][0]); engine.CenterPrintf ("Fill Server with %s bots...", &teams[selection][0]);
} }
void BotManager::RemoveAll (void) void BotManager::RemoveAll (void)
@ -573,31 +579,31 @@ void BotManager::RemoveMenu (edict_t *ent, int selection)
switch (selection) switch (selection)
{ {
case 1: case 1:
g_menus[14].validSlots = validSlots & static_cast <unsigned int> (-1); g_menus[BOT_MENU_KICK_PAGE_1].slots = validSlots & static_cast <unsigned int> (-1);
g_menus[14].menuText = tempBuffer; g_menus[14].text = tempBuffer;
DisplayMenuToClient (ent, &g_menus[14]); DisplayMenuToClient (ent, BOT_MENU_KICK_PAGE_1);
break; break;
case 2: case 2:
g_menus[15].validSlots = validSlots & static_cast <unsigned int> (-1); g_menus[BOT_MENU_KICK_PAGE_2].slots = validSlots & static_cast <unsigned int> (-1);
g_menus[15].menuText = tempBuffer; g_menus[BOT_MENU_KICK_PAGE_2].text = tempBuffer;
DisplayMenuToClient (ent, &g_menus[15]); DisplayMenuToClient (ent, BOT_MENU_KICK_PAGE_2);
break; break;
case 3: case 3:
g_menus[16].validSlots = validSlots & static_cast <unsigned int> (-1); g_menus[BOT_MENU_KICK_PAGE_3].slots = validSlots & static_cast <unsigned int> (-1);
g_menus[16].menuText = tempBuffer; g_menus[BOT_MENU_KICK_PAGE_3].text = tempBuffer;
DisplayMenuToClient (ent, &g_menus[16]); DisplayMenuToClient (ent, BOT_MENU_KICK_PAGE_3);
break; break;
case 4: case 4:
g_menus[17].validSlots = validSlots & static_cast <unsigned int> (-1); g_menus[BOT_MENU_KICK_PAGE_4].slots = validSlots & static_cast <unsigned int> (-1);
g_menus[17].menuText = tempBuffer; g_menus[BOT_MENU_KICK_PAGE_4].text = tempBuffer;
DisplayMenuToClient (ent, &g_menus[17]); DisplayMenuToClient (ent, BOT_MENU_KICK_PAGE_4);
break; break;
} }
} }

View file

@ -1105,7 +1105,13 @@ bool Bot::DoWaypointNav (void)
IgnoreCollisionShortly (); // don't consider being stuck IgnoreCollisionShortly (); // don't consider being stuck
if (Random.Int (1, 100) < 50) if (Random.Int (1, 100) < 50)
MDLL_Use (tr.pHit, GetEntity ()); // also 'use' the door randomly {
// do not use door directrly under xash, or we will get failed assert in gamedll code
if (g_gameFlags & GAME_XASH)
pev->button |= IN_USE;
else
MDLL_Use (tr.pHit, GetEntity ()); // also 'use' the door randomly
}
} }
// make sure we are always facing the door when going through it // make sure we are always facing the door when going through it

View file

@ -99,65 +99,80 @@ bool IsVisible (const Vector &origin, edict_t *ent)
return true; return true;
} }
void DisplayMenuToClient (edict_t *ent, MenuText *menu) void DisplayMenuToClient (edict_t *ent, MenuId menu)
{ {
static bool s_menusParsed = false;
// make menus looks like we need only once
if (!s_menusParsed)
{
for (int i = 0; i < ARRAYSIZE_HLSDK (g_menus); i++)
{
auto parsed = &g_menus[i];
// translate all the things
parsed->text.Replace ("\v", "\n");
parsed->text.Assign (engine.TraslateMessage (parsed->text.GetBuffer ()));
// make menu looks best
for (int j = 0; j < 10; j++)
parsed->text.Replace (FormatBuffer ("%d.", j), FormatBuffer ("\\r%d.\\w", j));
}
s_menusParsed = true;
}
if (!IsValidPlayer (ent)) if (!IsValidPlayer (ent))
return; return;
int clientIndex = engine.IndexOfEntity (ent) - 1; Client &client = g_clients[engine.IndexOfEntity (ent) - 1];
if (menu != nullptr) if (menu == BOT_MENU_IVALID)
{
String tempText = String (menu->menuText);
tempText.Replace ("\v", "\n");
const char *text = engine.TraslateMessage (tempText.GetBuffer ());
tempText = String (text);
// make menu looks best
for (int i = 0; i <= 9; i++)
tempText.Replace (FormatBuffer ("%d.", i), FormatBuffer ("\\r%d.\\w", i));
if ((g_gameFlags & (GAME_XASH | GAME_MOBILITY)) && !yb_display_menu_text.GetBool ())
text = " ";
else
text = tempText.GetBuffer ();
while (strlen (text) >= 64)
{
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, engine.FindMessageId (NETMSG_SHOWMENU), nullptr, ent);
WRITE_SHORT (menu->validSlots);
WRITE_CHAR (-1);
WRITE_BYTE (1);
for (int i = 0; i <= 63; i++)
WRITE_CHAR (text[i]);
MESSAGE_END ();
text += 64;
}
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, engine.FindMessageId (NETMSG_SHOWMENU), nullptr, ent);
WRITE_SHORT (menu->validSlots);
WRITE_CHAR (-1);
WRITE_BYTE (0);
WRITE_STRING (text);
MESSAGE_END();
g_clients[clientIndex].menu = menu;
}
else
{ {
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, engine.FindMessageId (NETMSG_SHOWMENU), nullptr, ent); MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, engine.FindMessageId (NETMSG_SHOWMENU), nullptr, ent);
WRITE_SHORT (0); WRITE_SHORT (0);
WRITE_CHAR (0); WRITE_CHAR (0);
WRITE_BYTE (0); WRITE_BYTE (0);
WRITE_STRING (""); WRITE_STRING ("");
MESSAGE_END(); MESSAGE_END ();
g_clients[clientIndex].menu = nullptr; client.menu = BOT_MENU_IVALID;
return;
} }
MenuText *menuPtr = nullptr;
for (int i = 0; i < ARRAYSIZE_HLSDK (g_menus); i++)
{
if (g_menus[i].id == menu)
{
menuPtr = &g_menus[i];
break;
}
}
char *displayText = (g_gameFlags & (GAME_XASH | GAME_MOBILITY)) && !yb_display_menu_text.GetBool () ? " " : menuPtr->text.GetBuffer ();
while (strlen (displayText) >= 64)
{
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, engine.FindMessageId (NETMSG_SHOWMENU), nullptr, ent);
WRITE_SHORT (menuPtr->slots);
WRITE_CHAR (-1);
WRITE_BYTE (1);
for (int i = 0; i <= 63; i++)
WRITE_CHAR (displayText[i]);
MESSAGE_END ();
displayText += 64;
}
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, engine.FindMessageId (NETMSG_SHOWMENU), nullptr, ent);
WRITE_SHORT (menuPtr->slots);
WRITE_CHAR (-1);
WRITE_BYTE (0);
WRITE_STRING (displayText);
MESSAGE_END();
client.menu = menu;
CLIENT_COMMAND (ent, "speak \"player/geiger1\"\n"); // Stops others from hearing menu sounds.. CLIENT_COMMAND (ent, "speak \"player/geiger1\"\n"); // Stops others from hearing menu sounds..
} }
@ -534,10 +549,10 @@ void CheckWelcomeMessage (void)
sentences.Push ("warning, medical attention required"); sentences.Push ("warning, medical attention required");
} }
if (IsAlive (g_hostEntity) && !alreadyReceived && receiveTime < 1.0 && (g_numWaypoints > 0 ? g_isCommencing : true)) if (IsAlive (g_hostEntity) && !alreadyReceived && receiveTime < 1.0 && (g_numWaypoints > 0 ? g_gameWelcomeSent : true))
receiveTime = engine.Time () + 4.0f; // receive welcome message in four seconds after game has commencing receiveTime = engine.Time () + 4.0f; // receive welcome message in four seconds after game has commencing
if (receiveTime > 0.0f && receiveTime < engine.Time () && !alreadyReceived && (g_numWaypoints > 0 ? g_isCommencing : true)) if (receiveTime > 0.0f && receiveTime < engine.Time () && !alreadyReceived && (g_numWaypoints > 0 ? g_gameWelcomeSent : true))
{ {
if (!(g_gameFlags & (GAME_MOBILITY | GAME_XASH))) if (!(g_gameFlags & (GAME_MOBILITY | GAME_XASH)))
engine.IssueCmd ("speak \"%s\"", const_cast <char *> (sentences.GetRandomElement ().GetBuffer ())); engine.IssueCmd ("speak \"%s\"", const_cast <char *> (sentences.GetRandomElement ().GetBuffer ()));