---------------------------------------------------------------------------------------------------------------
Flakgun Tutorial
---------------------------------------------------------------------------------------------------------------
This tutorial makes an effective non-heat seeking anti air weapon called a flakgun. It works like a chaingun, except its bullets explode throwing flak into the air, it has a wider spread then a chaingun and varrying distance before it explodes. It's particulary usefull against flare happy flag cappers and shrikes as a bomber tailgunner. This tut uses the chaingun damageType, you may want to add a flakgun damageType for it instead.

Update: Flakgun.cs has been updated with console error fixes by Mugzzzy.

Step #1
// ------------------------------------------
// inventoryHud.cs
// ------------------------------------------

1a) Add these to the top of the file.

$InvWeapon[12] = "Flakgun";

$NameToInv["Flakgun"] = "Flakgun";


1b) Add this to function buyFavorites and function buyDeployableFavorites

         case Flakgun:
            %client.player.setInventory( FlakgunAmmo, 400 );


Step #2
// ------------------------------------------
// weapons.cs
// ------------------------------------------

$WeaponsHudData[12, bitmapName]   = "gui/hud_chaingun";
$WeaponsHudData[12, itemDataName] = "Flakgun";
$WeaponsHudData[12, ammoDataName] = "FlakgunAmmo";

$WeaponsHudCount = 13;

$AmmoIncrement[FlakgunAmmo]        = 25;

exec("scripts/weapons/Flakgun.cs");


Step #3
// ------------------------------------------
// inventory.cs
// ------------------------------------------

3a) Add this with all the other 'case' in the function

function ShapeBase::hasAmmo( %this, %weapon )
{
   switch$ ( %weapon )
   {
      case FlakGun:
         return( %this.getInventory( FlakgununAmmo ) > 0 );
   }
}


3b) Add this with all the other cleared items

function ShapeBase::clearInventory(%this)
{
   %this.setInventory(Flakgun, 0);
   %this.setInventory(FlakgunAmmo, 0);
}


3c)

function serverCmdGiveAll(%client)
{
   if($TestCheats)
   {
      %player.setInventory(Flakgun, 1);
      %player.setInventory(FlakgunAmmo, 999);
   }
}


Step #4
// ------------------------------------------
// player.cs
// ------------------------------------------
4a) Add to player armor datablocks. Probably only want to give it to mediums and heavies.
    Recommend 50 ammo for mediums and 100 for heavies.

max [Flakgun] = 1;
max [FlakgunAmmo] = 50;


4b)  Add these to function armor::applyConcussion

      if( %weaps[12] = %player.getInventory("Flakgun") > 0 ) %numWeapons++;

and

      case 12:
         %player.use("Flakgun");


Step #5
// ------------------------------------------
// hud.cs
// ------------------------------------------
Ignore this step if you use any server side reticle workarounds.

function clientCmdSetWeaponsHudActive(%slot)
{
   weaponsHud.setActiveWeapon(%slot);
   switch$($WeaponNames[%slot])
   {
      case "Flakgun":
         reticleHud.setBitmap("gui/ret_chaingun");
         reticleFrameHud.setVisible(true);
   }
}


Step #6
// ------------------------------------------
// Ammopack.cs
// ------------------------------------------
Add ammo to ammopack, to increase with it.

$ammoItem[8] = FlakgunAmmo;
$numAmmoItems = 9;

datablock ItemData(AmmoPack)
{
   max[FlakgunAmmo] = 50;
}


Step #7
// ------------------------------------------
// OptionsDlg.cs
// ------------------------------------------
$RemapName[$RemapCount] = "Flakgun";
$RemapCmd[$RemapCount] = "useFlakgun";
$RemapCount++;


Step #8
// ------------------------------------------
// ControlDefaults.cs
// ------------------------------------------

function useFlakgun( %val )
{
   if ( %val )
     use( Flakgun );
}


Step #9
// ------------------------------------------
// Projectiles.cs
// ------------------------------------------
The parts of this step handle the weapon's random firing and basing damage on heat.

9a) Change made to the onFire Function for randomizing the projectile:

