---------------------------------------------------------------------------------------------------------------
Blastwall Tutorial
---------------------------------------------------------------------------------------------------------------
Note: This is based off of the Blastwall Tutorial by Parousia. This tutorial is only an update to the other tutorial and does not cover the parts to initially make the blastwall, So use the other tutorial before this one.

Now, onto the updates.

Step #7
// ------------------------------------------
// Deployables.cs
// ------------------------------------------
Change what's in step #7 of the other tut to look like this. This will make the blastwall scale to fit walls.
It'll look 10 meters up and 10 meters left and right. If it finds anything to attach to, it'll center
itself and scale to fit. Otherwise, it'll scale to its max size. All of this is handled in function
ShapeBaseImageData::onDeploy.

7a) Where it says:

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

Should become:

      if (%item.deployed.classname $= "Wall")
      { 
         %maxwidth = 20; // Max Width of blastwall
         %maxheight = 10; // Max Height of blastwall
         %up = "0 0 " @ %maxheight;
         %mask = $TypeMasks::InteriorObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType;
         %endpos =  VectorAdd(%item.surfacePt, %up);
         %res = containerRayCast(%item.surfacePt, %endpos, %mask, 0);         
         if(%res)
            %zscale=VectorDist("0 0 " @ getword(%res,3),"0 0 " @ getword(%item.SurfacePt,2));
         else
            %zscale=%maxheight;
         %vec1 = VectorNormalize(%plyr.getEyeVector());
         %vecx1 = getWord(%vec1, 0);
         %vecy1 = getWord(%vec1, 1);
         %vecz1 = getword(%vec1, 2);
         %vec2 = %vecy1 * -1 @ " " @ %vecx1 @ " 0";
         %vec3 = %vecy1 @ " " @ %vecx1 * -1 @ " 0";
         %initpos = VectorAdd(%item.SurfacePt, "0 0 " @ (%zscale / 2.4));
         %endpos =  VectorAdd(%initpos, VectorScale(%vec2, (%maxwidth/2)));
         %res = containerRayCast(%initpos, %endpos, %mask, 0);         
         if(%res)
            %left=VectorDist(getword(%res,1) SPC getword(%res,2) @ " 0", getword(%item.SurfacePt, 0) SPC getword(%item.SurfacePt, 1) @ " 0");
         else
            %left=%maxwidth/2;
         %endpos =  VectorAdd(%initpos, VectorScale(%vec3, (%maxwidth/2)));
         %res = containerRayCast(%initpos, %endpos, %mask, 0);
         if(%res)
            %right=VectorDist(getword(%res,1) SPC getword(%res,2) @ " 0", getword(%item.SurfacePt, 0) SPC getword(%item.SurfacePt, 1) @ " 0");
         else
            %right=%maxwidth/2;
         %wid = %left + %right;      
         %av = %wid / 2;
         %movedist = (%av - %left) * 1.3;
         %movepos = VectorScale(%vec3, %movedist);
         %xr1 = getWord(%movepos, 0);
         %yr1 = getWord(%movepos, 1);
         %scale = %zscale / 3.85 @ " " @ %wid / 3.1 @ " 1";      
         %plac = %xr1 @ " " @ %yr1 @ " " @ %zscale / 2;
         %deplObj = new (%className)()
         { 
            dataBlock = %item.deployed; 
            scale = %scale; 
         }; 
      }
      else
      { 
         %deplObj = new (%className)()
         { 
            dataBlock = %item.deployed; 
         }; 
      }    


