---------------------------------------------------------------------------------------------------------------
Secondary Projectile's Tutorial
---------------------------------------------------------------------------------------------------------------
This tutorial will show various examples of making projectiles spawn from other projectiles/objects. The first will shoot 5 mortars up in the air at varying arcs when a disc collides with something. The second will shoot 20 discs in random directions (any direction) upon explosion of a plasmabolt. The third will turn a missile into grenade spread midflight. The fourth will make the vehicle fireball debris do damage(created when the vehicle explodes).
Ex. #1, Disc to Mortar Fountain
--------------------------------------------------------------------------

function DiscProjectile::onCollision(%data, %projectile, %targetObject, %modifier, %position, %normal)
{
   %targetObject.damage(%projectile.sourceObject, %position, %data.directDamage * %modifier, %data.directDamageType);
   %pos = VectorAdd(%position, VectorScale(%normal, 2)); //Move off surface so it will fire ok
   for(%i=0;%i<5;%i++) //5 shots for fountain
   {
      %x = getRandom() - 0.5;
      %y = getRandom() - 0.5;
      %vec = %x SPC %y SPC 0.8; //Random Arc up
      %p = new GrenadeProjectile() {
         dataBlock        = MortarShot;
         initialDirection = %vec;
         initialPosition  = %pos;
         sourceObject     = %projectile.sourceObject;
         sourceSlot       = %projectile.sourceSlot;
         vehicleObject    = %projectile.vehicleObject;
      };
      MissionCleanup.add(%p);
   }
}


Ex. #2, Disc Burst
--------------------------------------------------------------------------
The best way to do this is give the PlasmaBolt a short lifetime so it usually explodes in midair.

function PlasmaBolt::onExplode(%data, %proj, %pos, %mod)
{
   if (%data.hasDamageRadius)
      RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType);
   for(%i=0;%i<20;%i++)
   {
      %x = (getRandom() * 2) - 1; //-1 to 1, ie: full circle
      %y = (getRandom() * 2) - 1;
      %z = (getRandom() * 2) - 1;
      %vec = %x SPC %y SPC %z; //Shoot any direction
      %p = new LinearProjectile() {
         dataBlock        = DiscProjectile;
         initialDirection = %vec;
         initialPosition  = %pos;
         sourceObject     = %projectile.sourceObject;
         sourceSlot       = %projectile.sourceSlot;
         vehicleObject    = %projectile.vehicleObject;
      };
      MissionCleanup.add(%p);
   }
}


Ex. #3, Missile to Grenade Spread
--------------------------------------------------------------------------
This can be called at any time. You can map it to a button so it can be performed when they want,
or schedule it when it's fired. Just call detMissile to start it. This has to be done before the
missile naturally explodes to work.

function DetMissile(%missile)
{
   if (!isObject(%missile))
      return;
   %missile.position1 = posFromTransform(%missile.getTransform());
   schedule(50, 0, "DetMissile2", %missile);
}

function DetMissile2(%missile)
{
   if (!isObject(%missile))
      return;
   %pos2 = posFromTransform(%missile.getTransform());
   %pos = %missile.position1;
   %vec = VectorAdd(%pos2, VectorScale(%pos, -1)); //Subtract pos from pos2 to create vector.
   %vec = VectorNormalize(%vec);
   for(%i=0;%i<5;%i++) //using 5 projectiles
   {
      %x = (getRandom() - 0.5) * 2 * 3.1415926 * 30 / 1000;
      %y = (getRandom() - 0.5) * 2 * 3.1415926 * 30 / 1000;
      %z = (getRandom() - 0.5) * 2 * 3.1415926 * 30 / 1000;
      %mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
      %vector = MatrixMulVector(%mat, %vec);
      %p = new GrenadeProjectile() {
         dataBlock        = BasicGrenade;
         initialDirection = %vector;
         initialPosition  = %pos2;
         sourceObject     = %missile.sourceObject;
         sourceSlot       = %missile.sourceSlot;
         vehicleObject    = %missile.vehicleObject;
      };
      MissionCleanup.add(%p);
   }
   %missile.schedule(1, "delete");
}


Ex. #4 Vehicle Fireballs
--------------------------------------------------------------------------
This will turn the Vehicle Debris Fireballs into burning flames of death (ok, fancy looking grenades).

Step #1
// ------------------------------------------
// vehicle_spec_fx.cs
// ------------------------------------------
1a) In the 3 datablocks, VehicleExplosion, LargeGroundVehicleExplosion, and LargeAirVehicleExplosion,
remove any lines that begin with debris. examples:

   debris = VehicleFireballDebris;
   debrisThetaMin = 10;
   debrisThetaMax = 60;
   debrisNum = 3;
   debrisNumVariance = 1;
   debrisVelocity = 20.0;
   debrisVelocityVariance = 5.0;


1b) At the bottom of the file, add this datablock and functions:

datablock GrenadeProjectileData(VehicleFireball)
{
   projectileShapeName = "weapon_chaingun_ammocasing.dts";
   emitterDelay        = -1;
   directDamage        = 0.0;
   hasDamageRadius     = true;
   indirectDamage      = 0.40;
   damageRadius        = 30.0;
   radiusDamageType    = $DamageType::Debris;
   kickBackStrength    = 3000;
   bubbleEmitTime      = 1.0;

   explosion = GrenadeExplosion;
   explodeOnMaxBounce = true;

   velInheritFactor    = 0.5;

   baseEmitter         = DebrisFireEmitter;
   smokeEmitter         = DebrisSmokeEmitter;

   grenadeElasticity = 0.4;
   grenadeFriction   = 0.2;
   armingDelayMS     = 400;
   muzzleVelocity    = 20.00;
   drag = 0.1;
};