function ShapeBaseImageData::onFire(%data, %obj, %slot)
{
      if(%data.projectileSpread)
      {
         %vector = %obj.getMuzzleVector(%slot);
         %x = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
         %y = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
         %z = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
         %mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
         %vector = MatrixMulVector(%mat, %vector);

         %p = new (%data.projectileType)() {
            dataBlock        = %datab;
            initialDirection = %vector;
            initialPosition  = %obj.getMuzzlePoint(%slot);
            sourceObject     = %obj;
            sourceSlot       = %slot;
            vehicleObject    = %vehicle;
         };
      }
      else
      {
         %p = new (%data.projectileType)() {
            dataBlock        = %datab;
            initialDirection = %obj.getMuzzleVector(%slot);
            initialPosition  = %obj.getMuzzlePoint(%slot);
            sourceObject     = %obj;
            sourceSlot       = %slot;
            vehicleObject    = %vehicle;
         };
      }
}

should become

function ShapeBaseImageData::onFire(%data, %obj, %slot)
{

   if(%data.item $= "Flakgun")
   {
      %position = %obj.getMuzzlePoint(%slot);
      %vector = %obj.getMuzzleVector(%slot);
      %range = (getRandom() * 300);
      %x = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
      %y = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
      %z = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
      %mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
      %vector = MatrixMulVector(%mat, %vector);
      %endpos = VectorAdd(%position, VectorScale(%vector, %range));
      %damageMasks = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType |
                     $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType |
                     $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType |
                     $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType |
                     $TypeMasks::ForceFieldObjectType | $TypeMasks::StaticObjectType |
                     $TypeMasks::MoveableObjectType | $TypeMasks::DamagableItemObjectType;
      %foundt = ContainerRayCast(%position, %endpos, %damageMasks);
      if (%foundt)
      {
         %endpos = %obj.getMuzzlePoint(%slot);
      }
      %position = %endpos;
      %p = new (%data.projectileType)() {
         dataBlock        = %data.projectile;
         initialDirection = %vector;
         initialPosition  = %position;
         sourceObject     = %obj;
         sourceSlot       = %slot;
         vehicleObject    = %vehicle;
      };
   }
   else if(%data.projectileSpread)
   {
      %vector = %obj.getMuzzleVector(%slot);
      %x = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
      %y = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
      %z = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
      %mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
      %vector = MatrixMulVector(%mat, %vector);

      %p = new (%data.projectileType)() {
         dataBlock        = %datab;
         initialDirection = %vector;
         initialPosition  = %obj.getMuzzlePoint(%slot);
         sourceObject     = %obj;
         sourceSlot       = %slot;
         vehicleObject    = %vehicle;
      };
   }
   else
   {
      %p = new (%data.projectileType)() {
         dataBlock        = %datab;
         initialDirection = %obj.getMuzzleVector(%slot);
         initialPosition  = %obj.getMuzzlePoint(%slot);
         sourceObject     = %obj;
         sourceSlot       = %slot;
         vehicleObject    = %vehicle;
      };
   }

}

9b) This handles the heat multiple of damaging of players (people standing around take little damage, people flying take lots):

function RadiusExplosion(%explosionSource, %position, %radius, %damage, %impulse, %sourceObject, %damageType)
{

      if(%amount > 0)
         %data.damageObject(%targetObject, %sourceObject, %position, %amount, %damageType, %momVec, %explosionSource.theClient, %explosionSource);


should become:


      if( %explosionSource.getDataBlock().getName() $= "FlakgunBullet" && %data.getClassName() $= "PlayerData" )
      {
         %amount = %amount * ((%targetObject.getHeat() * 4.0) + 0.1);
      }
      if(%amount > 0)
         %data.damageObject(%targetObject, %sourceObject, %position, %amount, %damageType, %momVec, %explosionSource.theClient, %explosionSource);

}


Step #10
// ------------------------------------------
// Flakgun.cs
// ------------------------------------------
Create a file called Flakgun.cs in your weapon's directory. Add all this into it.

//--------------------------------------
// Flakgun
//--------------------------------------

//--------------------------------------------------------------------------
// Force-Feedback Effects
//--------------------------------------
datablock EffectProfile(FlakgunSwitchEffect)
{
   effectname = "weapons/chaingun_activate";
   minDistance = 2.5;
};

