/*
==============================================================================
README.TXT

4 / MAY / 1997

Copyright (C) 1997 by Alan Kivlin (aka Virtuoso)

Routines for allowing a bot to change color as well as have its name and
frags on the rankings screen.

NOTE
----

client number 0 is player 1
shirt and pants color range is between 0 and 13

------------------------------------------------------------------------------

I have included sample routines for controlling the use of the client numbers
although I haven't had a chance to implement them in a multiplayer
(ie. 2 or more real players) environment:

when a real player enters the game you must set its bitflag by calling:
   clientSetUsed( self.colormap - 1 ) // in ClientConnect()

when a real player leaves the game you must set its bitflag by calling:
   clientSetFree( self.colormap - 1 ) // in ClientDisconnect()

when a bot is created you must search for a free client number by calling:
   fClientNo = clientNextAvailable();

   if( fClientNo == -1 )
      // do something here as there are no free client numbers available

   clientSetUsed( fClientNo );

   self.colormap = fClientNo + 1; // use the colormap for reference to the
                                  // bot's client number

a client number used by a bot can be taken over by a player joining the
game therefore you must check to see if the connecting player is using a 
client number currently occupied by a bot - if it is then you must find 
the next available client number and change the bot over to it - if none are
free then I guess its goodbye to the bot till a client number becomes
available

updating the frags should be done in ClientObituary()

updating the bots name frags and color should be done when its created and
also anytime its client number is taken over by a real player

------------------------------------------------------------------------------

I hope this is useful to bot makers out there and especially CTFBot which
IMO is the best bot release since the mighty ReaperBot.

------------------------------------------------------------------------------

I would like to say a big thank you to the authors of, Film At 11, as it was
through my curiosity of this cool DEM file editor that I saw 16 update 
frags / colors / name messages near the beginning in the list of message
blocks - this made me realise how easy it would be to implement bots on the 
rankings screen as well as being able to change its color.

I also would like to thank the authors of the Quake DEM specs for their 
amazing work documenting the Quake DEM files.

------------------------------------------------------------------------------

I've released this info after chatting with a few cool ppl in #quake who
wanted to know how I managed to get my bot on the rankings screen... here you
go Swift - pity about that cool parm1..parm16 idea, I'm afraid it doesn't
work due to them being globals and Quake only calls SetChangeParms() for real
clients :(

I am currently working on a QuakeC bot - heh tentatively called QCBot of 
which I have released a couple of .DEM files showing a little of the work I've
completed so far...

It shows up on the rankings screen as you can probably guess - but i've also 
completed a lot of work on bot movement, you'll see the bot walk effortlessly
on broken ground - heh it goes a little slower up the slope towards the
lightning gun on map START but I'm working on it!

There is a lot of other "never before seen in a bot (TM)" it does but I'll 
let you see some of them for yourself when you look at the demos, look out
for it jumping in E1M2 - heh it gave me so much future motivation when I
realised I had worked out how to get it to jump properly :)

I have completed a lot more than is being shown but I guess its still only
about 60% done, my main hope is that when its nearly finished, id Software
will like it and give me a little help with very very small changes to the
quake .EXE - primarily a method of carrying over globals to the next level
(or fixing the zone buffer overflow would be ok) and a new builtin which lets
me know what the maximum edictcount is. If at all possible I would really
like to have around 1024 (currently 500 odd in v1.08) edicts available but 
this is only really important in very big levels such as BASE32 etc (or for
32 player games when implemented for QW).

A dream change would be a new builtin for enabling one of the 16 (or 
maxplayers) edicts created after world, which would allow me to drop all my 
code for overcoming the bot not being MOVETYPE_WALK.

As I don't have an internet account I've no email address but I do visit my
local cybercafe quite frequently and you can usually find me sitting in #quake
on Undernet IRC.

One final thing, this quake bot is gonna be UNREAL (heh pun *IS* intended) :P
but since I haven't mentioned the sort of functional ability being coded into
it (except bits and pieces on Undernet IRC), I guess noone actually knows if 
it will be better!

Watch this space...
==============================================================================
*/

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

/*
==============================================================================
msgUpdateName

sends an update client name message to all clients in the game
==============================================================================
*/

void( float fClientNo, string sName ) msgUpdateName =
{
   WriteByte( MSG_ALL, MSG_UPDATENAME );
   WriteByte( MSG_ALL, fClientNo );
   WriteString( MSG_ALL, sName );
};

/*
==============================================================================
msgUpdateFrags

sends an update client frags message to all clients in the game
==============================================================================
*/

void( float fClientNo, float fFrags ) msgUpdateFrags =
{
   WriteByte( MSG_ALL, MSG_UPDATEFRAGS );
   WriteByte( MSG_ALL, fClientNo );
   WriteShort( MSG_ALL, fFrags );
};

/*
==============================================================================
msgUpdateColors

sends an update client colors message to all clients in the game
==============================================================================
*/

void( float fClientNo, float fShirt, float fPants ) msgUpdateColors =
{
   WriteByte( MSG_ALL, MSG_UPDATECOLORS );
   WriteByte( MSG_ALL, fClientNo );
   WriteByte( MSG_ALL, fShirt * 16 + fPants );
};

//----------------------------------------------------------------------------

// holds the bit flags for the (maximum) sixteen clients in standard quake
float fActiveClients;

/*
==============================================================================
clientBitFlag

returns the client's bit flag
==============================================================================
*/

float( float fClientNo ) clientBitFlag =
{
   local float fClientBitFlag;

   fClientBitFlag = 1;
   fClientNo = fClientNo + 1; // bit flags start at 1 not 0

   while( fClientNo > 1 )
   {
      fClientBitFlag = fClientBitFlag * 2;
      fClientNo = fClientNo - 1;
   }

   return fClientBitFlag;
};

/*
==============================================================================
clientIsActive

returns TRUE if the client number specified is in use by a bot or player
==============================================================================
*/

float( float fClientNo ) clientIsActive =
{
   if( fActiveClients & clientBitFlag( fClientNo ) )
      return TRUE;

   return FALSE;
};

/*
==============================================================================
clientSetUsed

marks the client's bit flag as being in use
==============================================================================
*/

float( float fClientNo ) clientSetUsed =
{
   fActiveClients = fActiveClients | clientBitFlag( fClientNo );
};

/*
==============================================================================
clientSetFree

marks the client's bit flag as being available
==============================================================================
*/

float( float fClientNo ) clientSetFree =
{
   fActiveClients = fActiveClients - 
      ( fActiveClients & clientBitFlag( fClientNo ) );
};

/*
==============================================================================
clientNextAvailable

returns the next available free client number (-1 = none available)
==============================================================================
*/

float() clientNextAvailable =
{
   local float fClientNo;

   fClientNo = 0;

   while( fClientNo <= 15 )
   {
      if( ! clientIsActive( fClientNo ) )
         return fClientNo;

      fClientNo = fClientNo + 1;
   }

   return -1;
};

