BloodknightStudios icon

TorqueScriptLib.cs

BloodknightStudios | PRO | 08/01/16 11:06:33 PM UTC | 0 ⭐ | 538 👁️ | Never ⏰ | []
C++ |

43.1 KB

|

None

|

0 👍

/

0 👎

//-----------------------------------------------------------------------------
// Torque Game Engine 
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
 
//----------------------------------------------------------------------------------------------------------------
// Library Functions v2.1
//----------------------------------------------------------------------------------------------------------------
// These are nifty lil functions that are usefull for other things then solely supporting the functions they
// were written to help.
 
//*************************************************************************************
//torque engine tidbits
//
// The rotation value returned for the z axis of an object in torque, is specified by
// the last 2 words.(it can be made a single value by: getWord(%rot, 2) * getWord(%rot, 3))
// This value will remain positive until the angle is larger than 4.18879 radians OR 240
// degrees, any angle larger than this will revert to a negative value.
// GOing clockwise around the torque compass there are the following degree values...
//
// North -  0 deg, 0 Rad
// East  - 90 deg, 1.5707963 rad
// South- 180 deg, 3.1415926 rad
//        240 deg, 4.18879 rad (changeover point, 30 degrees past south)
// West - 270 deg, -1.5707963 rad (the negative value for due east)
//
//  pi = 3.1415926 (3.14159265358979323846)
// 2pi = 6.2831853 (6.28318530717958647692)
//
// Table X degrees = X radians
//  1d = 0.0174532
//  5d = 0.0872664
// 10d = 0.1745329
// 45d = 0.785398
// 60d = 1.0471974
// 90d = 1.5707963
//180d = 3.1415926
//
// when getting a rotation via an objects ID.rotation, the final word of the rotation
// is in degrees, NOT radians!
// ID.rotation = x y z amount(in degrees)
 
 
// getWorldBox returns box.min.x, box.min.y, box.min.z, box.max.x, box.max.y, box.max.z
// which are two diagonaly opposiing corners of the box
 
// Just thought someone might find this usefull :D  -Founder
//*************************************************************************************
 
//-------------------------------------------------------------------------------------
// Rotations, positions, vectors, and Matricies OH MY!
//-------------------------------------------------------------------------------------
//set some usefull globals
$Pi = 3.14159;
$TwoPi = 6.28319;
 
$North   = 0;
$NE      = 0.785398; //45
$East    = 1.5708;   //90
$SE      = 2.35619;  //135
$South   = $Pi;      //180
$SW      = 3.92699;  //225
$West    = 4.71239;  //270
$NW      = 5.49779;  //315
 
//----Vectors----
 
//this function serves a similar purpose to vectorScale, except instead of scaling it
//makes the specified vector.length equal to the number provided
function setVectorLength(%vec, %desiredLength)
{
   error("setVectorLength vec:" SPC %vec SPC "desiredLength" SPC %desiredLength);
   //this only works if we start with a unit vector so we have the relative valuse for x y and z
   %vecNorm = vectorLen(%vec) > 1 ? vectorNormalize(%vec) : %vec;
 
   // x + y + z = the number to devide the length by in order to get the proper scale by which to
   //multiply the vector elements
   %nl = mAbs(getWord(%vecNorm, 0)) + mAbs(getWord(%vecNorm, 1)) + mAbs(getWord(%vecNorm, 2));
   %scale = %desiredLength / %nl;
   //now vector scale it and send it back
   %newVec = vectorScale(%vecNorm, %scale);
   error("finalVec:" SPC %newVec);
   return %newVec;
}
 
//----common transform utilities----
function posFromRaycast(%transform)
{
   // the 2nd, 3rd, and 4th words returned from a successful raycast call are the position of the point
   %position = getWord(%transform, 1) SPC getWord(%transform, 2) SPC getWord(%transform, 3);
   return %position;
}
 
function normalFromRaycast(%transform)
{
   // the   5th,    6th and 7th words returned from a successful    raycast call are the normal of the  surface
   %norm = getWord(%transform, 4) SPC getWord(%transform, 5) SPC getWord(%transform, 6);
   return %norm;
}
 
// these stay, since having to type %rot = %obj.rotFromTransform(%transform); after already having the transform is
// just way too much.
function posFromTransform(%transform)
{
   // the first three words of an object's transform are the object's position
   %position = getWord(%transform, 0) SPC getWord(%transform, 1) SPC getWord(%transform, 2);
   return %position;
}
 
function rotFromTransform(%transform)
{
   // the last four words of an object's transform are the object's rotation
   %rotation = getWord(%transform, 3) SPC getWord(%transform, 4) SPC getWord(%transform, 5) SPC getWord(%transform, 6);
   return %rotation;
}
 
//if we are going to make these inherited functions, might as welllet them get the transform as well
function SceneObject::posFromTransform(%obj, %transform)
{
   if(%transform $= "")
      %transform = %obj.getTransForm();
   // the first three words of an object's transform are the object's position
   %position = getWord(%transform, 0) SPC getWord(%transform, 1) SPC getWord(%transform, 2);
   return %position;
}
 
function SceneObject::rotFromTransform(%obj, %transform)
{
   if(%transform $= "")
      %transform = %obj.getTransForm();
   // the last four words of an object's transform are the object's rotation
   %rotation = getWord(%transform, 3) SPC getWord(%transform, 4) SPC getWord(%transform, 5) SPC getWord(%transform, 6);
   return %rotation;
}
 
//this finds the terrain height for the position and sets it x meters above the terrain
function bumpZ(%pos, %heightMod)
{
   %x = getword(%pos, 0);
   %y = getword(%pos, 1);
   %height = getTerrainHeight(%x SPC %y);
 
   return %x SPC %y SPC %height + %heightMod;
}
 
//this function merely zeroes the z of a pos, not used anymore
function gimpPosition(%pos)
{
   return getword(%pos, 0) SPC getword(%pos, 1) SPC "0";
}
 