datablock EffectProfile(FlakgunFireEffect)
{
   effectname = "weapons/chaingun_fire";
   minDistance = 4.0;
};

datablock EffectProfile(FlakgunSpinUpEffect)
{
   effectname = "weapons/chaingun_spinup";
   minDistance = 2.5;
};

datablock EffectProfile(FlakgunSpinDownEffect)
{
   effectname = "weapons/chaingun_spindown";
   minDistance = 2.5;
};

datablock EffectProfile(FlakgunDryFire)
{
   effectname = "weapons/chaingun_dryfire";
   minDistance = 2.5;
};

datablock EffectProfile(GrenadeExplosionEffect)
{
   effectname = "explosions/grenade_explode";
   minDistance = 10;
   maxDistance = 35;
};

//--------------------------------------------------------------------------
// Sounds
//--------------------------------------
datablock AudioProfile(FlakgunSwitchSound)
{
   filename = "fx/weapons/chaingun_activate.wav";
   description = AudioClosest3d;
   preload = true;
   effect = FlakgunSwitchEffect;
};

datablock AudioProfile(FlakgunFireSound)
{
   filename = "fx/weapons/chaingun_fire.wav";
   description = AudioDefaultLooping3d;
   preload = true;
   effect = FlakgunFireEffect;
};

datablock AudioProfile(FlakgunProjectile)
{
   filename = "fx/weapons/chaingun_projectile.wav";
   description = ProjectileLooping3d;
   preload = true;
};

datablock AudioProfile(FlakgunImpact)
{
   filename = "fx/weapons/chaingun_impact.WAV";
   description = AudioClosest3d;
   preload = true;
};

datablock AudioProfile(FlakgunSpinDownSound)
{
   filename = "fx/weapons/chaingun_spindown.wav";
   description = AudioClosest3d;
   preload = true;
   effect = FlakgunSpinDownEffect;
};

datablock AudioProfile(FlakgunSpinUpSound)
{
   filename = "fx/weapons/chaingun_spinup.wav";
   description = AudioClosest3d;
   preload = true;
   effect = FlakgunSpinUpEffect;
};

datablock AudioProfile(FlakgunDryFireSound)
{
   filename = "fx/weapons/chaingun_dryfire.wav";
   description = AudioClose3d;
   preload = true;
   effect = FlakgunDryFire;
};

datablock AudioProfile(ShrikeBlasterProjectileSound)
{
   filename = "fx/vehicles/shrike_blaster_projectile.wav";
   description = ProjectileLooping3d;
   preload = true;
};

datablock AudioProfile(GrenadeExplosionSound)
{
   filename = "fx/weapons/grenade_explode.wav";
   description = AudioExplosion3d;
   preload = true;
   effect = GrenadeExplosionEffect;
};


//--------------------------------------------------------------------------
// Splash
//--------------------------------------------------------------------------

datablock ParticleData( FlakgunSplashParticle )
{
   dragCoefficient = 1;
   gravityCoefficient = 0.0;
   inheritedVelFactor = 0.2;
   constantAcceleration = -1.4;
   lifetimeMS = 300;
   lifetimeVarianceMS = 0;
   textureName = "special/droplet";
   colors[0] = "0.7 0.8 1.0 1.0";
   colors[1] = "0.7 0.8 1.0 0.5";
   colors[2] = "0.7 0.8 1.0 0.0";
   sizes[0] = 0.05;
   sizes[1] = 0.2;
   sizes[2] = 0.2;
   times[0] = 0.0;
   times[1] = 0.5;
   times[2] = 1.0;
};

datablock ParticleEmitterData( FlakgunSplashEmitter )
{
   ejectionPeriodMS = 4;
   periodVarianceMS = 0;
   ejectionVelocity = 3;
   velocityVariance = 1.0;
   ejectionOffset = 0.0;
   thetaMin = 0;
   thetaMax = 50;
   phiReferenceVel = 0;
   phiVariance = 360;
   overrideAdvances = false;
   orientParticles = true;
   lifetimeMS = 100;
   particles = "FlakgunSplashParticle";
};


