---------------------------------------------------------------------------------------------------------------
Jumpad Tutorial
---------------------------------------------------------------------------------------------------------------
This creates a deployable Jumpad that launches people into the air when touched. It's created as an item, instead of static, due to the greater sensitivity of item collisions when flat.
Step #1
// ------------------------------------------
// defaultGame.cs
// ------------------------------------------

function DefaultGame::clearDeployableMaxes(%game)
{

      $TeamDeployedCount[%i, JumpadDeployable] = 0;

}

Step #2
// ------------------------------------------
// deployables.cs
// ------------------------------------------

2a)Near the top of the file add this:

$TeamDeployableMax[JumpadDeployable] = 5;


2b)All of this takes place in function ShapeBaseImageData::onDeploy:

   if(%item.deployed.className $= "DeployedTurret")
      %className = "Turret";
   else
      %className = "StaticShape";

   becomes:

   if(%item.deployed.className $= "DeployedTurret")
      %className = "Turret";
   else if (%item.deployed.className $= "Jumpad")
      %className = "Item";
   else
      %className = "StaticShape";

Next:

   %deplObj = new (%className)()
   {
      dataBlock = %item.deployed;
   };

   becomes:

   if (%item.deployed.classname $= "Jumpad")
   {
      %deplObj = new (%className)()
      {
         dataBlock = %item.deployed;
         scale = "0.55 0.7 0.3";
      };
   }
   else
   {
      %deplObj = new (%className)()
      {
         dataBlock = %item.deployed;
      };
   }

Next:

   if(%className $= "Turret")
      %deplObj.setDeployRotation(%item.surfacePt, %item.surfaceNrm);
   else
      %deplObj.setTransform(%item.surfacePt SPC %rot);

   becomes:

   if(%className $= "Turret")
      %deplObj.setDeployRotation(%item.surfacePt, %item.surfaceNrm);
   else if (%item.deployed.classname $= "Jumpad")
      %deplObj.setDeployRotation(getWords(%item.surfacePt, 0, 1) SPC getWord(%item.surfacePt, 2) + 0.1, %item.surfaceNrm);
   else
      %deplObj.setTransform(%item.surfacePt SPC %rot);

Next:

   %deplObj.deploy();

   becomes:

   if (%classname !$= "Item")
      %deplObj.deploy();


Step #3
// ------------------------------------------
// inventoryHud.cs
// ------------------------------------------
Add this near the top of the file:

$InvPack[18] = "Jump Pad";
$NTInvPack[11] = "Jump Pad";
$NameToInv["Jump Pad"] = "JumpadDeployable";


Step #4
// ------------------------------------------
// pack.cs
// ------------------------------------------
exec("scripts/packs/Jumpad.cs");


Step #5
// ------------------------------------------
// repairpack.cs
// ------------------------------------------
Find both instances of '%searchMasks =' in the file and add '| $TypeMasks::ItemObjectType' so the jumpad can be repaired.


Step #6
// ------------------------------------------
// player.cs
// ------------------------------------------

6a) In each player datablock add this. Since it's a deployable, only mediums and heavies need it.
   max[JumpadDeployable] = 1;


6b) At the bottom of function Armor::onCollision add this: (This handles the impulse. Adjust the 2200 for horizontal push and 7500 for vertical push).

      else if (%className $= "Jumpad")
      {
         if (%col.team == %obj.team)
         {
            %position = getWords(%obj.getTransform(), 0, 2);
            %vel = %obj.getVelocity();
            %x1 = getWord(%vel, 0) * 2200;
            %y1 = getWord(%vel, 1) * 2200;
            %impulseVec = %x1 SPC %y1 SPC 7500;
            %obj.applyImpulse(%position, %impulseVec);
            %obj.playAudio(0, MortarFireSound);
         }
      }


Step #7
// ------------------------------------------
// Jumpad.cs
// ------------------------------------------
Create a new file called Jumpad.cs in your packs directory and add all this:


//--------------------------------------------------------------------------
// Jumpad
//
//
//--------------------------------------------------------------------------

datablock ItemData(DeployedJumpad) : StaticShapeDamageProfile
{
   className = Jumpad;
   shapeFile = "dmiscf.dts"; // dmiscf.dts, alternate
   maxDamage = 2.0;
   destroyedLevel = 2.0;
   disabledLevel = 2.0;
   pickupRadius = 1;
   sticky=true;

   explosion      = HandGrenadeExplosion;
      expDmgRadius = 3.0;
      expDamage = 0.1;
      expImpulse = 200.0;
   dynamicType = $TypeMasks::StaticShapeObjectType;
   deployedObject = true;
   cmdCategory = "DSupport";
   cmdIcon = CMDSensorIcon;
   cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor";
   targetNameTag = 'Jump';
   targetTypeTag = 'Pad';
   deployAmbientThread = true;
   debrisShapeName = "debris_generic_small.dts";
   debris = DeployableDebris;
   heatSignature = 0;
};

