mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-18 00:22:11 +00:00
- Fixed: Bots added by different setting controllers could be assigned the same player number.
This commit is contained in:
parent
1c500cead6
commit
1b7c07df65
6 changed files with 111 additions and 72 deletions
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
14
src/b_bot.h
14
src/b_bot.h
|
@ -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);
|
||||||
|
|
159
src/b_game.cpp
159
src/b_game.cpp
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue