//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Rifle weapon. This file contains all the items related to this weapon
// including explosions, ammo, the item and the weapon item image.
// These objects rely on the item & inventory support system defined
// in item.cs and inventory.cs
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Projectile trail emitter
datablock ParticleData(RifleSmokeParticle)
{
   textureName          = "~/data/shapes/rifle/smokeParticle";

   dragCoeffiecient     = 0.0;
   gravityCoefficient   = 0;  // rises
   inheritedVelFactor   = 0.00;

   lifetimeMS           = 30000;   // time in ms
   lifetimeVarianceMS   = 150;   // ...more or less

   useInvAlpha = false;
   spinRandomMin = -30.0;
   spinRandomMax = 30.0;

   colors[0]     = "0 0.2 1 1.0";
   colors[1]     = "0 0.2 1 1.0";
   colors[2]     = "0 0 0 0";

   sizes[0]      = 0.25;
   sizes[1]      = 0.4;
   sizes[2]      = 0.6;

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

datablock ParticleEmitterData(RifleSmokeEmitter)
{
   ejectionPeriodMS = 100;
   periodVarianceMS = 0;

   ejectionVelocity = "10 0 0";
   velocityVariance = 0;
   ejectionOffset =  1;
   thetaMin         = 0.0;
   thetaMax         = 0.0; 
   phivariance = 0; 
   orientParticles = true;
   isChain = true;
   particles = RifleSmokeParticle;
};


//-----------------------------------------------------------------------------
// Weapon fire emitter

datablock ParticleData(RifleFireParticle)
{
   textureName          = "~/data/shapes/rifle/smokeParticle";

   dragCoeffiecient     = 0.0;
   gravityCoefficient   = -0.1;  // rises
   inheritedVelFactor   = 0.3;

   lifetimeMS           = 200;   // Time in ms
   lifetimeVarianceMS   = 50;    // ...more or less

   useInvAlpha = false;
   spinRandomMin = -30.0;
   spinRandomMax = 30.0;

   colors[0]     = "0 0.2 1 1.0";
   colors[1]     = "1 1 1 1.0";
   colors[2]     = "0 0 0 0";

   sizes[0]      = 0.2;
   sizes[1]      = 0.5;
   sizes[2]      = 1;

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

datablock ParticleEmitterData(RifleFireEmitter)
{
   ejectionPeriodMS = 30;
   periodVarianceMS = 5;

   ejectionVelocity = 2;
   ejectionOffset   = 0.1;
   velocityVariance = 0.10;

   thetaMin         = 0.0;
   thetaMax         = 10.0;  

   particles = RifleFireParticle;
};


//-----------------------------------------------------------------------------
// Projectile Explosion

datablock ParticleData(RifleExplosionParticle)
{
   dragCoefficient      = 2;
   gravityCoefficient   = 0.2;
   inheritedVelFactor   = 0.2;
   constantAcceleration = 0.0;
   lifetimeMS           = 750;
   lifetimeVarianceMS   = 150;
   textureName          = "~/data/shapes/rifle/smokeParticle";
   colors[0]     = "0 0.2 1 1.0";
   colors[1]     = "0 0.2 1 0.0";
   sizes[0]      = 0.5;
   sizes[1]      = 1.0;
};

datablock ParticleEmitterData(RifleExplosionEmitter)
{
   ejectionPeriodMS = 7;
   periodVarianceMS = 0;
   ejectionVelocity = 1;
   velocityVariance = 1.0;
   ejectionOffset   = 0.0;
   thetaMin         = 0;
   thetaMax         = 60;
   phiReferenceVel  = 0;
   phiVariance      = 360;
   overrideAdvances = false;
   particles = "RifleExplosionParticle";
};

datablock ExplosionData(RifleExplosion)
{
   //explosionShape = "~/data/shapes/rifle/explosion.dts";
   lifeTimeMS = 1500;

   particleEmitter = RifleExplosionEmitter;
   particleDensity = 50;
   particleRadius = 0.2;

   faceViewer     = true;
   explosionScale = "1 1 1";

   shakeCamera = true;
   camShakeFreq = "10.0 11.0 10.0";
   camShakeAmp = "1.0 1.0 1.0";
   camShakeDuration = 0.5;
   camShakeRadius = 10.0;

   // Dynamic light
   lightStartRadius = 6;
   lightEndRadius = 0;
   lightStartColor = "0 0 0.6";
   lightEndColor = "0 0 0";
};


//-----------------------------------------------------------------------------
// Projectile Object

datablock ProjectileData(RifleProjectile)
{
   projectileShapeName = "~/data/shapes/rifle/projectile.dts";
   directDamage        = 10;
   radiusDamage        = 10;
   damageRadius        = 0.5;
   explosion           = RifleExplosion;
   particleEmitter     = RifleSmokeEmitter;

   muzzleVelocity      = 10;
   velInheritFactor    = 1;

   armingDelay         = 0;
   lifetime            = 200000;
   fadeDelay           = 1500;
   bounceElasticity    = 0;
   bounceFriction      = 0;
   isBallistic         = true;
   gravityMod = 0.10;

   hasLight    = true;
   lightRadius = 3.0;
   lightColor  = "0 0 0.5";
};

function RifleProjectile::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,"RifleBullet");

   // 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, VectorAdd(%pos, VectorScale(%normal, 0.01)),
      %this.damageRadius,%this.radiusDamage,"Radius",40);
}