datablock SplashData(FlakgunSplash)
{
   numSegments = 10;
   ejectionFreq = 10;
   ejectionAngle = 20;
   ringLifetime = 0.4;
   lifetimeMS = 400;
   velocity = 3.0;
   startRadius = 0.0;
   acceleration = -3.0;
   texWrap = 5.0;

   texture = "special/water2";

   emitter[0] = FlakgunSplashEmitter;

   colors[0] = "0.7 0.8 1.0 0.0";
   colors[1] = "0.7 0.8 1.0 1.0";
   colors[2] = "0.7 0.8 1.0 0.0";
   colors[3] = "0.7 0.8 1.0 0.0";
   times[0] = 0.0;
   times[1] = 0.4;
   times[2] = 0.8;
   times[3] = 1.0;
};

//--------------------------------------------------------------------------
// Particle Effects
//--------------------------------------
datablock ParticleData(FlakgunFireParticle)
{
   dragCoefficient = 2.75;
   gravityCoefficient = 0.1;
   inheritedVelFactor = 0.0;
   constantAcceleration = 0.0;
   lifetimeMS = 550;
   lifetimeVarianceMS = 0;
   textureName = "particleTest";
   colors[0] = "0.46 0.36 0.26 1.0";
   colors[1] = "0.46 0.36 0.26 0.0";
   sizes[0] = 0.25;
   sizes[1] = 0.20;
};

datablock ParticleEmitterData(FlakgunFireEmitter)
{
   ejectionPeriodMS = 6;
   periodVarianceMS = 0;
   ejectionVelocity = 10;
   velocityVariance = 1.0;
   ejectionOffset = 0.0;
   thetaMin = 0;
   thetaMax = 12;
   phiReferenceVel = 0;
   phiVariance = 360;
   overrideAdvance = true;
   particles = "FlakgunFireParticle";
};

datablock ParticleData(GrenadeDust)
{
   dragCoefficient = 1.0;
   gravityCoefficient = -0.01;
   inheritedVelFactor = 0.0;
   constantAcceleration = 0.0;
   lifetimeMS = 1000;
   lifetimeVarianceMS = 100;
   useInvAlpha = true;
   spinRandomMin = -90.0;
   spinRandomMax = 500.0;
   textureName = "particleTest";
   colors[0] = "0.3 0.3 0.275 0.5";
   colors[1] = "0.3 0.425 0.27 0.5";
   colors[2] = "0.3 0.345 0.574 0.234";
   sizes[0] = 3.2;
   sizes[1] = 4.6;
   sizes[2] = 5.0;
   times[0] = 0.0;
   times[1] = 0.7;
   times[2] = 1.0;
};

datablock ParticleData( GDebrisSmokeParticle )
{
   dragCoeffiecient = 1.0;
   gravityCoefficient = 0.0;
   inheritedVelFactor = 0.2;

   lifetimeMS = 1000;
   lifetimeVarianceMS = 100;

   textureName = "particleTest";

   useInvAlpha = true;

   spinRandomMin = -60.0;
   spinRandomMax = 60.0;

   colors[0] = "0.234 0.4 0.4 1.0";
   colors[1] = "0.762 1.0 0.3 0.5";
   colors[2] = "0.65 0.234 0.0 0.0";
   sizes[0] = 0.0;
   sizes[1] = 1.0;
   sizes[2] = 1.0;
   times[0] = 0.0;
   times[1] = 0.5;
   times[2] = 1.0;
};


//--------------------------------------------------------------------------
// Explosions
//--------------------------------------
datablock ParticleData(FlakgunExplosionParticle1)
{
   dragCoefficient = 0.65;
   gravityCoefficient = 0.3;
   inheritedVelFactor = 0.0;
   constantAcceleration = 0.0;
   lifetimeMS = 500;
   lifetimeVarianceMS = 150;
   textureName = "particleTest";
   colors[0] = "0.56 0.36 0.26 1.0";
   colors[1] = "0.56 0.36 0.26 0.0";
   sizes[0] = 0.0625;
   sizes[1] = 0.2;
};

