// Blastwalls - These walls can be placed and spiked into the ground.
// Missiles and High Explosives are particularly effective against this

datablock ForceFieldBareData(BlastWallFF)
{
   Category = "ForceField";

   fadeMS           = 400;
   baseTranslucency = 0.0;
   powerOffTranslucency = 0.0;
   teamPermiable    = false;
   otherPermiable   = false;
   color            = "0.2 0.2 0.0";
   powerOffColor    = "0.0 0.0 0.0";

   texture[0] = "skins/forcef1";
   texture[1] = "skins/forcef2";
   texture[2] = "skins/forcef3";
   texture[3] = "skins/forcef4";
   texture[4] = "skins/forcef5";

   framesPerSec = 10;
   numFrames = 5;
   scrollSpeed = 15;
   umapping = 1.0;
   vmapping = 0.15;
};

function BlastWallFF::damageObject(%Data, %Field, %SourceObject, %Position, %Amount, %DamageType)
{
   // Passing Damage to blastwall
   %Field.BlastWall.getDataBlock().damageObject(%Data, %Field.BlastWall, %SourceObject, %Position, %Amount, %DamageType);
}

datablock ShapeBaseImageData(BlastWallImage)
{
   mass = 16.0;
   emap = true;

   shapeFile = "xmiscf.dts";
   item = BlastWallPack;
   deployed = TempBlastWall;

   mountPoint = 1;
   offset = "0 -0.4 -0.3";
   rotation = "1 0 0 90";

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

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

   maxDepSlope = 30;
};

datablock ItemData(BlastWallPack)
{
   className = Pack;
   catagory = "Deployables";
   shapeFile = "xmiscf.dts";

   mass = 2.0;
   elasticity = 0.2;
   friction = 0.6;
   pickupRadius = 1;
   rotate = false;

   image = BlastWallImage;
   pickUpName = "an undeployed blast wall";

   computeCRC = true;
   emap = true;
};

datablock ItemData(BlastWallSectionFall)
{
   className = Wall;

   shapeFile = "bmiscf.dts";
   mass = 1;

   image = BlastWallImage;

   heatSignature = 0;

   scale = "0.8 1.4 0.4";

   elasticity = 0.5;
   friction = 0.4;
   pickupRadius = 1;

   computeCRC = true;
   emap = true;
};

datablock StaticShapeData(BlastWallSection) : StaticShapeDamageProfile
{
   shapeFile = "bmiscf.dts";

   maxDamage = 3.2;
   destroyedLevel = 3.2;

   scale = "0.8 1.4 0.4";

   className = Wall;

   explosion = DeployablesExplosion;
   dynamicType = $TypeMasks::StaticShapeObjectType;
   deployedObject = false;

   cmdCategory = "DSupport";
   cmdIcon = CMDSensorIcon;
   cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor";

   targetNameTag = 'Blast Wall';

   deployAmbientThread = true;
   debrisShapeName = "debris_generic_small.dts";
   debris = DeployableDebris;

   heatSignature = 0;

   elasticity = 0.5;
   friction = 0.4;
   pickupRadius = 1;

   computeCRC = true;
   emap = true;

   name = "Blast Wall";

   damageScale[$DamageType::Energy] = 0.8;
   damageScale[$DamageType::Fire] = 0.26;
   damageScale[$DamageType::Bullet] = 1.1;
   damageScale[$DamageType::Explosion] = 0.3;
   damageScale[$DamageType::HighExplosion] = 1.45;
   damageScale[$DamageType::Electricity] = 0.65;
   damageScale[$DamageType::Laser] = 1.2;
};