function getAngleDifferance(%angleOne, %angleTwo)
{
   //we need the smallest angle from angle one to angle two
 
   //First ensure both angles are positive
   %angleOne = %angleOne < 0 ? $TwoPi + %angleOne : %angleOne;
   %angleTwo = %angleTwo < 0 ? $TwoPi + %angleTwo : %angleTwo;
 
   %diff = %angleTwo - %angleOne;
 
   %diff = %diff > $Pi ? $TwoPi - %diff : %diff;
   %diff = %diff < -$Pi ? -$TwoPi - %diff : %diff;
 
   return %diff;
}
 
//---Directional (compass) functions----
 
function getClosestCompassTick(%angle)
{
   %value = "";
 
   %angle = %angle < 0 ? $TwoPi + %angle : %angle;
 
   if(%angle >= mDegToRad(337.5) || %angle < mDegToRad(22.5))
      %value = "North" SPC $North;
   else if(%angle >= mDegToRad(22.5) && %angle < mDegToRad(67.5))
      %value = "NorthEast" SPC $NE;
   else if(%angle >= mDegToRad(67.5) && %angle < mDegToRad(112.5))
      %value = "East" SPC $East;
   else if(%angle >= mDegToRad(112.5) && %angle < mDegToRad(157.5))
      %value = "SouthEast" SPC $SE;
   else if(%angle >= mDegToRad(157.5) && %angle < mDegToRad(202.5))
      %value = "South" SPC $South;
   else if(%angle >= mDegToRad(202.5) && %angle < mDegToRad(247.5))
      %value = "SouthWest" SPC $SW;
   else if(%angle >= mDegToRad(247.5) && %angle < mDegToRad(292.5))
      %value = "West" SPC $West;
   else if(%angle >= mDegToRad(292.5) && %angle < mDegToRad(337.5))
      %value = "NorthWest" SPC $NW;
 
   return %value;
}
 
function getClosestCardinal(%angle)
{
   %value = "";
 
   %angle = %angle < 0 ? $TwoPi + %angle : %angle;
   %angle = %angle > $TwoPi ? %angle - $TwoPi : %angle;
 
   if(%angle >= mDegToRad(315) || %angle < mDegToRad(45))
      %value = "North" SPC $North;
   else if(%angle >= mDegToRad(45) && %angle < mDegToRad(135))
      %value = "East" SPC $East;
   else if(%angle >= mDegToRad(135) && %angle < mDegToRad(225))
      %value = "South" SPC $South;
   else if(%angle >= mDegToRad(225) && %angle < mDegToRad(315))
      %value = "West" SPC $West;
 
 
   //error("getClosestCardinal Value:" SPC %value);
   return %value;
}
 
//----angles and rotations----
 
function invertDegAngle(%angle)
{
   if(%angle > 0)
      %angle = -(180 - %angle);
   else
      %angle = mAbs(%angle + 180);
 
   return %angle;
}
 
function invertAngle(%angle)
{
   //add pi, then cap
   %angle += $PI;
   %angle = %angle > $TwoPi ? %angle - $TwoPi : %angle;
 
   return %angle;
}
 
function getAnglefromRot(%rot)
{
   //return a positive z angle in radians
   %angle = getWord(%rot, 2) * getWord(%rot, 3);
   %angle = %angle < 0 ? $TwoPi + %angle : %angle;
   return %angle;
}
 
function getDegAnglefromRot(%rot)
{
   //return the rot's z angle in positive degrees
   %angleOne = mRadtoDeg(getWord(%rot, 2) * getWord(%rot, 3));
   %angle = %angleOne < 0 ? 360 + %angleOne : %angleOne;
   return %angle;
}
 
function getZangle(%posOne, %posTwo)
{
   %vec = VectorSub(%posTwo, %posOne);
   //get the angle
   %rotAngleZ = mATan( firstWord(%vec), getWord(%vec, 1) );
   //add pi to the angle
   //%rotAngleZ += $Pi;
 
   //make this rotation a proper torque game value, anything more than 240 degrees is negative
   //if(%rotAngleZ > 4.18879)
      //subtract 2pi from the value, then make sure its positive
     // %rotAngleZ = -(mAbs(%rotAngleZ - $TwoPi));
 
   return %rotAngleZ;
}
 
function absRot(%rot)
{
   %rot = %rot < 0 ? %rot + $TwoPi : %rot;
 
   return %rot;
}
 
function adjustRot(%rot, %rotAdjust)
{
   %angle = getWord(%rot, 2) * getWord(%rot, 3);
   //%rotAdjust = ((%rotAdjust >= 4.18879) ? (($TwoPi - %rotAdjust) * -1) : %rotAdjust);
 
   %rotAdjust = %rotAdjust < 0 ? $TwoPi + %rotAdjust : %rotAdjust;
 
   //now add the angle adjustment to the refrence rot
   %adjust = %angle + %rotAdjust;
   //bring in back in line with the torque world
   %adjust = ((%adjust >= 4.18879) ? (%adjust - $TwoPi) : %adjust);
   //if it's negative we'll stuff it into the vector and leave the angle value unchanged
   %rotZ = ((%adjust >= 0) ? 1 : (-1));
   %adjust = mAbs(%adjust);
   %rot = getWord(%rot, 0) SPC getWord(%rot, 1)  SPC %rotZ SPC %adjust;
   return %rot;
}
 
// This lil function generates the rotation required for an object at PosOne to point at PosTwo (z rot only)
function pointToXYPos(%posOne, %posTwo)
{
   %vec = VectorSub(%posOne, %posTwo);
   //get the angle
   %rotAngleZ = mATan( firstWord(%vec), getWord(%vec, 1) );
   //add pi to the angle
   %rotAngleZ += $Pi;
 
   //make this rotation a proper torque game value, anything more than 240 degrees is negative
   if(%rotAngleZ > 4.18879)
   {
      //the rotation scale is seldom negative, instead make the axis value negative
      %modifier = -1;
      //subtract 2pi from the value, then make sure its positive
      %rotAngleZ = mAbs(%rotAngleZ - $TwoPi);
      //sigh, if only this were all true
   }
   else
      %modifier = 1;
 
   //assemble the rotation and send it back
   return "0 0" SPC %modifier SPC %rotAngleZ;
}
 
// And this lil function generates the rotation required for an object at posOne to
// point at PosTwo for X, Y And Z axis.
function pointToPos(%posOne, %posTwo)
{
   //sub the two positions so we get a vector pointing from the origin in the direction we want our object to face
   %vec = VectorSub(%posTwo, %posOne);
 
   // pull the values out of the vector
   %x = firstWord(%vec);
   %y = getWord(%vec, 1);
   %z = getWord(%vec, 2);
 
   //this finds the distance from origin to our point
   %len = vectorLen(%vec);
 
   //---------X-----------------
   //given the rise and length of our vector this will give us the angle in radians
   %rotAngleX = mATan( %z, %len );
 
   //---------Z-----------------
   //get the angle for the z axis
   %rotAngleZ = mATan( %x, %y );
 
   //create 2 matrices, one for the z rotation, the other for the x rotation
   %matrix = MatrixCreateFromEuler("0 0" SPC %rotAngleZ * -1);
   %matrix2 = MatrixCreateFromEuler(%rotAngleX SPC "0 0");
 
   //now multiply them together so we end up with the rotation we want
   %finalMat = MatrixMultiply(%matrix, %matrix2);
 
   //we're done, send the proper numbers back
   return getWords(%finalMat, 3, 6);
}
 
function getXYAngle(%posOne, %posTwo)
{
   //sub the two positions so we get a vector pointing from the origin in the direction we want our object to face
   %vec = VectorSub(%posTwo, %posOne);
 
   // pull the values out of the vector
   %x = firstWord(%vec);
   %y = getWord(%vec, 1);
   %z = getWord(%vec, 2);
 
   //this finds the distance from origin to our point
   %len = vectorLen(%vec);
 
   //---------XY-----------------
   //given the rise and length of our vector this will give us the angle in radians
   %rotAngleXY = mATan( %z, %len );
   //%rotAngleXY+=$Pi;
   return %rotAngleXY;
}
 
function getXYangleFromRot(%rot)
{
   %a = getWord(%rot, 3);
 
   %x = firstWord(%rot) * %a;
   %y = getWord(%rot, 1) * %a;
   %z = getWord(%rot, 2) * %a;
 
 
   %xy = mSqrt((%x * %x) + (%y * %y));
   %rotAngleXY = mATan( %xy, mAbs(%z) );
   return %rotAngleXY;
}
 
function getZrise(%rot, %posOne, %posTwo)
{
   %XYAngle = getXYangleFromRot(%rot);
 
   %vec = VectorSub(%posTwo, %posOne);
 
    //this finds the distance from origin to our point
   %len = vectorLen(%vec);
 
   //pythagorian theroem says right triangle sides: a squared + b squared = c squared
   //we need to find the rise amount based on the angle and length
   // c^2 - a^2 = b^2
   //the height of the right triangle equals the tangent of the angle times the length of the base
   //%zmod = mTan(%XYAngle + $Pi) * (%len + $Pi);
   %zmod = mTan(%XYAngle) * (%len - $Pi);
   return %zmod;
}
 
//--------------------------------------------------------------------------------------------
// Spline functions
//--------------------------------------------------------------------------------------------
 
// These functions draw a curve from the first point to the last point, going near any middle points at time t.
// t represents the percentage of distance between the first and last point that you want the curve point for
// They can be used to draw a 3-d spline when all three axis are run through the function.
 
// %t = (position Of Desired Spline Point) / (distance Between First And Last Points)
// %curvePoint1.x = get3PointCurveValue(%point1.x, %point2.x, %point3.x, %t)
// %curvePoint1.y = get3PointCurveValue(%point1.y, %point2.y, %point3.y, %t)
// %curvePoint1.z = get3PointCurveValue(%point1.z, %point2.z, %point3.z, %t)
 
// this lil guy doesn't actually draw a curve, but rather a line, however it is very usefull for mixing
// two values together based on a percentage of time or distance
function get2PointLineValue(%point1, %point2, %t)
{
   %pd = ( %point1 * (1-%t)) + (%point2 * %t);
   return %pd;
}
 
function get3PointCurveValue(%point1, %point2, %point3, %t)
{
   %step1 = %point1 * ((1-%t) * (1-%t));
   %step2 = %point2 * 2 * %t * (1 - %t);
   %step3 = %point3 * (%t * %t);
   %pd = %step1 + %step2 + %step3;
   return %pd;
}
 
function get4PointCurveValue(%point1, %point2, %point3, %point4, %t)
{
   %step1 = %point1 * ( (1 - %t)*(1 - %t)*(1 - %t) );
   %step2 = %point2 * 3 * %t * ( (1 - %t)*(1 - %t) );
   %step3 = %point3 * 3 * (%t * %t) * (1 - %t);
   %step4 = %point4 * (%t * %t * %t);
   %pd = %step1 + %step2 + %step3 + %step4;
   return %pd;
}
 
//---------------------------------------------------------------------------------------------------------------
// functions dealing with terrain
//---------------------------------------------------------------------------------------------------------------
 
//this takes the provided position, and sets it to the position of the earest terrain vertex
function findNearestTerrainPoint(%pos)
{
   %x = findGridPoint(firstWord(%pos));
   %y = findGridPoint(getWord(%pos, 1));
   %z = getWord(%pos, 2);
 
   return(%x SPC %y SPC %z);
}
 
function findGridPoint(%axis)
{
   if(%axis == 0)
      return 0;
   %axis = mFloor(%axis);
   %remainder = %axis % Terrain.squareSize;
 
   if(%remainder >= (Terrain.squareSize / 2))
   {
      while(%axis % Terrain.squareSize != 0)
         %axis++;
   }
   else
   {
      while(%axis % Terrain.squareSize != 0)
         %axis--;
   }
   return %axis;
}
 
