//******************************************************************************
//* Default StaticShape functions
//******************************************************************************

function StaticShapeData::onGainPowerEnabled(%data, %Object)
{
   if(%data.ambientThreadPowered)
      %Object.playThread($AmbientThread, "ambient");
   // if it's a deployed object, schedule the power thread; else play it immediately
   if(%data.deployAmbientThread)
      %Object.schedule(750, "playThread", $PowerThread, "Power");
   else
      %Object.playThread($PowerThread,"Power");
   // deployable objects get their recharge rate set right away -- don't set it again unless
   // the object has just been re-enabled
   if(%Object.initDeploy)
      %Object.initDeploy = false;
   else
   {
      if(%Object.getRechargeRate() <= 0)
      {
         %oldERate = %Object.getRechargeRate();
         %Object.setRechargeRate(%oldERate + %data.rechargeRate);
      }
   }
   if(%data.humSound !$= "")
      %Object.playAudio($HumSound, %data.humSound);
   %Object.setPoweredState(true);
}

function StaticShapeData::onLosePowerDisabled(%data, %Object)
{
   %client = %Object.getControllingClient();
   if(%client != 0)
      serverCmdResetControlObject(%client);
   
   if(%data.ambientThreadPowered)
      %Object.pauseThread($AmbientThread);
   if(!%data.alwaysAmbient)
   {
      %Object.stopThread($PowerThread);
      // MES -- drop shields and stop them from regenerating after power loss
      %Object.setRechargeRate(0.0);
      %Object.setEnergyLevel(0.0);
   }
   if(%data.humSound !$= "")
      %Object.stopAudio($HumSound);
   %Object.setPoweredState(false);
}

function StaticShapeData::gainPower(%data, %Object)
{
   if(%Object.isEnabled())
      %data.onGainPowerEnabled(%Object);
   Parent::gainPower(%data, %Object);
}

function StaticShapeData::losePower(%data, %Object)
{
   if(%Object.isEnabled())
      %data.onLosePowerDisabled(%Object);
   Parent::losePower(%data, %Object);
}

function ShapeBaseData::onEnabled()
{
}

function ShapeBaseData::onDisabled()
{
}

function StaticShapeData::onEnabled(%data, %Object, %prevState)
{
   if(%Object.isPowered())
      %data.onGainPowerEnabled(%Object);
   Parent::onEnabled(%data, %Object, %prevState);
}

function StaticShapeData::onDisabled(%data, %Object, %prevState)
{
   if(%Object.isPowered() || (%data.className $= "Generator"))
      %data.onLosePowerDisabled(%Object);

   AreaSmoke(%Object.getTransform());

   Parent::onDisabled(%data, %Object, %prevState);
}

function StaticShape::deploy(%this)
{
   %this.playThread($DeployThread, "deploy");
}

function StaticShapeData::onEndSequence(%data, %Object, %thread)
{
   if(%thread == $DeployThread)
      %Object.setSelfPowered();

   Parent::onEndSequence(%data, %Object, %thread);
}

function ShapeBaseData::onEndSequence()
{
}

//******************************************************************************
//* Example explosion
//******************************************************************************

datablock EffectProfile(ShapeExplosionEffect)
{
   effectname = "explosions/explosion.xpl03";
   minDistance = 10;
   maxDistance = 50;
};

datablock AudioProfile(ShapeExplosionSound)
{
   filename = "fx/explosions/explosion.xpl03.wav";
   description = AudioExplosion3d;
   preload = true;
   effect = ShapeExplosionEffect;
};

datablock ExplosionData(ShapeExplosion)
{
   explosionShape = "disc_explosion.dts";
   soundProfile = ShapeExplosionSound;
   faceViewer = true;
};

//******************************************************************************
//*   Player Armors  -  Data Blocks (live players are now StaticTSObjects)
//******************************************************************************

datablock StaticShapeData(HeavyMaleHuman_Dead)
{
   className = "deadArmor";
   catagory = "Player Armors";
   shapeFile = "heavy_male_dead.dts";
   isInvincible = true;
};

datablock StaticShapeData(MediumMaleHuman_Dead)
{
   className = "deadArmor";
   catagory = "Player Armors";
   shapeFile = "medium_male_dead.dts";
   isInvincible = true;
};

datablock StaticShapeData(LightMaleHuman_Dead)
{
   className = "deadArmor";
   catagory = "Player Armors";
   shapeFile = "light_male_dead.dts";
   isInvincible = true;
};