datablock ParticleEmitterData(FlakgunExplosionEmitter)
{
   ejectionPeriodMS = 10;
   periodVarianceMS = 0;
   ejectionVelocity = 0.75;
   velocityVariance = 0.25;
   ejectionOffset = 0.0;
   thetaMin = 0;
   thetaMax = 60;
   phiReferenceVel = 0;
   phiVariance = 360;
   overrideAdvances = false;
   particles = "FlakgunExplosionParticle1";
};




datablock ParticleData(FlakgunImpactSmokeParticle)
{
   dragCoefficient = 0.0;
   gravityCoefficient = -0.2;
   inheritedVelFactor = 0.0;
   constantAcceleration = 0.0;
   lifetimeMS = 1000;
   lifetimeVarianceMS = 200;
   useInvAlpha = true;
   spinRandomMin = -90.0;
   spinRandomMax = 90.0;
   textureName = "particleTest";
   colors[0] = "0.7 0.7 0.7 0.0";
   colors[1] = "0.7 0.7 0.7 0.4";
   colors[2] = "0.7 0.7 0.7 0.0";
   sizes[0] = 0.5;
   sizes[1] = 0.5;
   sizes[2] = 1.0;
   times[0] = 0.0;
   times[1] = 0.5;
   times[2] = 1.0;
};

datablock ParticleEmitterData(FlakgunImpactSmoke)
{
   ejectionPeriodMS = 8;
   periodVarianceMS = 1;
   ejectionVelocity = 1.0;
   velocityVariance = 0.5;
   ejectionOffset = 0.0;
   thetaMin = 0;
   thetaMax = 35;
   overrideAdvances = false;
   particles = "FlakgunImpactSmokeParticle";
   lifetimeMS = 50;
};


datablock ParticleData(FlakgunSparks)
{
   dragCoefficient = 1;
   gravityCoefficient = 0.0;
   inheritedVelFactor = 0.2;
   constantAcceleration = 0.0;
   lifetimeMS = 300;
   lifetimeVarianceMS = 0;
   textureName = "special/spark00";
   colors[0] = "0.56 0.36 0.26 1.0";
   colors[1] = "0.56 0.36 0.26 1.0";
   colors[2] = "1.0 0.36 0.26 0.0";
   sizes[0] = 0.6;
   sizes[1] = 0.2;
   sizes[2] = 0.05;
   times[0] = 0.0;
   times[1] = 0.2;
   times[2] = 1.0;
};

datablock ParticleEmitterData(FlakgunSparkEmitter)
{
   ejectionPeriodMS = 4;
   periodVarianceMS = 0;
   ejectionVelocity = 4;
   velocityVariance = 2.0;
   ejectionOffset = 0.0;
   thetaMin = 0;
   thetaMax = 50;
   phiReferenceVel = 0;
   phiVariance = 360;
   overrideAdvances = false;
   orientParticles = true;
   lifetimeMS = 100;
   particles = "FlakgunSparks";
};


datablock ShockwaveData(ScoutFlakgunHit)
{
   width = 0.5;
   numSegments = 13;
   numVertSegments = 1;
   velocity = 0.5;
   acceleration = 2.0;
   lifetimeMS = 900;
   height = 0.1;
   verticalCurve = 0.5;

   mapToTerrain = false;
   renderBottom = false;
   orientToNormal = true;

   texture[0] = "special/shockwave5";
   texture[1] = "special/gradient";
   texWrap = 3.0;

   times[0] = 0.0;
   times[1] = 0.5;
   times[2] = 1.0;

   colors[0] = "0.6 0.6 1.0 1.0";
   colors[1] = "0.6 0.3 1.0 0.5";
   colors[2] = "0.0 0.0 1.0 0.0";
};

datablock ParticleData(ScoutFlakgunExplosionParticle1)
{
   dragCoefficient = 2;
   gravityCoefficient = 0.0;
   inheritedVelFactor = 0.2;
   constantAcceleration = -0.0;
   lifetimeMS = 600;
   lifetimeVarianceMS = 000;
   textureName = "special/crescent4";
   colors[0] = "0.6 0.6 1.0 1.0";
   colors[1] = "0.6 0.3 1.0 1.0";
   colors[2] = "0.0 0.0 1.0 0.0";
   sizes[0] = 0.25;
   sizes[1] = 0.5;
   sizes[2] = 1.0;
   times[0] = 0.0;
   times[1] = 0.5;
   times[2] = 1.0;
};