function BlastWallSection::damageObject(%Data, %WallSection, %Player, %Position, %Amount, %DamageType)
{
   %WallSection.lastDamagedBy = %Player.client;

   %DamageScale = %data.damageScale[%DamageType];
   if (%DamageScale !$= "")
      %Amount *= %DamageScale;

   // if there's still damage to apply
   if (%Amount > 0)
      %WallSection.applyDamage(%Amount);

   %Damage = %WallSection.getDamageLevel();
   if (%Damage < %Data.destroyedLevel)
      return;

   // If the section is currently marked as destroyed, then quit
   if (%WallSection.getDamageState() $= "Destroyed")
      return;

   // Knock the piece off the wall, mark it as destroyed, and delete it
   if (%WallSection.lastDamagedBy !$= "")
   {
      %WallPosition = posFromTransform(%WallSection.getTransform());
      %AttackPosition = posFromTransform(%WallSection.lastDamagedBy.player.getTransform());
      %Vector = VectorNormalize(VectorSub(%WallPosition, %AttackPosition));
   } else {
      %Vector = "0 0 -1";
   }
   schedule(200, 0, KnockOverWall, %WallSection, %Vector);

   %Team = %WallSection.team;

   // Note the removal of the pieces now
   %BlastWallGroup = %WallSection.getGroup();
   %WallSection.ForceField.delete();
   %BlastWallGroup.Wall[%WallSection.WallNo] = "";
   %BlastWallGroup.count--;

   // If there are 2 or less pieces, then just knock those down now
   if (%BlastWallGroup.count < 3)
   {
      %i = 1;
      while (%i < 10)
      {
         %Wall = %BlastWallGroup.Wall[%i];
         if (%Wall !$= "")
         {
            %Wall.lastDamagedBy = "";
            %Wall.getDataBlock().damageObject(%Data, %Wall, %WallSection, "0 0 0", 100, 0);
         }

         %i++;
      }

      // Allow it to be repurchased if it is completed destroyed
      if (%BlastWallSection.getGroup().count <= 0)
         $TeamDeployedCount[%Team, BlastWallPack]--;

      %BlastWallGroup.schedule(1250, delete);
   } else {
      CheckBlastWall(%BlastWallGroup);
   }
}

datablock StaticShapeData(BlastWallCenter) : StaticShapeDamageProfile
{
   shapeFile = "xmiscf.dts";

   maxDamage = 3.8;
   destroyedLevel = 3.8;

   scale = "1.2 1.7 0.5";

   item = BlastWallPack;
   image = BlastWallImage;
   className = Wall;

   explosion = DeployablesExplosion;
   dynamicType = $TypeMasks::StaticShapeObjectType;
   deployedObject = false;

   cmdCategory = "DSupport";
   cmdIcon = CMDSensorIcon;
   cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor";

   targetNameTag = 'Blast Wall';

   deployAmbientThread = true;
   debrisShapeName = "debris_generic_small.dts";
   debris = DeployableDebris;

   heatSignature = 0;

   elasticity = 0.5;
   friction = 0.4;
   pickupRadius = 1;

   computeCRC = true;
   emap = true;

   name = "Blast Wall";

   damageScale[$DamageType::Energy] = 0.8;
   damageScale[$DamageType::Fire] = 0.22;
   damageScale[$DamageType::Bullet] = 1.1;
   damageScale[$DamageType::Explosion] = 0.28;
   damageScale[$DamageType::HighExplosion] = 1.45;
   damageScale[$DamageType::Electricity] = 0.65;
   damageScale[$DamageType::Laser] = 1.2;
};

function BlastWallCenter::damageObject(%Data, %WallSection, %Player, %Position, %Amount, %DamageType)
{
   %WallSection.lastDamagedBy = %Player.client;

   %DamageScale = %data.damageScale[%DamageType];
   if (%DamageScale !$= "")
      %Amount *= %DamageScale;

   // if there's still damage to apply
   if (%Amount > 0)
      %WallSection.applyDamage(%Amount);

   %Damage = %WallSection.getDamageLevel();
   if (%Damage < %Data.destroyedLevel)
      return;

   // If the section is currently marked as destroyed, then quit
   if (%WallSection.getDamageState() $= "Destroyed")
      return;

   // Knock the piece off the wall, mark it as destroyed, and delete it
   if (%WallSection.lastDamagedBy !$= "")
   {
      %WallPosition = posFromTransform(%WallSection.getTransform());
      %AttackPosition = posFromTransform(%WallSection.lastDamagedBy.player.getTransform());
      %Vector = VectorNormalize(VectorSub(%WallPosition, %AttackPosition));
   } else {
      %Vector = "0 0 -1";
   }
   schedule(200, 0, KnockOverWall, %WallSection, %Vector);

   // Note the removal of the pieces now
   %BlastWallGroup = %WallSection.getGroup();
   %WallSection.ForceField.delete();
   %BlastWallGroup.Wall[%WallSection.WallNo] = "";
   %BlastWallGroup.count -= 2;

   // If there are 2 or less pieces, then just knock those down now
   if (%BlastWallGroup.count < 3)
   {
      %i = 1;
      while (%i < 10)
      {
         %Wall = %BlastWallGroup.Wall[%i];
         %Wall.lastDamagedBy = "";
         %Wall.getDataBlock().damageObject(%Data, %Wall, %WallSection, "0 0 0", 100, 0);

         %i++;
      }

      // Allow it to be repurchased if it is completed destroyed
      if (%BlastWallSection.getGroup().count <= 0)
         $TeamDeployedCount[%BlastWallSection.team, BlastWallPack]--;

      %BlastWallGroup.schedule(1250, delete);
   } else {
      CheckBlastWall(%BlastWallGroup);
   }
}