function deadArmor::onAdd(%data, %Object)
{
   Parent::onAdd(%data, %Object);
}

//*****************************************************************************
//*   Flagstands - Data Blocks                        
//*****************************************************************************
datablock StaticShapeData(InteriorFlagStand)
{
   className = "FlagIntStand";
   catagory = "Objectives";
   shapefile = "int_flagstand.dts";
   isInvincible = true;
   needsNoPower = true;
};

datablock StaticShapeData(ExteriorFlagStand)
{
   className = "FlagIntStand";
   catagory = "Objectives";
   shapefile = "ext_flagstand.dts";
   isInvincible = true;
   needsNoPower = true;
};

///////////////////////////////////////////
//flagIntStand::onAdd(%this, %Object)
//%this: objects datablock
//%obj:  the actual object being added
///////////////////////////////////////////

function ExteriorFlagStand::onAdd(%this, %Object)
{
   Parent::onAdd(%this, %Object);
   %Object.playThread($ActivateThread, "activate");
}

function ExteriorFlagStand::onFlagTaken(%this, %Object)
{  
   %Object.setThreadDir($ActivateThread, 0);
}

function ExteriorFlagStand::onFlagReturn(%this, %Object)
{
   %Object.setThreadDir($ActivateThread, 1);
}
                        
function ExteriorFlagStand::onCollision(%this, %Object, %colObj)
{
   game.flagStandCollision(%this, %Object, %colObj);
}
                        
function InteriorFlagStand::onCollision(%this, %Object, %colObj)
{
   game.flagStandCollision(%this, %Object, %colObj);
}
                        
///////////////////////////////////////////////
//end flag stand functions
///////////////////////////////////////////////

datablock StaticShapeData(FlipFlop)
{
   catagory = "Objectives";
   shapefile = "switch.dts";

   isInvincible = true;
   cmdCategory = "Objectives";
   cmdIcon = "CMDSwitchIcon";
   cmdMiniIconName = "commander/MiniIcons/com_switch_grey";
   targetTypeTag = 'Switch';
   alwaysAmbient = true;
   needsNoPower = true;
   emap = true;
};

function FlipFlop::onCollision(%data,%Object,%col)
{
   if (%col.getDataBlock().className $= Armor && %col.getState() !$= "Dead")
      %data.playerTouch(%Object, %col);
}

function FlipFlop::playerTouch(%data,%Object,%col)
{
   messageAll('MsgPlayerTouchSwitch', 'Player %1 touched switch %2', %col, %Object);
}

//******************************************************************************
//*   Organics  -                                                              *
//******************************************************************************

//function to add random Organics to mission pre-creation
//(could be used to add other things...its cool with bioderm armors ;) )

