- Fixed: Bots added by different setting controllers could be assigned the same player number.

This commit is contained in:
ChillyDoom 2014-10-25 14:58:10 +01:00
parent 1c500cead6
commit 1b7c07df65
6 changed files with 111 additions and 72 deletions

View file

@ -125,7 +125,7 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam)
bot = bot->next; bot = bot->next;
if (bot) if (bot)
{ {
bot->inuse = false; bot->inuse = BOTINUSE_No;
bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE; bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE;
} }
if (players[i].Bot != NULL) if (players[i].Bot != NULL)
@ -172,7 +172,7 @@ CCMD (listbots)
while (thebot) 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; thebot = thebot->next;
count++; count++;
} }

View file

@ -60,6 +60,13 @@ struct botskill_t
FArchive &operator<< (FArchive &arc, botskill_t &skill); FArchive &operator<< (FArchive &arc, botskill_t &skill);
enum
{
BOTINUSE_No,
BOTINUSE_Waiting,
BOTINUSE_Yes,
};
//Info about all bots in the bots.cfg //Info about all bots in the bots.cfg
//Updated during each level start. //Updated during each level start.
//Info given to bots when they're spawned. //Info given to bots when they're spawned.
@ -69,7 +76,7 @@ struct botinfo_t
char *name; char *name;
char *info; char *info;
botskill_t skill; botskill_t skill;
bool inuse; int inuse;
int lastteam; int lastteam;
}; };
@ -88,7 +95,7 @@ public:
bool SpawnBot (const char *name, int color = NOCOLOR); bool SpawnBot (const char *name, int color = NOCOLOR);
bool LoadBots (); bool LoadBots ();
void ForgetBots (); void ForgetBots ();
void DoAddBot (BYTE **stream); void TryAddBot (BYTE **stream, int player);
void RemoveAllBots (bool fromlist); void RemoveAllBots (bool fromlist);
void DestroyAllBots (); void DestroyAllBots ();
@ -122,6 +129,9 @@ public:
bool m_Thinking; bool m_Thinking;
private: private:
//(B_Game.c)
bool DoAddBot (BYTE *info, botskill_t skill);
//(B_Func.c) //(B_Func.c)
bool Reachable (AActor *actor, AActor *target); bool Reachable (AActor *actor, AActor *target);
void Dofire (AActor *actor, ticcmd_t *cmd); void Dofire (AActor *actor, ticcmd_t *cmd);

View file