//Takes the pos provided, and sets the z value to the surface height
function getTerrainSurfacePoint(%pos)
{
   %x = getword(%pos, 0);
   %y = getword(%pos, 1);
   %height = getTerrainHeight(%x SPC %y);
   return %x SPC %y SPC %height;
}
 
//in a box with the given max and min x and y extents, this will find the average height value
function getAverageTerrainHeight(%minX, %maxX, %minY, %maxY, %squareSize)
{
   %total = 0;
   %count = 0;
   for(%x = %minX; %x <= %maxX; %x += %squareSize)
   {
      //we are already looping through x, so loop through Y while we're at it
      for(%y = %minY; %y <= %maxY; %y += %squareSize)
      {
         %total += getTerrainHeight(%x SPC %y);
         %count++;
      }
   }
   return %total / %count;
}
 
function getTerrainAngle(%point)
{
   %angleRad = mACos(vectorDot(%point, "0 0 1"));
   %angleDeg = mRadtoDeg(%angleRad);
   return %angleDeg;
}
 
function getTerrainLevel(%pos, %rad)
{
   while(%retries < 500)
   {
      %x = getWord(%pos, 0) + mFloor(getRandom(%rad * 2) - %rad);
      %y = getWord(%pos, 1) + mFloor(getRandom(%rad * 2) - %rad);
      %z = getWord(%pos, 2) + mFloor(getRandom(%rad * 2) - %rad);
 
      %start = %x @ " " @ %y @ " 5000";
      %end = %x @ " " @ %y @ " -1";
      %ground = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0);
      %z = getWord(%ground, 3);
 
      %z += 3.5;
      %position = %x @ " " @ %y @ " " @ %z;
 
      %mask = ( $TypeMasks::ShapeBaseObjectType | $TypeMasks::MoveableObjectType |
                $TypeMasks::StaticShapeObjectType | $TypeMasks::WaterObjectType | 
                $TypeMasks::InteriorObjectType );
 
      InitContainerRadiusSearch( %position, 3.5, %mask );
      if(containerSearchNext() == 0)
      {
         //error ("Position Is Good");
         return %position;
      }
      else
         %retries++;
   }
   return( %pos );
}
 
//---------------------------------------------------------------------------------------------------------------
// Functions for moving objects
//---------------------------------------------------------------------------------------------------------------
function SceneObject::setOnTerrain(%obj, %pos, %calcOnly)
{
   if(%pos $= "")
      %pos = %obj.position;
   %terHeight = getTerrainHeight(%pos);
   %offset = %obj.GetHeightOffset();
   %newPos = firstWord(%pos) SPC getWord(%pos, 1) SPC %terHeight + %offset;
   if(%calcOnly)
      return %newPos;
   else
      %obj.setTransform(%newPos SPC %obj.rotFromTransform());
}
 
function SceneObject::alignTransforms(%obj, %pos, %rot, %rotAdjust, %xAngle, %yRadius, %zMod, %invert, %calc)
{
   //rotation hack - these rots just aren't natural!
   if(%rot $= "0 0 1 0" || %rot $= "0 1 0 0"  || %rot $= "1 0 0 0")
      %rot = "0.0001 0.00001 0.99 0.001";
 
   //get the angle of the refrence object(rot) so we know what direction to go to find the new position
   %angle = getWord(%rot, 2) * getWord(%rot, 3);
 
   //this is the angle to find the position at, relative to the refrence point
   %xAngle = mDegToRad(%xAngle);
   //now adjust it to be compatible with the refrence rotation
   %xAngleMod = ((%angle < 0) ? (-1 * %xAngle) : %xAngle);
 
   //generate a vector to the adjusted position
   %matrix = VectorOrthoBasis(getXYangleFromRot(%rot) SPC getWords(%rot,1,2) SPC getWord(%rot, 3) + %xAngleMod);
   //%matrix = VectorOrthoBasis(getWords(%rot,0,2) SPC getWord(%rot, 3) + %xAngleMod);
   %yRot = getWords(%matrix, 3, 5);
 
   //now scale from our current position the yRadius amount to get our new position
   %zPos = vectorAdd(%pos, vectorScale(%yRot, %yRadius));
   %bPos = firstWord(%zPos) SPC getWord(%zPos, 1) SPC (getWord(%zPos, 2) + %zMod);
 
   //right now our new position is on the horizontal plane of world space, if the refrence rot is tilted
   //we need to move the pos up or down to account for it.
   //do wee need to adjust the Z hieght position to account for objects rotated on an x or y axis?
   %XYAngle = getXYangleFromRot(%rot);
   //only add to the Z if the angle is more then 1 deg (Otherwise the rotation hack above will try to bump the target up)
   if(mAbs(%XYAngle) > 0.0174533)
   {
      %zRise = getZrise(%rot, %bpos, %pos);// + $Pi;
      %bPos = getWords(%bPos, 0, 1) SPC getword(%bPos, 2) + %zRise;
   }
 
   //lets try using the trusty ole matrix to take care of any tilt
   //so first thing is to subtract the target position from the ref position.
 
 
 
   //it would probably more accurate to calculate this on the surface of a shpere instead of a circle then adjusting
   //the hieght, but since I don't know how to do that just now we'll go this route, which is plenty damned acurate
 
   //if the generated position needs to point in a certain direction relative to the refrence, then generate it's rot
   if(%rotAdjust !$= "" && %rotAdjust != 0)
   {
      //convert the adjustment to radians, then make it a valid torque world angle
      %rotAdjust = mDegToRad(%rotAdjust);
      %rotAdjust = ((%rotAdjust >= 4.18879) ? (($TwoPi - %rotAdjust) * -1) : %rotAdjust);
 
      //now add the angle adjustment to the refrence rot
      %adjust = %angle + %rotAdjust;
      //bring in back in line with the torque world
      %adjust = ((%adjust >= 4.18879) ? (%adjust - $TwoPi) : %adjust);
      //if it's negative we'll stuff it into the vector and leave the angle value unchanged
      %rotZ = ((%adjust >= 0) ? 1 : (-1));
      %adjust = mAbs(%adjust);
      %rot = getWord(%rot, 0) SPC getWord(%rot, 1)  SPC %rotZ SPC %adjust;
      %angle = getWord(%rot, 2) * getWord(%rot, 3);
   }
   if(%invert)
   {
      //this is for turning the generated position upside down, wonder if this and the above are broken
      //for tilted refrence rotations?
      %angleR = -1 * %angle;
      %Mrot = MatrixCreateFromEuler("0 3.14" SPC %angleR);
      %rot = getWord(%Mrot, 3) SPC getWord(%Mrot, 4) SPC getWord(%Mrot, 5) SPC getWord(%Mrot, 6);
   }
 
   //we're done, get the hell outta here!
   %transForm = %bPos SPC %rot;
   if(%calc)
      return %transForm;
   else
   {
      %obj.setTransform(%transForm);
      return;
   }
}
 
