Game Development Community

Possible to shoot projectile from the eye node?

by Richard Preziosi · in Torque Game Engine · 09/26/2009 (6:14 pm) · 20 replies

Wanted to create another post that is more specific to what I am trying to accomplish with my game.

Is shooting the "projectile" possible from the eyenode? make it look like someone is shooting something form their eyes?

#1
09/27/2009 (8:01 am)
Here is where the pojectile is created

// Create the projectile object
   %p = new (%this.projectileType)() {
      dataBlock        = %projectile;
      initialVelocity  = %muzzleVelocity;
      initialPosition  = %obj.getMuzzlePoint(%slot);
      sourceObject     = %obj;
      sourceSlot       = %slot;
      client           = %obj.client;
   };
   MissionCleanup.add(%p);
   return %p;
}

It would seem like i could just change the inital position to getEyePoint, but ofcourse that's not going to do anything. Is it hard coded to only look for initial positions on the weapon model itself?

If not, could i just add a muzzlePoint node to my player model and it look for it there if i delete the one from my weapon?
#2
09/27/2009 (9:39 am)
I have all my weapons shooting from the barrel, in which this is the code I used:
correctMuzzleVector = false;
So go ahead and use:
correctMuzzleVector = true;
And it should use you eyenode.

BTW: This is found in your
datablock ShapeBaseImageData(YOURWEAPONImage)
{
...
}
#3
09/27/2009 (12:32 pm)
Hmm I tried correctMuzzleVector = true, he helped.

However, there was still a bit of space before the projectile would go to the middle of the screen. Meaning I couldn't just barely peek over boxes or around them and shoot if the gun was being covered. I added another muzzlePoint to the code, and moved it on my weapon model and then moved it around and tested until it got it lined up pretty much with the eye node.

Now no matter what is infront of the gun, like a box, i shoot wherever the crosshair is, and the relation of the muzzle is taken out of the equation so to speak.

Now I just need to figure out how to make the projectile invisible.
#4
09/27/2009 (1:32 pm)
You know the best way for the gun to be accurate, would be to make an "IronSights" mode that moves the gun up to the players eyes...

I think that would be the best bet, as it wouldnt let you shoot if your gun is being blocked but it would bring the gun up just enough for the muzzle to be accurate.

I have a system in place that uses the "IronSights" technique, and while my models animation doesnt "truly" make it ironsights it does bring the gun up enough to make a visible change in accuracy.

Good luck though, I'm glad it helped at least.
#5
09/27/2009 (2:14 pm)
The thing about the muzzle and eye vector calculations is that they must compensate for the 1st (and also 3rd) person offset of your weapon -- which is why/how the "iron sights" dynamic offset works for so many people.

Depending on mount point relationship and weapon setup you can actually get dead on accuracy without any of the tricks that most other games use -- sounds like you're looking for a hitscan type weapon/projectile system.

To make the projectile invisible just simply comment out the shapename field in the projectile datablock and don't give the projectile an emitter.
#6
09/27/2009 (8:50 pm)
Quote:It would seem like i could just change the inital position to getEyePoint, but ofcourse that's not going to do anything. Is it hard coded to only look for initial positions on the weapon model itself?
getMuzzlePoint will only look at weapons, but getEyePoint should work for you - unless, of course, that console method doesn't exit :P. I do remember getting eye-projectiles working a long time ago, but I might have added methods to get the eye point and vector.
#7
09/28/2009 (6:19 am)
Yeah I'm still going to try and getEyePoint to work, cause I don't really want to fiddle with each weapon moving the muzzlePoint around until it lines up with the eye.

If someone figures this out before me, let me know please and thanks.
#8
09/28/2009 (7:21 am)
Well, checking the source reveals that ShapeBase does have a getEyePoint console method (as well as getEyeVector). You're sure that didn't work? How did you put it into the script?
#9
09/28/2009 (11:22 am)
basically just replaced all the muzzle with eye, but I have a feeling that the correct muzzle vector is probably what made it malfunction, i'll try commenting that out. Thanks.
#10
09/28/2009 (11:32 am)
I shouldthink it isn't much more complicated than this:
// Create the projectile object
   %p = new (%this.projectileType)() {
      dataBlock        = %projectile;
      initialVelocity  = %obj.getEyeVector() * %speed;
      initialPosition  = %obj.getEyePoint();
      sourceObject     = %obj;
      sourceSlot       = %slot;
      client           = %obj.client;
   };
   MissionCleanup.add(%p);
   return %p;
}
Of course, I haven't tried it. It might be, as you say, correctMuzzleVector messing it up, but as far as I remember, that flag is only used in the getMuzzleVector function, which you wouldn't use if you shot projectiles from the eye point.
#11
09/28/2009 (12:43 pm)
That works to a degree Daniel. It shoot straight up, and the bullet is really slow, if i look straight down though I can kill myself. Gonna play around with it some, lemme know if you figure it out before I post again. Thanks.
#12
09/28/2009 (12:54 pm)
Strange, I just tried the correctmuzzlevector change I suggested and it didnt work, I remember for the longest time I was stuck with eye-projectiles, and I hated it.