// ------------------------------------------------------------------------
// Temporary Object
// ------------------------------------------------------------------------
datablock StaticShapeData(TempBlastWall)
{  
   className = Station;
   catagory = "Temp";
   shapeFile = "turret_muzzlepoint.dts";

   deployed = deployFieldBare;
};

// This function waits for the object to be placed and then calls the function
// to build the rest of the wall from that point on
function TempBlastWall::onAdd(%Data, %Object, %Position)
{
   parent::onAdd(%Data, %Object, %Position);

   schedule(250, 0, CreateBlastWall, %Object);
}

// This function makes the rest of the wall from the one piece that is deployed.
function CreateBlastWall(%BlastWallSection)
{
   %Team = %BlastWallSection.team;
   %SourceObject = %BlastWallSection.owner.player;

   %Transform = %BlastWallSection.getTransform();
   %Rotation = rotFromTransform(%Transform);

   %PlacementPosition = posFromTransform(%Transform);
   %PositionXY = getWords(%PlacementPosition, 0, 1);
   %PositionZ = getWord(%PlacementPosition, 2) - 0.5;
   %Position = %PositionXY @ " " @ %PositionZ;

   // The rotation and position need to be adjusted so that the forcefield is
   // perpendicular to the player that placed it and centered in front of them.
   %NewRotation = getWords(%Rotation, 0, 2) @ " " @ getWord(%Rotation, 3) + 1.57;

   %PlayerTransform = %SourceObject.getTransform();
   %PlayerPosition = posFromTransform(%PlayerTransform);
   %PlayerRotation = rotFromTransform(%PlayerTransform);
   %PlayerVector = VectorNormalize(getWords(%SourceObject.getEyeVector(), 0, 1) @ " 0");

   %RotatedVector = VectorCross(%PlayerVector, "0 0 1");

   // Scan to determine the dimensions of the forcefield.
   %ScaleThick = 0.05;
   %ScaleWidth = 12.0;
   %ScaleHieght = 9;

   %SearchMask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType;

   // Scan from the NewPosition to up to see where the ceiling is.
   %VerticalVector = VectorScale("0 0 1", %ScaleHieght);
   %SearchPosition = getWords(%PlacementPosition, 0, 1) @ " " @ (getWord(%PlacementPosition, 2) + 0.1);
   %SearchEnd = VectorAdd(%SearchPosition, %VerticalVector);
   %Target = ContainerRayCast(%SearchPosition, %SearchEnd, %SearchMask);

   if (%Target !$= "0")
   {
      %TargetPosition = getWords(%Target, 1, 3);
      %ScaleHieght = VectorDist(%PlacementPosition, %TargetPosition);
   }

   // Scan either side by half the %ScaleWidth and see where the wall is.
   // We search to one side then the other from the center of the forcefield
   %SearchPosition = getWords(%PlacementPosition, 0, 1) @ " " @ getWord(%PlacementPosition, 2) + (%ScaleHieght / 2);

   %SearchEnd = VectorAdd(%SearchPosition, VectorScale(%RotatedVector, %ScaleWidth / 2));
   %Target = ContainerRayCast(%SearchPosition, %SearchEnd, %SearchMask);
   if (%Target !$= "0")
   {
      %TargetPosition = getWords(%Target, 1, 3);
      %ScaleWidth1 = VectorDist(%SearchPosition, %TargetPosition);
   } else {
      %ScaleWidth1 = (%ScaleWidth / 2);
   }

   %OtherRotatedVector = VectorScale(%RotatedVector, (-1 * %ScaleWidth) / 2);
   %SearchEnd = VectorAdd(%SearchPosition, %OtherRotatedVector);
   %Target = ContainerRayCast(%SearchPosition, %SearchEnd, %SearchMask);

   if (%Target !$= "0")
   {
      %TargetPosition = getWords(%Target, 1, 3);
      %ScaleWidth2 = VectorDist(%SearchPosition, %TargetPosition);
   } else {
      %ScaleWidth2 = (%ScaleWidth / 2);
   }

   %ScaleWidth = %ScaleWidth1 + %ScaleWidth2;

   if (getWord(%Rotation, 2) > 0.985)
      %NewRotatedVector = VectorScale(VectorCross(%PlayerVector, "0 0 1"), -1 * (%ScaleWidth2 + 0.5));
   else
      %NewRotatedVector = VectorScale(VectorCross(%PlayerVector, "0 0 1"), %ScaleWidth1 + 0.5);

   %NewPosition = VectorAdd(%Position, %NewRotatedVector);
   %NewTransform = %NewPosition @ " " @ %NewRotation;

   %Scale = %ScaleThick @ " " @ %ScaleWidth + 1 @ " " @ %ScaleHieght + 1;

   // Increment the BlastWall group 
   $BlastWallNo++;
   %BlastWallGroup = nameToID("MissionCleanup/Deployables/BlastWall" @ $BlastWallNo);
   if (%BlastWallGroup <= 0)
   {
      %DeployableGroup = nameToID("MissionCleanup/Deployables");
      if (%DeployableGroup <= 0)
      {
         %DeployableGroup = new SimGroup("Deployables");
         MissionCleanup.add(%DeployableGroup);
      }

      %BlastWallGroup = new SimGroup("BlastWall" @ $BlastWallNo);
      %DeployableGroup.add(%BlastWallGroup);
   }

   echo("Blast Wall Group: " @ %BlastWallGroup);

   // Begin recording information about the wall
   echo("Scale Hiegth: " @ %ScaleHieght);
   echo("Scale Width 1: " @ %ScaleWidth1);
   echo("Scale Width 2: " @ %ScaleWidth2);

   %BlastWallGroup.ScaleHieght = %ScaleHieght;
   %BlastWallGroup.ScaleWidth1 = %ScaleWidth1;
   %BlastWallGroup.ScaleWidth2 = %ScaleWidth2;
 
   // Define the Base Positions which are the center of the bottom 3 panels
   %PlacementPositionXY = getWords(%PlacementPosition, 0, 1);
   %PlacementPositionZ = getWord(%PlacementPosition, 2) + 1.5;

   %BasePosition = %PlacementPositionXY @ " " @ %PlacementPositionZ;
   %BasePosition2 = VectorAdd(%BasePosition, VectorScale(%RotatedVector, %ScaleWidth1 - 2));
   %BasePosition3 = VectorAdd(%BasePosition, VectorScale(%RotatedVector, -1 * (%ScaleWidth2 - 2)));

   %FFPosition = VectorAdd(VectorAdd(%PlacementPositionXY @ " " @ %PlacementPositionZ + 1.5, VectorScale(%RotatedVector, 2)), VectorScale(%PlayerVector, 0.05));
   %FFPosition2 = VectorAdd(%FFPosition, VectorScale(%RotatedVector, %ScaleWidth1 - 2));
   %FFPosition3 = VectorAdd(%FFPosition, VectorScale(%RotatedVector, -1 * (%ScaleWidth2 - 2)));

   // Define the shared rotation
   %WSRotationZ = (-1 * (getWord(%Rotation, 2) * getWord(%Rotation, 3))) + 1.57;
   %WSRotation = "0 1.57 " @ %WSRotationZ; 
   %Matrix = MatrixCreateFromEuler(%WSRotation);

   %Rotation = getWords(%Matrix, 3, 6);

   // Load the Scale
   %Scale = BlastWallSection.Scale;
   if (%Scale $= "")
      %Scale = "1 1 1";

   // Create the first piece, bottom center.
   %BlastWallSection = new StaticShape()
   {
      dataBlock = BlastWallSection;
      scale = %Scale;
      team = %Team;
   };
   %BlastWallSection.setTransform(%BasePosition @ " " @ %Rotation);
   %BlastWallGroup.Add(%BlastWallSection);

   %BlastWallGroup.Wall[1] = %BlastWallSection;
   %BlastWallSection.WallNo = 1;
   %BlastWallGroup.Add(%BlastWallSection);
   %BlastWallGroup.Count = 2;
   %BlastWallGroup.Wall[%BlastWallGroup.Count] = %BlastWallSection;

   %BlastWallSection.target = createTarget(%BlastWallSection, "", "", "", BlastWallSection.targetNameTag, %Team, 0);
   setTargetSensorGroup(%BlastWallSection.getTarget(), %Team);

   // Make the Internal ForceField now
   %ForceField = new ForceFieldBare()
   {
      dataBlock = "BlastWallFF";
      scale = "3 4 0.1";
      team = %Team;
   };
   %BlastWallGroup.add(%ForceField);
   %BlastWallSection.ForceField = %ForceField;

   %ForceField.BlastWall = %BlastWallSection;
   %ForceField.close();
   %ForceField.setTransform(%FFPosition @ " " @ %Rotation);

   KillAllPlayersWithinZone(%data, %ForceField);

   // Create the 2nd piece, above the first one.
   %Position2XY = getWords(%BasePosition, 0, 1);
   %Position2Z = getWord(%BasePosition, 2) + (%ScaleHieght / 3);
   %FFPosition2XY = getWords(%FFPosition, 0, 1);
   %FFPosition2Z = getWord(%FFPosition, 2) + (%ScaleHieght / 3);
   CreateBlastSection(%BasePosition, %Rotation, %Team, %Position2XY @ " " @ %Position2Z, %BlastWallGroup, BlastWallCenter, %FFPosition2XY @ " " @ %FFPosition2Z);

   // Create the 3rd piece, next to the 1st one.
   schedule(3250, 0, CreateBlastSection, %BasePosition, %Rotation, %Team, %BasePosition3, %BlastWallGroup, BlastWallSection, %FFPosition3);

   // Create the 4th piece, next to the 2nd one.
   %Position3XY = getWords(%BasePosition2, 0, 1);
   %Position3Z = getWord(%BasePosition2, 2) + (%ScaleHieght / 3);
   %FFPosition3XY = getWords(%FFPosition2, 0, 1);
   %FFPosition3Z = getWord(%FFPosition2, 2) + (%ScaleHieght / 3);
   schedule(3500, 0, CreateBlastSection, %Position2XY @ " " @ %Position2Z, %Rotation, %Team, %Position3XY @ " " @ %Position3Z, %BlastWallGroup, BlastWallSection, %FFPosition3XY @ " " @ %FFPosition3Z);

   // Create the 5th piece, next to the 1st one.
   schedule(6750, 0, CreateBlastSection, %BasePosition, %Rotation, %Team, %BasePosition2, %BlastWallGroup, BlastWallSection, %FFPosition2);

   // Create the 6th piece, above the 3rd one.
   %Position4XY = getWords(%BasePosition3, 0, 1);
   %Position4Z = getWord(%BasePosition3, 2) + (%ScaleHieght / 3);
   %FFPosition4XY = getWords(%FFPosition3, 0, 1);
   %FFPosition4Z = getWord(%FFPosition3, 2) + (%ScaleHieght / 3);
   schedule(7500, 0, CreateBlastSection, %BasePosition3, %Rotation, %Team, %Position4XY @ " " @ %Position4Z, %BlastWallGroup, BlastWallSection, %FFPosition4XY @ " " @ %FFPosition4Z);

   // Create the 7th piece, above the 2nd one.
   %Position5XY = getWords(%BasePosition, 0, 1);
   %Position5Z = getWord(%BasePosition, 2) + (2 * (%ScaleHieght / 3));
   %FFPosition5XY = getWords(%FFPosition, 0, 1);
   %FFPosition5Z = getWord(%FFPosition, 2) + (2 * (%ScaleHieght / 3));
   schedule(7550, 0, CreateBlastSection, %Position2XY @ " " @ %Position2Z, %Rotation, %Team, %Position5XY @ " " @ %Position5Z, %BlastWallGroup, BlastWallSection, %FFPosition5XY @ " " @ %FFPosition5Z);

   // Create the 8th piece, above the 6th one.
   %Position6XY = getWords(%BasePosition3, 0, 1);
   %Position6Z = getWord(%BasePosition3, 2) + (2 * (%ScaleHieght / 3));
   %FFPosition6XY = getWords(%FFPosition3, 0, 1);
   %FFPosition6Z = getWord(%FFPosition3, 2) + (2 * (%ScaleHieght / 3));
   schedule(10500, 0, CreateBlastSection, %Position4XY @ " " @ %Position4Z, %Rotation, %Team, %Position6XY @ " " @ %Position6Z, %BlastWallGroup, BlastWallSection, %FFPosition6XY @ " " @ %FFPosition6Z);

   // Create the 9th piece, above the 4th one.
   %Position7XY = getWords(%BasePosition2, 0, 1);
   %Position7Z = getWord(%BasePosition2, 2) + (2 * (%ScaleHieght / 3));
   %FFPosition7XY = getWords(%FFPosition2, 0, 1);
   %FFPosition7Z = getWord(%FFPosition2, 2) + (2 * (%ScaleHieght / 3));
   schedule(11500, 0, CreateBlastSection, %Position3XY @ " " @ %Position3Z, %Rotation, %Team, %Position7XY @ " " @ %Position7Z, %BlastWallGroup, BlastWallSection, %FFPosition7XY @ " " @ %FFPosition7Z);
}

