diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 969d57a1b..eb2052a26 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -125,7 +125,7 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam) bot = bot->next; if (bot) { - bot->inuse = false; + bot->inuse = BOTINUSE_No; bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE; } if (players[i].Bot != NULL) @@ -172,7 +172,7 @@ CCMD (listbots) while (thebot) { - Printf ("%s%s\n", thebot->name, thebot->inuse ? " (active)" : ""); + Printf ("%s%s\n", thebot->name, thebot->inuse == BOTINUSE_Yes ? " (active)" : ""); thebot = thebot->next; count++; } diff --git a/src/b_bot.h b/src/b_bot.h index 51fe64129..375b09abb 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -60,6 +60,13 @@ struct botskill_t FArchive &operator<< (FArchive &arc, botskill_t &skill); +enum +{ + BOTINUSE_No, + BOTINUSE_Waiting, + BOTINUSE_Yes, +}; + //Info about all bots in the bots.cfg //Updated during each level start. //Info given to bots when they're spawned. @@ -69,7 +76,7 @@ struct botinfo_t char *name; char *info; botskill_t skill; - bool inuse; + int inuse; int lastteam; }; @@ -88,7 +95,7 @@ public: bool SpawnBot (const char *name, int color = NOCOLOR); bool LoadBots (); void ForgetBots (); - void DoAddBot (BYTE **stream); + void TryAddBot (BYTE **stream, int player); void RemoveAllBots (bool fromlist); void DestroyAllBots (); @@ -122,6 +129,9 @@ public: bool m_Thinking; private: + //(B_Game.c) + bool DoAddBot (BYTE *info, botskill_t skill); + //(B_Func.c) bool Reachable (AActor *actor, AActor *target); void Dofire (AActor *actor, ticcmd_t *cmd); diff --git a/src/b_game.cpp b/src/b_game.cpp index 807ec2b46..f13c168db 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -89,8 +89,6 @@ enum BOTCFG_TEAM }; -static bool waitingforspawn[MAXPLAYERS]; - FCajunMaster::~FCajunMaster() { ForgetBots(); @@ -162,8 +160,6 @@ void FCajunMaster::Main (int buf) void FCajunMaster::Init () { - int i; - botnum = 0; firstthing = NULL; spawn_tries = 0; @@ -172,11 +168,6 @@ void FCajunMaster::Init () body1 = NULL; body2 = NULL; - for (i = 0; i < MAXPLAYERS; i++) - { - waitingforspawn[i] = false; - } - if (ctf && teamplay == false) teamplay = true; //Need teamplay for ctf. (which is not done yet) @@ -192,7 +183,7 @@ void FCajunMaster::Init () while (thebot != NULL) { - thebot->inuse = false; + thebot->inuse = BOTINUSE_No; thebot = thebot->next; } } @@ -232,12 +223,10 @@ void FCajunMaster::End () //The color parameter can be either a //color (range from 0-10), or = NOCOLOR. //The color parameter overides bots -//induvidual colors if not = NOCOLOR. +//individual colors if not = NOCOLOR. bool FCajunMaster::SpawnBot (const char *name, int color) { - int playernumber; - //COLORS static const char colors[11][17] = { @@ -254,36 +243,31 @@ bool FCajunMaster::SpawnBot (const char *name, int color) "\\color\\cf df 90" //10 = Bleached Bone }; - for (playernumber = 0; playernumber < MAXPLAYERS; playernumber++) - { - if (!playeringame[playernumber] && !waitingforspawn[playernumber]) - { - break; - } - } - - if (playernumber == MAXPLAYERS) - { - Printf ("The maximum of %d players/bots has been reached\n", MAXPLAYERS); - return false; - } - botinfo_t *thebot; + int botshift; if (name) { thebot = botinfo; // Check if exist or already in the game. + botshift = 0; while (thebot && stricmp (name, thebot->name)) + { thebot = thebot->next; + botshift++; + } if (thebot == NULL) { Printf ("couldn't find %s in %s\n", name, BOTFILENAME); return false; } - else if (thebot->inuse) + else if (thebot->inuse == BOTINUSE_Waiting) + { + return false; + } + else if (thebot->inuse == BOTINUSE_Yes) { Printf ("%s is already in the thick\n", name); return false; @@ -296,9 +280,13 @@ bool FCajunMaster::SpawnBot (const char *name, int color) { int rnum = (pr_botspawn() % loaded_bots); thebot = botinfo; + botshift = 0; while (rnum) + { --rnum, thebot = thebot->next; - if (!thebot->inuse) + botshift++; + } + if (thebot->inuse == BOTINUSE_No) vacant = true; } } @@ -308,10 +296,10 @@ bool FCajunMaster::SpawnBot (const char *name, int color) return false; } - waitingforspawn[playernumber] = true; + thebot->inuse = BOTINUSE_Waiting; Net_WriteByte (DEM_ADDBOT); - Net_WriteByte (playernumber); + Net_WriteByte (botshift); { //Set color. char concat[512]; @@ -332,61 +320,104 @@ bool FCajunMaster::SpawnBot (const char *name, int color) Net_WriteByte(thebot->skill.reaction); Net_WriteByte(thebot->skill.isp); - thebot->inuse = true; - - //Increment this. - botnum++; - return true; } -void FCajunMaster::DoAddBot (BYTE **stream) +void FCajunMaster::TryAddBot (BYTE **stream, int player) { - int bnum = ReadByte (stream); + int botshift = ReadByte (stream); char *info = ReadString (stream); - BYTE *infob = (BYTE *)info; botskill_t skill; skill.aiming = ReadByte (stream); skill.perfection = ReadByte (stream); skill.reaction = ReadByte (stream); skill.isp = ReadByte (stream); - D_ReadUserInfoStrings (bnum, &infob, false); + botinfo_t *thebot = NULL; + + if (consoleplayer == player) + { + thebot = botinfo; + + while (botshift > 0) + { + thebot = thebot->next; + botshift--; + } + } + + if (DoAddBot ((BYTE *)info, skill)) + { + if (consoleplayer == Net_Arbitrator) + { + //Increment this. + botnum++; + } + + if (thebot != NULL) + { + thebot->inuse = BOTINUSE_Yes; + } + } + else + { + if (thebot != NULL) + { + thebot->inuse = BOTINUSE_No; + } + } delete[] info; +} + +bool FCajunMaster::DoAddBot (BYTE *info, botskill_t skill) +{ + int bnum; + + for (bnum = 0; bnum < MAXPLAYERS; bnum++) + { + if (!playeringame[bnum]) + { + break; + } + } + + if (bnum == MAXPLAYERS) + { + Printf ("The maximum of %d players/bots has been reached\n", MAXPLAYERS); + return false; + } + + D_ReadUserInfoStrings (bnum, &info, false); if (!deathmatch && playerstarts[bnum].type == 0) { Printf ("%s tried to join, but there was no player %d start\n", players[bnum].userinfo.GetName(), bnum+1); ClearPlayer (bnum, false); // Make the bot inactive again - if (botnum > 0) - { - botnum--; - } + return false; } + + multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). + players[bnum].Bot = new DBot; + GC::WriteBarrier (players[bnum].Bot); + players[bnum].Bot->skill = skill; + playeringame[bnum] = true; + players[bnum].mo = NULL; + players[bnum].playerstate = PST_ENTER; + + if (teamplay) + Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName()); else + Printf ("%s joined the game\n", players[bnum].userinfo.GetName()); + + G_DoReborn (bnum, true); + if (StatusBar != NULL) { - multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). - players[bnum].Bot = new DBot; - GC::WriteBarrier (players[bnum].Bot); - players[bnum].Bot->skill = skill; - playeringame[bnum] = true; - players[bnum].mo = NULL; - players[bnum].playerstate = PST_ENTER; - - if (teamplay) - Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName()); - else - Printf ("%s joined the game\n", players[bnum].userinfo.GetName()); - - G_DoReborn (bnum, true); - if (StatusBar != NULL) - { - StatusBar->MultiplayerChanged (); - } + StatusBar->MultiplayerChanged (); } - waitingforspawn[bnum] = false; + + return true; } void FCajunMaster::RemoveAllBots (bool fromlist) @@ -421,8 +452,6 @@ void FCajunMaster::RemoveAllBots (bool fromlist) if (fromlist) { wanted_botnum = 0; - for (i = 0; i < MAXPLAYERS; i++) - waitingforspawn[i] = false; } botnum = 0; } diff --git a/src/d_net.cpp b/src/d_net.cpp index 89dc36d69..3d0d20b41 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2250,7 +2250,7 @@ void Net_DoCommand (int type, BYTE **stream, int player) break; case DEM_ADDBOT: - bglobal.DoAddBot (stream); + bglobal.TryAddBot (stream, player); break; case DEM_KILLBOTS: diff --git a/src/d_protocol.h b/src/d_protocol.h index 0d11c7760..f75ee1b59 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -112,7 +112,7 @@ enum EDemoCommand DEM_DROPPLAYER, // 13 Not implemented, takes a byte DEM_CHANGEMAP, // 14 Name of map to change to DEM_SUICIDE, // 15 Player wants to die - DEM_ADDBOT, // 16 Byte: player#, String: userinfo for bot, 4 Bytes: skill (aiming, perfection, reaction, isp) + DEM_ADDBOT, // 16 Byte: botshift, String: userinfo for bot, 4 Bytes: skill (aiming, perfection, reaction, isp) DEM_KILLBOTS, // 17 Remove all bots from the world DEM_INVUSEALL, // 18 Use every item (panic!) DEM_INVUSE, // 19 4 bytes: ID of item to use diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 5e9ecbdba..a677420f5 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -280,7 +280,7 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) } if (thebot) { - thebot->inuse = true; + thebot->inuse = BOTINUSE_Yes; } bglobal.botnum++; dst->userinfo.TransferFrom(uibackup2);