Though now that I think about it, it came down to incorrect model-node setup... Try removing the muzzle node and see if it works?
(because I think the problem may have been that with no muzzlenode it was resorting to the players eyenode)

Edit: Nope, no deal... sorry about that, just keep at it and you'll get it! :)
#13
09/28/2009 (1:29 pm)
seems like now the problem resides in this block of script

// Determine initial projectile velocity based on the 
   // gun's muzzle point and the object's current velocity
   %muzzleVector = %obj.getMuzzleVector(%slot);
   %objectVelocity = %obj.getVelocity();
   %muzzleVelocity = VectorAdd(
      VectorScale(%muzzleVector, %projectile.muzzleVelocity),
      VectorScale(%objectVelocity, %projectile.velInheritFactor));
#14
09/28/2009 (1:42 pm)
ok changing
initialVelocity  = %obj.getEyeVector() * %speed;
to
initialVelocity  = %obj.getEyeVector() * %MuzzleVelocity;
corrects the speed.

However now The bullet will only shoot in one direction, let's say North, no mattter what direction I turn, it always shoots north. It also shoots really low, i'm guessing that's because the camera node isn't set to the same position as the eye node, in which case I should be using the camera node to shoot form. Anyways here's a video of my current problem, it's .avi, incase it won't play for someone.

www.preziosidevelopment.com/mystuff/eyenodeproblem.avi

Thanks again for all the help so far.
#15
09/29/2009 (12:51 am)
// Determine initial projectile velocity based on the 
   // gun's muzzle point and the object's current velocity
   %muzzleVector = %obj.getMuzzleVector(%slot);
   %objectVelocity = %obj.getVelocity();
   %muzzleVelocity = VectorAdd(
      VectorScale(%muzzleVector, %projectile.muzzleVelocity),
      VectorScale(%objectVelocity, %projectile.velInheritFactor));
If you're using that, then the projectile will use the muzzle vector, since that's what you're asking it to get.

Quote:initialVelocity = %obj.getEyeVector() * %speed;
Sorry about that - I assumed you would change %speed to your own value, I just didn't know what that was.

Are you sure your character has an eye node? Try checking in TSTPro to verify that. I do seem to remembr having similar problems, though I was using muzzle vector. Projectiles would always shoot one direction, or would appear at the world origin.

I would try building the engine in debug mode and putting a breakpoint in the getEyePoint console function to see what's going wrong. Though that might be overkill. Can you post the entire part of the script dealing with the projectile for us to make sure everything's ok?
#16
09/29/2009 (12:56 pm)
I think I have too much tied to muzzle still, anytime I change anything else though i get no projectile to spawn at all.

// Projectile Object

datablock ProjectileData(CrossbowProjectile)
{
   projectileShapeName = "~/data/shapes/crossbow/projectile.dts";
   directDamage        = 20;
   radiusDamage        = 20;
   damageRadius        = 1.5;
   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;

   hasLight    = false;
   lightRadius = 4;
   lightColor  = "0.5 0.5 0.25";

   hasWaterLight     = true;
   waterLightColor   = "0 0.5 0.5";
   decals[0] = CrossbowHoleData;
};

function CrossbowProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
   // Apply damage to the object all shape base objects
   if (%col.getType() & $TypeMasks::ShapeBaseObjectType)
      %col.damage(%obj,%pos,%this.directDamage,"CrossbowBolt");

   // Radius damage is a support scripts defined in radiusDamage.cs
   // Push the contact point away from the contact surface slightly
   // along the contact normal to derive the explosion center. -dbs
   //radiusDamage(%obj, %pos, %this.damageRadius, %this.radiusDamage, //"Radius", %this.areaImpulse);
}


//-----------------------------------------------------------------------------