function randomOrg(%organicName, %num, %radius)
{
   %SPACING = 1.0; //meters between center of organic and another object

   //return help info
   if(%organicName $="" || !%num || !%radius) {
      echo("randomOrg(<shape name>, <quantity>, <radius of grove desired>);");
      return;
   }

   %organicIndex = -1;
   for (%i = 0; %i < $NumAStaticTSObjects; %i++) {
      if (getWord($StaticTSObjects[%i], 1) $= %organicName) {
         %organicIndex = %i;
         break;
      }
   }
   if (%organicIndex == -1) {
      error("There is no static shape named" SPC %organicName);
      return;
   }
   %shapeFileName = getWord($StaticTSObjects[%organicIndex], 2);

   %maxSlope = getWord($StaticTSObjects[%organicIndex], 3);
   if (%maxSlope $= "")
      %maxSlope = 40;

   %zOffset = getWord($StaticTSObjects[%organicIndex], 4);
   if (%zOffset $= "")
      %zOffset = 0;

   %slopeWithTerrain = getWord($StaticTSObjects[%organicIndex], 5);
   if (%slopeWithTerrain $= "")
      %slopeWithTerrain = false;

   %minScale = getWord($StaticTSObjects[%organicIndex], 6);
   %maxScale = getWord($StaticTSObjects[%organicIndex], 7);

   //set up folders in mis file
   $RandomOrganicsAdded++;  //to keep track of groups
   if(!isObject(RandomOrganics)) {
      %randomOrgGroup = new simGroup(RandomOrganics);
      MissionGroup.add(%randomOrgGroup);
   }
   %groupName = "Addition"@$RandomOrganicsAdded@%organicName;
   %group = new simGroup(%groupName);
   RandomOrganics.add(%group);
   
       
   %ctr = LocalClientConnection.camera.getPosition();
   %areaX = getWord(%ctr, 0) - %radius;
   %areaY = getWord(%ctr, 1) - %radius;
   
   %orgCount = %num;
   while((%orgCount > 0) && (%retries < (15000 / %maxSlope)))  //theoretically, a thorough number of retries 
   {
      //find a tile
      %x = (getRandom(mFloor(%areaX / 8), mFloor((%areaX + (%radius * 2)) / 8)) * 8) + 4;  //tile center             
      %y = (getRandom(mFloor(%areaY / 8), mFloor((%areaY + (%radius * 2)) / 8)) * 8) + 4;    

      %start = %x @ " " @ %y @ " 2000";
      %end = %x @ " " @ %y @ " -1";
      %ground = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0);      
      %z = getWord(%ground, 3);
      %z += %zOffset;            
      %position = %x @ " " @ %y @ " " @ %z;


      // get normal from both sides of the square      
      %start = %x + 2 @ " " @ %y @ " 2000";
      %end = %x + 2 @ " " @ %y @ " -1";
      %hit1 = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0);
            
      %start = %x - 2 @ " " @ %y @ " 2000";
      %end = %x - 2 @ " " @ %y @ " -1";
      %hit2 = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0);    

      %norm1 = getWord(%hit1, 4) @ " " @ getWord(%hit1, 5) @ " " @ getWord(%hit1, 6);
      %norm2 = getWord(%hit2, 4) @ " " @ getWord(%hit2, 5) @ " " @ getWord(%hit2, 6);

      //if either side of tile has greater slope than allowed, move on.
      %angNorm1 = getTerrainAngle(%norm1);
      %angNorm2 = getTerrainAngle(%norm2);
      if ((getTerrainAngle(%norm1) > %maxSlope) || (getTerrainAngle(%norm2) > %maxslope))
      {      
         %retries++;
         continue;
      }

      %terrainNormal = VectorAdd(%norm1, %norm2);
      %terrainNormal = VectorNormalize(%terrainNormal);       
      
      //search surroundings for obstacles. If obstructed, move on.      
      InitContainerRadiusSearch(%position, %spacing,  $TypeMasks::VehicleObjectType | 
                                          $TypeMasks::MoveableObjectType |
                                                $TypeMasks::StaticShapeObjectType |
                                                $TypeMasks::TSStaticShapeObjectType | 
                                                $TypeMasks::ForceFieldObjectType |
                                                $TypeMasks::TurretObjectType | 
                                                $TypeMasks::InteriorObjectType | 
                                                $TypeMasks::ItemObjectType);  
      %this = containerSearchNext();
      if(%this)
      {        
         %retries++;
         continue;         
      }
      
         
      //rotate it
      if(%slopeWithTerrain)
      {
         %rotAxis = vectorCross(%terrainNormal, "0 0 1");
         %rotAxis = vectorNormalize(%rotAxis);
         %rotation = %rotAxis @ " " @ getTerrainAngle(%terrainNormal);              
      }        
      else %rotation = "1 0 0 0";      
      %randomAngle = getRandom(360);
      %zrot = MatrixCreate("0 0 0", "0 0 1 " @ %randomAngle); 
      %orient = MatrixCreate(%position, %rotation);
      %finalXForm = MatrixMultiply(%orient, %zrot);
      

      //scale it
      %scaleMin = 8;  //default min
      %scaleMax = 14; //default max
      if(%minScale)
         %scaleMin = %minScale * 10;
      if(%maxScale)
         %scaleMax = %maxScale * 10;
      %scaleInt = getRandom(%scaleMin, %scaleMax);
      %scale = %scaleInt/10;
      %evenScale = %scale SPC %scale SPC %scale;

      //create it
      %position = %x SPC %y SPC (%z += %zoffset);        
      %newOrganic = new TSStatic() {
         position  = %position;
         rotation  = %rotation;
         scale     = %evenScale;
         shapeName = %shapeFileName;
      };
      %group.add(%newOrganic);
      %newOrganic.setTransform(%finalXForm);

      %orgCount--;   //dec number of shapes left to place
      %retries = 0; //reset retry counter
   }
   if (%orgCount > 0)
   {
      error("Unable to place all shapes, area saturated.");
      error("Looking for clear area " @ (%spacing * 2) @ " meters in diameter, with a max slope of " @ %maxSlope);
   }
   echo("Placed " @ %num - %orgCount @ " of " @ %num);
}

