This tutorial shows how to enable you
to set what speeds the player can go, and force them to remain at those
speeds. Most of the setting and checking is done on the client side,
so there should be no noticable increase in network traffic. The
system used should easily be altered to make use of any player class system
or take into account any special items that can alter someone's speed.
File names are shown in red.
Existing code is shown in yellow. Additions
you have to make are shown in green.
Server side changes
First, we must modify the server to send
the speed information to the client. Let's start by adding a variable
to the player class so the server knows when it needs to send an update
to the client, as well as a function to determine what the speed of the
player should be:
PLAYER.H (near
the bottom):
void
SetCustomDecalFrames( int nFrames );
int
GetCustomDecalFrames( void );
int
m_iClientSpeed; // What the client thinks the player's max speed
is
int
PlayerSpeed() {return 270;}
};
Change 270 to whatever speed you want,
or perform any calculations such as determining speed based on the player's
class or equipment, etc.
Next we need to set up the message to the
client:
PLAYER.CPP:
(near the top)
int
gmsgHealth = 0;
int
gmsgSpeed = 0;
int
gmsgDamage = 0;
(in CBasePlayer::Precache)
gmsgHealth
= REG_USER_MSG( "Health", 1 );
gmsgSpeed
= REG_USER_MSG( "Speed", 2);
gmsgDamage
= REG_USER_MSG( "Damage", 12 );
Now we'll set the server-side limitation
on speed, and force an update to the client:
(in CBasePlayer::Spawn)
m_lastx
= m_lasty = 0;
g_engfuncs.pfnSetClientMaxspeed(
ENT( pev ), PlayerSpeed() );
m_iClientSpeed
= 0; // force speed update to client
g_pGameRules->PlayerSpawn(
this );
}
Finally we need to actually send the message,
if necessary:
(in CBasePlayer::UpdateClientData)
m_iClientHealth = pev->health;
}
int
iSpeed = PlayerSpeed();
if
(iSpeed != m_iClientSpeed)
{
// send "Speed" update message
MESSAGE_BEGIN( MSG_ONE, gmsgSpeed, NULL, pev );
WRITE_SHORT( iSpeed );
MESSAGE_END();
m_iClientSpeed = iSpeed;
}
if
(pev->armorvalue != m_iClientBattery)
Whew! That's it for the server side.
All it basically does is send the speed to the client whenever it's changed.
Now on to the part that actually makes things happen...
Client side changes
The easy part is that you'll need to download
SPEED.CPP
and add it to your client's project. You'll want to look at the CHudSpeed::SetSpeed
function. Currently I have it setting the side and back speeds to
half the forward speed (because I'm a realism nut), and the walk to run
ratio is 0.5. You can alter these as you wish, but if you do, be
sure to change the CHudSpeed::Think function in the same way. If
you want the speeds to be set independant of each other, you'll need to
modify both the server and client to send an individual message for each
speed.
Before compiling, though, we need to add
a few lines to some other files. First let's add a new class definition
for the new CHudSpeed class, and add an instance of it to the CHud class:
HUD.H (add
anywhere):
class
CHudSpeed: public CHudBase
{
public:
int
m_iSpeed;
int
Init( void );
void
Think( void );
void
SetSpeed( void );
int
MsgFunc_Speed(const char *pszName, int iSize, void *pbuf);
};
(in class CHud, near bottom of file):
CHudBattery
m_Battery;
CHudSpeed
m_Speed;
CHudTrain
m_Train;
And finally, we need to call the Init function:
HUD.CPP (in
CHud::Init):
m_Menu.Init();
m_Speed.Init();
MsgFunc_ResetHUD(0,
0, NULL );
That's it! Hopefully everything compiles,
and you now have very rigid player speeds that can't be modified.
Some issues not covered in this tutorial are the numbers used by Half-Life
for determining things such as when to show the player as running or walking,
and how loud and frequently to play footstep noises. Search for "speed"
in PLAYER.CPP and you'll see what I mean. You should be able to base
these off the PlayerSpeed() function instead of the existing hard-coded
values pretty easily. |