Wavelength Logo
tl.jpg (2351 bytes) blank.gif (837 bytes) tr.jpg (2446 bytes)
blank.gif (837 bytes)
Controlling Player Speeds by Fireball
blank.gif (837 bytes)
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. 

 

blank.gif (837 bytes)
bl.jpg (2471 bytes) blank.gif (837 bytes) br.jpg (2132 bytes)