@ -89,8 +89,6 @@ enum
BOTCFG_TEAM BOTCFG_TEAM
}; };
static bool waitingforspawn[MAXPLAYERS];
FCajunMaster::~FCajunMaster() FCajunMaster::~FCajunMaster()
{ {
ForgetBots(); ForgetBots();
@ -162,8 +160,6 @@ void FCajunMaster::Main (int buf)
void FCajunMaster::Init () void FCajunMaster::Init ()
{ {
int i;
botnum = 0; botnum = 0;
firstthing = NULL; firstthing = NULL;
spawn_tries = 0; spawn_tries = 0;
@ -172,11 +168,6 @@ void FCajunMaster::Init ()
body1 = NULL; body1 = NULL;
body2 = NULL; body2 = NULL;
for (i = 0; i < MAXPLAYERS; i++)
{
waitingforspawn[i] = false;
}
if (ctf && teamplay == false) if (ctf && teamplay == false)
teamplay = true; //Need teamplay for ctf. (which is not done yet) teamplay = true; //Need teamplay for ctf. (which is not done yet)
@ -192,7 +183,7 @@ void FCajunMaster::Init ()
while (thebot != NULL) while (thebot != NULL)
{ {
thebot->inuse = false; thebot->inuse = BOTINUSE_No;
thebot = thebot->next; thebot = thebot->next;
} }
} }
@ -232,12 +223,10 @@ void FCajunMaster::End ()
//The color parameter can be either a //The color parameter can be either a
//color (range from 0-10), or = NOCOLOR. //color (range from 0-10), or = NOCOLOR.
//The color parameter overides bots //The color parameter overides bots
//induvidual colors if not = NOCOLOR. //individual colors if not = NOCOLOR.
bool FCajunMaster::SpawnBot (const char *name, int color) bool FCajunMaster::SpawnBot (const char *name, int color)
{ {
int playernumber;
//COLORS //COLORS
static const char colors[11][17] = 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 "\\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; botinfo_t *thebot;
int botshift;
if (name) if (name)
{ {
thebot = botinfo; thebot = botinfo;
// Check if exist or already in the game. // Check if exist or already in the game.
botshift = 0;
while (thebot && stricmp (name, thebot->name)) while (thebot && stricmp (name, thebot->name))
{
thebot = thebot->next; thebot = thebot->next;
botshift++;
}
if (thebot == NULL) if (thebot == NULL)
{ {
Printf ("couldn't find %s in %s\n", name, BOTFILENAME); Printf ("couldn't find %s in %s\n", name, BOTFILENAME);
return false; 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); Printf ("%s is already in the thick\n", name);
return false; return false;
@ -296,9 +280,13 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
{ {
int rnum = (pr_botspawn() % loaded_bots); int rnum = (pr_botspawn() % loaded_bots);
thebot = botinfo; thebot = botinfo;
botshift = 0;
while (rnum) while (rnum)
{
--rnum, thebot = thebot->next; --rnum, thebot = thebot->next;
if (!thebot->inuse) botshift++;
}
if (thebot->inuse == BOTINUSE_No)
vacant = true; vacant = true;
} }
} }
@ -308,10 +296,10 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
return false; return false;
} }
waitingforspawn[playernumber] = true; thebot->inuse = BOTINUSE_Waiting;
Net_WriteByte (DEM_ADDBOT); Net_WriteByte (DEM_ADDBOT);
Net_WriteByte (playernumber); Net_WriteByte (botshift);
{ {
//Set color. //Set color.
char concat[512]; char concat[512];
@ -332,61 +320,104 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
Net_WriteByte(thebot->skill.reaction); Net_WriteByte(thebot->skill.reaction);
Net_WriteByte(thebot->skill.isp); Net_WriteByte(thebot->skill.isp);
thebot->inuse = true;
//Increment this.
botnum++;
return true; 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); char *info = ReadString (stream);
BYTE *infob = (BYTE *)info;
botskill_t skill; botskill_t skill;
skill.aiming = ReadByte (stream); skill.aiming = ReadByte (stream);
skill.perfection = ReadByte (stream); skill.perfection = ReadByte (stream);
skill.reaction = ReadByte (stream); skill.reaction = ReadByte (stream);
skill.isp = 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; 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) if (!deathmatch && playerstarts[bnum].type == 0)
{ {
Printf ("%s tried to join, but there was no player %d start\n", Printf ("%s tried to join, but there was no player %d start\n",
players[bnum].userinfo.GetName(), bnum+1); players[bnum].userinfo.GetName(), bnum+1);
ClearPlayer (bnum, false); // Make the bot inactive again ClearPlayer (bnum, false); // Make the bot inactive again
if (botnum > 0) return false;
{
botnum--;
}
} }
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 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). StatusBar->MultiplayerChanged ();
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 ();
}
} }
waitingforspawn[bnum] = false;
return true;
} }
void FCajunMaster::RemoveAllBots (bool fromlist) void FCajunMaster::RemoveAllBots (bool fromlist)
@ -421,8 +452,6 @@ void FCajunMaster::RemoveAllBots (bool fromlist)
if (fromlist) if (fromlist)
{ {
wanted_botnum = 0; wanted_botnum = 0;
for (i = 0; i < MAXPLAYERS; i++)
waitingforspawn[i] = false;
} }
botnum = 0; botnum = 0;
} }

View file

@ -2250,7 +2250,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
break; break;
case DEM_ADDBOT: case DEM_ADDBOT:
bglobal.DoAddBot (stream); bglobal.TryAddBot (stream, player);
break; break;
case DEM_KILLBOTS: case DEM_KILLBOTS:

View file

@ -112,7 +112,7 @@ enum EDemoCommand
DEM_DROPPLAYER, // 13 Not implemented, takes a byte DEM_DROPPLAYER, // 13 Not implemented, takes a byte
DEM_CHANGEMAP, // 14 Name of map to change to DEM_CHANGEMAP, // 14 Name of map to change to
DEM_SUICIDE, // 15 Player wants to die 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_KILLBOTS, // 17 Remove all bots from the world
DEM_INVUSEALL, // 18 Use every item (panic!) DEM_INVUSEALL, // 18 Use every item (panic!)
DEM_INVUSE, // 19 4 bytes: ID of item to use DEM_INVUSE, // 19 4 bytes: ID of item to use

View file

@ -280,7 +280,7 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name)
} }
if (thebot) if (thebot)
{ {
thebot->inuse = true; thebot->inuse = BOTINUSE_Yes;
} }
bglobal.botnum++; bglobal.botnum++;
dst->userinfo.TransferFrom(uibackup2); dst->userinfo.TransferFrom(uibackup2);