datablock ParticleEmitterData(ScoutFlakgunExplosionEmitter)
{
   ejectionPeriodMS = 10;
   periodVarianceMS = 0;
   ejectionVelocity = 2;
   velocityVariance = 1.5;
   ejectionOffset = 0.0;
   thetaMin = 80;
   thetaMax = 90;
   phiReferenceVel = 0;
   phiVariance = 360;
   overrideAdvances = false;
   orientParticles = true;
   lifetimeMS = 200;
   particles = "ScoutFlakgunExplosionParticle1";
};

datablock ExplosionData(ScoutFlakgunExplosion)
{
   soundProfile = blasterExpSound;
   shockwave = ScoutFlakgunHit;
   emitter[0] = ScoutFlakgunExplosionEmitter;
};

datablock ParticleEmitterData( FlakDebrisSmokeEmitter )
{
   ejectionPeriodMS = 7;
   periodVarianceMS = 1;

   ejectionVelocity = 1.0; // A little oomph at the back end
   velocityVariance = 0.2;

   thetaMin = 0.0;
   thetaMax = 40.0;

   particles = "GDebrisSmokeParticle";
};

//--------------------------------------------------------------------------
// Particle effects
//--------------------------------------


datablock DebrisData( ShellDebris )
{
   shapeName = "weapon_Chaingun_ammocasing.dts";

   lifetime = 3.0;

   minSpinSpeed = 300.0;
   maxSpinSpeed = 400.0;

   elasticity = 0.5;
   friction = 0.2;

   numBounces = 3;

   fade = true;
   staticOnMaxBounce = true;
   snapOnMaxBounce = true;
};

datablock DebrisData( GrenadeDebris )
{
   emitters[0] = FlakDebrisSmokeEmitter;

   explodeOnMaxBounce = true;

   elasticity = 0.4;
   friction = 0.2;

   lifetime = 0.3;
   lifetimeVariance = 0.02;

   numBounces = 1;
};

datablock ParticleEmitterData(FlakGrenadeDustEmitter)
{
   ejectionPeriodMS = 5;
   periodVarianceMS = 0;
   ejectionVelocity = 15.0;
   velocityVariance = 0.0;
   ejectionOffset = 0.0;
   thetaMin = 85;
   thetaMax = 85;
   phiReferenceVel = 0;
   phiVariance = 360;
   overrideAdvances = false;
   lifetimeMS = 250;
   particles = "GrenadeDust";
};

datablock ParticleData(GrenadeSparks)
{
   dragCoefficient = 1;
   gravityCoefficient = 0.0;
   inheritedVelFactor = 0.2;
   constantAcceleration = 0.0;
   lifetimeMS = 500;
   lifetimeVarianceMS = 350;
   textureName = "special/bigspark";
   colors[0] = "0.56 0.36 0.26 1.0";
   colors[1] = "0.236 0.36 0.2 1.0";
   colors[2] = "1.0 0.274 0.2 0.2";
   sizes[0] = 0.5;
   sizes[1] = 0.5;
   sizes[2] = 0.75;
   times[0] = 0.0;
   times[1] = 0.5;
   times[2] = 1.0;

};

datablock ParticleEmitterData(FlakGrenadeSparksEmitter)
{
   ejectionPeriodMS = 2;
   periodVarianceMS = 0;
   ejectionVelocity = 12;
   velocityVariance = 6.75;
   ejectionOffset = 0.0;
   thetaMin = 0;
   thetaMax = 60;
   phiReferenceVel = 0;
   phiVariance = 360;
   overrideAdvances = false;
   orientParticles = true;
   lifetimeMS = 100;
   particles = "GrenadeSparks";
};

//--------------------------------------------------------------------------
// Projectile
//--------------------------------------
datablock DecalData(FlakgunDecal1)
{
   sizeX = 0.05;
   sizeY = 0.05;
   textureName = "special/bullethole1";
};
datablock DecalData(FlakgunDecal2) : FlakgunDecal1
{
   textureName = "special/bullethole2";
};

