There
are a few ways of implementing a class system. The first is to just
have a flag indicating the class, then do a switch or series of if
statements everytime something differs for each class. This can get
incredibly cumbersome. Especially if you have multiple classes.
Now before I go into more detail, I'm going to have a disclaimer.
This tutorial is meant for programmers who are very familiar with
Object Oriented Programming (OOP) in C++, and those who aren't
should just skip this and do the cumbersome method :) Feel free to
ask me questions about the tutorial so long as they aren't basic C++
or OOP questions.
That said, my suggestion is to make a new class that is the base
class for all your player classes (I called it CBaseClass). Then,
derive all your classes from that. Add functions like
CBaseClass::PlayerSpeed() which return a value. Then, make a pointer
to the class in CBasePlayer, and call it's memeber functions to
determine what you need to do.
Example 1: The basics
---------------------
OK, quick example. I'll just make 2 actual classes so the code
doesn't go on forever. I'll start by just adding one function which
you use to determine the class's speed:
Make a new file "classes.h"
with the following code:
class CBaseClass {
public:
virtual int PlayerSpeed() { return 200; };
};
class CSpy : public CBaseClass {
public:
virtual int PlayerSpeed() { return 500; };
};
class CSloth : public CBaseClass {
public:
virtual int PlayerSpeed() { return 100; };
};
Now, go modify player.h
to include a pointer to a
CBaseClass (make sure its public).
CBaseClass * m_pClass;
So it knows what a CBaseClass
is, right before the definition of
CBasePlayer, add the line:
class CBaseClass;
This'll tell the compiler that there is a class called
CBaseClass, but we don't
need to worry about its details yet. Now,
in player.cpp, add an
include for classes.h
#include "classes.h"
How you determine who is what class is up to you, one way is to
randomly assign the player to a class when he joins. A better way
would be to bring up a menu and let the player select it, but that
brings up alot of other nasty issues. Check out my observer tutorial
and the menu tutorial to get an idea how this is done.
To do the random select thing, do this in
RecountTeams():
float fRand = RANDOM_FLOAT( 0, 1
);
if(fRand < 0.5)
pPlayer->m_pClass = new CSpy;
else
pPlayer->m_pClass = new CSloth;
Don't forget to delete the pointers before you allocate new ones if
this function will be called more than once during the game! Now,
finally, in PlayStepSound():
g_engfuncs.pfnSetClientMaxspeed(
ENT( pev ), m_pClass->PlayerSpeed() );
No if statements, and everything is nicely abstracted!
Example 2: Changing the model
-----------------------------
Say we want to change the player's model based on his class (you're
probably going to want to do this). In each of the object's
constructors, add this line:
g_engfuncs.pfnSetClientKeyValue(
m_pPlayer->entindex(), g_engfuncs.pfnGetInfoKeyBuffer(
m_pPlayer->edict() ), "model", "gordon");
where "gordon" can be any model you want. The one thing i left out
that you need to make this work (didn't need it until now), is a
pointer to the player who's using this class, so add a public
constructor to the base class, and a member variable to hold the
pointer to the player:
public: CBaseClass(CBasePlayer *
pPlayer); CBasePlayer * m_pPlayer;
And now you'll want a classes.cpp
file, so make it, and add this code to it:
#include "classes.h"
#include "player.h"
CBaseClass::CBaseClass(CBasePlayer * pPlayer) {
m_pPlayer = pPlayer;
}
I think that should do it. Note that if you want special
action for each class's constructor, you'll need to overide the
constructor with this code in the .h file:
public:
CSpy(CBasePlayer * pPlayer);
and this code in the .cpp file:
CSpy::CSpy(CBasePlayer * pPlayer)
: CBaseClass(pPlayer) {
// Do whatever you want
}
You'll also have to modify
RecountTeams() again where you created the object like this:
float fRand = RANDOM_FLOAT( 0, 1
);
if(fRand < 0.5)
pPlayer->m_pClass = new CSpy;
else
pPlayer->m_pClass = new CSloth;
change it to:
float fRand = RANDOM_FLOAT( 0, 1
);
if(fRand < 0.5)
pPlayer->m_pClass = new CSpy(pPlayer);
else
pPlayer->m_pClass = new CSloth(pPlayer);
because you are going to need to pass in a pointer to the player who
is using it. |