/* ============================================================================== RANKINGS.QC by Alan Kivlin 07 / JUNE / 1997 Copyright (C) 1997 by Alan Kivlin. ============================================================================== */ // client number of the player/bot .float fClientNo; // bit flags for the (maximum) sixteen clients in standard quake float fActiveClients; // number of client entities available for the current game float fMaxClients; //---------------------------------------------------------------------------- // stores in fMaxClients, the maximum number of client's allowed in the game void() clientInitMaxClients; // returns the client's bit flag float( float fClientNo ) clientBitFlag; // returns TRUE if the client number specified is in use by a bot or player float( float fClientNo ) clientIsActive; // marks the client's bit flag as being in use void( float fClientNo ) clientSetUsed; // marks the client's bit flag as being available void( float fClientNo ) clientSetFree; // returns the next available free client number (-1 = none available) float() clientNextAvailable; //---------------------------------------------------------------------------- // bot's shirt and pants color .float fShirt; .float fPants; //---------------------------------------------------------------------------- // sample routine for connecting a bot //void() botConnect; // sample routine for disconnecting a bot void( entity bot ) botDisconnect; // moves the conflicting bot over to a free client number, if none it disconnects void( float clientno ) botInvalidClientNo; //---------------------------------------------------------------------------- float MSG_UPDATENAME = 13; // message id for update name float MSG_UPDATEFRAGS = 14; // message id for update frags float MSG_UPDATECOLORS = 17; // message id for update colors //---------------------------------------------------------------------------- // sends an update client name message to a player in the game void( entity player, float clientno, string clientname ) msgUpdateNameToPlayer; // sends an update client colors message to a player in the game void( entity player, float clientno, float clientshirt, float clientpants ) msgUpdateColorsToPlayer; // sends an update client frags message to a player in the game void( entity player, float clientno, float clientfrags ) msgUpdateFragsToPlayer; // sends an update client name message to all players in the game void( float clientno, string clientname ) msgUpdateNameToAll; // sends an update client colors message to all players in the game void( float clientno, float clientshirt, float clientpants ) msgUpdateColorsToAll; // sends an update client frags message to all players in the game void( float clientno, float clientfrags ) msgUpdateFragsToAll; //---------------------------------------------------------------------------- /* ============================================================================== clientInitMaxClients stores in fMaxClients, the maximum number of client's allowed in the game ============================================================================== */ void() clientInitMaxClients = { local entity ent; // this works by counting the number of entities created after world // so you must call it right at the beginning of worldspawn in WORLD.QC ent = nextent( world ); while( ent.classname != "worldspawn" ) { fMaxClients = fMaxClients + 1; ent = nextent( ent ); } }; /* ============================================================================== clientBitFlag returns the client's bit flag ============================================================================== */ float( float clientno ) clientBitFlag = { local float bitflag; bitflag = 1; while( clientno > 0 ) { bitflag = bitflag * 2; clientno = clientno - 1; } return bitflag; }; /* ============================================================================== clientIsActive returns TRUE if the client number specified is in use by a bot or player ============================================================================== */ float( float clientno ) clientIsActive = { if( fActiveClients & clientBitFlag( clientno ) ) return TRUE; return FALSE; }; /* ============================================================================== clientSetUsed marks the client's bit flag as being in use ============================================================================== */ void( float clientno ) clientSetUsed = { fActiveClients |= clientBitFlag( clientno ); }; /* ============================================================================== clientSetFree marks the client's bit flag as being available ============================================================================== */ void( float clientno ) clientSetFree = { fActiveClients = fActiveClients - ( fActiveClients & clientBitFlag( clientno ) ); }; /* ============================================================================== clientNextAvailable returns the next available free client number (-1 = none available) ============================================================================== */ float() clientNextAvailable = { local float clientno; clientno = 0; while( clientno < fMaxClients ) { if( ! clientIsActive( clientno ) ) return clientno; clientno = clientno + 1; } return -1; }; //---------------------------------------------------------------------------- /* ============================================================================== botConnect sample routine for connecting a bot ============================================================================== void() botConnect = { local float clientno; local entity bot; clientno = clientNextAvailable(); if( clientno == -1 ) { bprint( "Unable to connect a bot, server is full.\n" ); return; } clientSetUsed( clientno ); bot = spawn(); bot.fClientNo = clientno; bot.colormap = clientno + 1; // give the bot a name - you provide this routine // botSetName( bot ); bot.fShirt = floor( random() * 13 ); bot.fPants = floor( random() * 13 ); msgUpdateNameToAll( bot.fClientNo, bot.netname ); msgUpdateColorsToAll( bot.fClientNo, bot.fShirt, bot.fPants ); msgUpdateFragsToAll( bot.fClientNo, bot.frags ); bprint( bot.netname ); bprint( " entered the game\n" ); // add code to initialise the bot }; */ /* ============================================================================== botDisconnect sample routine for disconnecting a bot ============================================================================== */ void(string gibname, float dm) ThrowGib; void( entity bot ) botDisconnect = { if( bot.fClientNo != -1 ) { // the bot's client number is not in use by a real player so we // must remove it's entry in the rankings msgUpdateNameToAll( bot.fClientNo, string_null ); msgUpdateColorsToAll( bot.fClientNo, 0, 0 ); msgUpdateFragsToAll( bot.fClientNo, 0 ); clientSetFree( bot.fClientNo ); bot.fClientNo = -1; } bprint( bot.netname ); bprint( " left the game with " ); bprint( ftos( bot.frags ) ); bprint( " frags\n" ); botcounter = botcounter - 1; //sound( bot, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE ); //POX - 1.01b - Just gib the fucker... //POX - make a nice gib in Gib mode if (deathmatch & DM_GIB) bot.health = bot.health - 40; //POX-changed self to head model for multi skin support ThrowGib ("progs/gib3.mdl", bot.health); ThrowGib ("progs/gib1.mdl", bot.health); ThrowGib ("progs/gib2.mdl", bot.health); setmodel (bot, "progs/h_player.mdl"); setsize (bot, '0 0 0', '0 0 0'); bot.solid = SOLID_NOT; bot.movetype = MOVETYPE_TOSS; bot.deadflag = DEAD_DEAD; bot.nextthink = -1; if (random() < 0.5) sound (self, CHAN_VOICE, "player/gib.wav", 1, ATTN_NONE); else sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NONE); /* // add code to set the bot's suicide frame, copy it to the bodyque, etc //set_bot_suicide_frame (bot); bodyque_head.angles = bot.angles; bodyque_head.model = bot.model; bodyque_head.modelindex = bot.modelindex; bodyque_head.frame = bot.frame; bodyque_head.colormap = bot.colormap; bodyque_head.movetype = bot.movetype; bodyque_head.velocity = bot.velocity; bodyque_head.skin = bot.skin; bodyque_head.flags = 0; setorigin (bodyque_head, bot.origin); setsize (bodyque_head, bot.mins, bot.maxs); bodyque_head = bodyque_head.owner; */ remove (bot); }; /* ============================================================================== botInvalidClientNo moves the conflicting bot over to a free client number, if none it disconnects ============================================================================== */ void( float clientno ) botInvalidClientNo = { local entity bot; bot = find( world, classname, "bot" ); while( bot ) { if( bot.fClientNo == clientno ) { clientno = clientNextAvailable(); if( clientno != -1 ) { clientSetUsed( clientno ); bot.fClientNo = clientno; bot.colormap = bot.fClientNo + 1; msgUpdateNameToAll( bot.fClientNo, bot.netname ); msgUpdateColorsToAll( bot.fClientNo, bot.fShirt, bot.fPants ); msgUpdateFragsToAll( bot.fClientNo, bot.frags ); } else { bot.fClientNo = -1; botDisconnect( bot ); } return; } bot = bot.chain; //POX v1.1 Does this make more sense? //bot = find( bot, classname, "bot" ); } }; //---------------------------------------------------------------------------- /* ============================================================================== The following player specific update routines didn't work as I expected. For some reason, sending messages via MSG_ONE to a player that's just connected has no effect. My first thought was that the player would still be in the init stage so I sent via MSG_INIT but this also had no effect. Messages sent via MSG_ALL *DO* get to a player that's just connected so these routines aren't really necessary but I left them in anyway and made them call the relevent ToAll routines. ============================================================================== */ /* ============================================================================== msgUpdateNameToPlayer sends an update client name message to a player in the game ============================================================================== */ void( entity player, float clientno, string clientname ) msgUpdateNameToPlayer = { msgUpdateNameToAll( clientno, clientname ); return; //msg_entity = player; //WriteByte( MSG_ONE, MSG_UPDATENAME ); //WriteByte( MSG_ONE, clientno ); //WriteString( MSG_ONE, clientname ); }; /* ============================================================================== msgUpdateColorsToPlayer sends an update client colors message to a player in the game ============================================================================== */ void( entity player, float clientno, float clientshirt, float clientpants ) msgUpdateColorsToPlayer = { msgUpdateColorsToAll( clientno, clientshirt, clientpants ); return; //msg_entity = player; //WriteByte( MSG_ONE, MSG_UPDATECOLORS ); // WriteByte( MSG_ONE, clientno ); // WriteByte( MSG_ONE, clientshirt * 16 + clientpants ); }; /* ============================================================================== msgUpdateFragsToPlayer sends an update client frags message to a player in the game ============================================================================== */ void( entity player, float clientno, float clientfrags ) msgUpdateFragsToPlayer = { msgUpdateFragsToAll( clientno, clientfrags ); return; // msg_entity = player; //WriteByte( MSG_ONE, MSG_UPDATEFRAGS ); // WriteByte( MSG_ONE, clientno ); //WriteShort( MSG_ONE, clientfrags ); }; /* ============================================================================== msgUpdateNameToAll sends an update client name message to all players in the game ============================================================================== */ void( float clientno, string clientname ) msgUpdateNameToAll = { WriteByte (MSG_ALL, MSG_UPDATENAME); WriteByte (MSG_ALL, clientno); WriteString (MSG_ALL, clientname); }; /* ============================================================================== msgUpdateColorsToAll sends an update client colors message to all players in the game ============================================================================== */ void( float clientno, float clientshirt, float clientpants ) msgUpdateColorsToAll = { WriteByte (MSG_ALL, MSG_UPDATECOLORS); WriteByte (MSG_ALL, clientno); WriteByte (MSG_ALL, clientshirt * 16 + clientpants); }; /* ============================================================================== msgUpdateFragsToAll sends an update client frags message to all players in the game ============================================================================== */ void( float clientno, float clientfrags ) msgUpdateFragsToAll = { WriteByte (MSG_ALL, MSG_UPDATEFRAGS); WriteByte (MSG_ALL, clientno); WriteShort (MSG_ALL, clientfrags); };