Grapple hook
by Andrew Wiblemo · in Torque Game Engine · 06/09/2008 (11:06 am) · 13 replies
Ok, trying to adapt http://www.garagegames.com/mg/forums/result.thread.php?qt=19947 to be a bit more functional. But as I've had little chance to mess with the SDK since getting it, I'm gonna need some help.
I want to have a script exposed variable in the player class, grappleID, which stores the object ID of the hook object asociated with the player, or 0 if there isn't one. That way I can just have it create a new hook object on projectile collision and assign it with a %player.hookID = %newHook; type of thing.
I figure zeroing out the ID would make the movement code easier as an if(hookID) could make an effective code bypass.
In the movement code I'm planning on having it get the hook's location every tick, that way I can integrate it with Ramen's moving platforms code with a simple mount call on hook object creation.
Extending/retracting the line and disengaging the hook are simple enough.
Not going to bother with the graphics for the line yet.
My questions:
Are there functions for taking an object ID and returning a pointer to the object? I assume so but don't know for sure.
Will the script side send the object ID if I were to do it that way? Both the setting of an object ID and zeroing it out?
I want to have a script exposed variable in the player class, grappleID, which stores the object ID of the hook object asociated with the player, or 0 if there isn't one. That way I can just have it create a new hook object on projectile collision and assign it with a %player.hookID = %newHook; type of thing.
I figure zeroing out the ID would make the movement code easier as an if(hookID) could make an effective code bypass.
In the movement code I'm planning on having it get the hook's location every tick, that way I can integrate it with Ramen's moving platforms code with a simple mount call on hook object creation.
Extending/retracting the line and disengaging the hook are simple enough.
Not going to bother with the graphics for the line yet.
My questions:
Are there functions for taking an object ID and returning a pointer to the object? I assume so but don't know for sure.
Will the script side send the object ID if I were to do it that way? Both the setting of an object ID and zeroing it out?
About the author
#2
So you know what's going on here, "Gate1" is the name of the object I want to get the position on. (must be named in the world inspector) In order to find it in torque, I need its unique Id. (which changes just about every other time the game is played)
Once I get the "transform" of the object, I can set it to another simply.
I don't think you can set the id to 0. Torque uses that id number to tell all connected clients what the object is. That reduces the overhead in the packets.
07/12/2008 (2:03 pm)
%trans = nameToId("Gate1").getTransform();
%rot = getWord(%trans, 3)
SPC getWord(%trans, 4)
SPC getWord(%trans, 5)
SPC getWord(%trans, 6);
nameToId("Gate1").setTransform("-145.244 199.162 46.3842" SPC %rot );So you know what's going on here, "Gate1" is the name of the object I want to get the position on. (must be named in the world inspector) In order to find it in torque, I need its unique Id. (which changes just about every other time the game is played)
Once I get the "transform" of the object, I can set it to another simply.
I don't think you can set the id to 0. Torque uses that id number to tell all connected clients what the object is. That reduces the overhead in the packets.
#3
Moot point, I found what I was looking for in a guided projectile resource just a minute ago. Didn't think to look in there till I realized the same basic idea.
Sim::findObject( is what I was looking for, now I just need to go about doing the rewrite I was planning.
07/12/2008 (2:20 pm)
Sorry, meant in code not script.Moot point, I found what I was looking for in a guided projectile resource just a minute ago. Didn't think to look in there till I realized the same basic idea.
Sim::findObject( is what I was looking for, now I just need to go about doing the rewrite I was planning.
#4
I'm wondering because in some resources people use persistfields while others use class functions they expose via console methods.
07/13/2008 (11:59 am)
Ok, new question, initPersistField() exposes variables from a class so they can be read and altered via script, right? No issues there, just straight up direct access with immediate propagation of the changes?I'm wondering because in some resources people use persistfields while others use class functions they expose via console methods.
#5
Some things really confuse me, which is to be expected.
1: What's the difference between a Point3F and a VectorF?
I see both being used the same way, and next to eachother, but there has to be a difference I'm not getting.
2: Can you alter variables in the player class via script directly, or do you have to do it via class functions?
3: Gravity isn't a global value is it? It's hardcoded at -20.0f, correct?
07/13/2008 (4:49 pm)
Ok after a lot of digging I've found a couple answers and a heck of a lot more questions.Some things really confuse me, which is to be expected.
1: What's the difference between a Point3F and a VectorF?
I see both being used the same way, and next to eachother, but there has to be a difference I'm not getting.
2: Can you alter variables in the player class via script directly, or do you have to do it via class functions?
3: Gravity isn't a global value is it? It's hardcoded at -20.0f, correct?
#6
#2. I don't know for sure, but I think you can alter them thru script.
#3. gravityMod= is the key to gravity. You can add it thru script to modify the gravity of a player or vehicle.
07/13/2008 (5:49 pm)
#1. Gahh!! This is covered in great detail in Ed Maurinas new book, that just happens to be in my truck at work. #2. I don't know for sure, but I think you can alter them thru script.
#3. gravityMod= is the key to gravity. You can add it thru script to modify the gravity of a player or vehicle.
#7
I think I've got a viable grapple, if the physics perform as I think. The VectorF/Point3F thing is holding up the moveUpdate side, and the script/code crossover is holding up the rest.
07/13/2008 (7:56 pm)
Thanks mike.I think I've got a viable grapple, if the physics perform as I think. The VectorF/Point3F thing is holding up the moveUpdate side, and the script/code crossover is holding up the rest.
#8
Point3F getVelocity() const;
void setVelocity(const VectorF& vel);
Get velocity returns a Point3F, white set requires a VectorF. Get just returns mVelocity, which is a VectorF, no changes just return mVelocity;.
I'm really confused as to why, if they're interchangable, why not just standardize on one or the other?
Also, can anyone answer me about initPersistFields and the player class? Do I just add the function to the class, add the parent::init call and my 2 fields, and call it good? Is there a reason none of the player class variables are exposed directly?
07/21/2008 (11:57 am)
This is confusing, in the Player class in player.h there's this:Point3F getVelocity() const;
void setVelocity(const VectorF& vel);
Get velocity returns a Point3F, white set requires a VectorF. Get just returns mVelocity, which is a VectorF, no changes just return mVelocity;.
I'm really confused as to why, if they're interchangable, why not just standardize on one or the other?
Also, can anyone answer me about initPersistFields and the player class? Do I just add the function to the class, add the parent::init call and my 2 fields, and call it good? Is there a reason none of the player class variables are exposed directly?
#9
Ok so it works, it's cludgy and the movement is jumpy, though I think that has to do with the fact I'm accelerating the player object by gravity * (distance/set distance)^2. which really ramps up when the player sets the line from 70 to 2, acceleration of 20.0f * gravitymod * ticksec * 1225 = squish on impact.
Anyway, it's more like a bungie cord than a hard rope, so with minor script modifications this could easily become a tractor beam.
I'm going to tweak the movement code a bit, try to clamp the speed, and possibly figure out how to differentiate between objects hit by the projectile, then post the code tonight.
07/23/2008 (2:31 pm)
Caffein is my friend.Ok so it works, it's cludgy and the movement is jumpy, though I think that has to do with the fact I'm accelerating the player object by gravity * (distance/set distance)^2. which really ramps up when the player sets the line from 70 to 2, acceleration of 20.0f * gravitymod * ticksec * 1225 = squish on impact.
Anyway, it's more like a bungie cord than a hard rope, so with minor script modifications this could easily become a tractor beam.
I'm going to tweak the movement code a bit, try to clamp the speed, and possibly figure out how to differentiate between objects hit by the projectile, then post the code tonight.
#10
player.h:
inside player class public space:
player.cc:
at the end of Player::packUpdate and unpackUpdate, sneak in as appropriate:
in Player::updateMove, right after
add:
at the end of player.cc, add
07/31/2008 (10:44 am)
Okies, it's working decently, though I still need to get a line draw added in. Been considering some options, will decide later.player.h:
inside player class public space:
S32 mGrappleID; F32 mGrappleLength; static void initPersistFields();
player.cc:
at the end of Player::packUpdate and unpackUpdate, sneak in as appropriate:
stream->writeInt(mGrappleID, 32); stream->writeFloat(mGrappleLength, 32); and mGrappleID = stream->readInt(32); mGrappleLength = stream->readFloat(32);
in Player::updateMove, right after
mVelocity += acc;
add:
//Grapple Hook movement code
if(mGrappleID && mGrappleLength)
{
ShapeBase* hookObject;
if(Sim::findObject(mGrappleID, hookObject))
{
VectorF grappleVector = getPosition() - hookObject->getPosition();
F32 lineLength = grappleVector.len();
if(lineLength > mGrappleLength)
{
F32 velocity;
grappleVector.normalize();
mVelocity += (1000 * moveVec / mMass) * TickSec;
velocity = mVelocity.len(); //Get current velocity
if(velocity) //Make sure player is moving
{
if(mAcos(mDot(grappleVector, mVelocity)/velocity) < 1.57)
{
mVelocity -= (mDot(grappleVector, mVelocity)/mDot(grappleVector, grappleVector)) * grappleVector;
mVelocity.normalize();
mVelocity *= velocity;
}
}
if(lineLength + 5 > mGrappleLength) //Accelerate if too far from grapple zone
{
F32 lenRatio = lineLength / mGrappleLength;
if(lenRatio > 5)
lenRatio = 5;
velocity = mGravity * mGravityMod * TickSec * lenRatio * lenRatio;
grappleVector *= velocity;
mVelocity += grappleVector;
}
}
}
}at the end of player.cc, add
void Player::initPersistFields()
{
Parent::initPersistFields();
addField("grappleID", TypeS32, Offset(mGrappleID, Player), "Grapple target ObjectID");
addField("grappleLength", TypeF32, Offset(mGrappleLength, Player), "Grapple line length" );
}
#11
at end of default.bind.cs
game.cs
in onServerCreated, right after the crossbow.cs exec
gameconnection::ondeath
Gameconnection::createPlayer, right before the }; of new Player()
create grapple.cs
07/31/2008 (11:06 am)
Script side,at end of default.bind.cs
//------------------------------------------------------------------------------ // Grapple Hook bind setups //------------------------------------------------------------------------------ $RemapName[$RemapCount] = "Fire Grapple"; $RemapCmd[$RemapCount] = "fireGrappleHook"; $RemapCount++; $RemapName[$RemapCount] = "Grapple Reel Min"; $RemapCmd[$RemapCount] = "grappleReelMin"; $RemapCount++; $RemapName[$RemapCount] = "Grapple Reel In"; $RemapCmd[$RemapCount] = "grappleReelIn"; $RemapCount++; $RemapName[$RemapCount] = "Grapple Reel Out"; $RemapCmd[$RemapCount] = "grappleReelOut"; $RemapCount++; $RemapName[$RemapCount] = "Grapple Reel Max"; $RemapCmd[$RemapCount] = "grappleReelMax"; $RemapCount++;
game.cs
in onServerCreated, right after the crossbow.cs exec
exec("./grapple.cs");gameconnection::ondeath
%this.player.grappleID = 0; %this.grappleLength = 1;
Gameconnection::createPlayer, right before the }; of new Player()
grappleProjectile = 0;
grappleLengthMax = 100;
grappleID = 0;
grappleLength = 2;create grapple.cs
//------------------------------------------------------------------------------
//Test Grapple
//
function ServerCmdGrappleLineReel(%client, %n1)
{
grappleLineReel(%client.player, %n1);
}
function grappleLineReel(%player, %amount)
{
%newLength = %amount + %player.grappleLength;
if(%newlength > %player.grappleLengthMax)
%newLength = %player.grappleLengthMax;
if(%newLength < 2)
%newlength = 2;
%player.grappleLength = %newlength;
}
datablock ProjectileData(HookProjectile)
{
projectileShapeName = "~/data/shapes/crossbow/projectile.dts";
directDamage = 20;
radiusDamage = 0;
damageRadius = 1.0;
areaImpulse = 2000;
explosion = CrossbowExplosion;
waterExplosion = CrossbowWaterExplosion;
particleEmitter = CrossbowBoltEmitter;
particleWaterEmitter= CrossbowBoltBubbleEmitter;
splash = CrossbowSplash;
muzzleVelocity = 100;
velInheritFactor = 0.3;
armingDelay = 0;
lifetime = 5000;
fadeDelay = 5000;
bounceElasticity = 0;
bounceFriction = 0;
isBallistic = false;
gravityMod = 0.80;
hasLight = true;
lightRadius = 4;
lightColor = "0.5 0.5 0.25";
hasWaterLight = true;
waterLightColor = "0 0.5 0.5";
};
function ServerCmdFireGrapple(%client)
{
fireGrapple(%client.player);
}
function fireGrapple(%player)
{
if(%player.grappleID != 0)
{
//delete grapple line here
%player.grappleID.delete();
%player.grappleID = 0;
return;
}
if(%player.grappleProjectile != 0)
{
//delete grapple line here
%player.grappleProjectile.delete();
%player.grappleProjectile = 0;
return;
}
%hookProj = HookProjectile;
%shotVector = %player.getEyeVector();
%shotVelocity = %player.getVelocity();
%shotVelocity = VectorAdd( VectorScale(%shotVector, %hookProj.muzzleVelocity), VectorScale(%shotVelocity, %hookProj.velInheritFactor) );
%player.grappleProjectile = new Projectile()
{
dataBlock = %hookProj;
initialVelocity = %shotVelocity;
initialPosition = %player.getEyePoint();
sourceObject = %player;
client = %player.getControllingClient();
};
//Create grapple line here
MissionCleanup.add(%player.grappleProjectile);
//MissionCleanup.add(%player.grappleLine);
}
function hookProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
echo("Grapple projectile collision at" SPC %pos);
%hook = new StaticShape(GrappleHook)
{
datablock = "GrappleHookDatablock";
position = %pos;
rotation = %normal;
surfaceObject = %col;
};
echo("Grapple hook ID" SPC %hook);
// %col.attachchild(%hook);
//create line to hook here
%lineLength = vectorDist(%obj.client.player.getPosition(), %pos);
if(%lineLength < 1)
{
%lineLength = 2;
}
%obj.client.player.grappleLength = %lineLength;
%obj.client.player.grappleID = %hook;
echo("Length =" SPC %obj.client.player.grappleLength SPC "ID =" SPC %obj.client.player.grappleID);
%obj.client.player.grappleProjectile = 0;
MissionCleanup.add(%hook);
//MissionCleanup.add(%obj.client.player.grappleLine);
}
datablock StaticShapeData(GrappleHookDataBlock)
{
shapeFile = "~/data/shapes/items/healthKit.dts";
};
function fireGrappleHook(%val)
{
if(%val)
commandToServer('FireGrapple');
}
function grappleReelMin(%val)
{
if(%val)
commandToServer('GrappleLineReel', -1000);
}
function grappleReelIn(%val)
{
if(%val)
commandToServer('GrappleLineReel', -5);
}
function grappleReelOut(%val)
{
if(%val)
commandToServer('GrappleLineReel', 5);
}
function grappleReelMax(%val)
{
if(%val)
commandToServer('GrappleLineReel', 1000);
}
#12
I'm also going to eventually move most of the script code to source, to make sure things like lineLength never get set below 1.
This is a combination of my attempt at the grapple plus the code I linked to before, my origional code is the stuff past if(lineLength + 5 > mGrappleLength), and if the other stuff is removed it makes a decent bungie cord/tractor beam. If anyone wants it I've got it's origional incarnation still.
Also, if anyone knows why the movement is so jerky and/or how to smooth it out, I'd be very appreciative.
07/31/2008 (11:16 am)
Bind keys as you like, I use the mousewheel click to fire the grapple, with retract/extend done by home/end. Eventually I'm going to change it to mousewheel to reel in and out, shift+mousewheel to go min and max.I'm also going to eventually move most of the script code to source, to make sure things like lineLength never get set below 1.
This is a combination of my attempt at the grapple plus the code I linked to before, my origional code is the stuff past if(lineLength + 5 > mGrappleLength), and if the other stuff is removed it makes a decent bungie cord/tractor beam. If anyone wants it I've got it's origional incarnation still.
Also, if anyone knows why the movement is so jerky and/or how to smooth it out, I'd be very appreciative.
#13
12/02/2008 (7:38 pm)
Did you figure out how to draw the line yet?
Torque 3D Owner Andrew Wiblemo
Given an object ID, what's the easiest way to get that referenced object's position?