Okay, here's again one of the weirdest bugs ever - those who drive you mad for hours bunking your face on walls until it turns into an obnoxious red/grey mixture.
I use ClientDisconnect() in my bot code to keep track of bots and players disconnecting, in order to reset their structures and/or adapt the players and bot counts, and other stuff, etc, etc.
Here's a typical ClientDisconnect() function from one of my bot DLLs (in this case, it's a The Specialists version, but it's the same for the other MODs)
Code:
void ClientDisconnect (edict_t *pEntity)
{
// this function is called whenever a client is VOLUNTARILY disconnected from the server,
// either because the client dropped the connection, or because the server dropped him from
// the game (latency timeout). The effect is the freeing of a client slot on the server. Note
// that clients and bots disconnected because of a level change NOT NECESSARILY call this
// function, because in case of a level change, it's a server shutdown, and not a normal
// disconnection. I find that completely stupid, but that's it. Anyway it's time to update
// the bots and players counts, and in case the client disconnecting is a bot, to back its
// brain(s) up to disk. We also try to notice when a listenserver client disconnects, so as
// to reset his entity pointer for safety. There are still a few server frames to go once a
// listen server client disconnects, and we don't want to send him any sort of message then.
printf ("RACC BOT DISCONNECTING\n");
// only process bots if we are in multiplayer mode
if (server.is_multiplayer && !DebugLevel.is_paused)
{
int player_index;
player_index = ENTINDEX (pEntity) - 1; // get this player's index
bots[player_index].is_active = FALSE; // mark this bot slot as free
// was this client a bot ?
if (players[player_index].is_racc_bot)
{
if (!FNullEnt (bots[player_index].pIllumination))
bots[player_index].pIllumination->v.flags |= FL_KILLME; // kill its light entity
BotShutdownPathMachine (&bots[player_index]); // shutdown our bot's pathmachine
BotNavSaveBrain (&bots[player_index]); // save our bot's nav brain
BotHALSaveBrain (&bots[player_index]); // save our bot's HAL brain
bot_count--; // decrement the bot count as we know this bot is disconnecting
}
memset (&players[player_index], 0, sizeof (players[player_index])); // reset his structure
players[player_index].pEntity = NULL; // clear his entity pointer
player_count--; // decrement the player count as we know this client is disconnected
}
(*other_gFunctionTable.pfnClientDisconnect) (pEntity);
}
....ah yes, because perhaps I never annoucned it yet, but the next release of my bot will probably support The Specialists
Now THE PROBLEM, is that, as the commenting says, ClientDisconnect() doesn't seem to be called each time someone is disconnected.
It looks like if you use the 'kick' command, ClientDisconnect() is not called. Neither is it on map changes (but NOT all cases, and THAT's the weirdest thing !!!)
I am completely puzzled. Is there a reason and eventually a fix to apply somewhere or do I need to move all the connecting/disconnecting stuff to the beginning of StartFrame ??? That would be more portable perhaps but since these functions are provided for this purpose it would be a shame not to use them.. ???