function getTerrainAngle(%point)
{
   %up = "0 0 1";
   %angleRad = mACos(vectorDot(%point, %up));
   %angleDeg = mRadToDeg(%angleRad);
   //echo("angle is "@%angleDeg);
   return %angleDeg;
}


//--------------------------------------------------------------------------
//-------------------------------------- Organics
//--------------------------------------------------------------------------


//******************************************************************************
//*   Pulse Sensor  -  Data Blocks                                             *
//******************************************************************************

datablock DebrisData( StaticShapeDebris )
{
   explodeOnMaxBounce = false;

   elasticity = 0.20;
   friction = 0.5;

   lifetime = 17.0;
   lifetimeVariance = 0.0;

   minSpinSpeed = 60;
   maxSpinSpeed = 600;

   numBounces = 10;
   bounceVariance = 0;

   staticOnMaxBounce = true;

   useRadiusMass = true;
   baseRadius = 0.4;

   velocity = 9.0;
   velocityVariance = 4.5;
};             

datablock DebrisData( SmallShapeDebris )
{
   explodeOnMaxBounce = false;

   elasticity = 0.20;
   friction = 0.5;

   lifetime = 17.0;
   lifetimeVariance = 0.0;

   minSpinSpeed = 60;
   maxSpinSpeed = 600;

   numBounces = 10;
   bounceVariance = 0;

   staticOnMaxBounce = true;

   useRadiusMass = true;
   baseRadius = 0.2;

   velocity = 5.0;
   velocityVariance = 2.5;
};             

datablock AudioProfile(SensorHumSound)
{
   filename    = "fx/powered/sensor_hum.wav";
   description = CloseLooping3d;
   preload = true;
};

datablock SensorData(SensorLgPulseObj)
{
   detects = true;
   detectsUsingLOS = true;
   detectsPassiveJammed = false;
   detectsActiveJammed = false;
   detectsCloaked = false;
   detectionPings = true;
   detectRadius = 300;
};

datablock StaticShapeData(SensorLargePulse) : StaticShapeDamageProfile
{
   className = Sensor;  
   catagory = "Sensors";
   shapeFile = "sensor_pulse_large.dts";
   maxDamage = 1.5;
   destroyedLevel = 1.5;
   disabledLevel = 0.85;
   explosion      = ShapeExplosion;
   expDmgRadius = 10.0;
   expDamage = 0.5;
   expImpulse = 2000.0;

   dynamicType = $TypeMasks::SensorObjectType;
   isShielded = true;
   energyPerDamagePoint = 65;
   maxEnergy = 240;
   rechargeRate = 0.12;
   ambientThreadPowered = true;
   humSound = SensorHumSound;

   name = "large pulse sensor";

   cmdCategory = "Support";
   cmdIcon = CMDSensorIcon;
   cmdMiniIconName = "commander/MiniIcons/com_sensor_grey";
   targetNameTag = 'Large';
   targetTypeTag = 'Sensor';
   sensorData = SensorLgPulseObj;
   sensorRadius = SensorLgPulseObj.detectRadius;
   sensorColor = "255 194 9";

   debrisShapeName = "debris_generic.dts";
   debris = StaticShapeDebris;
};

datablock SensorData(SensorMedPulseObj)
{
   detects = true;
   detectsUsingLOS = true;
   detectsPassiveJammed = false;
   detectsActiveJammed = false;
   detectsCloaked = false;
   detectionPings = true;
   detectRadius = 175;
};

datablock StaticShapeData(SensorMediumPulse) : StaticShapeDamageProfile
{
   className = Sensor;  
   catagory = "Sensors";
   shapeFile = "sensor_pulse_medium.dts";
   maxDamage = 1.2;
   destroyedLevel = 1.2;
   disabledLevel = 0.68;
   explosion      = ShapeExplosion;
   expDmgRadius = 7.0;
   expDamage = 0.4;
   expImpulse = 1500;

   dynamicType = $TypeMasks::SensorObjectType;
   isShielded = true;
   energyPerDamagePoint = 75;
   maxEnergy = 160;
   rechargeRate = 0.08;
   ambientThreadPowered = true;
   humSound = SensorHumSound;

   name = "medium pulse sensor";

   cmdCategory = "Support";
   cmdIcon = CMDSensorIcon;
   cmdMiniIconName = "commander/MiniIcons/com_sensor_grey";
   targetNameTag = 'Medium';
   targetTypeTag = 'Sensor';
   sensorData = SensorMedPulseObj;
   sensorRadius = SensorMedPulseObj.detectRadius;
   sensorColor = "255 194 9";

   debrisShapeName = "debris_generic.dts";
   debris = StaticShapeDebris;
};