// This function makes a new section and moves it into place slowly.
function CreateBlastSection(%Position, %Rotation, %Team, %Position2, %BlastWallGroup, %BlastWallType, %Position3)
{
   // Play the deploying sound effect
   serverPlay3D(SensorDeploySound, %Position);

   // Load the Scale
   %Scale = %BlastWallType.Scale;
   if (%Scale $= "")
      %Scale = "1 1 1";

   // Make the section of the wall
   %BlastWallSection = new StaticShape()
   {
      dataBlock = %BlastWallType;
      scale = %Scale;
      team = %Team;
   };
   %BlastWallSection.setTransform(%Position @ " " @ %Rotation);
   %BlastWallGroup.Add(%BlastWallSection);

   %BlastWallSection.WallNo = %BlastWallGroup.Count;
   %BlastWallGroup.Wall[%BlastWallGroup.Count] = %BlastWallSection;
   %BlastWallGroup.Count++;

   %BlastWallSection.target = createTarget(%BlastWallSection, "", "", "", %BlastWallType.targetNameTag, %Team, 0);
   setTargetSensorGroup(%BlastWallSection.getTarget(), %Team);

   // Move the section into place gradually
   %Difference = VectorSub(%Position2, %Position);
   %Length = VectorLen(%Difference);

   %Step = VectorNormalize(%Difference);

   %Transform = %BlastWallSection.getTransform();

   %i = 0;
   while (%i < %Length)
   {
      %Position = VectorAdd(%Position, %Step);
      %NewTransform = %Position @ " " @ %Rotation;

      %BlastWallSection.schedule(1000 * %i, "setTransform", %NewTransform);

      %i++;
   }

   %NewTransform = %Position2 @ " " @ %Rotation;
   %BlastWallSection.schedule(1000 * %i, "setTransform", %NewTransform);

   // Make the Internal ForceField now
   %ForceField = new ForceFieldBare()
   {
      dataBlock = "BlastWallFF";
      scale = "3 4 0.1";
      team = %team;
   };
   %BlastWallGroup.add(%ForceField);
   %BlastWallSection.ForceField = %ForceField;

   %ForceField.BlastWall = %BlastWallSection;
   %ForceField.close();
   %ForceField.setTransform(%Position3 @ " " @ %Rotation);

   KillAllPlayersWithinZone(%data, %ForceField);

   // Play the final clamping into place sound effect
   schedule(%i * 1000, 0, serverPlay3D, RFootHeavyMetalSound, %NewTranform);
}

