Charge Jump
by James Laker (BurNinG) · 05/26/2005 (11:23 pm) · 36 comments
Wanted to do this a while ago, but canned the project do to real life taking
way too much time :( Anyway... I promised Adam Brookman ;)
So let's get right to it...
Open up 'example\\client\scripts\default.bind.cs' and
change 'function jump(%val)' to look like this:
As you can see we call the JumpCharge on the server (scripting) side. Now open
example\starter.lighthouse\server\scripts\commands.cs. This is where we usually
store client function calls as you'll see.
Now add this function in there with the rest:
Now we add a new variable in the Player class which holds the Jumpcharge variable.
So in 'class Player: public ShapeBase' (player.h) in the Protected section add:
Now in the Public section we add the setter (and the Optional Getter)
On to the player.cc. We add the Functions here and initialize the value.
in Player::Player() add the following
And add this there somewhere to. You'll see the place.
We need to expose these 2 functions to the script for the call in
ServerCmdJumpCharge(%client,%val) to '%client.player.setJumpCharge(%val);'
to work (where the other ConsoleMethods are) :
Almost done... To apply the force to the actuall jump action we go to
'void Player::updateMove(const Move* move)'. That should make sense :)
Change this piece of code, but before you do... sit 30secs and go through it.
It isn't too hard to understand, right?:
The Jumping here is a bit strong... But you'll nail Trinity in a Highjump competition!
Compile, run and Juuummmmmppppp!
Also try adding the resource for 'Air Control' posted by F.W. Hardijzer for a cooler
effect!
NOTE! Delete *.dso for the script files you've changed if for some reason it doesn't
work. If you have any problems just give me a shout.
Cheers
Burning
way too much time :( Anyway... I promised Adam Brookman ;)
So let's get right to it...
Open up 'example\
change 'function jump(%val)' to look like this:
function jump(%val)
{
//if %val = 0 the button is released (OnkeyUp); 1 if pressed (onKeydown)
if (%val)
{
//We Save the time when we pressed the key in $startTime
$startTime = getSimTime();
echo("Starting Jump : " @ $startTime);
}
else
{
//WE Save Time when the key was released in $endTime
$endTime = getSimTime();
//Subtract the 2 to find out how long we held the key
$chargeTime = $endTime - $startTime;
echo("Charge Time : " @ $chargeTime);
CommandToServer('JumpCharge',$chargeTime);
// I know the following is weird, but it's a hack and i don't know any better.
// I works fine though!
$mvTriggerCount2++; //Adds the JumpTrigger....
$mvTriggerCount2++; //Removes Trigger again so Kork doesn't keep hopping crazy!
}
}As you can see we call the JumpCharge on the server (scripting) side. Now open
example\starter.lighthouse\server\scripts\commands.cs. This is where we usually
store client function calls as you'll see.
Now add this function in there with the rest:
function ServerCmdJumpCharge(%client,%val)
{
// We handle the Maximums and minimums here so the Client can't cheat or
// send crazy values
// 2500 = 2.5secs
if (%val > 2500)
{
%val = 2500;
}
//Divide it to something reasonable (change this to alter the jump strength)
%val = %val / 450;
if (%val < 1)
{
%val = 1;
}
// Okay here we make a call to code... this means the clients' player class
// is calling the setJumpCharge in that class. (getJumpCharge is optional)
%client.player.setJumpCharge(%val);
echo("Jump Charge : " @ %client.player.getJumpCharge());
}Now we add a new variable in the Player class which holds the Jumpcharge variable.
So in 'class Player: public ShapeBase' (player.h) in the Protected section add:
F32 mJumpCharge;
Now in the Public section we add the setter (and the Optional Getter)
F32 getJumpCharge(); void setJumpCharge(F32 JumpCharge);
On to the player.cc. We add the Functions here and initialize the value.
in Player::Player() add the following
mJumpCharge = 1;
And add this there somewhere to. You'll see the place.
F32 Player::getJumpCharge()
{
return mJumpCharge;
}
void Player::setJumpCharge(F32 JumpCharge) //Optional
{
//Only if Client
if (!isGhost())
{
mJumpCharge = JumpCharge;
}
}We need to expose these 2 functions to the script for the call in
ServerCmdJumpCharge(%client,%val) to '%client.player.setJumpCharge(%val);'
to work (where the other ConsoleMethods are) :
ConsoleMethod( Player, setJumpCharge, void, 2, 4, "(F32 Jumpcharge)")
{
object->setJumpCharge(dAtof(argv[2]));
}
//Optional
ConsoleMethod( Player, getJumpCharge, F32, 0, 0, "(Return the current JumpCharging Var)")
{
return object->getJumpCharge();
}Almost done... To apply the force to the actuall jump action we go to
'void Player::updateMove(const Move* move)'. That should make sense :)
Change this piece of code, but before you do... sit 30secs and go through it.
It isn't too hard to understand, right?:
F32 impulse = mDataBlock->jumpForce / mMass;
if (dot <= 0)
acc.z += mJumpSurfaceNormal.z * scaleZ * impulse * zSpeedScale;
else
{
acc.x += pv.x * impulse * dot;
acc.y += pv.y * impulse * dot;
acc.z += mJumpSurfaceNormal.z * scaleZ * impulse * zSpeedScale;
}to this:F32 impulse = mDataBlock->jumpForce / mMass;
if (dot <= 0)
acc.z += mJumpSurfaceNormal.z * scaleZ * impulse * zSpeedScale * mJumpCharge;
else
{
acc.x += pv.x * impulse * dot;
acc.y += pv.y * impulse * dot;
acc.z += mJumpSurfaceNormal.z * scaleZ * impulse * zSpeedScale * mJumpCharge;
}The Jumping here is a bit strong... But you'll nail Trinity in a Highjump competition!
Compile, run and Juuummmmmppppp!
Also try adding the resource for 'Air Control' posted by F.W. Hardijzer for a cooler
effect!
NOTE! Delete *.dso for the script files you've changed if for some reason it doesn't
work. If you have any problems just give me a shout.
Cheers
Burning
About the author
#2
05/12/2005 (1:03 am)
lol... K
#3
Nice work. I'm curious, how responsive is it networked? Since the client player object doesn't get any info about the change in jump force, I'm wondering what happens when the client has to predict when there is some lag, like if the jump initially looks small, then is forced up into the air by the server.
Anyways, looks good!
05/12/2005 (6:15 am)
Hi Burning,Nice work. I'm curious, how responsive is it networked? Since the client player object doesn't get any info about the change in jump force, I'm wondering what happens when the client has to predict when there is some lag, like if the jump initially looks small, then is forced up into the air by the server.
Anyways, looks good!
#4
But it should look smooth on the Client.
05/12/2005 (6:27 am)
Well... The client handles how much charge is built up... That is sent to the Server only on releasing the button. So that value is handled on the server side. It all depends on your connection speed I guess.But it should look smooth on the Client.
#5
How will that stop cheating? Anyone could exploit the code.
05/13/2005 (12:19 am)
Quote: // We handle the Maximums and minimums here so the Client can't cheat
How will that stop cheating? Anyone could exploit the code.
#6
Only value is sent to the Server, where the value is reworked into somethning usable... If we do our calculations on the client-side and send the final value to the server for straight use, the client can send odd or invalid jump strengths to the server by just changing his default.bind.dso.
05/13/2005 (12:33 am)
No they cant....Only value is sent to the Server, where the value is reworked into somethning usable... If we do our calculations on the client-side and send the final value to the server for straight use, the client can send odd or invalid jump strengths to the server by just changing his default.bind.dso.
#7
05/13/2005 (3:43 pm)
Well, I tried it. I know it isn't your code. (Extremely well written and commented, btw.) But the changes in the script refuse to take place. I deleted the corresponding *.dso files, but when I rerun the program the *.dso files do not reappear and I lose the functionality of those files. I don't know what is going on!
#8
Can you still open the console?
What do you mean it's not my code?
05/15/2005 (11:03 pm)
What does it say in the console?Can you still open the console?
What do you mean it's not my code?
#9
05/16/2005 (2:04 am)
I mean it isn't your code that is giving me errors.
#10
Open your console (~) and look for compile errors or alternatively mail me your console.log file.
This shouldn't be hard :)
05/16/2005 (4:19 am)
The reason for the dso's not appearing (compiling) is because there's errors.Open your console (~) and look for compile errors or alternatively mail me your console.log file.
This shouldn't be hard :)
#11
Here's how a client can exploit this code for advantage....
Ok, the maximum charge is 2.5 seconds, so lets say player A is holding down his button for 2.5 seconds(more or less, players aren't perfect) to get maximum jump power, and I come along using your code, and a few custom binds like these...
As you can see, I can get a precise jump every time(which could be ANY setting I choose) and while everyone else is holding their button down for 2.5 seconds to achieve a maximum jump, I'd simply tap the F5 key and get a full jump from it. This is obviously an unfair advantage and depending on how critical jump timing is to your game(EXAMPLE: Precise jump sequences that take normal users several tries to master), it could easily be mastered with a simple script. So as I was saying, you have not stopped a user from exploiting your code for advantage against other players, or to circumvent skill building excersises.
06/01/2005 (12:25 am)
Quote:Only value is sent to the Server, where the value is reworked into somethning usable... If we do our calculations on the client-side and send the final value to the server for straight use, the client can send odd or invalid jump strengths to the server by just changing his default.bind.dso.
Here's how a client can exploit this code for advantage....
Ok, the maximum charge is 2.5 seconds, so lets say player A is holding down his button for 2.5 seconds(more or less, players aren't perfect) to get maximum jump power, and I come along using your code, and a few custom binds like these...
function doJump(%time)
{
CommandToServer('JumpCharge', %time);
}
PlayMap.bindCmd(keyboard, "F1", "", "doJump(\"500\");"); // Half second
PlayMap.bindCmd(keyboard, "F2", "", "doJump(\"1000\");"); // One second
PlayMap.bindCmd(keyboard, "F3", "", "doJump(\"1500\");"); // One and a half seconds
PlayMap.bindCmd(keyboard, "F4", "", "doJump(\"2000\");"); // Two seconds
PlayMap.bindCmd(keyboard, "F5", "", "doJump(\"2500\");"); // Two and a half secondsAs you can see, I can get a precise jump every time(which could be ANY setting I choose) and while everyone else is holding their button down for 2.5 seconds to achieve a maximum jump, I'd simply tap the F5 key and get a full jump from it. This is obviously an unfair advantage and depending on how critical jump timing is to your game(EXAMPLE: Precise jump sequences that take normal users several tries to master), it could easily be mastered with a simple script. So as I was saying, you have not stopped a user from exploiting your code for advantage against other players, or to circumvent skill building excersises.
#12
But at least there is some control. The Min and max value is handled on server side. So people changing the script can still only jump as high (or low) as the rest in the rest.
06/01/2005 (12:54 am)
I see what you mean... Guess it depends on the type of game.But at least there is some control. The Min and max value is handled on server side. So people changing the script can still only jump as high (or low) as the rest in the rest.
#13
Although this method is more secure against script intervention, it has the drawback of suffering from latency. Meaning, if I had a ping of 150 m/s and I held the button for exactly 2000 m/s then released the key, the server would record my jump time as 2150 m/s. The good news is that it compensates both ways. Meaning when I first press the key there is a 150 m/s delay(my ping rate) before the command is registered so it will pretty much even out for anyone with a steady ping. If you wanted you could record the users ping at the times the jump is started and ended and use them to compensate for ping variances. The main goal here is to insure that a client cannot use "Scripted Skill" to beat his opponents.
06/01/2005 (1:50 am)
If you wanted to take away that exploit, you could move the timing into the server and make the client call the server for start and stop like this....function ServerCmdStartJumpTime(%client)
{
// Start our jump timer
%client.jumpStart = getSimTime();
}
function ServerCmdEndJumpTime(%client)
{
// Calculate the jump time
%client.jumpCharge = (getSimTime() - %client.jumpStart);
// Reset the jumpStart to prevent conflicts
%client.jumpStart = 0;
// Check the tolerence
if (%client.jumpCharge > 2500)
{
%client.jumpCharge = 2500;
}
else if(%client.jumpCharge < 1)
{
%client.jumpCharge = 1;
}
// Make the jump
%client.player.setJumpCharge(%client.jumpCharge);
}
// Pressing the key down sends "StartJumpTime" and letting go sends "EndJumpTIme"
PlayMap.bindCmd(keyboard, "F1", "CommandToServer('StartJumpTime');", "CommandToServer('EndJumpTime');");Although this method is more secure against script intervention, it has the drawback of suffering from latency. Meaning, if I had a ping of 150 m/s and I held the button for exactly 2000 m/s then released the key, the server would record my jump time as 2150 m/s. The good news is that it compensates both ways. Meaning when I first press the key there is a 150 m/s delay(my ping rate) before the command is registered so it will pretty much even out for anyone with a steady ping. If you wanted you could record the users ping at the times the jump is started and ended and use them to compensate for ping variances. The main goal here is to insure that a client cannot use "Scripted Skill" to beat his opponents.
#14
Do you think one might bounce back upward? Hmmm... I might just have found a way around you max of 2500... :P A negative value could bounce me back up... -10000 could really send you somewhere. ;)
Just a thought,
Zach
07/05/2005 (4:44 am)
More interestingly, (and I don't have nor use Torque but this occured to me) what happens if I use Gonzo's script and input a negative value? Looking at the code I don't think it would crash it but would I jump down? :) ...Might get thrown a little way due to crashing into the ground...Do you think one might bounce back upward? Hmmm... I might just have found a way around you max of 2500... :P A negative value could bounce me back up... -10000 could really send you somewhere. ;)
Just a thought,
Zach
#15
07/10/2005 (10:28 pm)
If the game featured 'Impact' damage the likely result would be like a major body slam with -10000 resulting in instant death.
#16
07/11/2005 (7:48 am)
lol... if that is the case, nvm then. :)
#17
Could you go into more detail please :)
Im not a programmer, but im learning. (im a modeler), so if you would, please show the surrounding code, or what exactily us newbs are looking for. I had a hell of a time trying to get the proper placement of the code:
"And add this there somewhere to. You'll see the place." sooo many rebuilds... 6hours worth of time, but hey, im learning.
What file(s) do you edit with the code posted above, and what other files need to be edited so the server works?
Thanks James and Gonzo!
07/14/2005 (4:32 am)
Gonzo:Could you go into more detail please :)
Im not a programmer, but im learning. (im a modeler), so if you would, please show the surrounding code, or what exactily us newbs are looking for. I had a hell of a time trying to get the proper placement of the code:
"And add this there somewhere to. You'll see the place." sooo many rebuilds... 6hours worth of time, but hey, im learning.
What file(s) do you edit with the code posted above, and what other files need to be edited so the server works?
Thanks James and Gonzo!
#18
07/14/2005 (4:44 am)
@Zach: You won't bounce (even if impact damage was in)....
#19
It was just a thought! :P
07/14/2005 (1:20 pm)
I think you would in real Physics so that's what I was thinking.It was just a thought! :P
#20
where would i put it?
Thanks in advance for your help!!
07/15/2005 (9:36 pm)
is there a way to get the charging to reduce the players Energy?where would i put it?
Thanks in advance for your help!!

Torque Owner Gonzo T. Clown
EDIT: James, I've been trying to get you some code for a while, I'm just going to email it to you, I'm tired of trying to post and getting rejected with 403 errors