function Sensor::onGainPowerEnabled(%data, %Object)
{
   setTargetSensorData(%Object.target, %data.sensorData);
   Parent::onGainPowerEnabled(%data, %Object);
}

function Sensor::onLosePowerDisabled(%data, %Object)
{
   setTargetSensorData(%Object.target, 0);
   Parent::onLosePowerDisabled(%data, %Object);
}

//******************************************************************************
//*   Generator  -  Data Blocks                                                *
//******************************************************************************

datablock AudioProfile(GeneratorHumSound)
{
   filename    = "fx/powered/generator_hum.wav";
   description = CloseLooping3d;
   preload = true;
};


datablock StaticShapeData(GeneratorLarge) : StaticShapeDamageProfile 
{   
   className      = Generator;
   catagory       = "Generators";
   shapeFile      = "station_generator_large.dts";
   explosion      = ShapeExplosion;
   maxDamage      = 1.50;
   destroyedLevel = 1.50;
   disabledLevel  = 0.85;
   expDmgRadius = 10.0;
   expDamage = 0.5;
   expImpulse = 1500.0;
   noIndividualDamage = true; //flag to make these invulnerable for certain mission types

   name = "base generator";

   dynamicType = $TypeMasks::GeneratorObjectType;
   isShielded = true;
   energyPerDamagePoint = 55;
   maxEnergy = 50;
   rechargeRate = 0.065;
   humSound = GeneratorHumSound;
   
   cmdCategory = "Support";
   cmdIcon = "CMDGeneratorIcon";
   cmdMiniIconName = "commander/MiniIcons/com_generator";   
   targetTypeTag = 'Generator';

   debrisShapeName = "debris_generic.dts";
   debris = StaticShapeDebris;
};

datablock StaticShapeData(SolarPanel) : StaticShapeDamageProfile
{
   className = Generator;
   catagory = "Generators";
   shapeFile = "solarpanel.dts";
   explosion = ShapeExplosion;
   maxDamage = 1.00;
   destroyedLevel = 1.00;
   disabledLevel = 0.55;
   expDmgRadius = 5.0;
   expDamage = 0.3;
   expImpulse = 1000.0;
   noIndividualDamage = true; //flag to make these invulnerable for certain mission types
   emap = true;

   name = "solar panel";

   isShielded = true;
   energyPerDamagePoint = 65;
   maxEnergy = 30;
   rechargeRate = 0.05;

   dynamicType = $TypeMasks::GeneratorObjectType;
   humSound = GeneratorHumSound;

   cmdCategory = "Support";
   cmdIcon = CMDSolarGeneratorIcon;
   cmdMiniIconName = "commander/MiniIcons/com_solargen_grey";
   targetTypeTag = 'Solar Panel';

   debrisShapeName = "debris_generic.dts";
   debris = StaticShapeDebris;
};

function Generator::onDisabled(%data, %Object, %prevState)
{
   %Object.decPowerCount();
   Parent::onDisabled(%data, %Object, %prevState);
}

function Generator::onEnabled(%data, %Object, %prevState)
{
   %Object.incPowerCount();
   Parent::onEnabled(%data, %Object, %prevState);
}  

//******************************************************************************
//Nexus Effect (Hunters)
//******************************************************************************

datablock StaticShapeData(Nexus_Effect)
{
   catagory = "Objectives";
   shapefile = "nexus_effect.dts";
   mass = 10;
   elasticity = 0.2;
   friction = 0.6;
   pickupRadius = 2;
};


datablock StaticShapeData(NexusBase)
{
   catagory = "Objectives";
   shapefile = "Nexusbase.dts";
   mass = 10;
   elasticity = 0.2;
   friction = 0.6;
   pickupRadius = 2;
};


datablock StaticShapeData(NexusCap)
{
   catagory = "Objectives";
   shapefile = "Nexuscap.dts";
   mass = 10;
   elasticity = 0.2;
   friction = 0.6;
   pickupRadius = 2;
};

//******************************************************************************
//*   Static Shape  -  Functions                                               *
//******************************************************************************

function StaticShapeData::create(%block)
{
   %obj = new StaticShape() 
   {
      dataBlock = %block;
   };
   return(%Object);
}