// This function checks to see if there is enough support for each piece for
// them to remain upright.  It assigns the following values and needs to have
// at least 3 support points for it to not fall.
// Attached to walls - 2
// Attached to Ceiling - 2
// Supported on Ground/Section Below exists - 3
// Section to side exists - 2
// Section Above exists - 2
// Section Diagonally exists - 1
//
// Sections 1, 3, 5 are not checked since they are on the ground
function CheckBlastWall(%BlastWallGroup)
{
   // If the Object no longer exists, then stop all together
   if (isObject(%BlastWallGroup) == false)
      return;

   if (%BlastWallGroup.Count > 7)
      return;

   echo("Checking BlastWall");

   // Check section 9
   if (%BlastWallGroup.Wall[9] !$= "")
   {
      %Support = 0;
      // If it ran into the wall there
      if (%BlastWallGroup.ScaleWidth1 < 6)
         %Support += 4;

      // If it ran into the ceiling there
      if (%BlastWallGroup.ScaleHieght < 9)
         %Support = 2;

      // If BlastWall 4 is there
      if (%BlastWallGroup.Wall[4] !$= "")
          %Support += 3;
         
      // If BlastWall 7 is there
      if (%BlastWallGroup.Wall[7] !$= "")
          %Support += 2;

      // If BlastWall 2 is there
      if (%BlastWallGroup.Wall[2] !$= "")
          %Support += 1;

      echo("Section 9 Support: " @ %Support);

      if (%Support < 3)
         %BlastWallGroup.Wall[9].getDataBlock().schedule(850, damageObject, %BlastWallGroup.Wall[9], %BlastWallGroup.Wall[9], "0 0 0", 100, 0);
   }

   // Check section 8
   if (%BlastWallGroup.Wall[8] !$= "")
   {
      %Support = 0;
      // If it ran into the wall there
      if (%BlastWallGroup.ScaleWidth2 < 6)
         %Support += 2;

      // If it ran into the ceiling there
      if (%BlastWallGroup.ScaleHieght < 9)
         %Support = 2;

      // If BlastWall 6 is there
      if (%BlastWallGroup.Wall[6] !$= "")
          %Support += 3;
         
      // If BlastWall 7 is there
      if (%BlastWallGroup.Wall[7] !$= "")
          %Support += 2;

      // If BlastWall 2 is there
      if (%BlastWallGroup.Wall[2] !$= "")
          %Support += 1;

      echo("Section 8 Support: " @ %Support);

      if (%Support < 3)
         %BlastWallGroup.Wall[8].getDataBlock().schedule(850, damageObject, %BlastWallGroup.Wall[8], %BlastWallGroup.Wall[8], "0 0 0", 100, 0);
   }

   // Check section 7
   if (%BlastWallGroup.Wall[7] !$= "")
   {
      %Support = 0;
      // If it ran into the ceiling there
      if (%BlastWallGroup.ScaleHieght < 9)
         %Support += 2;

      // If BlastWall 2 is there
      if (%BlastWallGroup.Wall[2] !$= "")
          %Support += 3;
         
      // If BlastWall 8 is there
      if (%BlastWallGroup.Wall[8] !$= "")
          %Support += 2;

      // If BlastWall 9 is there
      if (%BlastWallGroup.Wall[9] !$= "")
          %Support += 2;

      // If BlastWall 6 is there
      if (%BlastWallGroup.Wall[6] !$= "")
          %Support += 1;

      // If BlastWall 4 is there
      if (%BlastWallGroup.Wall[4] !$= "")
          %Support += 1;

      echo("Section 7 Support: " @ %Support);

      if (%Support < 3)
         %BlastWallGroup.Wall[7].getDataBlock().schedule(850, damageObject, %BlastWallGroup.Wall[7], %BlastWallGroup.Wall[7], "0 0 0", 100, 0);
   }

   // Check section 6
   if (%BlastWallGroup.Wall[6] !$= "")
   {
      %Support = 0;
      // If it ran into the wall there
      if (%BlastWallGroup.ScaleWidth2 < 6)
         %Support += 2;

      // If BlastWall 3 is there
      if (%BlastWallGroup.Wall[3] !$= "")
          %Support += 3;
         
      // If BlastWall 8 is there
      if (%BlastWallGroup.Wall[8] !$= "")
          %Support += 2;

      // If BlastWall 2 is there
      if (%BlastWallGroup.Wall[2] !$= "")
          %Support += 2;

      // If BlastWall 7 is there
      if (%BlastWallGroup.Wall[7] !$= "")
          %Support += 1;

      // If BlastWall 1 is there
      if (%BlastWallGroup.Wall[1] !$= "")
          %Support += 1;

      echo("Section 6 Support: " @ %Support);

      if (%Support < 3)
                  %BlastWallGroup.Wall[6].getDataBlock().schedule(850, damageObject, %BlastWallGroup.Wall[6], %BlastWallGroup.Wall[6], "0 0 0", 100, 0);
   }

   // Check section 4
   if (%BlastWallGroup.Wall[4] !$= "")
   {
      %Support = 0;

      // If it ran into the wall there
      if (%BlastWallGroup.ScaleWidth1 < 6)
         %Support += 2;

      // If BlastWall 5 is there
      if (%BlastWallGroup.Wall[5] !$= "")
          %Support += 3;
         
      // If BlastWall 9 is there
      if (%BlastWallGroup.Wall[9] !$= "")
          %Support += 2;

      // If BlastWall 2 is there
      if (%BlastWallGroup.Wall[2] !$= "")
          %Support += 2;

      // If BlastWall 7 is there
      if (%BlastWallGroup.Wall[7] !$= "")
          %Support += 1;

      // If BlastWall 1 is there
      if (%BlastWallGroup.Wall[1] !$= "")
          %Support += 1;

      echo("Section 4 Support: " @ %Support);

      if (%Support < 3)
         %BlastWallGroup.Wall[4].getDataBlock().schedule(850, damageObject, %BlastWallGroup.Wall[4], %BlastWallGroup.Wall[4], "0 0 0", 100, 0);
   }

   // Check section 2
   if (%BlastWallGroup.Wall[2] !$= "")
   {
      %Support = 0;

      // If BlastWall 1 is there
      if (%BlastWallGroup.Wall[1] !$= "")
          %Support += 3;
         
      // If BlastWall 7 is there
      if (%BlastWallGroup.Wall[7] !$= "")
          %Support += 2;

      // If BlastWall 6 is there
      if (%BlastWallGroup.Wall[6] !$= "")
          %Support += 2;

      // If BlastWall 4 is there
      if (%BlastWallGroup.Wall[4] !$= "")
          %Support += 2;

      // If BlastWall 8 is there
      if (%BlastWallGroup.Wall[8] !$= "")
          %Support += 1;

      // If BlastWall 9 is there
      if (%BlastWallGroup.Wall[9] !$= "")
          %Support += 1;

      // If BlastWall 3 is there
      if (%BlastWallGroup.Wall[3] !$= "")
          %Support += 1;

      // If BlastWall 5 is there
      if (%BlastWallGroup.Wall[5] !$= "")
          %Support += 1;

      echo("Section 2 Support: " @ %Support);

      if (%Support < 3)
         %BlastWallGroup.Wall[2].getDataBlock().schedule(850, damageObject, %BlastWallGroup.Wall[2], %BlastWallGroup.Wall[2], "0 0 0", 100, 0);
   }

   // If it is not connected to any wall or ceiling and all the bases are gone, everything falls over
   if (%BlastWallGroup.Wall[1] $= "" && %BlastWallGroup.Wall[3] $= "" && %BlastWallGroup.Wall[5] $= "")
   {
      echo("Bottom Row is gone");
      echo("Scale Width1: " @ %BlastWallGroup.ScaleWidth1);
      echo("Scale Width1: " @ %BlastWallGroup.ScaleWidth2);
      echo("Scale Hieght: " @ %BlastWallGroup.ScaleHieght);
      if (%BlastWallGroup.ScaleWidth1 >= 5.8 && %BlastWallGroup.ScaleWidth2 >= 5.8 && %BlastWallGroup.ScaleHieght >= 8.8)
      {
         echo("Removing the other panels");
         %i = 1;
         while (%i < 10)
         {
            %Wall = %BlastWallGroup.Wall[%i];
            if (%Wall !$= "")
            {
               %Wall.lastDamagedBy = "";
               %Wall.getDataBlock().damageObject(%Data, %Wall, %WallSection, "0 0 0", 100, 0);
            }

            %i++;
         }
      }
   }
}

