Game Development Community

Projectiles Explode on Water Impact

by Josh Moore · 12/14/2004 (11:09 pm) · 1 comments

This is a really simple tutorial to get projectiles to explode on water impact.

I had to hack up the processTick function to get projectile splashes to show up when your projectile impacts the water. If you don't want splashes when your projectile explode on water, leave out that part.

You might find this projectile fix useful, it's kind of related. Projectile Splash Fix

Anyway, to the tut:

First, you'll need to add the datablock bool:

In projectile.h, find
F32 muzzleVelocity;

and add this below it:

// Explode on Water Impact - T_F
bool explodeOnWater;

Then, in projectile.cc find:

isBallistic = false;

and add this right before it.

// Explode on Water Impact - T_F
explodeOnWater = false;

In ProjectileData::initPersistFields(), add:

// Explode on Water Impact - T_F
addNamedField(explodeOnWater, TypeBool, ProjectileData);

Then, in ProjectileData::packData, add:

// Explode on Water Impact - T_F
stream->writeFlag(explodeOnWater);

Now add this to ProjectileData::unpackData.

// Explode on Water Impact - T_F
explodeOnWater = stream->readFlag();

Ok, so now we have the datablcok boolean. Before adding in the water impact code, we need to fix a double explosion bug that it will cause.

Find
if (mDataBlock->waterExplosion && pointInWater(p))

and replace it with this:
if (mDataBlock->waterExplosion && (pointInWater(p) || collideType & U32(WaterObjectType)))

Now to make it all work:

Find this raycast if.

if (getContainer()->castRay(oldPosition, newPosition, csmDynamicCollisionMask | csmStaticCollisionMask, &rInfo) == true)

and replace it with this:

// Explode on Water Impact - T_F
   U32 colMask;
   if(mDataBlock->explodeOnWater)
      colMask = csmDynamicCollisionMask | csmStaticCollisionMask | WaterObjectType;
   else
      colMask = csmDynamicCollisionMask | csmStaticCollisionMask;
   if (getContainer()->castRay(oldPosition, newPosition, colMask, &rInfo) == true)

That's about it. Just put this in your projectile datablock to make it explode on water impact.

explodeOnWater = true;

To get the projectile splashes to work with this new feature, add this above
onCollision(rInfo.point, rInfo.normal, rInfo.object);

in Projectile::processTick:

if(isClientObject() && mDataBlock->explodeOnWater && (rInfo.object->getType() & U32(WaterObjectType)))
         {
            MatrixF trans = getTransform();
            trans.setPosition(rInfo.point);

            Splash *splash = new Splash();
            splash->onNewDataBlock(mDataBlock->splash);
            splash->setTransform(trans);
            splash->setInitialState(trans.getPosition(), Point3F(0.0, 0.0, 1.0));
            if (!splash->registerObject())
            {
               delete splash;
               splash = NULL;
            }
         }