//--------------------------------------------------------------------------------------------
//
//  SceneObject::alignTransforms() -by Founder
//
//--------------------------------------------------------------------------------------------
// Here it is!! THE mother of all functions!! AMAZING!!
//
// usage: %objectID.alignTransforms(%pos, %rot, %rotAdjust, %xAngle, %yRadius, %zMod, %invert, %calc);
//
//  %pos is the position of the object(or point) around which to move the (%objectID)
//  %rot is the final rotation you want %objectID to face
//  %rotAdjust is for making a rotational offset of %objectID relative to the provided %rot
//      valid values go from 0 to 360; going clockwise from north(0), east(90)
//      south(180), west(270) etc. 360 will work, but I don't know what kind of
//      dumbass would rotate an object by 360 degrees in the z.
//  %xAngle and %yRadius are vars for adjusting %objectID's position relative to %pos
//      %yRadius describes a circle of (%yRadius) in size, along which you wish %objectID to be
//      placed. %xAngle is the relative angle in degrees (0 - 360) from %pos. Where this
//      angle intersects the circle is the position the object will be placed.
//
//  %zMod is how far up you want to move the object relative to %pos
//  %invert is weather or not you want to turn %objectID upside down.
//      true and 1 will invert it, 0, false, or giveing it no value will not.
//  %calc will have the function return the calculated transform instead of actually moving
//      the object.
// if for any option you do not want to make an adjustment fill the spot with a 0(zero)
// negative values will subtract from x y and z axis, but negative values are not valid for
// the %rotAdjust value
// examples:
//              %deplObj.alignTransforms(%pos, %rot, 270, 0, 0, 8, true);
//              %deplObj.alignTransforms(%dPos, %rot, 0, 0, 0.7, -0.05);
//
//
//
//                               --
//                          -          X
//                         -            -
//                               P
//                         -            -
//                          -          -
//                               --
//
//
//  In the diagram above, P equals the position of the player or the position generated by the
//  deploy code or the postion of the reference object. The circle made up of (-)'s represents
//  a %yRadius of 5 meters. Or if you prefer, a circle which represents the distance
//  away from P that you want this object to be. X represents the object for whom we are
//  generating the new position, and where we want it. X is at an approximately 45 degree angle
//  from P, which is the northEast tick on the Torque compass. In order to keep X's position relative
//  to P, no matter what direction P faces you would use the following line of code:
//         %ObjectID.alignTransforms(%pos(of P), %rot(of P), 0, 45, 5, 0);
//--------------------------------------------------------------------------------------------
 
function SceneObject::alignGroupRot(%obj, %pos, %rot, %rotAdjust, %xAngle, %yRadius, %zMod, %invert, %calc)
{
   %vAngle = getWord(%rot, 3);
   %angle = getWord(%rot, 2) * getWord(%rot, 3);
   %xAngle = mDegToRad(%xAngle);
   %xAngleMod = ((%angle < 0) ? (-1 * %xAngle) : %xAngle);
   %vRot =  getWords(%rot,0,2);
   %matrix = VectorOrthoBasis(%vRot SPC %vAngle + %xAngleMod);
   %yRot = getWords(%matrix, 3, 5);
   %zPos = vectorAdd(%pos, vectorScale(%yRot, %yRadius));
   %bPos = firstWord(%zPos) SPC getWord(%zPos, 1) SPC (getWord(%zPos, 2) + %zMod);
   if(%rotAdjust !$= "" && %rotAdjust != 0)
   {
      %deg = mRadtoDeg(%angle);
      %rotAdjust = ((%rotAdjust >= 240) ? ((360 - %rotAdjust) * -1) : %rotAdjust);
      %adjust = %deg + %rotAdjust;
      %adjust = ((%adjust >= 240) ? (%adjust - 360) : %adjust);
      %rotZ = ((%adjust >= 0) ? 1 : (-1));
      %adjust = mAbs(%adjust);
      %finAngle = mDegToRad(%adjust);
      %rot = getWord(%rot, 0) SPC getWord(%rot, 1)  SPC %rotZ SPC %finAngle;
      %angle = getWord(%rot, 2) * getWord(%rot, 3);
   }
   if(%invert)
   {
      %angleR = -1 * %angle;
      %Mrot = MatrixCreateFromEuler("0 3.14" SPC %angleR);
      %rot = getWord(%Mrot, 3) SPC getWord(%Mrot, 4) SPC getWord(%Mrot, 5) SPC getWord(%Mrot, 6);
   }
   %transForm = %bPos SPC %rot;
   if(%calc)
      return %transForm;
   else
   {
      %obj.setTransform(%transForm);
      return;
   }
}
 
function SceneObject::StartMoveObject(%obj, %endpos, %time, %smoothness, %delay)
{
   if(isObject(%obj))
   {
      %startpos = %obj.getTransform();
      %diff = VectorSub(%endpos, %startpos);
      %numsteps = (%time/1000) * %smoothness;
      %interval = 1000 / %smoothness;
      %stepvec = VectorScale(%diff, (1/%numsteps));
      %numstepsleft = %numsteps;
      %currpos = %startpos;
      %obj.MoveObject(%startpos, %endpos, %numsteps, %numstepsleft, %stepvec, %currpos, %interval, %delay);
   }
}
 
