Jetpack - 1.4 / 1.5 Compliant
by Tim Heldna · 11/13/2006 (4:44 pm) · 56 comments
This resource will allow you to add a jetting functionality to your player. This enables the player to press a mouse button, or keyboard input and begin to fly.
It also adds the ability of movement whilst jumping or jetting when in the air.
It supports the use of energy. When energy is drained you will not be able to jet until it has regenerated. This of course is optional. If desired, you may permit players to jet indefinitely. This is controlled through script.
Although this has a similar feel to the Tribes jetting functionality, it is not the same. It does not support skiing.
I do not take credit for the code used in this resource. I merely used the Jet Pack Love resource, combined with the Air Control resource and updated it to work with 1.4. & 1.5. I also cleaned some code and did some reformatting.
Files affected:
Source Code
player.cc
player.h
Script
player.cs
default.bind.cs
Install Instructions:
All code changes have been encased with:
player.cc
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
This next bit is a little tricky. It's a trap for young players, people always seem to get confused as to where the code starts and ends. Make sure all your opening and closing brackets line up! Please take some extra care with the next few step. Read slowly and carefully. I'll try to make it as easy as possible for you.
Find
Directly underneath, replace the next if statement with this
I tend to comment code out rather than deleting it, makes life easier when debugging.
Directly underneath the section of code you just commented out, and above this
Add this
Now just a few lines below find this
And replace those two lines of code with
If you've followed my instructions correctly, you should find this directly underneath the section of code you just pasted in.
Directly after the closing brace { of above mentioned if statement, E.g.
Add
Tricky part is over.
Find this if statement
And change it to look like this
Find this function
Directly underneath add this new function
That's all for player.cc
player.h
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
Find
Underneath that add
That takes care of all head code changes. Recompile now.
Now we only have some minor scripting additions to make.
player.cs
Anywhere in the PlayerData datablock add
default.bind.cs
Anywhere you like add
That will bind jetting to the right mouse button. Feel free to change the binding to anything you like.
Make sure you delete your client\config.cs file for the new keybinding to take affect.
Season the datablock values inside the PlayerData datablock to your liking.
This concludes today's code snippet, enjoy!
It also adds the ability of movement whilst jumping or jetting when in the air.
It supports the use of energy. When energy is drained you will not be able to jet until it has regenerated. This of course is optional. If desired, you may permit players to jet indefinitely. This is controlled through script.
Although this has a similar feel to the Tribes jetting functionality, it is not the same. It does not support skiing.
I do not take credit for the code used in this resource. I merely used the Jet Pack Love resource, combined with the Air Control resource and updated it to work with 1.4. & 1.5. I also cleaned some code and did some reformatting.
Files affected:
Source Code
player.cc
player.h
Script
player.cs
default.bind.cs
Install Instructions:
All code changes have been encased with:
// Added for player jetting start // Added for player jetting end
player.cc
Find
maxJumpSpeed = 2 * minJumpSpeed;
Underneath that add
// Added for player jetting start jetJumpForce = 75 * 5; jetJumpEnergyDrain = 0; jetMinJumpEnergy = 0; jetJumpSurfaceAngle = 78; jetMinJumpSpeed = 20; jetMaxJumpSpeed = 100; // Added for player jetting end
Find
groundImpactShakeFalloff = 10.0;
Underneath that add
// Added for player jetting start airControl=0.0f; // Added for player jetting end
Find
if (minJumpEnergy < jumpEnergyDrain)
minJumpEnergy = jumpEnergyDrain;Underneath that add
// Added for player jetting start
if (jetMinJumpEnergy < jetJumpEnergyDrain)
jetMinJumpEnergy = jetJumpEnergyDrain;
// Added for player jetting endFind
addField("jumpDelay", TypeS32, Offset(jumpDelay, PlayerData));Underneath that add
// Added for player jetting start
addField("jetJumpForce", TypeF32, Offset(jetJumpForce, PlayerData));
addField("jetJumpEnergyDrain", TypeF32, Offset(jetJumpEnergyDrain, PlayerData));
addField("jetMinJumpEnergy", TypeF32, Offset(jetMinJumpEnergy, PlayerData));
addField("jetMinJumpSpeed", TypeF32, Offset(jetMinJumpSpeed, PlayerData));
addField("jetMaxJumpSpeed", TypeF32, Offset(jetMaxJumpSpeed, PlayerData));
addField("jetJumpSurfaceAngle", TypeF32, Offset(jetJumpSurfaceAngle, PlayerData));
// Added for player jetting endFind
addField("groundImpactShakeFalloff", TypeF32, Offset(groundImpactShakeFalloff, PlayerData));Underneath that add
// Added for player jetting start
addField("airControl", TypeF32, Offset(airControl,PlayerData));
// Added for player jetting endFind
stream->writeInt(jumpDelay,JumpDelayBits);
Underneath that add
// Added for player jetting start stream->write(jetJumpForce); stream->write(jetJumpEnergyDrain); stream->write(jetMinJumpEnergy); stream->write(jetMinJumpSpeed); stream->write(jetMaxJumpSpeed); stream->write(jetJumpSurfaceAngle); // Added for player jetting end
Find
stream->write(groundImpactShakeFalloff);
Underneath that add
// Added for player jetting start stream->write(airControl); // Added for player jetting end
Find
jumpDelay = stream->readInt(JumpDelayBits);
Underneath that add
// Added for player jetting start stream->read(&jetJumpForce); stream->read(&jetJumpEnergyDrain); stream->read(&jetMinJumpEnergy); stream->read(&jetMinJumpSpeed); stream->read(&jetMaxJumpSpeed); stream->read(&jetJumpSurfaceAngle); // Added for player jetting end
Find
stream->read(&groundImpactShakeFalloff);
Underneath that add
// Added for player jetting start stream->read(&airControl); // Added for player jetting end
This next bit is a little tricky. It's a trap for young players, people always seem to get confused as to where the code starts and ends. Make sure all your opening and closing brackets line up! Please take some extra care with the next few step. Read slowly and carefully. I'll try to make it as easy as possible for you.
Find
// Adjust the players's requested dir. to be parallel
// to the contact surface.
F32 pvl = pv.len();Directly underneath, replace the next if statement with this
// Removed for player jetting start
/*
if (pvl) {
VectorF nn;
mCross(pv,VectorF(0,0,1),&nn);
nn *= 1 / pvl;
VectorF cv = contactNormal;
cv -= nn * mDot(nn,cv);
pv -= cv * mDot(pv,cv);
pvl = pv.len();
}
*/
// Removed for player jetting endI tend to comment code out rather than deleting it, makes life easier when debugging.
Directly underneath the section of code you just commented out, and above this
// Convert to acceleration
if (pvl)
pv *= moveSpeed / pvl;
VectorF runAcc = pv - (mVelocity + acc);
F32 runSpeed = runAcc.len();Add this
// Added for player jetting start
if(mJetting)
{
pvl = moveVec.len();
if (pvl)
{
VectorF nn;
mCross(pv,VectorF(0,0,0),&nn);
nn *= 1 / pvl;
VectorF cv;
cv.set(0,0,0);
cv -= nn * mDot(nn,cv);
pv -= cv * mDot(pv,cv);
pvl = pv.len();
}
}
else
{
if (pvl)
{
VectorF nn;
mCross(pv,VectorF(0,0,1),&nn);
nn *= 1 / pvl;
VectorF cv = contactNormal;
cv -= nn * mDot(nn,cv);
pv -= cv * mDot(pv,cv);
pvl = pv.len();
}
}
// Added for player jetting endNow just a few lines below find this
else
mContactTimer++;And replace those two lines of code with
// Removed for player jetting start
// else
// mContactTimer++;
// Removed for player jetting end
// Added for player jetting start
else
{
mContactTimer++;
if (!inLiquid && mDataBlock->airControl > 0.0f)
{
VectorF pv;
pv = moveVec;
F32 pvl = pv.len();
if (pvl)
pv *= moveSpeed / pvl;
VectorF runAcc = pv - acc;
runAcc.z = 0;
runAcc.x = runAcc.x * mDataBlock->airControl;
runAcc.y = runAcc.y * mDataBlock->airControl;
F32 runSpeed = runAcc.len();
F32 maxAcc = (mDataBlock->runForce / mMass) * TickSec * mDataBlock->airControl;
if (runSpeed > maxAcc)
runAcc *= maxAcc / runSpeed;
acc += runAcc;
}
}
// Added for player jetting endIf you've followed my instructions correctly, you should find this directly underneath the section of code you just pasted in.
// Acceleration from Jumping if (move->trigger[2] && !isMounted() && canJump())
Directly after the closing brace { of above mentioned if statement, E.g.
setActionThread((mVelocity.len() < 0.5)?
PlayerData::StandJumpAnim: PlayerData::JumpAnim, true, false, true);
mJumpSurfaceLastContact = JumpSkipContactsMax;
}
} [b]<-- this is the last closing bracket[/b] Add
// Added for player jetting start
if (move->trigger[1] && !isMounted() && canJetJump())
{
mJetting = true;
// Scale the jump impulse base on maxJumpSpeed
F32 zSpeedScale = mVelocity.z;
if (zSpeedScale <= mDataBlock->jetMaxJumpSpeed)
{
zSpeedScale = (zSpeedScale <= mDataBlock->jetMinJumpSpeed)? 1:
1 - (zSpeedScale - mDataBlock->jetMinJumpSpeed) / (mDataBlock->jetMaxJumpSpeed - mDataBlock->jetMinJumpSpeed);
// Desired jump direction
VectorF pv = moveVec;
F32 len = pv.len();
if (len > 0)
pv *= 1 / len;
// If we are facing into the surface jump up, otherwise
// jump away from surface.
F32 dot = mDot(pv,mJumpSurfaceNormal);
F32 impulse = mDataBlock->jetJumpForce / mMass;
if (dot <= 0)
acc.z += mJumpSurfaceNormal.z * impulse * zSpeedScale;
else
{
acc.x += pv.x * impulse * dot;
acc.y += pv.y * impulse * dot;
acc.z += mJumpSurfaceNormal.z * impulse * zSpeedScale;
}
mEnergy -= mDataBlock->jetJumpEnergyDrain;
setActionThread((mVelocity.len() < 0.5)?
// PlayerData::StandJumpAnim: PlayerData::JumpAnim, true, false, true); // Removed as it was causing people problems with the jump animation whilst jetting
}
}
else
{
mJetting = false;
}
if (mJetting)
{
F32 newEnergy = mEnergy - mDataBlock->minJumpEnergy;
if (newEnergy < 0)
{
newEnergy = 0;
mJetting = false;
}
mEnergy = newEnergy;
}
// Added for player jetting endTricky part is over.
Find this if statement
// Container buoyancy & drag
if (mBuoyancy != 0)
{ // Applying buoyancy when standing still causing some jitters-
if (mBuoyancy > 1.0 || !mVelocity.isZero() || !runSurface)
mVelocity.z -= mBuoyancy * mGravity * mGravityMod * TickSec;
}And change it to look like this
// Container buoyancy & drag
if (mBuoyancy != 0)
{ // Applying buoyancy when standing still causing some jitters-
// Removed for player jetting start
//if (mBuoyancy > 1.0 || !mVelocity.isZero() || !runSurface)
// Removed for player jetting end
// Added for player jetting start
if (mBuoyancy > 1.0 || !runSurface)
// Added for player jetting end
mVelocity.z -= mBuoyancy * mGravity * mGravityMod * TickSec;
}Find this function
bool Player::canJump()
{
return mState == MoveState && mDamageState == Enabled && !isMounted() && !mJumpDelay && mEnergy >= mDataBlock->minJumpEnergy && mJumpSurfaceLastContact < JumpSkipContactsMax;
}Directly underneath add this new function
// Added for player jetting start
bool Player::canJetJump()
{
return mState == MoveState && mDamageState == Enabled && !isMounted() && mEnergy >= mDataBlock->jetMinJumpEnergy;
}
// Added for player jetting endThat's all for player.cc
player.h
Find
S32 jumpDelay;
Underneath that add
// Added for player jetting start F32 jetJumpForce; F32 jetJumpEnergyDrain; // Energy per jump F32 jetMinJumpEnergy; F32 jetMinJumpSpeed; F32 jetMaxJumpSpeed; F32 jetJumpSurfaceAngle; // Angle vertical degrees // Added for player jetting end
Find
F32 footSplashHeight;
Underneath that add
// Added for player jetting start F32 airControl; // Added for player jetting end
Find
void updateState();
Underneath that add
// Added for player jetting start bool mJetting; // Added for player jetting end
Find
bool canJump();
Underneath that add
// Added for player jetting start bool canJetJump(); // Added for player jetting end
That takes care of all head code changes. Recompile now.
Now we only have some minor scripting additions to make.
player.cs
Anywhere in the PlayerData datablock add
// Added for player jetting start airControl = 0.3; jetJumpForce = (8.3 * 10); jetJumpEnergyDrain = 0.8; jetMinJumpEnergy = 0; // Added for player jetting end
default.bind.cs
Anywhere you like add
// Added for player jetting start
function mouseJet(%val)
{
$mvTriggerCount1++;
}
moveMap.bind(mouse, button1, mouseJet);
// Added for player jetting endThat will bind jetting to the right mouse button. Feel free to change the binding to anything you like.
Make sure you delete your client\config.cs file for the new keybinding to take affect.
Season the datablock values inside the PlayerData datablock to your liking.
This concludes today's code snippet, enjoy!
About the author
Recent Blogs
• BCS Street props• Character Pack - Vince
• Recent Artwork
• Progress of our Weapon Pack
• Digital Speedometer
#2
09/23/2006 (12:11 pm)
Thank you again Tim.
#3
09/23/2006 (12:20 pm)
Please let me know how you go. I want to iron any problems out as quickly as possible. Thanks.
#4
i uploaded my files Tim so u can look over them, i added your code but it wasnt working, if nothing is wronge ill zip and upload a copy of the project.
www.talnaus.com/personal/files/sourceandscripts.zip
i put the 4 files in the zip that u mentioned to edit
09/23/2006 (11:47 pm)
Hmm it didnt work when i tried it. maybe i missed somthing but i thought i followed it to the letter.i uploaded my files Tim so u can look over them, i added your code but it wasnt working, if nothing is wronge ill zip and upload a copy of the project.
www.talnaus.com/personal/files/sourceandscripts.zip
i put the 4 files in the zip that u mentioned to edit
#5
You made one very small error in player.cc.
Please go to line 1666 of player.cc, and you will see that you're missing the letter "F".
E.g. Your code at line 1666 reads:
When it should be reading:
That section of code in the resource is fine. You must have accidently lost the "F" when copy / pasting. Once that fix was made, your file compiled fine for me.
09/24/2006 (5:54 am)
Hi Travis, thanks for sending me your files. Made debugging quick and easy.You made one very small error in player.cc.
Please go to line 1666 of player.cc, and you will see that you're missing the letter "F".
E.g. Your code at line 1666 reads:
32 maxAcc = (mDataBlock->runForce / mMass) * TickSec * mDataBlock->airControl;
When it should be reading:
[b]F[/b]32 maxAcc = (mDataBlock->runForce / mMass) * TickSec * mDataBlock->airControl;
That section of code in the resource is fine. You must have accidently lost the "F" when copy / pasting. Once that fix was made, your file compiled fine for me.
#7
09/26/2006 (7:40 am)
This worked great on my modified TGE source. Very cool.
#9
However, I notice that when the player is jetting, it keeps doing the jump animation? Is there anyway that I can change the animation to the root animation when it is in the air, or some other animation?
10/21/2006 (2:12 am)
Nice resource. I find it very useful.However, I notice that when the player is jetting, it keeps doing the jump animation? Is there anyway that I can change the animation to the root animation when it is in the air, or some other animation?
#10
no errors/warnings at all :)
EDIT: found a small nusiance dealing with Air Control...
while jumping and still hitting forward "W", you actually increase speed.
the longer you are in air the faster you move forward, like there is no cap on how fast you can go.
11/03/2006 (3:11 pm)
works like a charm with stock 1.5 also!no errors/warnings at all :)
EDIT: found a small nusiance dealing with Air Control...
while jumping and still hitting forward "W", you actually increase speed.
the longer you are in air the faster you move forward, like there is no cap on how fast you can go.
#11
I can't get this to work... I've made all the changes - I think I followed the instructions exactly, everything compiled fine in xcode, I made the changes to the script too. When I load up the game and press the key that I have binded mouseJet to nothing happens - although it looks like as if the player is trying to move upwards as the player is shaking a bit as I press the key.
Have you any idea why this might be happening? It wouldn't have anything to do with the fact that I'm using the advCamera in orbit mode instead of the observer camera - so that the mouse movements are controlling the camera and not the player would it??
I have put the 4 files in a zip file on http://student.cs.ucc.ie/~fvc2/TGE/gamefiles.zip - I don't mean for you to debug my code for me or anything - but if you could see if there is a glaringly obvious reason as to why this won't work I would appreciate it a lot!
11/04/2006 (8:43 am)
Hi Tim,I can't get this to work... I've made all the changes - I think I followed the instructions exactly, everything compiled fine in xcode, I made the changes to the script too. When I load up the game and press the key that I have binded mouseJet to nothing happens - although it looks like as if the player is trying to move upwards as the player is shaking a bit as I press the key.
Have you any idea why this might be happening? It wouldn't have anything to do with the fact that I'm using the advCamera in orbit mode instead of the observer camera - so that the mouse movements are controlling the camera and not the player would it??
I have put the 4 files in a zip file on http://student.cs.ucc.ie/~fvc2/TGE/gamefiles.zip - I don't mean for you to debug my code for me or anything - but if you could see if there is a glaringly obvious reason as to why this won't work I would appreciate it a lot!
#12
The game crashes if the player takes damage from falling from of a Jetpack induced height. Has anyone else had this happen?
Does anyone know where I can comment out falling damage from the various player files?
11/17/2006 (3:20 pm)
Hello. Fun resource. One problem though:The game crashes if the player takes damage from falling from of a Jetpack induced height. Has anyone else had this happen?
Does anyone know where I can comment out falling damage from the various player files?
#13
The player character I was using doesn't have a "Land" animation. Ie; when you hit the ground from a certain height, the player is supposed to go into the "land", when it wasn't there, the engine crashed.
11/17/2006 (3:41 pm)
Ah, nevermind. I figured out my problem:The player character I was using doesn't have a "Land" animation. Ie; when you hit the ground from a certain height, the player is supposed to go into the "land", when it wasn't there, the engine crashed.
#14
any ideas why?
11/20/2006 (5:00 pm)
Anyone else having a problem with this code on slopes? I put the jump delay to 0 to get bunnyhopping but when on a slope, i can jump but it wont jet straight up :\any ideas why?
#15
Just like Lui " Quted from Lui"
12/24/2006 (2:59 pm)
I got this working. Nice Resource. Thanks very much!Just like Lui " Quted from Lui"
However, I notice that when the player is jetting, it keeps doing the jump animation? Is there anyway that I can change the animation to the root animation when it is in the air, or some other animation?
#16
@Challon & Liu Yi
I hacked it by commenting out:
//setActionThread((mVelocity.len() < 0.5)?
//PlayerData::StandJumpAnim: PlayerData::JumpAnim, true, false, true);
Theres two places in player.cc like that. Comment out the second one only or your regular jump anim wont play.
12/24/2006 (10:23 pm)
Nice resource, thanks!@Challon & Liu Yi
I hacked it by commenting out:
//setActionThread((mVelocity.len() < 0.5)?
//PlayerData::StandJumpAnim: PlayerData::JumpAnim, true, false, true);
Theres two places in player.cc like that. Comment out the second one only or your regular jump anim wont play.
#17
12/25/2006 (1:27 am)
Thanks for that mb, I have updated the resource with the fix. The jump animation shouldn't loop when jetting now.
#18
Does your player still jump before jetting? Mine didn't so I just added a function that plays animations. But another easier way I think would be to add this to your 'mouseJet' function in default.bind.cs:
commandToServer('PlayCel', "wave"); // change the animation... named celwave
What I did was make a seperate function by coping the PlayCel, and the playCelAnimation functions. It does the same thing except it doesnt add cell to the animation name.
player.cs
default.bind.cs
commands.cs
12/26/2006 (6:38 pm)
@TimDoes your player still jump before jetting? Mine didn't so I just added a function that plays animations. But another easier way I think would be to add this to your 'mouseJet' function in default.bind.cs:
commandToServer('PlayCel', "wave"); // change the animation... named celwave
What I did was make a seperate function by coping the PlayCel, and the playCelAnimation functions. It does the same thing except it doesnt add cell to the animation name.
player.cs
// Jetpack Animation
function Player::playAnimation(%this,%anim)
{
if (%this.getState() !$= "Dead")
%this.setActionThread(%anim);
}
// Jetpack Animation enddefault.bind.cs
// Added for player jetting start
function mouseJet(%val)
{
commandToServer('PlayAnim', "celsalute");
$mvTriggerCount1++;
}
moveMap.bind(mouse, button1, mouseJet);
// Added for player jetting endcommands.cs
// Jetpack Animation
function serverCmdPlayAnim(%client,%anim)
{
if (isObject(%client.player))
%client.player.playAnimation(%anim);
}
// Jetpack Animation end
#19
I'm not actually using jetting or any of this code in my game so it's hard for me to test at the moment.
12/27/2006 (5:07 am)
Actually to be honest with you I never had a problem with the jump anim whilst jetting. I assumed that I must have made a typo whilst creating this resource and that's why people were having problems; either that or they were implementing the resource incorrectly.I'm not actually using jetting or any of this code in my game so it's hard for me to test at the moment.
#20
12/27/2006 (11:24 am)
Maybe its the player objects animations that are cycling. I cant test this right now, but that maybe the problem if so.. then its not really a problem at all. :D Plus my code above doesnt work %100 of the time, and I'm using some free player object I found so I dont know for sure. 
Torque Owner Gilles Jr Lafrance