function FlyingVehicleData::onDamage(%this,%obj)
{
   %damage = %obj.getDamageLevel();
   if (%damage >= %this.destroyedLevel)
   {
      if(%obj.getDamageState() !$= "Destroyed")
      {
         if(%obj.lastpilot)
            %source = %obj.lastpilot;
         else
            %source = %obj;
         for (%i=0;%i<3;%i++)
         {
            %x = (getRandom() * 2) - 1;
            %y = (getRandom() * 2) - 1;
            %z = getRandom() / 2;
            %vec = %x SPC %y SPC %z;
            %pos = VectorAdd(posFromTransform(%obj.getTransform()), VectorScale(%vec, 3));
            %p = new (GrenadeProjectile)() {
               dataBlock        = VehicleFireball;
               initialDirection = %vec;
               initialPosition  = %pos;
               sourceObject     = %source;
               sourceSlot       = 1;
               vehicleObject    = %obj;
            };
            MissionCleanup.add(%p);
         }
      }
   }
   Parent::onDamage(%this, %obj);
}

function HoverVehicleData::onDamage(%this,%obj)
{
   %damage = %obj.getDamageLevel();
   if (%damage >= %this.destroyedLevel)
   {
      if(%obj.getDamageState() !$= "Destroyed")
      {
         if(%obj.lastpilot)
            %source = %obj.lastpilot;
         else
            %source = %obj;
         for (%i=0;%i<3;%i++)
         {
            %x = (getRandom() * 2) - 1;
            %y = (getRandom() * 2) - 1;
            %z = getRandom() / 2;
            %vec = %x SPC %y SPC %z;
            %pos = VectorAdd(posFromTransform(%obj.getTransform()), VectorScale(%vec, 3));
            %p = new (GrenadeProjectile)() {
               dataBlock        = VehicleFireball;
               initialDirection = %vec;
               initialPosition  = %pos;
               sourceObject     = %source;
               sourceSlot       = 1;
               vehicleObject    = %obj;
            };
            MissionCleanup.add(%p);
         }
      }
   }
   Parent::onDamage(%this, %obj);
}

function WheeledVehicleData::onDamage(%this,%obj)
{
   %damage = %obj.getDamageLevel();
   if (%damage >= %this.destroyedLevel)
   {
      if(%obj.getDamageState() !$= "Destroyed")
      {
         if(%obj.lastpilot)
            %source = %obj.lastpilot;
         else
            %source = %obj;
         for (%i=0;%i<3;%i++)
         {
            %x = (getRandom() * 2) - 1;
            %y = (getRandom() * 2) - 1;
            %z = getRandom() / 2;
            %vec = %x SPC %y SPC %z;
            %pos = VectorAdd(posFromTransform(%obj.getTransform()), VectorScale(%vec, 3));
            %p = new (GrenadeProjectile)() {
               dataBlock        = VehicleFireball;
               initialDirection = %vec;
               initialPosition  = %pos;
               sourceObject     = %source;
               sourceSlot       = 1;
               vehicleObject    = %obj;
            };
            MissionCleanup.add(%p);
         }
      }
   }
   Parent::onDamage(%this, %obj);
}


Step #3
// ------------------------------------------
// Player.cs
// ------------------------------------------
in function Armor::onCollision, find the lines

         if(%node == 0)
            commandToClient(%obj.client,'SetPilotVehicleKeys', true);

and replace them with

         if(%node == 0)
         {
            %col.lastpilot = %obj;
            commandToClient(%obj.client,'SetPilotVehicleKeys', true);
         }


Step #4
// ------------------------------------------
// DamageTypes.cs
// ------------------------------------------
Add all this in thier respective spots in the file. I made the debris damages the same as the grenade.

$DamageType::Debris = 37;
$DamageTypeText[37] = "Debris";

shieldDamageScale[$DamageType::Debris] = 1.0;
damageScale[$DamageType::Debris] = 0.75;


Step #5
// ------------------------------------------
// DeathMessage.cs
// ------------------------------------------
Add all this in thier respective spots in the file.

$DeathMessageSelfKill[$DamageType::Debris, 0] = '\c0%1 survives the fall, but not the debris.';
$DeathMessageSelfKill[$DamageType::Debris, 1] = '\c0%1 didn\'t jump out of the vehicle fast enough.';
$DeathMessageSelfKill[$DamageType::Debris, 2] = '\c0%1 gets run over by what\'s left of %3 vehicle.';
$DeathMessageSelfKill[$DamageType::Debris, 3] = '\c0%1 becomes %3 own bumper sticker.';
$DeathMessageSelfKill[$DamageType::Debris, 4] = '\c0%1 Didn\'t see what hit him. Which is sad, because it\'s %3 vehicle.';

$DeathMessageTeamKill[$DamageType::Debris, 0] = '\c0%4 explodes %3 vehicle by TEAMMATE %1!';

$DeathMessage[$DamageType::Debris, 0] = '\c0%1 needs to watch out for debris.';
$DeathMessage[$DamageType::Debris, 1] = '\c0%4 kamikazes, and takes out %1.';
$DeathMessage[$DamageType::Debris, 2] = '\c0%1 needs to look up.';
$DeathMessage[$DamageType::Debris, 3] = '\c0%1, that\'s vehicle parts landing on your head, try avoiding them.';
$DeathMessage[$DamageType::Debris, 4] = '\c0%1 wonders what just hit %5.';