//-----------------------------------------------------------------------------
// Ammo Item

datablock ItemData(RifleAmmo)
{
   // Mission editor category
   category = "Ammo";

   // Add the Ammo namespace as a parent.  The ammo namespace provides
   // common ammo related functions and hooks into the inventory system.
   className = "Ammo";

   // Basic Item properties
   shapeFile = "~/data/shapes/rifle/ammo.dts";
   mass = 1;
   elasticity = 0.2;
   friction = 0.6;

	// Dynamic properties defined by the scripts
	pickUpName = "rifle ammo";
   maxInventory = 50;
};


//--------------------------------------------------------------------------
// Rifle shell that's ejected during reload.

datablock DebrisData(RifleShell)
{
   shapeFile = "~/data/shapes/rifle/shell.dts";
   lifetime = 3.0;
   minSpinSpeed = 300.0;
   maxSpinSpeed = 400.0;
   elasticity = 0.5;
   friction = 0.2;
   numBounces = 4;
   staticOnMaxBounce = true;
   snapOnMaxBounce = false;
   fade = true;
};


//--------------------------------------------------------------------------
// Weapon Item.  This is the item that exists in the world, i.e. when it's
// been dropped, thrown or is acting as re-spawnable item.  When the weapon
// is mounted onto a shape, the RifleImage is used.

datablock ItemData(Rifle)
{
   // Mission editor category
   category = "Weapon";

   // Hook into Item Weapon class hierarchy. The weapon namespace
   // provides common weapon handling functions in addition to hooks
   // into the inventory system.
   className = "Weapon";

   // Basic Item properties
   shapeFile = "~/data/shapes/rifle/weapon.dts";
   mass = 1;
   elasticity = 0.2;
   friction = 0.6;
   emap = true;

	// Dynamic properties defined by the scripts
	pickUpName = "a rifle";
	image = RifleImage;
};


//--------------------------------------------------------------------------
// Rifle image which does all the work.  Images do not normally exist in
// the world, they can only be mounted on ShapeBase objects.