datablock DecalData(FlakgunDecal3) : FlakgunDecal1
{
   textureName = "special/bullethole3";
};
datablock DecalData(FlakgunDecal4) : FlakgunDecal1
{
textureName = "special/bullethole4";
};
datablock DecalData(FlakgunDecal5) : FlakgunDecal1
{
   textureName = "special/bullethole5";
};
datablock DecalData(FlakgunDecal6) : FlakgunDecal1
{
   textureName = "special/bullethole6";
};

datablock ParticleData(FlakSmokeParticle)
{
   dragCoeffiecient = 0.0;
   gravityCoefficient = -0.2; // rises slowly
   inheritedVelFactor = 0.00;

   lifetimeMS = 700; // lasts 2 second
   lifetimeVarianceMS = 150; // ...more or less

   textureName = "particleTest";

   useInvAlpha = true;
   spinRandomMin = -30.0;
   spinRandomMax = 30.0;

   colors[0] = "0.9 0.9 0.9 1.0";
   colors[1] = "0.6 0.6 0.6 1.0";
   colors[2] = "0.4 0.4 0.4 0.0";

   sizes[0] = 10;
   sizes[1] = 23.5;
   sizes[2] = 45.0;

   times[0] = 0.0;
   times[1] = 0.2;
   times[2] = 1.0;
};

datablock ParticleEmitterData(FlakSmokeEmitter)
{
   ejectionPeriodMS = 15;
   periodVarianceMS = 5;

   ejectionVelocity = 1.25;
   velocityVariance = 0.50;

   thetaMin = 0.0;
   thetaMax = 90.0;

   particles = "FlakSmokeParticle";
};


datablock ExplosionData(FlakgunExplosion)
{
   soundProfile = GrenadeExplosionSound;

   faceViewer = true;
   explosionScale = "0.8 0.8 0.8";

   debris = GrenadeDebris;
   debrisThetaMin = 10;
   debrisThetaMax = 50;
   debrisNum = 8;
   debrisVelocity = 26.0;
   debrisVelocityVariance = 7.0;

   emitter[0] = FlakGrenadeDustEmitter;
   emitter[1] = FlakSmokeEmitter;
   emitter[2] = FlakGrenadeSparksEmitter;

   shakeCamera = true;
   camShakeFreq = "10.0 6.0 9.0";
   camShakeAmp = "20.0 20.0 20.0";
   camShakeDuration = 0.25;
   camShakeRadius = 10.0;
};

datablock TracerProjectileData(FlakgunBullet)
{
   doDynamicClientHits = true;

   directDamageType = $DamageType::chaingun;
   splash = FlakgunSplash;

   kickBackStrength = 0.0;
   sound = FlakgunProjectile;

   dryVelocity = 425.0;
   wetVelocity = 100.0;
   velInheritFactor = 1.0;
   fizzleTimeMS = 200;
   lifetimeMS = 200;
   explodeOnDeath = true;
   explosion = FlakgunExplosion;
   radiusDamageType = $DamageType::chaingun;
   directDamage = 0.0;
   hasDamageRadius = true;
   indirectDamage = 0.45;
   damageRadius = 45;

   reflectOnWaterImpactAngle = 0.0;
   explodeOnWaterImpact = false;
   deflectionOnWaterImpact = 0.0;
   fizzleUnderwaterMS = 3000;

   tracerLength = 15.0;
   tracerAlpha = false;
   tracerMinPixels = 6;
   tracerColor = 211.0/255.0 @ " " @ 215.0/255.0 @ " " @ 120.0/255.0 @ " 0.75";
   tracerTex[0] = "special/tracer00";
   tracerTex[1] = "special/tracercross";
   tracerWidth = 0.30;
   crossSize = 0.007;
   crossViewAng = 0.990;
   renderCross = true;

   decalData[0] = FlakgunDecal1;
   decalData[1] = FlakgunDecal2;
   decalData[2] = FlakgunDecal3;
   decalData[3] = FlakgunDecal4;
   decalData[4] = FlakgunDecal5;
   decalData[5] = FlakgunDecal6;
};

//--------------------------------------------------------------------------
// Ammo
//--------------------------------------