// This function creates an item just like the wall section that is being destroyed
// and knocks it away from the point of attack, then fades it and deletes it
// It also marks the wall as destroyed and deletes it
function KnockOverWall(%WallSection, %Vector)
{
   // Return if already falling or it is gone.
   if (%WallSection.Falling == true || isObject(%WallSection) == false)
      return;

   // Mark the section as falling so subsequent ones will not mess with it.
   %WallSection.Falling = true;

   if (%Vector $= "")
      %Vector = "0 0 -1";

   // Load the position and rotation of the real wall
   %Transform = %WallSection.getTransform();
   %Rotation = rotFromTransform(%Transform);
   %Position = posFromTransform(%Transform);
   %NewPosition = VectorAdd(%Position, VectorScale(%Vector, 3.2));

   // Set the piece as destroyed
   %WallSection.setDamageState(Destroyed);
   %WallSection.schedule(250, delete);

   // Make the new wall piece
   %NewWall = new Item()
   {
      dataBlock = BlastWallSectionFall;
   };
   MissionCleanUp.Add(%NewWall);
   %NewWall.setTransform(%NewPosition @ " " @ %Rotation);

   // Push the wall piece in the direction of the last blast
   %NewWall.ApplyImpulse(%Position, VectorScale(%Vector, 15));

   // Start the wall piece fading and delete it.
   %NewWall.schedule(2650, "setCloaked", true);
   %NewWall.schedule(3450, delete);
}