Name of Mod        : Advanced Bot Frame
File Name          : abframe.zip
Version            : N/A
Date               : November 08, 1999
Author             : Rich Whitehouse
E-mail             : thefatal@telefragged.com
Web Site           : http://www.telefragged.com/thefatal/
---------------------------------------------------------
This is for people wanting to make their own Half-Life bot.
Before you start you will need the standard/pro SDK for
Half-Life, and a compiler capable of compiling it (such as
Microsoft Visual C++ 5.0 or later).

The following files are included with the archive:

basemonster.h
bot.cpp
client.cpp
player.cpp
player.h

To compile the code properly, copy client.cpp, basemonster.h,
player.cpp, and player.h into your folder containing the SDK code over
the original copies, and copy bot.cpp into the same folder. Now, open
the project and add bot.cpp to it. Compile it and you'll have a fully
working mp.dll. Put the liblist.gam file included in the archive in a
folder under your Half-Life directory called "bot", then create a
folder called "dlls" under the bot folder and put the mp.dll file in
that. Start HL, select the bot with the custom game option, start a
LAN game, type "addbot" in the console once you've loaded up a map,
and you can see the bot that you've spawned enter the level. Now, onto
explaining the source code bit by bit.

Note that all modifications to the existing project files are marked
by "START BOT" and "END BOT". bot.cpp is written from scratch, so it
is not marked. Also note that these basemonster.h and client.cpp files
are from the standard SDK and not the pro SDK, so if you have the pro
SDK you may want to insert the changes in the files manually instead
of copying them over the pro SDK files. The pro SDK files are different
in other ways and may cause compilation errors if you copy the standard
SDK files over them.

First, let's open basemonster.h. Skip down to line 39, and you'll see:

	virtual int	 BloodColor( void ) { return m_bloodColor; }
	//The above line is only needed if you are using the standard SDK and
	//not the pro SDK.
	int isabot;
	float fwd_val;
	float side_val;
	EHANDLE enemy;
	EHANDLE item;

The BloodColor virtual function only needs to be added if you don't have
the pro SDK. It causes the bots and other players to "bleed", which was
originally taken out of the standard SDK.
The isabot value is used to store if a client is a bot or player. We'll
set it to 1 for bots, and leave it at 0 for players.
The fwd_val and side_val variables will be used later in the actual bot
AI, so don't worry about them right now.
The enemy and item EHANDLEs are used to handle and keep track of
enemies and items the bot is after. This will also be used in bot.cpp
later in the actual AI, so again, don't worry about it right now.

Now open player.h. Scroll down to line 172, and you will see:

	float timechangedir;
	int roamdir;
	virtual void BThink ( void );

The timechangedir and roamdir variables are used in the bot's roaming
function in bot.cpp. You can take a look at that later, after we get
through all of this.
The BThink virtual function will be our function which acts as the bot's
think function and is called for it each frame. It will be defined in
full later in bot.cpp, so don't worry about it for now.

Now, let's open client.cpp. Move down to line 317, and you'll see:

	void BotConnect( edict_t *aEntity);

This just predeclares the bot connection function (in bot.cpp) so that
it can be called later in another function. Now, skip to line 376.

	else if (FStrEq(pcmd, "addbot" ))
	{
		BotConnect(pEntity); //If user types "addbot" in console, add a bot.
	}

This checks to see if the "addbot" command has been entered by a client,
and if it has, it calls our bot connection function in bot.cpp. Now onto
line 508.

CBasePlayer	*CBasePlayerByIndex( int playerIndex )
{
	CBasePlayer *pPlayer = NULL;
	entvars_t *pev;

	if ( playerIndex > 0 && playerIndex <= gpGlobals->maxClients )
	{
		edict_t *pPlayerEdict = INDEXENT( playerIndex );
		if ( pPlayerEdict && !pPlayerEdict->free && (pPlayerEdict->v.flags & FL_FAKECLIENT || pPlayerEdict->v.flags & FL_CLIENT) ) //fake
		{
			pev = &pPlayerEdict->v;
			pPlayer = GetClassPtr((CBasePlayer *)pev);
		}
	}
	
	return pPlayer;
}

This function finds a player given his index number and returns him to us.
This function is used directly below down on line 530.

	for ( int i = 1; i <= gpGlobals->maxClients; i++ )
	{
		CBasePlayer *pPlayer = CBasePlayerByIndex( i );

		if (pPlayer && pPlayer->isabot == 1) {
			pPlayer->BThink(); //Find a bot each frame and call its think function.
		}
	}

This is under the StartFrame function so that it is called once every
frame. It cycles through all clients in the game, and if it finds one
that is a bot, it calls the bot think function for it. Well, that's
all for client.cpp, so, open up player.cpp. We hardly have to do anything
here. Scroll down to line 3091. You'll see:

	pev->flags			= FL_CLIENT;
	if (isabot == 1)
		pev->flags = pev->flags + FL_FAKECLIENT;

This tells us to flag the player as a fake client also if it's a bot. 
We're done here now, so, finally, go and open up bot.cpp.

In bot.cpp, we first define the CBot class so we can set the isnetclient
value to false for bots as it should be.

Next, we define the bot think function. This calls our main AI function
and the physics function. See the comments by the code for more help.

The following functions are fairly self-explanitory. They create a fake
client edict using pfnCreateFakeClient and connect the bot to the server
by attaching it to a player object.

After you've taken a look at all that, go back to the BasicAI function.
It may confuse you a little at first, but I tried to make it as simple
as I could. It's completely commented and documented, so study it for a
while, and hopefully you'll catch on. After that, you can begin making
your own modifications and advancements to get started on your own
bot.

Well then, that should be all you need to get started on your own bot.
Good luck.

COPYRIGHT/PERMISSIONS
---------------------
You may do whatever you want with this code, as long as you give me
some credit for it.
