2002-02-17 03:18:55 +00:00
|
|
|
/*
|
|
|
|
==============================================================================
|
|
|
|
RANKINGS.QC by Alan Kivlin <e-mail: alan.kivlin@cybersurf.co.uk>
|
|
|
|
|
|
|
|
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 =
|
|
|
|
{
|
2004-02-08 06:18:03 +00:00
|
|
|
fActiveClients |= clientBitFlag( clientno );
|
2002-02-17 03:18:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============================================================================
|
|
|
|
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);
|
|
|
|
};
|
|
|
|
|