The Place to Start


Class System Tutorial
NewCoder
Intermediate


Class System Tutorial
    by NewCoder

Hi!  This is my first tutorial, so you may need to bear with me a little bit.  Basically, this is on creating character
classes the "cumbersome" way.  You may have read the tutorial on creating a class system at Wavelength and
didn't understand it fully.  We are going to do classes a different way, and hopefully it will be somewhat easier to
understand.  This is meant to be a stepping stone for you to make a killer class system.  Anyway, if you do use
this in your mod, please give me some credit.  If you have any problems, please e-mail me at
ferrari141@yahoo.com.

My code = RED

Regular HL code = CYAN

Before we begin churning out the code, lets think about what we're doing.  We want to give the player different
weapons when he respawns, based on his class.  So, we will probably need some sort of variable to tell us
what the class is, right?  Lets do that now.

Open up player.h and go to around line 89.
You should see these two lines.

int                     weapon;
float                 m_flFlashLightTime;     // Time until next battery draw/Recharge

Now, lets add our new variable.

int                     weapon;
int                     m_iPlayerClass; // *NewCoder* This is the integer that will store our class.
float                 m_flFlashLightTime;     // Time until next battery draw/Recharge

Pretty easy, eh?  We just defined what we call a "public" variable.  Coincidentally, if you scroll up, you will see
something like public:. What does a public variable do?  Basically, it allows you to access this variable from
virtually ANYWHERE in our code (its public, right?).

Now, open up multiplayer_gamerules.cpp and scroll down to line 470. This code handles what happens to the
player as he respawns.  Find these lines:

if ( addDefault )
    {
       pPlayer->GiveNamedItem( "weapon_crowbar" );
       pPlayer->GiveNamedItem( "weapon_9mmAR" );
       pPlayer->GiveAmmo( 68, "9mm", _9MM_MAX_CARRY );// 4 full reloads
    }

Ok, this should be pretty self-explanatory.   Obviously we want to give the player different weapons depending
on his class.   So lets do that now.

if ( addDefault )
    {
       if (pPlayer->m_iPlayerClass <= 0 || pPlayer->m_iPlayerClass > 2)

        {
            pPlayer->m_iPlayerClass = 1;
        } //This part of the code checks to see if m_iPlayerClass is less than 0 or greater than 2.

        if (pPlayer->m_iPlayerClass == 1) //If m_iPlayerClass is equal to 1...
        { //Then lets give him this junk....

        pPlayer->GiveNamedItem( "weapon_357" ); //This should be pretty self explanatory.
        pPlayer->GiveNamedItem( "weapon_357" );
        pPlayer->GiveNamedItem( "weapon_crowbar" );
        pPlayer->GiveNamedItem( "weapon_9mmhandgun" );
        pPlayer->GiveNamedItem( "weapon_handgrenade" );
        pPlayer->GiveAmmo( 68, "9mm", _9MM_MAX_CARRY );// 4 full reloads
        g_engfuncs.pfnSetClientMaxspeed( ENT( pPlayer->pev ), 600); //This sets the classes speed
        ClientPrint(pPlayer->pev, HUD_PRINTTALK, "You are now spy class."); //This prints "You are now spy
class"

        }
        else if (pPlayer->m_iPlayerClass == 2) //If m_iPlayerClass is equal to 2...
        {
 

        pPlayer->GiveNamedItem( "weapon_crowbar" );
        pPlayer->GiveNamedItem( "weapon_9mmAR" ); //He should be special and have a MP5
        pPlayer->GiveAmmo( 68, "9mm", _9MM_MAX_CARRY );// 4 full reloads
        pPlayer->GiveNamedItem( "weapon_handgrenade" );
        pPlayer->GiveNamedItem( "item_battery" );
        pPlayer->GiveNamedItem( "item_battery" ); //Give some armor...
        g_engfuncs.pfnSetClientMaxspeed( ENT( pPlayer->pev ), 300); //Set slower speed
        ClientPrint(pPlayer->pev, HUD_PRINTTALK, "You are now submachine gun infantry."); //Print to client
 

        }
    }

Sorry to give you all that at once!  Thats a lot of code!  It should be moderately self-explanatory.  I would like to
touch on the fact, however, that we used pPlayer->m_iPlayerClass instead of just m_iPlayerClass.  Remember
how we put the variable m_iPlayerClass in player.h?   Well, since we put it in that public area I was talking
about, we can access it in other files! Since we didn't create m_iPlayerClass in the multiplay_gamerules.cpp
(or multiplay_gamerules.h), then we can't refer to it as just "m_iPlayerClass".

==Advanced Stuff==
|    Don't feel like you have to read this...  But the reason we used pPlayer->m_iPlayerClass, for
|    more technical reasons, is that there is a "pointer" that we declared called pPlayer.
|    pPlayer basically, points to CBasePlayer, and lets us access the variables there.
=====

Ok, lets finish this up.  We made it so that, depending on the value of m_iPlayerClass, it would give us different
weapons.  Now, we have to change the value of m_iPlayerClass based on a button the player pushes.  So,
open up *FIX*client.cpp*FIX* and scroll down to about line 114.

{
GetClassPtr((CBasePlayer *)pev)->SelectLastItem();
}

else if (FStrEq(pcmd, "changeclass" )) //NewCoder - If you type changeclass in console....
{
        GetClassPtr((CBasePlayer *)pev)->ChangeClass(); //We'll run the ChangeClass routine...
  }  //NewCoder

Now, we have to write the actual routine that will change our class.    Open up player.h and and goto to about
line 180.

virtual void Spawn( void );
void Pain( void );

virtual void ChangeClass( void );
//Define the function for changing our class... This function will change the value of m_iPlayerClass.

virtual void Think( void );
virtual void Jump( void );

Yay!  We're almost done!  Now, open up player.cpp and go to line 4879.

return TRUE;
}

void CBasePlayer :: ChangeClass( void )
{ //This should be self-explanatory
    if (m_iPlayerClass == 2) //If m_iPlayerClass is equal to 2...
    {
        ClientPrint(pev, HUD_PRINTTALK, "You will now respawn as a spy..."); //Then print this...

        m_iPlayerClass = 1; //And m_iPlayerClass to 1....
    }
    else if(m_iPlayerClass == 1)
    {
        ClientPrint(pev, HUD_PRINTTALK, "You will now respawn as a submachine gun infantry...");
        m_iPlayerClass = 2;
    }
}

There you go! Thats all for today! Compile your project, and then go run a multiplayer game.  Bind a key to "changeclass", and have fun! (For those of you that don't know, "binding" a key is the process of assigning a value to a key)

If you need help, or would like some tips or advice, or I did something wrong, please e-mail at
ferrari141@yahoo.com.