function ShapeBase::damage(%this, %sourceObject, %position, %amount, %damageType)
{
   %this.getDataBlock().damageObject(%this, %sourceObject, %position, %amount, %damageType);
}

function ShapeBaseData::damageObject(%data, %targetObject, %position, %sourceObject, %amount, %damageType)
{

}

function ShapeBaseData::onDestroyed(%data, %Object, %prevState)
{

}

function ShapeBaseData::checkShields(%Data, %Object, %Position, %Amount, %DamageType)
{
   %Energy = %Object.getEnergyLevel();
   %EnergyDrain = %Data.energyPerDamagePoint;
   %ShieldStrength = %Energy / %EnergyDrain;

   %ShieldScale = $shieldDamageScale[%damageType];
   if(%ShieldScale $= "")
      %ShieldScale = 1;

   %Amount *= %ShieldScale;
      
   if (%Amount <= %ShieldStrength) {

      // Shields Held
      %Lost = %Amount * %EnergyDrain;
      %Object.setEnergyLevel(%Energy - %Lost);
      %Amount = 0;
   } else {

      // Shields exhausted
      %Amount -= %ShieldStrength;
      %Object.setEnergyLevel(0);
   }

   %Object.playShieldEffect("0.0 0.0 1.0");

   if (%Amount > 0)
      %Amount /= %ShieldScale;
   return(%Amount);
}

function ShapeBaseData::CheckForShields(%Data, %Object)
{
   // If the object can be shielded and has enough power, then yes it is shielded
   if (%Object.getDataBlock().isShielded == true && %Object.getEnergyLevel() > 15)
      return(true);

   // Otherwise, no they are not shielded.
   return(false);
}