7b) The part in the tut that says:

   if(%className $= "Turret")
      %deplObj.setDeployRotation(%item.surfacePt, %item.surfaceNrm);
   else if (%item.deployed.classname $= "Wall") { 
      // %item.deployed.classname refers to the static 
      //shape data, in deployables, 
      //or the deployedwall datablock in blastwall.cs
      %d2 = -1 * (getWord(%rot, 3) * getWord(%rot, 2));
      %d2 += 1.57;
      %rot = "0 1.57 " @ %d2; //this is where you set the 
      //rotation, it goes x, y, z, its in 
      // radians so 1.57 is 90 degrees.
      %mat = MatrixCreateFromEuler(%rot);
      %deplObj.setTransform(VectorAdd(%item.surfacePt, "0 0 2") SPC getWord(%mat, 3) SPC getWord(%mat, 4) SPC GetWord(%mat, 5) SPC getWord(%mat, 6));
   }
   else
      %deplObj.setTransform(%item.surfacePt SPC %rot);


should become:

   if(%className $= "Turret")
      %deplObj.setDeployRotation(%item.surfacePt, %item.surfaceNrm);
   else if (%item.deployed.classname $= "Wall") { 
      // %item.deployed.classname refers to the static 
      //shape data, in deployables, 
      //or the deployedwall datablock in blastwall.cs
      %d2 = -1 * (getWord(%rot, 3) * getWord(%rot, 2));
      %d2 += 1.57;
      %rot = "0 1.57 " @ %d2;
      %mat = MatrixCreateFromEuler(%rot);
      %deplObj.setTransform(VectorAdd(%item.surfacePt, %plac) SPC getWord(%mat, 3) SPC getWord(%mat, 4) SPC GetWord(%mat, 5) SPC getWord(%mat, 6));
   }
   else
      %deplObj.setTransform(%item.surfacePt SPC %rot);


--------------------------------------------------------------------------------------------------------------
Optional Code #1 (Team friendly Walls)
Another addition is an option that can be added which causes the blastwall to dissapear for 2 seconds, and then
reapears if someone on the same team runs into it, so it doesn't create a barrier against teamates.

Step #1
// ------------------------------------------
// Player.cs
// ------------------------------------------
At the bottom of function armor::onCollision, add this code:

   else if (%className $= "Wall")
   {
      if ((%col.team == %obj.team) && (%col.getDamageState() $= "Enabled"))
      {
         if (posFromTransform(%col.getTransform()) !$= "0 0 -1000")
            %col.initTransform = %col.getTransform();
         %col.setTransform("0 0 -1000 0 0 0 1");
         schedule(2000, %col, "wallcheckclear", %col);
      }
   }


Step #2
// ------------------------------------------
// blastwall.cs
// ------------------------------------------
At the bottom of blastwall.cs, add this function:

function wallcheckclear(%obj)
{
   %obj.setTransform(%obj.initTransform);
}


--------------------------------------------------------------------------------------------------------------
Optional Code #2 (Stackable Walls)
This makes it so walls can be stacked on top of each other. Note: if you make the walls as statics, when the
wall below it gets destroyed, the wall above will sit in midair. If you want the wall to fall, you'll have to
create it as an item instead. See the jumpad tutorial on how to create a deployable item.

Step #1
// ------------------------------------------
// Deployables.cs
// ------------------------------------------

1a) In function ShapeBaseImageData::testObjectTooClose, above line:

   %test = containerSearchNext();

add this:

   if (%item.deployed.ClassName $= "Wall")
   {
      while ((%test = containerSearchNext()) != 0)
      {
         if (%test.getType() & $TypeMasks::StaticShapeObjectType)
         {
            if (%test.getDataBlock().className !$= "Wall")
               return %test;
         }
         else
            return %test;
      }
      return 0;
   }


1b) and in function Deployables::searchView, above line

   %searchResult = containerRayCast(%eyePos, %eyeEnd, %mask, 0);

add this:

   %pack = %obj.getMountedImage($BackpackSlot);
   if (%pack.deployed.ClassName $= "Wall")
   {
      %mask2 = $TypeMasks::StaticObjectType;
      %searchResult = containerRayCast(%eyePos, %eyeEnd, %mask2, 0);   
      if (%searchResult)
      {
         if (%searchResult.getDataBlock().className $= "Wall")
           return %searchResult;
         %searchResult = "";
      }
   }