Dynamically change player speed in script
by Amr Bekhit · 04/10/2007 (9:08 am) · 26 comments
Background
In order to move a player, a client sets the corresponding $mvActionValue variable to 1. So in order to move forward, $mvForwardAction is set to 1. However, it is perfectly possible to set the variable to anything from 0.0 to 1.0. So, if $mvForwardAction is set to 0.5, the player will move forward at 0.5 times their maximum speed (defined in the player's datablock).
This can be used to slow down a player, but can be also used to speed them up. As an example, let's say a player's normal speed is 10 and their boost speed is 40. In the player datablock, maxForwardSpeed would be set to 40. When moving the player normally, $mvForwardAction would be set to 0.25 (0.25*40 = 10). Whenever you want to speed up, set $mvForwardAction to anything above 0.25.
You need to store some sort of speed modifier in your player object to keep track of current speed. Also, the client will need to keep a copy of the current speed modifier, which the server will update when the speed changes.
The following code will add a Speed pickup to the game. When the player picks it up, their forward speed will be 4 times their normal speed (normal = 14, max = 56) for a short period of time, then return to normal. Therefore, for maximum speed, $mvForwardAction needs to be 1 and for normal speed, $mvForwardAction needs to be 0.25.
Note: This code is based on the starter.fps of TGE 1.5. It should work for other versions as well, since I haven't relied on anything fundamentally different
Known Issues
Thanks to Vincent van Delden, it has been pointed out that a client could potentially cheat with this system, because they can type $mvForwardAction = 1; in the console and get a boost of speed whenever they want.
In retrospect though, this might not be so much of a problem, since it is probably not a good idea to give clients access to the console during a multiplayer game anyway, and in a single player game, it is not a problem if a player cheats or no.
-----------------------------------------------------------------------------------
~/server/scripts/player.cs
There's a few things we need to do here. First we need to set up the player's maximum speed, and we also need someway to change the speed and tell the client about it.
In the middle of the PlayerData datablock, modify the following:
Now, we need to write a function that will enable us to change the player's speed and update this information on the client. At the bottom of player.cs add the following function:
When we call this function on the player, the speed will be stored in a variable called speedMod, then we use commandToClient to notify the client of the change. We will write the client-side function in a short while.
Now that we have a way to change player speed, we need to make sure that the player starts off at normal speed, so add this at the bottom of Armor::onAdd:
Now, when a player is added to the level, we immediately set their speed to 0.25 times their maximum speed (0.25*56 = 14), which in our case is the normal speed.
-----------------------------------------------------------------------------------
~/client/scripts/default.bind.cs
It is here that the client will update the movement of the player. First off, we need a function to respond to the commandToServer we wrote in player.cs above. Add this somewhere in the file:
When the server sends the client the player's speed, we store that in a global variable called $SpeedFactor. Then, we need to check if the player is already moving forward. If they are then we need to update their speed.
Finally, modify the function moveForward as follows:
If a key is pressed (%val is 1), then the player will move at the speed defined in $SpeedFactor.
This way, whenever we want to change the player's speed, use player.setSpeed, and this updates the client to use the new speed.
-----------------------------------------------------------------------------------
~/server/scripts/speedPickup.cs
To demonstrate the use of these functions, here is a speed pickup which will speed up the player for 5 seconds when picked up. You'll need to create a new file called speedPickup.cs and place it in ~/server/scripts/. Add the following code to it:
When a player collides with the item, the item is hidden, and then we schedule it to reappear after 5 seconds. Next, we set the player's speed to maximum. We also schedule the player to go back to their original speed after 5 seconds. This way, when the player picks up the speed pickup, there speed will be boosted to max for 5 seconds, then go back to normal.
-----------------------------------------------------------------------------------
~/server/scripts/game.cs
Because we added a new script file, we need to tell the game to load it when we play. Simply add the following line to the bottom of onServerCreated:
Once all the code is in, start up a level and add the speed pickup somewhere (you'll find it under the Items category). Then, run over it and watch how the player speeds up.
-----------------------------------------------------------------------------------
Adding a sprint key
Adding a sprint key is quite simple and works like this: when the player presses the sprint key, the client sends a command to the server telling it that the player wants to sprint. The server then uses the setSpeed function above, which sets the player's speed and updates the client with a new speed. Follow the steps below to add a sprint key to your game.
-----------------------------------------------------------------------------------
~/client/scripts/default.bind.cs
Only one thing we need to do here, and that's adding a sprint key and the function that handles it. Add the following somewhere in the file:
The last command binds left shift to the sprint function. When left shift is pressed, %val is 1, so the function sends a 1 to the server. When the key is released %val is 0 so the server receives a 0. Next, we'll add the server side sprint function.
-----------------------------------------------------------------------------------
~/server/scripts/player.cs
Here is where the work is done. Depending on the value the server gets from the client, the server will either boost the player or bring them back to their normal speed. Add the following at the bottom of the file:
To test the code, first delete the file ~/client/config.cs. This will allow the new key command we added to take effect. After that, simply run your game and hold down left shift to sprint.
In order to move a player, a client sets the corresponding $mvActionValue variable to 1. So in order to move forward, $mvForwardAction is set to 1. However, it is perfectly possible to set the variable to anything from 0.0 to 1.0. So, if $mvForwardAction is set to 0.5, the player will move forward at 0.5 times their maximum speed (defined in the player's datablock).
This can be used to slow down a player, but can be also used to speed them up. As an example, let's say a player's normal speed is 10 and their boost speed is 40. In the player datablock, maxForwardSpeed would be set to 40. When moving the player normally, $mvForwardAction would be set to 0.25 (0.25*40 = 10). Whenever you want to speed up, set $mvForwardAction to anything above 0.25.
You need to store some sort of speed modifier in your player object to keep track of current speed. Also, the client will need to keep a copy of the current speed modifier, which the server will update when the speed changes.
The following code will add a Speed pickup to the game. When the player picks it up, their forward speed will be 4 times their normal speed (normal = 14, max = 56) for a short period of time, then return to normal. Therefore, for maximum speed, $mvForwardAction needs to be 1 and for normal speed, $mvForwardAction needs to be 0.25.
Note: This code is based on the starter.fps of TGE 1.5. It should work for other versions as well, since I haven't relied on anything fundamentally different
Known Issues
Thanks to Vincent van Delden, it has been pointed out that a client could potentially cheat with this system, because they can type $mvForwardAction = 1; in the console and get a boost of speed whenever they want.
In retrospect though, this might not be so much of a problem, since it is probably not a good idea to give clients access to the console during a multiplayer game anyway, and in a single player game, it is not a problem if a player cheats or no.
-----------------------------------------------------------------------------------
~/server/scripts/player.cs
There's a few things we need to do here. First we need to set up the player's maximum speed, and we also need someway to change the speed and tell the client about it.
In the middle of the PlayerData datablock, modify the following:
datablock PlayerData(PlayerBody)
{
renderFirstPerson = false;
emap = true;
.
.
.
[b]maxForwardSpeed = 56;[/b] //Change the player's maximum forward speed
//to the maximum speed you want your player to move at
maxBackwardSpeed = 13;
maxSideSpeed = 13;Now, we need to write a function that will enable us to change the player's speed and update this information on the client. At the bottom of player.cs add the following function:
function Player::setSpeed(%this,%speed)
{
%this.speedMod=%speed;
//Now tell the client that we've sped up the player
commandToClient(%this.client,'SpeedChanged',%this.speedMod);
}When we call this function on the player, the speed will be stored in a variable called speedMod, then we use commandToClient to notify the client of the change. We will write the client-side function in a short while.
Now that we have a way to change player speed, we need to make sure that the player starts off at normal speed, so add this at the bottom of Armor::onAdd:
%obj.setSpeed(0.25);
Now, when a player is added to the level, we immediately set their speed to 0.25 times their maximum speed (0.25*56 = 14), which in our case is the normal speed.
-----------------------------------------------------------------------------------
~/client/scripts/default.bind.cs
It is here that the client will update the movement of the player. First off, we need a function to respond to the commandToServer we wrote in player.cs above. Add this somewhere in the file:
function clientCmdSpeedChanged(%speed)
{
$SpeedFactor=%speed;
//Check to see if the user is already moving forward
if ($mvForwardAction)
$mvForwardAction=$SpeedFactor; //User is moving forward so update their speed
}When the server sends the client the player's speed, we store that in a global variable called $SpeedFactor. Then, we need to check if the player is already moving forward. If they are then we need to update their speed.
Finally, modify the function moveForward as follows:
function moveforward(%val)
{
$mvForwardAction = %val * $SpeedFactor;
}If a key is pressed (%val is 1), then the player will move at the speed defined in $SpeedFactor.
This way, whenever we want to change the player's speed, use player.setSpeed, and this updates the client to use the new speed.
-----------------------------------------------------------------------------------
~/server/scripts/speedPickup.cs
To demonstrate the use of these functions, here is a speed pickup which will speed up the player for 5 seconds when picked up. You'll need to create a new file called speedPickup.cs and place it in ~/server/scripts/. Add the following code to it:
//Speed pickup
datablock ItemData(SpeedPickup)
{
shapeFile="~/data/shapes/items/speedPickup.dts"; //NOTE: You will need to provde
//your own model for the item, or
//just use one of the models already there.
category="Items";
};
function SpeedPickup::onCollision(%this,%obj,%col)
{
//Check to see that the collided object is a player
if (%col.getType() & $TypeMasks::PlayerObjectType)
{
//Hide the shape and show it after 5 seconds
%obj.setHidden(true);
%obj.schedule(5000,"setHidden",false);
%obj.schedule(5000,"startFade",500,0,false);
//Now speed up the player
%col.setSpeed(1); //1 = max speed of 56
//After 5 seconds, we want to slow the player down.
%col.schedule(5000,"setSpeed",0.25); //0.25 = regular speed of 14
}
}When a player collides with the item, the item is hidden, and then we schedule it to reappear after 5 seconds. Next, we set the player's speed to maximum. We also schedule the player to go back to their original speed after 5 seconds. This way, when the player picks up the speed pickup, there speed will be boosted to max for 5 seconds, then go back to normal.
-----------------------------------------------------------------------------------
~/server/scripts/game.cs
Because we added a new script file, we need to tell the game to load it when we play. Simply add the following line to the bottom of onServerCreated:
exec("./speedPickup.cs");Once all the code is in, start up a level and add the speed pickup somewhere (you'll find it under the Items category). Then, run over it and watch how the player speeds up.
-----------------------------------------------------------------------------------
Adding a sprint key
Adding a sprint key is quite simple and works like this: when the player presses the sprint key, the client sends a command to the server telling it that the player wants to sprint. The server then uses the setSpeed function above, which sets the player's speed and updates the client with a new speed. Follow the steps below to add a sprint key to your game.
-----------------------------------------------------------------------------------
~/client/scripts/default.bind.cs
Only one thing we need to do here, and that's adding a sprint key and the function that handles it. Add the following somewhere in the file:
function sprint(%val)
{
commandToServer('sprint',%val);
}
moveMap.bind(keyboard,lshift,sprint);The last command binds left shift to the sprint function. When left shift is pressed, %val is 1, so the function sends a 1 to the server. When the key is released %val is 0 so the server receives a 0. Next, we'll add the server side sprint function.
-----------------------------------------------------------------------------------
~/server/scripts/player.cs
Here is where the work is done. Depending on the value the server gets from the client, the server will either boost the player or bring them back to their normal speed. Add the following at the bottom of the file:
function serverCmdSprint(%client,%val)
{
if (%val)
%client.player.setSpeed(1); //The client wants to sprint, so boost the player's speed up to max
else
%client.player.setSpeed(0.25); //Bring the player's speedback to normal (0.25 * max speed)
}To test the code, first delete the file ~/client/config.cs. This will allow the new key command we added to take effect. After that, simply run your game and hold down left shift to sprint.
#22
07/24/2008 (12:52 pm)
ok i implemented all of the above code that you provided Amr but when i try to use the sprit key lshift it doesnt work am i missing something im using TGE_1_5_2 could this be apart of my problem?
#23
07/24/2008 (12:54 pm)
sry also when i try the speed pickup where do i place my model in my scripts and will i change the name of it in the SpeedPickup.cs file? or change the model name to fit the code? I guess either way would work.
#24
07/31/2008 (1:24 pm)
is it work TGe 1.5.2?
#26
Michael
07/26/2009 (8:24 pm)
Hey Amr I just wanted to let you know that I tried out all the code provided and it worked out perfectly. Thank you a bunch =].Michael

Torque Owner Jason Gossiaux
Indie Dev