datablock ShapeBaseImageData(RifleImage)
{
   // Basic Item properties
   shapeFile = "~/data/shapes/rifle/weapon.dts";
   emap = true;

   // Specify mount point & offset for 3rd person, and eye offset
   // for first person rendering.
   mountPoint = 0;
   offset = "0 0 0";
   eyeOffset = "0.1 0.2 -0.55";

   // When firing from a point offset from the eye, muzzle correction
   // will adjust the muzzle vector to point to the eye LOS point.
   // Since this weapon doesn't actually fire from the muzzle point,
   // we need to turn this off.  
   correctMuzzleVector = false;

   // Add the WeaponImage namespace as a parent, WeaponImage namespace
   // provides some hooks into the inventory system.
   className = "WeaponImage";

   // Projectile && Ammo.
   item = Rifle;
   ammo = RifleAmmo;
   projectile = RifleProjectile;
   projectileType = Projectile;
   casing = RifleShell;

   // Images have a state system which controls how the animations
   // are run, which sounds are played, script callbacks, etc. This
   // state system is downloaded to the client so that clients can
   // predict state changes and animate accordingly.  The following
   // system supports basic ready->fire->reload transitions as
   // well as a no-ammo->dryfire idle state.

   // Initial start up state
   stateName[0]                     = "Preactivate";
   stateTransitionOnLoaded[0]       = "Activate";
   stateTransitionOnNoAmmo[0]       = "NoAmmo";

   // Activating the gun.  Called when the weapon is first
   // mounted and there is ammo.
   stateName[1]                     = "Activate";
   stateTransitionOnTimeout[1]      = "Ready";
   stateTimeoutValue[1]             = 0.5;
   stateSequence[1]                 = "Activate";

   // Ready to fire, just waiting for the trigger
   stateName[2]                     = "Ready";
   stateTransitionOnNoAmmo[2]       = "NoAmmo";
   stateTransitionOnTriggerDown[2]  = "Fire";

   // Fire the weapon. Calls the fire script which does 
   // the actual work.
   stateName[3]                     = "Fire";
   stateTransitionOnTimeout[3]      = "Reload";
   stateTimeoutValue[3]             = 0.1;
   stateFire[3]                     = true;
   stateRecoil[3]                   = LightRecoil;
   stateAllowImageChange[3]         = false;
   stateSequence[3]                 = "Fire";
   stateScript[3]                   = "onFire";
   stateEmitter[3]                  = RifleFireEmitter;
   stateEmitterTime[3]              = 0.3;

   // Play the relead animation, and transition into
   stateName[4]                     = "Reload";
   stateTransitionOnNoAmmo[4]       = "NoAmmo";
   stateTransitionOnTimeout[4]      = "Ready";
   stateTimeoutValue[4]             = 0.1;
   stateAllowImageChange[4]         = false;
   stateSequence[4]                 = "Reload";
   stateEjectShell[4]               = true;

   // No ammo in the weapon, just idle until something
   // shows up. Play the dry fire sound if the trigger is
   // pulled.
   stateName[5]                     = "NoAmmo";
   stateTransitionOnAmmo[5]         = "Reload";
   stateSequence[5]                 = "NoAmmo";
   stateTransitionOnTriggerDown[5]  = "DryFire";

   // No ammo dry fire
   stateName[6]                     = "DryFire";
   stateTimeoutValue[6]             = 1.0;
   stateTransitionOnTimeout[6]      = "NoAmmo";
};


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

$weaponSettings1[RifleImage]  = "3 -1 Test Gun";
$weaponSetting1[RifleImage,0] = "Normal";
$weaponSetting1[RifleImage,1] = "Rotate";
$weaponSetting1[RifleImage,2] = "Deconstruct current piece";
$weaponSetting1[RifleImage,3] = "Spin";

$weaponSettings2[RifleImage]  = "5 -1 Test Gun";
$weaponSetting2[RifleImage,0] = "5 degrees pull";
$weaponSetting2[RifleImage,1] = "10 degrees pull";
$weaponSetting2[RifleImage,2] = "20 degrees pull";
$weaponSetting2[RifleImage,3] = "5 degrees push";
$weaponSetting2[RifleImage,4] = "10 degrees push";
$weaponSetting2[RifleImage,5] = "20 degrees push";


function RifleImage::onFire(%this, %obj, %slot)
{

%ray = %obj.EyeRay();

if (%ray.object)
   {
   %target = %ray.object;
   if (%obj.weaponSet1 ==2) {
      if (%target.iscubic) {
	  %target.startFade(250,250,1);
          %target.schedule(500,"delete");
	}
      %ray.delete();	
      return "";
      }
   if (%obj.weaponSet1 == 1) {
        if (%target.iscubic) {
        %nrm = %ray.normal;
	%nrm2 = VectorNormalize(%target.bestSide(%ray.point,%ray.normal));	
	%axis = VectorNormalize(VectorCross(%nrm,%Nrm2));
	
	if (%obj.weaponset2 $= "") 
		%angle = 5;
	else
		%angle = getWord($weaponSetting2[RifleImage,%obj.weaponset2],0) * ((%obj.weaponset2 <3)*2-1);
	%target.setRotation(rotadd(%target.getRotation(),%axis SPC mDegToRad(%angle)));
        }
        %ray.delete();
        return"";
       }
   }
   if (%obj.weaponSet1 == 3) {
      if (%target.iscubic) {
	if (%obj.weaponset2 $= "") 
		%angle = 10;
	else
		%angle = getWord($weaponSetting2[RifleImage,%obj.weaponset2],0) * ((%obj.weaponset2 <3)*2-1);
	  %target.time = %angle == 0 ? 10 : 360/%angle;
	  orbit(%target);
	}
        %ray.delete();	
       return "";
   }
   %projectile = %this.projectile;

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

   // Determin 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  = %muzzleVelocity;
      initialPosition  = %obj.getMuzzlePoint(%slot);
      sourceObject     = %obj;
      sourceSlot       = %slot;
      client           = %obj.client;      
   };
   MissionCleanup.add(%p);
   %ray.delete();
   return %p;

}