function SceneObject::MoveObject(%obj, %startpos, %endpos, %numsteps, %numstepsleft, %stepvec, %currpos, %interval, %delay)
{
   %rot = rotFromTransform(%obj.getTransform());
   %currpos = VectorAdd(%currpos, %stepvec);
 
   %obj.setTransForm(%currpos SPC %rot);
   %numstepsleft--;
   if(%numstepsleft < 1)
      return;
   else
      %obj.schedule(%interval, "MoveObject", %startpos, %endpos, %numsteps, %numstepsleft, %stepvec, %currpos, %interval, %delay);
}
 
function getObjectTypeMask(%obj)
{
   if(%obj.getType() & $TypeMasks::StaticObjectType)
    error("\c4Type is: $TypeMasks::StaticObjectType");
   else if(%obj.getType() & $TypeMasks::EnvironmentObjectType)
    error("\c4Type is: $TypeMasks::EnvironmentObjectType");
   else if(%obj.getType() & $TypeMasks::TerrainObjectType)
    error("\c4Type is: $TypeMasks::TerrainObjectType");
   else if(%obj.getType() & $TypeMasks::InteriorObjectType)
    error("\c4Type is: $TypeMasks::InteriorObjectType");
   else if(%obj.getType() & $TypeMasks::WaterObjectType)
    error("\c4Type is: $TypeMasks::WaterObjectType");
   else if(%obj.getType() & $TypeMasks::TriggerObjectType)
    error("\c4Type is: $TypeMasks::TriggerObjectType");
   else if(%obj.getType() & $TypeMasks::MarkerObjectType)
    error("\c4Type is: $TypeMasks::MarkerObjectType");
   else if(%obj.getType() & $TypeMasks::GameBaseObjectType)
    error("\c4Type is: $TypeMasks::GameBaseObjectType");
   else if(%obj.getType() & $TypeMasks::ShapeBaseObjectType)
    error("\c4Type is: $TypeMasks::ShapeBaseObjectType");
   else if(%obj.getType() & $TypeMasks::CameraObjectType)
    error("\c4Type is: $TypeMasks::CameraObjectType");
   else if(%obj.getType() & $TypeMasks::StaticShapeObjectType)
    error("\c4Type is: $TypeMasks::StaticShapeObjectType");
   else if(%obj.getType() & $TypeMasks::PlayerObjectType)
    error("\c4Type is: $TypeMasks::PlayerObjectType");
   else if(%obj.getType() & $TypeMasks::ItemObjectType)
    error("\c4Type is: $TypeMasks::ItemObjectType");
   else if(%obj.getType() & $TypeMasks::VehicleObjectType)
    error("\c4Type is: $TypeMasks::VehicleObjectType");
   else if(%obj.getType() & $TypeMasks::VehicleBlockerObjectType)
    error("\c4Type is: $TypeMasks::VehicleBlockerObjectType");
   else if(%obj.getType() & $TypeMasks::ProjectileObjectType)
    error("\c4Type is: $TypeMasks::ProjectileObjectType");
   else if(%obj.getType() & $TypeMasks::ExplosionObjectType)
    error("\c4Type is: $TypeMasks::ExplosionObjectType");
   else if(%obj.getType() & $TypeMasks::CorpseObjectType)
    error("\c4Type is: $TypeMasks::CorpseObjectType");
   else if(%obj.getType() & $TypeMasks::DebrisObjectType)
    error("\c4Type is: $TypeMasks::DebrisObjectType");
   else if(%obj.getType() & $TypeMasks::PhysicalZoneObjectType)
    error("\c4Type is: $TypeMasks::PhysicalZoneObjectType");
   else if(%obj.getType() & $TypeMasks::StaticTSObjectType)
    error("\c4Type is: $TypeMasks::StaticTSObjectType");
   else if(%obj.getType() & $TypeMasks::StaticRenderedObjectType)
    error("\c4Type is: $TypeMasks::StaticRenderedObjectType");
   else if(%obj.getType() & $TypeMasks::DamagableItemObjectType)
    error("\c4Type is: $TypeMasks::DamagableItemObjectType");
   else
      error("\c4Object type is: UNKNOWN");
}
 
// Founder: Apply kickbak to anything
function SceneObject::applyKickback(%obj, %kick)
{
   %dir = %obj.getVectorFromTransform( %obj.getTransform(), "reverse" );
   %force = vectorScale( %dir, %kick );
   %obj.applyImpulse( %obj.posFromTransform(), %force );
}
 
// ZOD: Modified version of above to allow different directions
function SceneObject::applyKick(%obj, %amt, %velCap, %dir)
{
   %vec = %obj.getVectorFromTransform( %obj.getTransform(), %dir );
   %data = %obj.getDataBlock();
   %pos = %obj.posFromTransform();
   %velocity = %obj.getVelocity();
   %normal = VectorDot( %velocity, VectorNormalize( %velocity ) );
 
   if( %velCap != 0 && %normal > %velCap) // Whatever cap we wish..
   {
      %kick = %amt / %Normal; // Reduce impulse.
      //retrun; // Or apply no impulse at all and exit out.
   }
   else
      %kick = %amt;
 
   %impulse = VectorScale( %vec, %data.mass * %kick );
   %obj.applyImpulse(%pos, %impulse);
}
 
//--------------------------------------------------------------------------------------------
// Taken from Harold Paul /*Wedge*/ DElia's post in the GG mod forums
// http://www.garagegames.com/mg/forums/result.thread.php?qt=50109
function SceneObject::getVectorFromTransform(%obj, %transform, %vector)
{
   %aa = getWords(%transform, 3, 6);   
   %tmat = VectorOrthoBasis(%aa);
 
   %rv = getWords(%tMat, 0, 2);
   %fv = getWords(%tMat, 3, 5);
   %uv = getWords(%tMat, 6, 8);
 
   if(%vector $= "up")
      return %uv;
 
   if(%vector $= "down")
      return VectorScale(%uv, -1);
 
   if(%vector $= "left")
      return VectorScale(%rv, -1);
 
   if(%vector $= "right")
      return %rv;
 
   if(%vector $= "forward")
      return %fv;
 
   if(%vector $= "reverse")
     return VectorScale(%fv, -1);
}
 