datablock ItemData(FlakgunAmmo)
{
   className = Ammo;
   catagory = "Ammo";
   shapeFile = "ammo_chaingun.dts";
   mass = 1;
   elasticity = 0.2;
   friction = 0.6;
   pickupRadius = 2;
   pickUpName = "some flakgun ammo";

   computeCRC = true;
};

//--------------------------------------------------------------------------
// Weapon
//--------------------------------------
datablock ShapeBaseImageData(FlakgunImage)
{
   className = WeaponImage;
   shapeFile = "weapon_chaingun.dts";
   item = Flakgun;
   showname = "Flakgun";
   ammo = flakgunAmmo;
   projectile = flakgunBullet;
   projectileType = TracerProjectile;
   emap = true;

   casing = ShellDebris;
   shellExitDir = "1.0 0.3 1.0";
   shellExitOffset = "0.15 -0.56 -0.1";
   shellExitVariance = 15.0;
   shellVelocity = 3.0;

   projectileSpread = 70.0 / 1000.0;

   //--------------------------------------
   stateName[0] = "Activate";
   stateSequence[0] = "Activate";
   stateSound[0] = FlakgunSwitchSound;
   stateAllowImageChange[0] = false;
   //
   stateTimeoutValue[0] = 0.5;
   stateTransitionOnTimeout[0] = "Ready";
   stateTransitionOnNoAmmo[0] = "NoAmmo";

   //--------------------------------------
   stateName[1] = "Ready";
   stateSpinThread[1] = Stop;
   //
   stateTransitionOnTriggerDown[1] = "Spinup";
   stateTransitionOnNoAmmo[1] = "NoAmmo";

   //--------------------------------------
   stateName[2] = "NoAmmo";
   stateTransitionOnAmmo[2] = "Ready";
   stateSpinThread[2] = Stop;
   stateTransitionOnTriggerDown[2] = "DryFire";

   //--------------------------------------
   stateName[3] = "Spinup";
   stateSpinThread[3] = SpinUp;
   stateSound[3] = FlakgunSpinupSound;
   //
   stateTimeoutValue[3] = 0.5;
   stateWaitForTimeout[3] = false;
   stateTransitionOnTimeout[3] = "Fire";
   stateTransitionOnTriggerUp[3] = "Spindown";

   //--------------------------------------
   stateName[4] = "Fire";
   stateSequence[4] = "Fire";
   stateSequenceRandomFlash[4] = true;
   stateSpinThread[4] = FullSpeed;
   stateSound[4] = FlakgunFireSound;
   //stateRecoil[4] = LightRecoil;
   stateAllowImageChange[4] = false;
   stateScript[4] = "onFire";
   stateFire[4] = true;
   stateEjectShell[4] = true;
   //
   stateTimeoutValue[4] = 0.375;
   stateTransitionOnTimeout[4] = "Fire";
   stateTransitionOnTriggerUp[4] = "Spindown";
   stateTransitionOnNoAmmo[4] = "EmptySpindown";

   //--------------------------------------
   stateName[5] = "Spindown";
   stateSound[5] = FlakgunSpinDownSound;
   stateSpinThread[5] = SpinDown;
   //
   stateTimeoutValue[5] = 1.0;
   stateWaitForTimeout[5] = true;
   stateTransitionOnTimeout[5] = "Ready";
   stateTransitionOnTriggerDown[5] = "Spinup";

   //--------------------------------------
   stateName[6] = "EmptySpindown";
   stateSound[6] = FlakgunSpinDownSound;
   stateSpinThread[6] = SpinDown;
   //
   stateTimeoutValue[6] = 0.5;
   stateTransitionOnTimeout[6] = "NoAmmo";

   //--------------------------------------
   stateName[7] = "DryFire";
   stateSound[7] = FlakgunDryFireSound;
   stateTimeoutValue[7] = 0.5;
   stateTransitionOnTimeout[7] = "NoAmmo";
};

datablock ItemData(Flakgun)
{
   className = Weapon;
   catagory = "Spawn Items";
   shapeFile = "weapon_chaingun.dts";
   image = FlakgunImage;
   mass = 1;
   elasticity = 0.2;
   friction = 0.6;
   pickupRadius = 2;
   pickUpName = "a flakgun";

   computeCRC = true;
   emap = true;
};