datablock ShapeBaseImageData(JumpadDeployableImage)
{
   mass = 10;
   emap = true;
   shapeFile = "Stackable1s.dts";
   item = JumpadDeployable;
   mountPoint = 1;
   offset = "0 0 0";
   deployed = DeployedJumpad;
   heatSignature = 0;

   stateName[0] = "Idle";
   stateTransitionOnTriggerDown[0] = "Activate";

   stateName[1] = "Activate";
   stateScript[1] = "onActivate";
   stateTransitionOnTriggerUp[1] = "Idle";

   isLarge = true;
   maxDepSlope = 30; // 30
   deploySound = ItemPickupSound;

   minDeployDis = 0.5;
   maxDeployDis = 5.0;
};

datablock ItemData(JumpadDeployable)
{
   className = Pack;
   catagory = "Deployables";
   shapeFile = "Stackable1s.dts";
   mass = 5.0;
   elasticity = 0.2;
   friction = 0.6;
   pickupRadius = 1;
   rotate = true;
   image = "JumpadDeployableImage";
   pickUpName = "a jump pad";
   heatSignature = 0;
   emap = true;
};

function JumpadDeployable::onPickup(%this, %obj, %shape, %amount)
{
   // created to prevent console errors
}

function DeployedJumpad::onDestroyed(%this, %obj, %prevState)
{
   Parent::onDestroyed(%this, %obj, %prevState);
   $TeamDeployedCount[%obj.team, JumpadDeployable]--;
   %obj.schedule(500, "delete");
}

//Functions below here give StaticShape damage to the Jumpad item.
function DeployedJumpad::onDamage(%this,%obj)
{
   // Set damage state based on current damage level
   %damage = %obj.getDamageLevel();
   if(%damage >= %this.destroyedLevel)
   {
      if(%obj.getDamageState() !$= "Destroyed")
      {
         %obj.setDamageState(Destroyed);
         // if object has an explosion damage radius associated with it, apply explosion damage
         if(%this.expDmgRadius)
            RadiusExplosion(%obj, %obj.getWorldBoxCenter(), %this.expDmgRadius, %this.expDamage, %this.expImpulse, %obj, $DamageType::Explosion);
      }
   }
   else
   {
      if(%damage >= %this.disabledLevel)
      {
         if(%obj.getDamageState() !$= "Disabled")
            %obj.setDamageState(Disabled);
      }
      else
      {
         if(%obj.getDamageState() !$= "Enabled")
            %obj.setDamageState(Enabled);
      }
   }
}

function DeployedJumpad::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType)
{
   // if this is a non-team mission type and the object is "protected", don't damage it
   if(%data.noIndividualDamage && Game.allowsProtectedStatics())
      return;

   // if this is a Siege mission and this object shouldn't take damage (e.g. vehicle stations)
   if(%data.noDamageInSiege && Game.class $= "SiegeGame")
      return;

   if(%sourceObject)
   {
      if(%sourceObject.client)
      {
        %targetObject.lastDamagedBy = %sourceObject.client;
        %targetObject.lastDamagedByTeam = %sourceObject.client.team;
        %targetObject.damageTimeMS = GetSimTime();
      }
      else
      {
        %targetObject.lastDamagedBy = %sourceObject;
        %targetObject.lastDamagedByTeam = %sourceObject.team;
        %targetObject.damageTimeMS = GetSimTime();
      }
   }

   // Scale damage type & include shield calculations...
   if (%data.isShielded)
      %amount = %data.checkShields(%targetObject, %position, %amount, %damageType);

   %damageScale = %data.damageScale[%damageType];
   if(%damageScale !$= "")
      %amount *= %damageScale;

    //if team damage is off, cap the amount of damage so as not to disable the object...
    if (!$TeamDamage && !%targetObject.getDataBlock().deployedObject)
    {
       //see if the object is being shot by a friendly
       if(%sourceObject.getDataBlock().catagory $= "Vehicles")
          %attackerTeam = getVehicleAttackerTeam(%sourceObject);
       else %attackerTeam = %sourceObject.team;

      if (isTargetFriendly(%targetObject.getTarget(), %attackerTeam))
      {
         %curDamage = %targetObject.getDamageLevel();
         %availableDamage = %targetObject.getDataBlock().disabledLevel - %curDamage - 0.05;
         if (%amount > %availableDamage)
            %amount = %availableDamage;
      }
    }

   // if there's still damage to apply
   if (%amount > 0)
      %targetObject.applyDamage(%amount);
}