function CrossbowImage::onFire(%this, %obj, %slot)
{
   %projectile = %this.projectile;

   // Decrement inventory ammo. The image's ammo state is update
   // automatically by the ammo inventory hooks.
   %obj.decInventory(%this.ammo,1);
   %currentAmmo = %obj.getInventory(%this.ammo);
   %obj.client.setAmmoAmountHud(%currentAmmo);

   // Determine initial projectile velocity based on the 
   // gun's muzzle point and the object's current velocity
   %muzzleVector = %obj.getMuzzleVector(%slot);
   %objectVelocity = %obj.getVelocity();
   %muzzleVelocity = VectorAdd(
      VectorScale(%muzzleVector, %projectile.muzzleVelocity),
      VectorScale(%objectVelocity, %projectile.velInheritFactor));

   // Create the projectile object
   %p = new (%this.projectileType)() {
      dataBlock        = %projectile;
      initialVelocity  = %obj.getEyeVector() * %MuzzleVelocity;
      initialPosition  = %obj.getEyePoint();
      sourceObject     = %obj;
      sourceSlot       = %slot;
      client           = %obj.client;
   };
   MissionCleanup.add(%p);
   return %p;
}

As far as the model having an eye node, not sure, Was using the blueguy that comes with torque, figured he was set up to have everything.

Ok I used the model from 3D Game Programming All in One, and it for sure has an eye node.

I think I'm going about this in the total wrong way for what i'm trying to do. It appears that the eye node is not tied to what the player is seeing through, that's the camera node, for some reason I thought the camera node was a third person thing. and while in first person the camera was using the eye node for positioning. That's why it's only shooting one way, it seems that the eye node does not move at all while rendered in first person.

So I guess what i need to do is shoot from the camera node, so it's back to square one, unless my above assumptions are completely wrong.
#17
10/01/2009 (3:25 pm)
I do believe the problem with the script you have is the reference to the weapon muzzle vector here...

%muzzleVelocity = VectorAdd(   
VectorScale(%muzzleVector, %projectile.muzzleVelocity),   
VectorScale(%objectVelocity, %projectile.velInheritFactor));

and attempting to multiply it here...

...
%p = new (%this.projectileType)() {   
   dataBlock        = %projectile;   
   initialVelocity  = %obj.getEyeVector() * %MuzzleVelocity;   
   initialPosition  = %obj.getEyePoint();   
...

This would be multiplying the eye vector with a vector for the muzzle's velocity, which would natually yield a horrible answer. I would try

initialVelocity = VectorScale(%obj.getEyeVector(), %speed);

so that the projectile's velocity would be where the player is looking and be going at the speed you choose. Inheiriting some velocity from the player would depend on what you want to inheirit it from.

(btw, this is my first real try at solving a problem. I could be wrong.)
#18
10/01/2009 (9:45 pm)
Michael, I think you're right. Aside from the fact that multiplying vectors like that isn't really supported in TS, it won't give the desired result want anyway.

Rich - try Michael's suggestion, but make sure you define %speed. I'd do something like this:
%muzzleVelocity = VectorAdd(
      VectorScale(%muzzleVector, %projectile.muzzleVelocity),
      VectorScale(%objectVelocity, %projectile.velInheritFactor));

   //Get the length of the muzzle velocity
   %speed = VectorLen(%MuzzleVelocity);
#19
10/02/2009 (2:40 pm)
Beautiful, works like a charm need to adjust my eye node just a bit so it's a little more center, but this is beautiful code. Gonna post the whole onfire datablock below that works in 1.5.2 incase someone else is in need of the code.

function CrossbowImage::onFire(%this, %obj, %slot)
{
   %projectile = %this.projectile;

   // Decrement inventory ammo. The image's ammo state is update
   // automatically by the ammo inventory hooks.
   %obj.decInventory(%this.ammo,1);
   %currentAmmo = %obj.getInventory(%this.ammo);
   %obj.client.setAmmoAmountHud(%currentAmmo);

   // Determine initial projectile velocity based on the 
   // gun's muzzle point and the object's current velocity
   %muzzleVector = %obj.getMuzzleVector(%slot);
   %objectVelocity = %obj.getVelocity();
   %muzzleVelocity = VectorAdd(
      VectorScale(%muzzleVector, %projectile.muzzleVelocity),
      VectorScale(%objectVelocity, %projectile.velInheritFactor));
   
   %speed = VectorLen(%MuzzleVelocity);

   // Create the projectile object
   %p = new (%this.projectileType)() {
      dataBlock        = %projectile;
      initialVelocity  = VectorScale(%obj.getEyeVector(), %speed);
      initialPosition  = %obj.getEyePoint();
      sourceObject     = %obj;
      sourceSlot       = %slot;
      client           = %obj.client;
   };
   MissionCleanup.add(%p);
   return %p;
}

Thanks again for all the help.
#20
10/02/2009 (9:37 pm)
Glad you got it working! And thanks for posting the final code. It' be really great if the GG forums could have some sort of 'fixed' marker for threads that you could specify when searching for a problem. So many times I've just come across threads that seem to be going in the direction I want, then they just... end... or the person seems to have found their answer and disappeared ;P.