//--------------------------------------------------------------------------------------------
 
function stripTaggedVar(%var)
{
   return stripChars( detag( getTaggedString( %var ) ), "\cp\co\c6\c7\c8\c9" );
}
 
//------------------------------------------------------------------------------------
// Object Box functions
//------------------------------------------------------------------------------------
//box = min.x min.y min.z max.x max.y max.z
 
//parse out a particular element
function getBoxMinX(%box){ return getWord(%box, 0); }
function getBoxMinY(%box){ return getWord(%box, 1); }
function getBoxMinZ(%box){ return getWord(%box, 2); }
function getBoxMaxX(%box){ return getWord(%box, 3); }
function getBoxMaxY(%box){ return getWord(%box, 4); }
function getBoxMaxZ(%box){ return getWord(%box, 5); }
 
function SceneObject::getWorldBoxMin(%obj)
{
   %box = %obj.getObjectBox();
   %matrix = %obj.getTransForm();
   return MatrixMulPoint(%matrix, getWords(%box, 0, 2));
}
 
function SceneObject::getWorldBoxMax(%obj)
{
   %box = %obj.getObjectBox();
   %matrix = %obj.getTransForm();
   return MatrixMulPoint(%matrix, getWords(%box, 3, 5));
}
 
function SceneObject::getWorldBoxMinX(%obj) { return getWord(%obj.getWorldBoxMin(), 0); }
function SceneObject::getWorldBoxMinY(%obj) { return getWord(%obj.getWorldBoxMin(), 1); }
function SceneObject::getWorldBoxMinZ(%obj) { return getWord(%obj.getWorldBoxMin(), 2); }
function SceneObject::getWorldBoxMaxX(%obj) { return getWord(%obj.getWorldBoxMax(), 0); }
function SceneObject::getWorldBoxMaxY(%obj) { return getWord(%obj.getWorldBoxMax(), 1); }
function SceneObject::getWorldBoxMaxZ(%obj) { return getWord(%obj.getWorldBoxMax(), 2); }
 
 
//return a box dimension
function SceneObject::GetBoxWidth(%obj)
{
   %box = %obj.getObjectBox();
   return mAbs(getBoxMaxX(%box)) + mAbs(getBoxMinX(%box));
}
 
function SceneObject::GetBoxLength(%obj)
{
   %box = %obj.getObjectBox();
   return mAbs(getBoxMaxY(%box)) + mAbs(getBoxMinY(%box));
}
 
function SceneObject::GetBoxHeight(%obj)
{
   %box = %obj.getObjectBox();
   return mAbs(getBoxMaxZ(%box)) + mAbs(getBoxMinZ(%box));
}
 
function SceneObject::GetBoxCenter(%obj)
{
   //box center by default will be 0 0 0, so use a lil matrix math, get it's current world position
   %matrix = %obj.getTransForm();
   %box = %obj.getObjectBox();
   %newBox = MatrixMulPoint(%matrix, getWords(%box, 0, 2));
   %newBox = %newBox SPC MatrixMulPoint(%matrix, getWords(%box, 3, 5));
   %centerX = (getBoxMinX(%newBox) + getBoxMaxX(%newBox)) * 0.5;
   %centerY = (getBoxMinY(%newBox) + getBoxMaxY(%newBox)) * 0.5;
   %centerZ = (getBoxMinZ(%newBox) + getBoxMaxZ(%newBox)) * 0.5;
   return %centerX SPC %centerY SPC %centerZ;
}
 
function SceneObject::GetHeightOffset(%obj)
{
   return mAbs(getWord(%obj.position, 2) - %obj.getWorldBoxMinZ());
}
 
//------------------------------------------------------------------------------------
// Other functionality
//------------------------------------------------------------------------------------
 
 
function getValidSpawnSurface(%pos, %rad)
{
   while(%retries < 500)
   {
      %x = getWord(%pos, 0) + mFloor(getRandom(%rad * 2) - %rad);
      %y = getWord(%pos, 1) + mFloor(getRandom(%rad * 2) - %rad);
 
      %start = %x SPC %y SPC VectorAdd(getWord(%pos, 2), 3.5);
      %end = %x SPC %y SPC "-1";
      %surface = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType, 0);
 
      %z = getWord(%surface, 3);
      %position = %x SPC %y SPC %z;
 
      %mask = ( $TypeMasks::ShapeBaseObjectType | $TypeMasks::MoveableObjectType |
                $TypeMasks::StaticShapeObjectType | $TypeMasks::WaterObjectType );
 
      InitContainerRadiusSearch( %position, 3.5, %mask );
      if ( containerSearchNext() == 0 )
      {
         //error("Random Position Is Good");
         return %position;
      }
      else
         %retries++;
 
   }
   //error("Random Position Is Bad");
   return( %pos );
}
 
 
//--------------------------------------------------------------------------------
//a lil function to mark a position with an object and a default object to use as marker
 
datablock StaticShapeData(markerObject)
{
   category = "Misc";
   shapeFile = "~/data/shapes/markers/octahedron.dts";
   dynamicType = $TypeMasks::StaticShapeObjectType;
};
 
function markPoint(%pos, %rot, %block, %type, %name)
{
   if(%block $= "" && %type $= "")
   {
      %type = StaticShape;
      %block = markerObject;
   }
 
   %obj = new (%type)(%name) {
      dataBlock = %block;
   };
   MissionCleanup.add(%obj);
 
   %obj.setTransform(%pos SPC %rot);
}
 
function markPointArray(%array)
{
   %count = %array.count();
   for(%i = 0; %i < %count; %i++)
   {
      markPoint(%array.getValue(%i));
   }
}
//--------------------------------------------------------------------------------------------
// String functions
//--------------------------------------------------------------------------------------------
 