function StaticShapeData::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)
   {
      %targetObject.lastDamagedBy = %sourceObject.client;
      %targetObject.lastDamagedByTeam = %sourceObject.client.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
       %srcClient = %sourceObject.client;
       if (isObject(%srcClient))
       {
          if (isTargetFriendly(%targetObject.getTarget() , %srcClient.getSensorGroup()))
          {
             %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);
}

function StaticShapeData::onDamage(%this,%Object)
{
   // Set damage state based on current damage level
   %damage = %Object.getDamageLevel();
   if(%damage >= %this.destroyedLevel)
   {
      if(%Object.getDamageState() !$= "Destroyed")
      {
         %Object.setDamageState(Destroyed);

         // if object has an explosion damage radius associated with it, apply explosion damage
         if(%this.expDmgRadius)
            RadiusExplosion(%Object, %Object.getWorldBoxCenter(), %this.expDmgRadius, %this.expDamage, %this.expImpulse, %Object, $DamageType::Explosion);

         // Make the effects of smoking after destroyed.
         %Position = posFromTransform(%Object.getTransform());

         AreaSmoke(%Position);
         schedule(1000, 0, AreaSmoke, %Position);
      }
   }
   else
   {
      if(%damage >= %this.disabledLevel)
      {
         if(%Object.getDamageState() !$= "Disabled")
            %Object.setDamageState(Disabled);
      }
      else
      {
         if(%Object.getDamageState() !$= "Enabled")
            %Object.setDamageState(Enabled);
      }
   }

   if (%Object.SensorTap !$= "")
     schedule(450, 0, MonitorSensorTapStatus, %Object, "Enabled");
}   

// --------------------------------------------------------------------
// Team logos - only the logo projector should be placed in a mission

datablock StaticShapeData(StormLogo)
{
   className = Logo;
   shapeFile = "teamlogo_storm.dts";
   alwaysAmbient = true;
};

datablock StaticShapeData(InfernoLogo)
{
   className = Logo;
   shapeFile = "teamlogo_inf.dts";
   alwaysAmbient = true;
};

datablock StaticShapeData(BiodermLogo)
{
   className = Logo;
   shapeFile = "teamlogo_bd.dts";
   alwaysAmbient = true;
};

datablock StaticShapeData(BloodEagleLogo)
{
   className = Logo;
   shapeFile = "teamlogo_be.dts";
   alwaysAmbient = true;
};

datablock StaticShapeData(DSwordLogo)
{
   className = Logo;
   shapeFile = "teamlogo_ds.dts";
   alwaysAmbient = true;
};

datablock StaticShapeData(HarbingerLogo)
{
   className = Logo;
   shapeFile = "teamlogo_hb.dts";
   alwaysAmbient = true;
};

datablock StaticShapeData(StarwolfLogo)
{
   className = Logo;
   shapeFile = "teamlogo_sw.dts";
   alwaysAmbient = true;
};

datablock StaticShapeData(LogoProjector)
{
   className = Projector;
   catagory = "Objectives";
   shapeFile = "teamlogo_projector.dts";
   alwaysAmbient = true;
   isInvincible = true;
};

function Projector::onAdd(%data, %Object)
{
   Parent::onAdd(%data, %Object);
   %Object.holo = 0;
}

////////////////////////////////////////////
//  Tapestries
///////////////////////////////////////////
datablock StaticShapeData(Banner_Honor)
{     
   catagory = "Eyecandy";
   shapefile = "banner_honor.dts";   
};

datablock StaticShapeData(Banner_Strength)
{     
   catagory = "Eyecandy";
   shapefile = "banner_strength.dts";   
};

datablock StaticShapeData(Banner_Unity)
{     
   catagory = "Eyecandy";
   shapefile = "banner_unity.dts";   
};

////////////////////////////////////////////////////////////////////////////////
//

//--------------------------------------------------------------------------
// Totally static objects
//  The format of these strings are:
//  0: Catagory
//  1: Name
//  2: File
//  3:      MaxSlope             [ only used with the randomOrg function ]
//  4:      ZOffset              [ only used with the randomOrg function ]
//  5:      slopeWithTerrain     [ only used with the randomOrg function ]
//  6:      minScale             [ only used with the randomOrg function ]
//  7:      maxScale             [ only used with the randomOrg function ]


$StaticTSObjects[0]  = "Organics BiodermPlant3 xorg3.dts";
$StaticTSObjects[1]  = "Organics BiodermPlant4 xorg4.dts";
$StaticTSObjects[2]  = "Organics BiodermPlant5 xorg5.dts";
$StaticTSObjects[3]  = "Organics BiodermPlant20 xorg20.dts";
$StaticTSObjects[4]  = "Organics BiodermPlant21 xorg21.dts";
$StaticTSObjects[5]  = "Organics BiodermPlant22 xorg22.dts";

$StaticTSObjects[6]  = "Organics BEPlant1 borg1.dts 40 0.35 1 0.5 2";
$StaticTSObjects[7] = "Organics BEPlant5 borg5.dts 40 0.0 1 1 1.5";
$StaticTSObjects[8] = "Organics BEPlant6 borg6.dts";
$StaticTSObjects[9] = "Organics BEPlant7 borg7.dts";

$StaticTSObjects[10] = "Organics BEPlant12 borg12.dts";
$StaticTSObjects[11] = "Organics BEPlant13 borg13.dts";
$StaticTSObjects[12] = "Organics BELgTree16 borg16.dts 20 -3.0 0 0.8 1.5";
$StaticTSObjects[13] = "Organics BESmTree17 borg17.dts 20 -3.0 1 0.8 1.5";
$StaticTSObjects[14] = "Organics BELgTree18 borg18.dts 20 -3.0 0 0.8 1.5";
$StaticTSObjects[15] = "Organics BELgTree19 borg19.dts 20 -3.0 0 0.8 1.5";
$StaticTSObjects[16] = "Organics BEPlant20 borg20.dts";

$StaticTSObjects[17] = "Organics BEPlant23 borg23.dts";
$StaticTSObjects[18] = "Organics BEPlant25 borg25.dts";

$StaticTSObjects[19] = "Organics BEPlant31 borg31.dts";
$StaticTSObjects[20] = "Organics BEPlant32 borg32.dts";
$StaticTSObjects[21] = "Organics BEPlant33 borg33.dts";
$StaticTSObjects[22] = "Organics BEPlant34 borg34.dts";

$StaticTSObjects[23] = "Organics PhoenixPlant1 porg1.dts";
$StaticTSObjects[24] = "Organics PhoenixPlant2 porg2.dts";
$StaticTSObjects[25] = "Organics PhoenixPlant3 porg3.dts";
$StaticTSObjects[26] = "Organics PhoenixPlant5 porg5.dts 25 -0.2 1 0.6 1.0";
$StaticTSObjects[27] = "Organics PhoenixPlant6 porg6.dts";
$StaticTSObjects[28] = "Organics PhoenixPlant20 porg20.dts";

$StaticTSObjects[29] = "Organics PhoenixPlant22 porg22.dts 25 0.1 1 0.8 1.4";
$StaticTSObjects[30] = "Organics SWTree20 sorg20.dts";
$StaticTSObjects[31] = "Organics SWShrub21 sorg21.dts";
$StaticTSObjects[32] = "Organics SWTree22 sorg22.dts";
$StaticTSObjects[33] = "Organics SWShrub23 sorg23.dts";
$StaticTSObjects[34] = "Organics SWShrub24 sorg24.dts";
$StaticTSObjects[35] = "Stackables Crate1 stackable1l.dts";
$StaticTSObjects[36] = "Stackables Crate2 stackable1m.dts";
$StaticTSObjects[37] = "Stackables Crate3 stackable1s.dts";
$StaticTSObjects[38] = "Stackables Crate4 stackable2l.dts";
$StaticTSObjects[39] = "Stackables Crate5 stackable2m.dts";
$StaticTSObjects[40] = "Stackables Crate6 stackable2s.dts";
$StaticTSObjects[41] = "Stackables Crate7 stackable3l.dts";
$StaticTSObjects[42] = "Stackables Crate8 stackable3m.dts";
$StaticTSObjects[43] = "Stackables Crate9 stackable3s.dts";
$StaticTSObjects[44] = "Stackables Crate10 stackable4l.dts";
$StaticTSObjects[45] = "Stackables Crate11 stackable4m.dts";
$StaticTSObjects[46] = "Stackables Crate12 stackable5l.dts";
$StaticTSObjects[47] = "VehicleWrecks ScoutWreckageShape vehicle_air_scout_wreck.dts";
$StaticTSObjects[48] = "VehicleWrecks TankWreckageShape vehicle_land_assault_wreck.dts";
$StaticTSObjects[49] = "Organics DSPlant16 dorg16.dts 20 -3.0 0 0.8 1.5";
$StaticTSObjects[50] = "Organics DSPlant17 dorg17.dts 20 -3.0 1 0.8 1.5";
$StaticTSObjects[51] = "Organics DSPlant18 dorg18.dts 20 -3.0 0 0.8 1.5";
$StaticTSObjects[52] = "Organics DSPlant19 dorg19.dts 20 -3.0 0 0.8 1.5";

$StaticTSObjects[53] = "PlayerArmors LightMaleHumanArmorImage light_male.dts";
$StaticTSObjects[54] = "PlayerArmors MediumMaleHumanArmorImage medium_male.dts";
$StaticTSObjects[55] = "PlayerArmors HeavyMaleHumanArmorImage heavy_male.dts";
$StaticTSObjects[56] = "PlayerArmors LightFemaleHumanArmorImage light_female.dts";
$StaticTSObjects[57] = "PlayerArmors MediumFemaleHumanArmorImage medium_female.dts";
$StaticTSObjects[58] = "PlayerArmors HeavyFemaleHumanArmorImage heavy_male.dts";
$StaticTSObjects[59] = "PlayerArmors LightMaleBiodermArmorImage bioderm_light.dts";
$StaticTSObjects[60] = "PlayerArmors MediumMaleBiodermArmorImage bioderm_medium.dts";
$StaticTSObjects[61] = "PlayerArmors HeavyMaleBiodermArmorImage bioderm_heavy.dts";

$StaticTSObjects[62] = "Organics BEGrass1 Borg6.dts";

$StaticTSObjects[63] = "Plugs bePlug bmiscf.dts";
$StaticTSObjects[64] = "Plugs dsPlug dmiscf.dts";
$StaticTSObjects[65] = "Plugs xPlug xmiscf.dts";
$StaticTSObjects[66] = "Plugs hPlug pmiscf.dts";
$StaticTSObjects[67] = "Plugs swPlug smiscf.dts";

$StaticTSObjects[68] = "Statues Base statue_base.dts";
$StaticTSObjects[69] = "Statues HeavyMaleStatue statue_hmale.dts";
$StaticTSObjects[70] = "Statues LightFemaleStatue statue_lfemale.dts";
$StaticTSObjects[71] = "Statues LightMaleStatue statue_lmale.dts";
$StaticTSObjects[72] = "Statues Plaque statue_plaque.dts";

$NumStaticTSObjects = 73;

function TSStatic::create(%shapeName)
{
   echo("Foo:" SPC %shapeName);
   %obj = new TSStatic() 
   {
      shapeName = %shapeName;
   };
   return(%Object);
}

function TSStatic::damage(%this)
{
   // prevent console error spam
}