Game Development Community

Armor piercing projectiles

by Ronald J Nelson · in Torque Game Engine · 09/09/2006 (4:26 am) · 12 replies

I have been working diligently to create a material mapping system that influences projectile collisions with objects.

Now the next step in my process is to replace my current system for generating the piercing round. In the following I illustrate the problem.

i72.photobucket.com/albums/i192/DTDA/projectlieproblem.jpg
The following examples explain the problem and proposed solution.

A. here we have step 1 where the player fires the weapon at a target. Step 2 the projectile travels along casting an invisible ray until it sees something. With my materal mapping code it uses the target's texture file name to look up flags and information I have set up to create conditions for that object. In this case it determines whether or not a projectile can or cannot pierce this target. This system is set up to only allow certain projectiles to even make this check so we don't have every bullet trying to perform my functions. Then step 3 after determining the object meets the criteria it places the bulet hole decal at the collision point, emits the particles appropriate for that type of object based again on the material mapping and then spawns another projectile on the other side of the target. Now in this example you see that it should create the projectile directly on the backside of the target, emit the particles and place the bullet decal and progress on the same path the original projectile it was until it meets another object. It must be done this way because it is an extremely bad idea to disable collisions to just try and pass an object through another, it is the stuff catastrophic crashes are made of.

#1
09/09/2006 (4:26 am)
B. Here is where my problem is. Step 1 is perform as before. When it gets to step 2 it does the same ray cast as before. Now it does put the decal and particle emmiters in the correct impact point. I have not added this to the exit system yet for the following reason. In step 3 since my code to create the new projectile's position is based off of the original's velocity and it creates the new projectile as if the the old one had never made the collision. This is an issue in terms of high velocity rounds. due to processing speed of the server, by the time the server creates the high velocity round the projectile would have been consideralby past the exit side of the target and therefore the new projectile is placed there. his creates severa problems. Obviously any particle emitters and decals are created a considerable distance past the point they should have been created. Also, any object directly behind the target may or may not be hit by the projectile as it should have been. Additionally, in projectile physics even if the object did pass through the target, its velocity would have decreased as well. There for considerably lowering the amount of damage it would inflict. Considering TGE's current damage distribution system is based off an set variable that you assign for a projectile to apply damage, it creates an unrealistic effect.

C. My proposed solution involves step 1 same as always. However, step 2 the projectile casts 2 rays. One where it was directly in front of the projectile as before, the second a distance ahead of the projectile and directed in the opposite direction of the first(or the second can be cast at the point when the first projectile collides with the target). It would perform all as before but at the collision pointthe second raycast would also be looking in the opposite direction to see if it could see the backside of the target. Then it would fire a dummy projectile towards the target at exactly the opposite trajectory as the original projectile and its collision would create the exit decal and particles. At the time the dummy projectile makes contact with the target's backside, the piercing projectile would be created and the dummy projectiles collision point with the target. It be created traveling at a lowered velocity, but still travelling in the same direction as the original projectile. Sure I realize there is often deflection and yes I am considering creating a randomized deflection adjustment to the final projectile's trajectory. I am also wanting have the directdamage variable used to apply damage to objects and clients be a derivative of the direct damage variable based upon the projectile's velocity.

My problem with creating this is that I do not understand the relationship of the coordinate values when used to determine distance from point a to point b in terms of distance. A simple conversion to tell me if you determined the difference and say for example along the X-Axis the difference is 4. How does that relate in terms of distance to say inches or feet? Second I need to know how to create the second raycast based upon the position of the projectile but faced in the opposing direction. When I know how to do this I will be able to finish this up quickly.

Any assistance of helping me get the answers to my TGE coordinate noobness would be greatly appreciated.

Also sorry for all the spelling errors.
#2
09/09/2006 (9:52 am)
OK here is what I have. My issue is I am not getting the dummy projectile to travel in a reversed direction of the original projectile. To give you an idea what you are looking at here:

%obj.piercePosition is where the bullet would be if it had never hit anything.

%obj.pierceObjPoint is the backside of the target.


%obj.pierceObject is the is target as seen from the backside to make sure it was the same as the %col value for the original collision.


function piercingProjectile(%this, %obj, %pos, %col)
{
   // Create the projectile object
   %pierceThis = %obj.client.player.getMountedImage($WeaponSlot);
   %slot = %pierceThis.mountPoint;
   %projectile = %pierceThis.projectile;
   %dummyProjectile = %pierceThis.dummyProjectile;

   %PObj = %obj.client.player;

   %muzzleVector = %PObj.getMuzzleVector(%slot);

   %objectVelocity = %obj.pierceVelocity;

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

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

   if(%obj.pierceObjCheck)
   {
      echo("This might actually work!!");
      echo("This is %obj: " @ %obj);
      echo("This is %projectile: " @ %projectile);
      echo("This is %dummyProjectile: " @ %dummyProjectile);

      echo("This is %obj.pierceObject: " @ %obj.pierceObject);
      echo("This is %obj.pierceObjPoint: " @ %obj.pierceObjPoint);
      echo("This is %obj.piercePosition: " @ %obj.piercePosition);
      echo("This is %muzzleVector: " @ %muzzleVector);

      echo("This is %col: " @ %col);
      echo("This is %pos: " @ %pos);

      // Create the dummy projectile object
      %d = new (%pierceThis.projectileType)() 
      {
         dataBlock        = %dummyProjectile;
         initialVelocity  = %dummyMuzVelocity;
         initialPosition  = %obj.piercePosition;
         sourceObject     = %PObj;
         sourceSlot       = %slot;
         client           = %obj.client;
      };

      MissionCleanup.add(%d);
      return %d;

      // Create the projectile object
      %p = new (%pierceThis.projectileType)() 
      {
         dataBlock        = %projectile;
         initialVelocity  = %muzzleVelocity;
         initialPosition  = %obj.pierceObjPoint;
         sourceObject     = %PObj;
         sourceSlot       = %slot;
         client           = %obj.client;
      };

      MissionCleanup.add(%p);
      return %p;
   }
}