// Returns true if a string passed to it consists of nothing but digits and/or decimals.
// Passes false for strings with more than one decimal, or with a +
// or - as anything but the first character (+ or - are only allowed as the first character in the string)
function isCleanNumber(%string)
{
   %dot = 0;
   for(%i = 0; (%char = getSubStr(%string, %i, 1)) !$= ""; %i++)
   {
      switch$(%char)
      {
         case "0" or "1" or "2" or "3" or "4" or "5" or "6" or "7" or "8" or "9":
            continue;
 
         case ".":
            if(%dot > 1)
               return false;
 
            %dot++;
            continue;
 
         case "-":
            if(%i) // only valid as first character
               return false;
 
            continue;
 
         case "+":
            if(%i) // only valid as first character
               return false;
 
            continue;
 
         default:
            return false;
        }
    }
    // %text passed the test
    return true;
}
 
//this function takes a pathed filename (common/missions/blah.mis) and takes out everything excpet the name (blah)
function cropToName(%filePAth)
{
   %name = "";
  %length = strlen(%filePAth);
   %dot = 0;
 
   for(%i = 0; %i < %length; %i++)
   {
      if(getSubStr(%filePAth, %i, 1) $= "/")
         %lastDir = %i;
      if(getSubStr(%filePAth, %i, 1) $= ".")
         %dot = %i;
   }
 
   if(%dot > 0)
   {
      if(%lastDir $= "")
         %name = getSubStr(%filePAth, 0, %dot - 1);
      else
         %name = getSubStr(%filePAth, %lastDir + 1, %dot - 1);
   }
 
   else
      %name = getSubStr(%filePAth, %lastDir + 1, %length);
 
  return %name;
 
}
 
function cropDecimal(%num)
{
  %length = strlen(%num);
  %dot = 0;
 
   for(%i = 0; %i < %length; %i++)
   {
      if(getSubStr(%num, %i, 1) $= ".")
         %dot = %i;
   }
 
   if(%dot > 0)
     %name = getSubStr(%num, 0, %dot);
   else
      %name = %num;
 
  return %name;
}
 
function messageTest()
{
   messageAll('MsgTestColors', '\c0Color 0 \c1Color 1 \c2Color 2 \c3 Color 3 \c4 Color 4 \c5 Color 5 \c6 Color 6 \c7Color 7 \c8 Color 8 \c9 Color 9');
   echo("\c0test \c1test \c2test \c3test \c4test \c5test \c6test \c7test \c8test \c9test");
}
 
//--------------------------------------------------------------------------------------------
// Taken from Harold "LabRat" Brown's .plan
// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=10202
function dec2hex(%val)
{
   // Converts a decimal number into a 2 digit HEX number
   %digits ="0123456789ABCDEF"; //HEX digit table
    
   // To get the first number we divide by 16 and then round down, using 
   // that number as a lookup into our HEX table.
   %firstDigit = getSubStr(%digits,mFloor(%val/16),1);
    
   // To get the second number we do a MOD 16 and using that number as a
   // lookup into our HEX table.
   %secDigit = getSubStr(%digits,%val % 16,1);
    
   // return our two digit HEX number
   return %firstDigit @ %secDigit;
}
 
function chrValue(%chr)
{
   // So we don't have to do any C++ changes we approximate the function
   // to return ASCII Values for a character.  This ignores the first 31
   // characters and the last 128.
    
   // Setup our Character Table.  Starting with ASCII character 32 (SPACE)
   %charTable = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~\t\n\r";
    
   //Find the position in the string for the Character we are looking for the value of
   %value = strpos(%charTable,%chr);
 
   // Add 32 to the value to get the true ASCII value
   %value = %value + 32;
    
   //HACK:  Encode TAB, New Line and Carriage Return
   if (%value >= 127)
   {
      if(%value == 127)
         %value = 9;
      if(%value == 128)
         %value = 10;
      if(%value == 129)
         %value = 13;
   }
   //return the value of the character
   return %value;
}
 
function URLEncode(%rawString)
{
   // Encode strings to be HTTP safe for URL use
 
   // Table of characters that are valid in an HTTP URL
   %validChars = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz:/.?=_-$(){}~&";
 
   // If the string we are encoding has text... start encoding
   if (strlen(%rawString) > 0)
   {
      // Loop through each character in the string
      for(%i=0;%i<strlen(%rawString);%i++)
      {
         // Grab the character at our current index location
         %chrTemp = getSubStr(%rawString,%i,1);
 
         //  If the character is not valid for an HTTP URL... Encode it
         if (strstr(%validChars,%chrTemp) == -1)
         {
            //Get the HEX value for the character
            %chrTemp = dec2hex(chrValue(%chrTemp));
 
            // Is it a space?  Change it to a "+" symbol
            if (%chrTemp $= "20")
            {
               %chrTemp = "+";
            }
            else
            {
               // It's not a space, prepend the HEX value with a %
               %chrTemp = "%" @ %chrTemp;
            }
         }
         // Build our encoded string
         %encodeString = %encodeString @ %chrTemp;
      }
   }
   // Return the encoded string value
   return %encodeString;
}
 
//--------------------------------------------------------------------------------------------
// Zod: A default raycast function
function ShapeBase::doRaycast(%this, %range, %mask)
{
   // get the eye vector and eye transform of the player
   %eyeVec   = %this.getEyeVector();
   %eyeTrans = %this.getEyeTransform();
 
   // extract the position of the player's camera from the eye transform (first 3 words)
   %eyePos = posFromTransform(%eyeTrans);
 
   // normalize the eye vector
   %nEyeVec = VectorNormalize(%eyeVec);
 
   // scale (lengthen) the normalized eye vector according to the search range
   %scEyeVec = VectorScale(%nEyeVec, %range);
 
   // add the scaled & normalized eye vector to the position of the camera
   %eyeEnd = VectorAdd(%eyePos, %scEyeVec);
 
   // see if anything gets hit
   %searchResult = containerRayCast(%eyePos, %eyeEnd, %mask, %this);
 
   return %searchResult;
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