What I am getting now is that my second projectile is not appearing the way it should and that the dummy projectile is still moving forward. Help!!!
#3
09/09/2006 (10:31 am)
Use the same projectile. Set it past the target object. Also create the rear decals at the same time you're creating the front ones. The front decals and emitters are appearing fine, the rear should appear equally fine if you create them at the same time. If you want to do blood n guts projectiles out of the back of the target, the datablocks should be on the target and probably be created by that target since it knows what it is and can therefore spew it's guts better than anyone.
#4
09/10/2006 (12:31 pm)
To be accurate determine how much distance the object can go through. If this greater than the thickness you are traveling through (might be difficult to quantify) then place the projectile on the other side of the object. You may also want to reduce the speed to account for lost momentum. You might also do a materials check to help determine how much you can go through.
#5
09/10/2006 (8:19 pm)
Well Frank I have managed to do just that. The distance for the new projectile is based on a Point3f variable that is in the projectile's datablock that can easily be adjusted if trying to simulate a more powerful type of projectile. The new projectile that appears on the back of the object is working perfectly regardless of the velocity of the projectile now.

I have even added a factor to the datablock of the projectile that adjusts the velocity of the projectile each time it passes through an object. Also it checks before creating the new projectile if the muzzle velocity of the projectile that just collided with our target is enough to pierce the object.

Kirk, that is a nice idea, but if you are trying to deal with a more accurate vector for placement of emitters and decals you want to be on the same tragectory as the entry point when you create the exit. Sure it could be offset slightly but that is really not that necessary for a game. With my proposed method the explosion created by the dummy projectile could easily be a blood emitter.

I have already got a working material by texture system for the most part, it just doesn't like dts objects yet. That will come though.

Now what I have to do is design the dummy projectile so that it is travelling in the exact opposite direction as my new projectile. It can be going considerably slower to ensure the material of the object is ready correctely. There is what I have a problem with, how to make a new projectile traveling at exactly the opposite direction of the new projectile?
#6
09/10/2006 (8:35 pm)
Hmmm Well you could simply check for this when the first collision occurs.

Get it's velocity, do some math and determine how much farther it could travel based on what material it hit. The do another ray cast from that location toward the original impact. it should give you the location of the other side of the material.

Hope that makes some sense.
#7
09/11/2006 (12:43 am)
Ramen-sama, I have all of that no problem. What I need right now is how to reverse the vector of the new projectile to it can be used for my dummy projectile.
#8
09/11/2006 (1:00 am)
I think you are looking at your issue a bit too deeply--you're simply needing to do a very simple vector scale of your current vector, something like VectorScale(vector, -1); should do the trick if my thinking is straight (it's late).
#9
09/11/2006 (1:21 am)
Stephen, thanks but I really want the direction of the dummy projectile to travel reverse of the new one to ensure that regardless of the angle the weapon is fired or the shape of the object, the decals and explosions take place at the correct locations.

This is what I have so far. To be honest I know it can be simplified, I am just new to this part of my development and having to do a lot of experimenting.

%dummyVelocity = %muzzleVelocity;
      %dummyMuzVelocity = VectorAdd(
         VectorScale(%dummyVector, %dummyProjectile.muzzleVelocity),
         VectorScale(%dummyVelocity, %dummyProjectile.velInheritFactor));

What I haven't determined yet is the value of %dummyVector. It is the value that I want to be the exact opposite of the other projectile's %muzzleVector. Since I do not want to use the player as the reference point for direction, I need to use the other projectile's but reverse it so that my dummy projectile will travel in the opposite direction.
#10
09/11/2006 (1:34 am)
Which is exactly what a vectorScale with a -1.0 scalar does...

In your block above, you are not correctly using vectorScale--it takes a single vector and a scalar (constant), not two vectors.

%dummyMuzVelocity = vectorScale(%dummyVelocity, -1.0);

Will give you a vector in the opposite direction from %dummyVelocity.
#11
09/11/2006 (1:43 am)
Stephen thank you so very much!!! This was exactly what I needed and now my armor piercing rounds work perfectly!
#12
09/11/2006 (6:44 pm)
Ron,
Very nice! Can't wait to see some demos.