//Custom functions by Mostlikely
//There's a lot of outdated stuff here
//But those things are needed for basic deploying until I can update the code.
//Be sure to mail any questions to "sebastiaan_keek@hotmail.com"


// Basic dynamic movement script.
// Fps reduction and lag producing [[A bit]]
// To be expanded/uniformed in later versions

$Pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;     //3.1415926535897932
$AnimationTime = 150;

function lev(%num) {
	if (%num < 0)
		return -1;
	else
		if (%num > 0)
			return 1;
	else
		return 0;
}

//function abs(%num) {
//	%num = %num * lev(%num);
//	if (%num == 0)
//		%num = 0;
//	return %num;
//}

function vlev(%vec)
{
return lev(getWord(%vec,0)) SPC lev(getWord(%vec,1)) SPC lev(getWord(%vec,2));
}

function vAbs(%vec) {
	return mAbs(getWord(%vec,0)) SPC mAbs(getWord(%vec,1)) SPC mAbs(getWord(%vec,2));
}

//Basic test.. don't use this function jet... it won't stop

function DynamicRotate(%obj,%vec,%crot)
{
%vec = vectorNormalize(%vec);
//%rot = getrot(getRotation(%obj));
//%rx = getWord(%rot,0);
//%ry = getWord(%rot,1);
//%rz = getWord(%rot,2);
//%xr = %rx+ getWord(%pace,0);
//%yr = %ry + getWord(%pace,1);
//%zr = %rz + getWord(%pace,2);
%oldrot = rotFromTransform(%Obj.getTransform());
//Schedule(50, %obj,"dynamicRotate2", %obj, %vec, %crot,%oldrot);
}

function DynamicRotate2(%obj,%vec,%crot,%oldrot)
{
%vec = vectorNormalize("0 0 1");
%crot = %crot + 0.1;
%newrot = %vec SPC %crot;
%setrot = rotAdd(%oldrot,%newrot);
setRotation(%obj, %setrot);
Schedule(50, %obj,"dynamicRotate2", %obj, %vec, %crot,%oldrot);
}

//DynamicScale
//Better than dynamicmove...
//To be expanded.

function DynamicScale(%obj,%time,%pace,%end)
{
%scale = %obj.GetScale();
%sx = getWord(%scale,0);
%sy = getWord(%scale,1);
%sz = getWord(%scale,2);
%newx = %sx + getWord(%pace,0);
%newy = %sy + getWord(%pace,1);
%newz = %sz + getWord(%pace,2);


%done = 1;
if (mAbs(%newx - getWord(%end,0)) > mAbs(%sx - getWord(%end,0)))
   %xscale = getWord(%end,0); // If we didn't make progress..
else
   {
   %xscale = %newx; // If we did make progress..
   %done = 0;
   }
if (mAbs(%newy - getWord(%end,1)) > mAbs(%sy - getWord(%end,1)))
   %yscale = getWord(%end,1); // If we didn't make progress..
else
   {
   %yscale = %newy; // If we did make progress..
   %done = 0;
   }
if (mAbs(%newz - getWord(%end,2)) > mAbs(%sz - getWord(%end,2)))
   %zscale = getWord(%end,2); // If we didn't make progress..
else
   {
   %zscale = %newz; // If we did make progress..
   %done = 0;
   }

%newscale = %xscale SPC %yscale SPC %zscale;
%obj.setScale(%newscale);
if (%done == 0)
	schedule(%time, %obj,"dynamicScale", %obj, %time, %pace, %end ,%plyr);
}

//Returns xyz rotation from tribes uniformalized 4 digit rotation.

function getrot(%rotation)
{
%xr = getWord(%rotation,0)*getWord(%rotation,3);
%yr = getWord(%rotation,1)*getWord(%rotation,3);
%zr = getWord(%rotation,2)*getWord(%rotation,3);
return %xr SPC %yr SPC %zr;
}

//Returns tribes rotation from xyz rotation in an outdated way.

function setrot(%rot)
{
%mat = MatrixCreateFromEuler(%rot);
return getWord(%mat,3) SPC getWord(%mat,4) SPC getWord(%mat,5) SPC getWord(%mat,6);
}

//Controlled version setrot
//Soon to be used in deploying.

function setrot2(%rot)
{
%vn = vectorNormalize(%rot);
if (getWord(%vn,0) != 0)
%zn = getWord(%rot,0) / getWord(%vn,0);
else if (getWord(%vn,1) != 0)
%zn = getWord(%rot,1) / getWord(%vn,1);
else if (getWord(%vn,2) != 0)
%zn = getWord(%rot,2) / getWord(%vn,2);
else
%zn = 0;
return %vn SPC %zn;
}

//Returns a rotation from a normal that matches the normal and faces up the slope

// for loadscreen.cs
//if ($MissionDisplay != true)
//	%of = true;

function slopfromnrm(%up)
{

%x=getWord(%up,0);
%y=getWord(%up,1);
%z=getWord(%up,2);
%xy = Mpow((Mpow(%x,2)+Mpow(%y,2)),0.5);
%zrot = MAtan(%y,%x)-1.5708;
%xrot = -MAtan(%xy,%z);
return  %xrot SPC "0" SPC %zrot;
}

//expanded version of slopfromnrm
//Doesn't not work properly.. to be updated.

function rotfromnrm(%up,%le)
{
%le = vectorScale(vectorright(%up,%le),-1);
%fo = VectorCross(%up,%le);
%x = getWord(%fo,0);
%y = getWord(%fo,1);
%zrot = MAtan(%y,%x);
%up = rotatenormal(%up,0,0,-1 * %zrot);
%fo = rotatenormal(%fo,0,0,-1 * %zrot);
%le = rotatenormal(%le,0,0,-1 * %zrot);
%x = getWord(%fo,0);
%y = getWord(%fo,2);
%yrot =  MAtan(%y,%x);
%up = rotatenormal(%up,0,-1 * %yrot,0);
%fo = rotatenormal(%fo,0,-1 * %yrot,0);
%le = rotatenormal(%le,0,-1 * %yrot,0);
%x = getWord(%up,1);
%y = getWord(%up,2);
%xrot =  MAtan(%x,%y);
%up = rotatenormal(%up, %xrot,0,0);
%fo = rotatenormal(%fo, %xrot,0,0);
%le = rotatenormal(%le, %xrot,0,0);
return  %xrot SPC %yrot SPC %zrot + 3.14159;
}

// for loadscreen.cs
//if (%of == true) {
//	return;
//}

//Should rotate things in the same order as tribes2 does.
function rotatenormal(%vector,%xr,%yr,%zr)
{
                // z > x
                // z > y
                // y > x
//x rot
%x = getWord(%vector,0);
%y = getWord(%vector,1);
%z = getWord(%vector,2);
%vector =  %x SPC rotatedot(%y SPC %z, %xr);
//y rot
%x = getWord(%vector,0);
%y = getWord(%vector,1);
%z = getWord(%vector,2);
%vector = getWord(rotatedot(%x SPC %z,%yr),0) SPC %y SPC getWord(rotatedot(%x SPC %z,%yr),1);
//z rot
%x = getWord(%vector,0);
%y = getWord(%vector,1);
%z = getWord(%vector,2);
%vector =  rotatedot(%x SPC %y, %zr) SPC %z;
return %vector;
}

//2dimensional rotation... used in some calculations

function rotatedot(%vector,%rot)
{
%nx = MCos(%rot) * getWord(%vector,0) + -1 *  MSin(%rot) * getWord(%vector,1);
%ny = MSin(%rot) * getWord(%vector,0) + MCos(%rot) * getWord(%vector,1);
%nvector = %nx SPC %ny;
return %nvector;
}

//Returns the proper y as when a proper x and problematic y are introduced

function vectorright(%mainvec,%chanvec)
{
%temp = VectorCross(%mainvec,%chanvec);
return vectorNormalize(VectorCross(%mainvec,%temp));
}

//Returns the vector that %vector is heading in %direction

function vectorproject(%vector,%direction)
{
%v = %vector;//VectorSub(%item.surfacePt,%item.surface.getTransform());
%a = %direction; //VectorCross(%item.surface.up,%item.surfaceNrm);
return vectorScale(%a,(VectorDot(%a,%v) / MPow (VectorLen(%a),2)));
}

//Returns the lengt of %vector in %direction

function vectorcouple(%vector,%direction)
{
%v = %vector;//VectorSub(%item.surfacePt,%item.surface.getTransform());
%a = %direction; //VectorCross(%item.surface.up,%item.surfaceNrm);
return (VectorDot(%a,%v) / MPow (VectorLen(%a),2));
}

function rotAdd(%rotation1,%rotation2)
{
%v1 = "0 0 0" SPC %rotation1;
%v2 = "0 0 0" SPC %rotation2;
// This is the function verified to sometimes return "inf" or "nan". The others are checked for safety's sake
%v3 = validateVal(MatrixMultiply(%v1,%v2));
%axis = vectorNormalize(getWords(%v3,3,5));
return %axis SPC getWord(%v3,6);
}

function realrot(%obj,%rotation)
{
%rot = rot(%Obj);
//[Note] Old notation caused trouble.
//Not sure if the new one is totaly accurate.. but it works ;)
//return rotAdd(rotAdd(%rot,%rotation),invrot(%rot));
%axis = realvec(%obj,getWords(%rotation,0,2));
return %axis SPC getWord(%rotation,3);
}

function virrot(%obj,%rotation)
{
%rot = rot(%Obj);
//return rotAdd(rotAdd(invrot(%rot),%rotation),%rot);
%axis = virvec(%obj,getWords(%rotation,0,2));
return %axis SPC getWord(%rotation,3);
}

function remoteRotate(%mobj,%rot,%cobj,%mcenter)
{
%oldrot = rot(%mObj);
%oldpos = vectorAdd(pos(%mObj),%center);
%center = vectorAdd(pos(%cObj),Realvec(%cobj,VectorMultiply(%mcenter,vectorScale(realSize(%cobj),-1))));
%rrot = realrot(%cobj,%rot);
%newpos = vectorAdd(validateVal(MatrixMulPoint("0 0 0" SPC %rrot,vectorSub(%oldpos,%center))),%center);
return %newpos SPC rotAdd(%rrot,%oldrot);
}

function realSize(%obj) {
	if (%obj.getType() & $TypeMasks::StaticShapeObjectType)
		%ws = (%obj.getDataBlock().getName() $= "DeployedWoodSpine");
	if (isCubic(%obj) || %ws) {
		%scale = %obj.GetScale();
		if (%ws)
			return vectorDivide(%scale,1.845 SPC 2 SPC 1.744); // Update spine.cs if changed!
		else
			return (getWord(%scale,0) * 4) SPC (getWord(%scale,1) * 3) SPC (getWord(%scale,2) * 0.5);
	}
}

function isCubic(%obj) {
	if (!isObject(%obj))
		return;
	if (!(%obj.getType() & $TypeMasks::StaticShapeObjectType))
		return;
	%shape = %obj.getDatablock().shapefile;
	if (getSubStr(%shape,1,strLen(%shape)) $= "miscf.dts")
		return 1;
	else
		return "";
}

function realvec(%obj,%vec) {
	%rot = rot(%Obj);
	return validateVal(MatrixMulVector("0 0 0" SPC %rot ,%vec));
}

function virvec(%obj,%vec)
{
%rot = rot(%Obj);
%rot = getWord(%rot,0) SPC getWord(%rot,1) SPC getWord(%rot,2) SPC (-1*getWord(%rot,3) );
return validateVal(MatrixMulVector("0 0 0" SPC %rot ,%vec));
}

function vectorangle(%vec1,%vec2)
{
return MACos(VectorDot(%vec1,%vec2)/(VectorLen(%vec1)*VectorLen(%vec2)));
}

function vectormultiply(%vec1,%vec2)
{
return getWord(%vec1,0) * getWord(%vec2,0) SPC getWord(%vec1,1)*  getWord(%vec2,1) SPC getWord(%vec1,2)*  getWord(%vec2,2);
}

// An updated version of this function is located further down in the file - JackTL
//function vectordivide(%vec1,%vec2)
//{
//return getWord(%vec1,0) / getWord(%vec2,0) SPC getWord(%vec1,1) /  getWord(%vec2,1) SPC getWord(%vec1,2) /  getWord(%vec2,2);
//}

function vectordescale(%vec1,%scale)
{
return %scale/getWord(%vec1,0)  SPC %scale/getWord(%vec1,1)  SPC %scale /getWord(%vec1,2);
}

function getface(%obj,%vec)
{
%rot = getWords(rot(%Obj),0,2) SPC -1 * getWord(rot(%Obj),3);
return validateVal(MatrixMulVector("0 0 0" SPC %rot ,%vec));
}

function floorvec(%vec,%size)
{
%mod = vLev(%vec);
%vec = vAbs(vectorScale(%vec,%size));
%vec = Mfloor(getWord(%vec,0)) SPC  Mfloor(getWord(%vec,1)) SPC  Mfloor(getWord(%vec,2));
return VectorMultiply(vectorScale(%vec,(1/%size)),%mod);
}

function invface(%face)
{
return VectorSub("1 1 1",vAbs(%face));
}

function getfacesize(%obj,%face)
{
return VectorMultiply(vAbs(invface(%face)),realSize(%obj));
}

function breach(%val,%border)
{
if (%border < 0)
return %val;
if (%val > %border)
return (%val-%border);
else
return 0;
}

function topface(%vec)
{
if (mAbs(getWord(%vec,0)) >= mAbs(getWord(%vec,1)) + mAbs(getWord(%vec,2)))
return getWord(%vec,0) SPC "0 0";
if (mAbs(getWord(%vec,1)) >= mAbs(getWord(%vec,0)) + mAbs(getWord(%vec,2)))
return "0" SPC getWord(%vec,1) SPC "0";
if (mAbs(getWord(%vec,2)) >= mAbs(getWord(%vec,0)) + mAbs(getWord(%vec,1)))
return "0 0" SPC getWord(%vec,2);
}

function pullaxis(%vec1,%vec2)
{
%face = invface(%vec2);
%hit = vectorNormalize(topface(vectormultiply(%vec1,%face)));
return vectorNormalize(VectorCross(%hit,%vec2));
}

function pullobject(%obj,%vec1,%vec2,%angle,%center) {
	if (!isObject(%obj))
		return;
	%pos = pos(%Obj);
	%rot = rot(%Obj);
	%vec = vectorSub(%vec1,%pos);
	%vec = virVec(%obj,%vec);
	%vec = vectorAdd(vectorDivide(%vec,vectorScale( realSize(%obj),0.5 ) ),"0 0 -1");
	%axis = pullAxis(%vec,%vec2);
	if (!isCubic(%obj) && %obj.getDataBlock().getName() !$= "DeployedWoodSpine")
		%axis = "0 0 1";
	if (%obj.getType() & $TypeMasks::ForceFieldObjectType)
		return;
	%obj.setTransform(remoteRotate(%obj,%axis SPC %angle,%obj,%center));
		checkAfterRot(%obj);
}

function rotateSection(%obj,%list,%rotation) {
	%count = getWordCount(%list);
	for (%id = 0; %id < %count; %id++) {
		%obj2 = getWord(%list,%id);
		if (isObject(%obj2)) {
			%obj2.setTransform(remoteRotate(%obj2,%rotation,%obj));
			checkAfterRot(%obj2);
		}
	}
}

function checkAfterRot(%obj) {
	if (!$Host::AllowUnderground) {
		%terrain = getTerrainHeight2(%obj.getPosition());
		if (getWord(%obj.getPosition(),2) < getWord(%terrain,2) || %terrain $= "")
			%obj.setPosition(%terrain);
	}
	if (isObject(%obj.pzone))
		%obj.pzone.setTransform(%obj.getTransform());
	if (isObject(%obj.trigger))
		adjustTrigger(%obj);
	if (isObject(%obj.beam))
		tp_adjustBeam(%obj);
	if (isObject(%obj.holo))
		adjustHolo(%obj);
	if (isObject(%obj.light))
		adjustLight(%obj);
	if (isObject(%obj.lMain))
		adjustLMain(%obj);
	if (%obj.getDataBlock().needsPower) {
		%obj.powerCount = "";
		checkPowerObject(%obj);
	}
	// TODO - handle gens
    PostOperationCheck(%obj);
}

function adjustTrigger(%obj) {
	// TODO - adjust trigger for InventoryDeployable
	%dataBlockName = %obj.getDataBlock().getName();
	if (%dataBlockName $= "StationInventory") {
		%adjust = vectorMultiply(realVec(%obj,"0 0 1"),"1 1 3");
		%adjustUp = getWord(%adjust,2);
		%adjust = getWords(%adjust,0,1) SPC ((%adjustUp * 0.5) + (mAbs(%adjustUp) * -0.5));
		%obj.trigger.setTransform(vectorAdd(%obj.getPosition(),%adjust) SPC "0 0 0"); // %obj.rotation);
	}
}

// Oh hush, it works. :)
function adjustLMain(%obj) {
	%dataBlockName = %obj.lMain.getDataBlock().getName();
	if (getSubStr(%dataBlockName,0,18) $= "DeployedDecoration") {
		%pos = %obj.getPosition();
		%rot = %obj.getRotation();
		%nrm = realVec(%obj,"0 0 1");
		%nrm2 = realVec(%obj,"1 0 0");
		%nrm3 = realVec(%obj,"0 1 0");
		%no = trim(getSubStr(%dataBlockName,18,2));
		if (%no < 3) {
			%nrm2 = vectorScale(%nrm2,-1);
			%pos = vectorAdd(%pos,vectorScale(%nrm3,2.80));
			%pos = vectorAdd(%pos,vectorScale(%nrm,0.25));
			%rot =  rotAdd(%rot,"1 0 0" SPC $Pi / 2);
			%rot =  rotAdd(%rot,"0 1 0" SPC $Pi);
		}
		else if (%no > 2 && %no < 6) {
			%pos = vectorAdd(%pos,vectorScale(%nrm,-0.2));
			if (%no == 3) {
				%pos = vectorAdd(%pos,vectorScale(%nrm2,0.14));
				%pos = vectorAdd(%pos,vectorScale(%nrm3,-0.51));
			}
			if (%no == 4) {
				%pos = vectorAdd(%pos,vectorScale(%nrm2,-0.25));
				%pos = vectorAdd(%pos,vectorScale(%nrm3,0.4));
			}
			if (%no == 5) {
				%pos = vectorAdd(%pos,vectorScale(%nrm2,-0.05));
				%pos = vectorAdd(%pos,vectorScale(%nrm3,-0.4));
				%rot =  rotAdd(%rot,"0 0 -1" SPC $Pi / 4);
			}
		}
		else if (%no > 11 && %no < 16) {
			%pos = vectorAdd(%pos,vectorScale(%nrm,1));
			%pos = vectorAdd(%pos,vectorScale(%nrm3,23.1));
			%rot =  rotAdd(%rot,"-1 0 0" SPC $Pi / 2);
		}
		%obj.lMain.setTransform(%pos SPC %rot);
	}
	else if (getSubStr(%dataBlockName,0,18) $= "DeployedEscapePod") {
		adjustEscapePod(%obj.lMain);
		%epod = %obj.lMain.podVehicle;
		if (isObject(%epod) && %epod.used == false)
			%epod.delete();
	}
}

function invrot(%rot)
{
return vectorScale(getWord(%rot,0) SPC getWord(%rot,1) SPC getWord(%rot,2),-1) SPC getWord(%rot,3);
}

//Tones down the outer parts
//In real cube size.

function cubefix(%cube,%point,%joint)
{
%limit = vectorScale(realSize(%cube),0.5);
%px = getWord(%point,0) - ( lev( getWord(%point,0) ) * breach( mAbs(getWord(%point,0)) , getWord(%limit,0)-getWord(%joint,0) ) );
%py = getWord(%point,1) - ( lev( getWord(%point,1) ) * breach( mAbs(getWord(%point,1)) , getWord(%limit,1)-getWord(%joint,1) ) );
%pz = getWord(%point,2) - ( lev( getWord(%point,2) ) * breach( mAbs(getWord(%point,2)) , getWord(%limit,2)-getWord(%joint,2) ) );
return %px SPC %py SPC %pz;
}

//Same as cubefix
//Only in virtual cube size.

function vircubefix(%point,%joint)
{
%limit = "1 1 1";
%px = getWord(%point,0) - ( lev( getWord(%point,0) ) * breach( mAbs(getWord(%point,0)) , getWord(%limit,0)-getWord(%joint,0) ) );
%py = getWord(%point,1) - ( lev( getWord(%point,1) ) * breach( mAbs(getWord(%point,1)) , getWord(%limit,1)-getWord(%joint,1) ) );
%pz = getWord(%point,2) - ( lev( getWord(%point,2) ) * breach( mAbs(getWord(%point,2)) , getWord(%limit,2)-getWord(%joint,2) ) );
return %px SPC %py SPC %pz;
}

//Obj = Surface.
//face = surfaceNrm (Real)
//point = surfacePt (Real)
//joint = dobj surface size (Real)
//center = relative center for surface (Virtual)

function sidelink(%obj,%face,%point,%joint,%center)
{
%loc = pos(%Obj);

//Fitting All stuff to virtual space
%relpoint = VectorSub(%point,%loc);
%virpoint =  virvec(%obj,%relpoint);
%virpoint = VectorDivide(%virpoint,vectorScale( realSize(%obj),0.5 ));
%virpoint = vectorAdd(%virpoint,vectorScale(%center,2));

%virjoint = VectorDivide( %joint,vectorScale( realSize(%obj),1 ));
%virface = virvec(%obj,%face);

//Desiding which side should be linked to.
%sidedir = pullaxis(%virpoint,%virface);
%side = VectorCross(%sidedir,%virface);

//Keeping the movement on that side within bounds.
%virpoint = vircubefix(%virpoint,%virjoint);
%virpoint = VectorMultiply( %virpoint, vAbs(%sidedir));

//Fitting the new location next to the object.
%overpull = VectorMultiply(vectorScale(%side,-1),vectorAdd(%virjoint,"1 1 1"));


//Getting it all together.
%mask = vectorAdd(vectorAdd(%virpoint,%virface),%overpull);


//Returning to real space.
%virpoint = vectorAdd(%mask,vectorScale(%center,-2));

%virpoint = VectorMultiply(vectorScale(realSize(%obj),0.5),%virpoint);

%relpoint = realvec( %obj , %virpoint);

//Also returning the side used.
//echo(floorvec(%virface,1));
if (vAbs(vlev(floorvec(%virface,100))) $= "0 1 0")
%goodside = VectorCross(%virface,"0 0 1");
else
%goodside = VectorCross(%virface,"0 1 0");

%realside = vectorNormalize(realvec(%obj,%side));
%dirside = vectorNormalize(realvec(%obj,%goodside));

return vectorAdd(%loc,%relpoint) SPC %realside SPC %dirside;
}



//Function returns the fited placement.
//Obj = Surface object.
//Face = surface normal. (Virtual)
//Point = Surface Hit point. (Real)
//Joint = Surface size placement object. (Real)
//Center = Models t2 center relative to the real center.  (Virtual)


function link(%obj,%face,%point,%joint,%center)
{
%loc = pos(%Obj);
%relpoint = VectorSub(%point,%loc);

	%virpoint =  virvec(%obj,%relpoint);

                %adjust = VectorMultiply(%center,realSize(%obj));

		%virpoint = vectorAdd(%virpoint,%adjust);


		%virpoint = cubefix(%obj,%virpoint,%joint);

		%virpoint = VectorMultiply( %virpoint, invface(%face) );

		%mask = VectorMultiply(vectorScale(realSize(%obj),0.5), %face);

                %virpoint = vectorAdd(%mask,%virpoint);

                %virpoint = vectorAdd(%virpoint,vectorScale(%adjust,-1));

	%relpoint = realvec( %obj , %virpoint);

return vectorAdd(%loc,%relpoint);
}



function slopeRot(%vec)
{
if (vAbs(floorvec(%vec,100)) $= "0 0 1")
   return "1 0 0" SPC $Pi/2 - (lev(getWord(%vec,2))*$Pi/2);
else
   %secv = "0 0 1";
%axis = VectorCross(%vec,%secv);
%angle = VectorAngle(%vec,%secv);
return validateVal(vectorNormalize(%axis) SPC %angle);
}

function intRot(%rot,%vec)
{
%vec1 =  validateVal(MatrixMulVector("0 0 0" SPC invrot(%rot),%vec));
%vec1 = vectorNormalize(getWord(%vec1,0) SPC getWord(%vec1,1) SPC "0");
%angle = MAtan(getWord(%vec1,1),getWord(%vec1,0));
return "0 0 -1" SPC %angle;
}

//Function returns rotation.
//Vec1 = Alignment direction.
//Vec2 = Facing direction.

function fullrot(%vec,%vec2)
{
%rot = slopeRot(%vec);
return rotAdd(%rot,intRot(%rot,%vec2));
}

function rayDist(%vecs,%sizes,%mask,%obj) {
	if (!%mask)
		%mask = -1;
	%obj = mAbs(%obj);
	%start = getWords(%vecs,0,2);
	%dir = vectorNormalize(getWords(%vecs,3,5));
	%min = getWord(%sizes,0);
	%norm = getWord(%sizes,1);
	%max = getWord(%sizes,2);
	%endPos = vectorAdd(%start,vectorScale(%dir,%max));

	%res = containerRayCast(%start, %endPos, %mask, %obj);

	if (%res) {
		if (%res.getType() & $TypeMasks::TerrainObjectType)
			%res = containerRayCast(vectorAdd(%start,"0 0 0.1"), %endPos, %mask, %obj);
		if (%res > 0) {
			%hit = getWords(%res,1,3);
			%dist = vectorDist(%start,%hit);
		}
	}
	if (%dist <= 0)
		%dist = %norm;
	if (%dist < %min)
		%dist = %min;
	return %dist;
}


//Function Returns scale and transform of a wall.
//Vec1 = Start,Fitdirection1,Fitdirection2.
//Sizes = Minsize & thickness, No hit size, Max fit size.
//Center = Models t2 center relative to the real center.

function pad(%vecs,%sizes,%center,%mask,%obj) {
	if (!%mask)
		%mask = $AllObjMask;
	%obj = mAbs(%obj);
	%start1 = getWords(%vecs,0,2);
	%dir1 = vectorNormalize(getWords(%vecs,3,5));
	%dir2 = vectorNormalize(getWords(%vecs,6,8));
	%dir3 = vectorNormalize(VectorCross(%dir1,%dir2));
	%height = rayDist(%start1 SPC %dir1,%sizes,%mask,%obj);
	%start2 = vectorAdd(vectorScale(%dir1,%height/2),%start1);
	%right = rayDist(%start2 SPC %dir2,%sizes,%mask,%obj);
	%left = rayDist(%start2 SPC vectorScale(%dir2,-1),%sizes,%mask,%obj);
	if ((%left + %right)>getWord(%sizes,2)) {
		%lef = %left;
		%left = %left-(((%left+%right)-getWord(%sizes,2))/2);
		%right = %right-(((%lef+%right)-getWord(%sizes,2))/2);
	}
	%scale1 = %height;
	%scale2 = (%left+%right);
	%scale3 = getWord(%sizes,0);
	%scale = %scale1 SPC %scale2 SPC %scale3;

	%moveDist1 = vectorScale( %dir2, ( ( (%left+%right)/2 ) - %left ) );
	%moveDist2 = vectorScale( %dir1, %height/2 );
	%moveDist3 = "0 0 0";//vectorScale(%dir3,getWord(%sizes,0)*getWord(%center,2));

	%Adjust1 = vectorScale(%dir1,%scale1*getWord(%center,0));
	%Adjust2 = vectorScale(%dir2,%scale2*getWord(%center,1));
	%Adjust3 = vectorScale(%dir3,%scale3*getWord(%center,2));

	%moveDist = vectorAdd(vectorAdd(%movedist1,%movedist2),%movedist3);
	%Adjust = vectorAdd(vectorAdd(%Adjust1,%Adjust2),%Adjust3);
	%TotalMove = vectorAdd(%movedist,%adjust);

	%rot = slopeRot(%dir1);
	%rot2 = rotAdd("0 0 1" SPC (1/2 * $Pi),"0 1 0" SPC (1/2 * $Pi));
	%rot = rotAdd(%rot,intRot(%rot,%dir2));
	%rotation = rotAdd(%rot,%rot2);
	return %scale SPC vectorAdd(%TotalMove,%start1) SPC %rotation;
}

//// [[[[List operations]]]];

function createList(%size) {
	for(%id = 0; %id < %size; %id++)
		%list = %list SPC "0";
	return trim(%list);
}

function listAdd(%list,%words,%location) {
	if (%location == -1)
		%list = %list SPC %words;
	else if (%location == 0)
		%list = %words SPC %list;
	else
		%list = getWords(%list,0,%location-1) SPC %words SPC getWords(%list,%location,getWordCount(%list));
	return trim(%list);
}

function listReplace(%list,%words,%location) {
	if (%location == 0)
		%list = %words SPC getWords(%list,1,getWordCount(%list));
	else if (%location == getWordCount(%list))
		%list = getWords(%list,0,%location) SPC %words;
	else
		%list = getWords(%list,0,%location-1) SPC %words SPC getWords(%list,%location+1,getWordCount(%list));
	return trim(%list);
}

function listDel(%list,%ids) {
	%size = getWordCount(%list);
	for(%id = 0; %id < %size; %id++) {
			if (findWord(%ids,%id) $= "")
				%tempList = %tempList SPC getWord(%list,%id);
	}
	return trim(%tempList);
}

function listSort(%list,%sortList) {
	for (%id = 0; %id < getWordCount(%sortList); %id++)
		%tempList = %tempList SPC getWord(%list,getWord(%sortList,%id));
	return trim(%tempList);
}

function listBuild(%list,%sortList) {
	%tempList = createList(getWordCount(%sortList));
	for (%id = 0; %id < getWordCount(%sortList); %id++)
		%tempList = listReplace(%tempList,getWord(%list,%id),getWord(%sortList,%id));
	return trim(%tempList);
}

function findWord(%list,%words) {
	%result = "";
	%size = getWordCount(%list);
	%size2 = getWordCount(%words);
	for (%marker = 0; %marker < %size; %marker++) {
		for (%find = 0; %find < %size2; %find++) {
			if (getWord(%words,%find) $= getWord(%list,%marker))
				%result = %result SPC %marker;
		}
	}
	return trim(%result);
}

//function stripEndSpaces(%list) {
//	if (getSubStr(%list,0,1) $= " ")
//		%list = getSubStr(%list,1,strLen(%list)-1);
//	return stripTrailingSpaces(%list);
//}


function pos(%loc,%mod) {
	if (!isObject(%loc))
		return;
	if (!%mod)
		return posFromTransform(%loc.getTransform());
	%mainmod = getWord(%mod,0);
	if (%mainmod $="o") {
		if (%loc) {
			%trans = %loc.getTransform();
			%xyz = posFromTransform(%trans);
			%mod =getWords(%mod,1,getWordCount(%mod));
		}
	}
	else if (%mainmod $="t") {
		if (%loc) {
			%xyz = posFromTransform(%loc);
			%mod =getWords(%mod,1,getWordCount(%mod));
		}
	}
	for(%i = 0; %i < getWordCount(%mod); %i++)
		%result = %result SPC poshelp1(%xyz,getWord(%mod,%i));
	return %result;
}


function poshelp1(%xyz,%id)
{
if (%id $= "x")
              return getWord(%xyz,0);
if (%id $= "y")
              return getWord(%xyz,1);
if (%id $= "z")
              return getWord(%xyz,2);

    return getWord(%xyz,%id);
}


function rot(%loc,%mod) {
	if (!isObject(%loc))
		return;
	if (!%mod)
		return rotFromTransform(%loc.getTransform());
	%mainmod = getWord(%mod,0);
	if (%mainmod $="o") {
		if (%loc) {
			%trans = %loc.getTransform();
			%xyz = rotFromTransform(%trans);
			%mod =getWords(%mod,1,getWordCount(%mod));
		}
	}
	else if (%mainmod $="t"){
		if (%loc){
			%xyz = rotFromTransform(%loc);
			%mod =getWords(%mod,1,getWordCount(%mod));
		}
	}
	for(%i = 0; %i < getWordCount(%mod); %i++)
		%result = %result SPC rothelp1(%xyz,getWord(%mod,%i));
	return %result;
}


function rothelp1(%xyz,%id)
{
if (%id $= "x")
              return getWord(%xyz,0);
if (%id $= "y")
              return getWord(%xyz,1);
if (%id $= "z")
              return getWord(%xyz,2);
if (%id $= "a")
              return getWord(%xyz,3);
return getWord(%xyz,%id);
}

function getjoint(%item)
{
if (%item.item.joint)
    return %item.item.joint;
else
    return "0.5 0.5 0.5";
}

//

function findhit(%plyr)
{
   $MaxDeployDistance = %item.maxDeployDis;
   $MinDeployDistance = %item.minDeployDis;

   %surface = Deployables::searchView(%plyr,
                                      $MaxDeployDistance,
                                      ($TypeMasks::TerrainObjectType |
                                       $TypeMasks::InteriorObjectType));
   if (%surface)
   {
      %surfacePt  = posFromRaycast(%surface);
      %surfaceNrm = normalFromRaycast(%surface);
      return %surface SPC %surfacept SPC %surfacenrm;
   }
return "";
}

function getTerrainHeight2(%loc,%rail,%obj) {
	%mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType;
	if (%rail $= "" || %rail $= "0")
		%rail = "0 0 1";
	//else if (getWord(%rail,2) <= 0)
	//%rail = vAbs(%rail);
	%rail = vectorNormalize(%rail);
	%start = vectorAdd(%loc,vectorScale(%rail,-100000));
	%end = vectorAdd(%loc,vectorScale(%rail,100000));
	%res = containerRayCast(%start, %end, %mask,%obj);
	if (%res)
		return getWords(%res,1,3);
	else
		return "";
}

// Animations

function groundpop(%obj,%rail,%time)
{
%oldpos = pos(%obj);
%rail = vectorNormalize(%rail);
%top = VectorLen(VectorMultiply(realSize(%obj),vAbs(vlev(floorvec( virvec(%obj,%rail),1000)))));
%newpos = vectorAdd(GetHeight(pos(%obj),%rail),vectorScale(%rail,(-0.5 * %top) -0.2));
%movement = VectorSub(pos(%obj),%newpos);
%speed = (VectorLen(%movement) / %time)*150;
%tick = vectorScale(vectorNormalize(%movement),%speed);
%obj.setTransform(%newpos SPC rot(%obj));
dynamicMove(%obj,%tick,%time/150,%oldpos);
}

function DynamicMove(%obj,%tick,%times,%end)
{
%pos = posFromTransform(%Obj.getTransform());
%rot = rotFromTransform(%Obj.getTransform());
if (%times < 1)
    %tick = vectorScale(%tick,%times);
%newpos = vectorAdd(%pos,%tick);
%Obj.setTransform(%newpos SPC %rot);
%times=%times-1;
if (%times > 0)
   schedule($AnimationTime, %obj, "dynamicMove", %obj, %tick,%times,%end);
else
   %Obj.setTransform(%end SPC %rot);
}

function getRandomVec() {
	%vec = getRandom() - 0.5 SPC getRandom() - 0.5 SPC getRandom() - 0.5;
	return vectorNormalize(%vec);
}

function validateVal(%val) {
	if (strStr(%val,"nan") != -1 || strStr(%val,"inf") != -1) {
		%val = "";
		error("Rot error no. " @ $RotErrors++);
	}
	return %val;
}

//////// Dfunctions additon Volume 2
//////// 1-9-2002

///Returns the vector off by a certain amount.
function VectorMiss(%vec)
{
%x = (getRandom() - 0.5) * 2 * 3.1415926 * %miss/10000;
%y = (getRandom() - 0.5) * 2 * 3.1415926 * %miss/10000;
%z = (getRandom() - 0.5) * 2 * 3.1415926 * %miss/10000;
%mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
return validateVal(MatrixMulVector(%mat, %vec));
}

//Returns the Volume of the object's box
function GameBase::GetVolume(%obj)
{
%size = VectorMultiply(VectorSub(GetWords(%obj.getObjectbox(),0,2),GetWords(%obj.getObjectbox(),3,5)),%obj.getScale());
return VectorDot(%size,%size);
}

//Returns the surfaces of the object's box
function GameBase::GetSurface(%obj)
{
%size = VectorMultiply(VectorSub(GetWords(%obj.getObjectbox(),0,2),GetWords(%obj.getObjectbox(),3,5)),%obj.getScale());
%sizex = GetWord(%size,1)*GetWord(%size,2);
%sizey = GetWord(%size,0)*GetWord(%size,2);
%sizez = GetWord(%size,0)*GetWord(%size,1);
return %sizex SPC %sizey SPC %sizez;
}

//Limits the value between boundries

function limit(%value,%min,%max)
{
if (%value > %max && %max !$= "")
   return %max;
if (%value < %min && %min !$= "")
   return %min;
return %value;
}

//Returns -1 or 1

function randomlev()
{
 if(getRandom(1))
      return 1;
   else
      return -1;
}

//Returns if the target is an forcefield
function GameBase::isforcefield(%target)
{
if (%target && isObject(%target))
   {
   if (%target.getDatablock().classname $= "forcefield")
      return 1;
   }
return "";
}


//A random bool going from always 0 when the imputed value is below min
//To awlays 1 when the imputed value is above max
function Change(%value,%min,%max)
{
return ((%value-%min)/(%max-%min)) > getRandom();
}

//Returns a random player
function Randomplayer()
{
if (!ClientGroup.getCount())
   return "";

%client = ClientGroup.getObject(GetRandom()*ClientGroup.getCount());
return %client.player;
}

//Retuns a random deployable
function randomdeployable()
{
%group = nameToID("MissionCleanup/Deployables");
%count = %group.getCount();

if (!%count)
   return "";

return %group.getObject(getRandom()*%count);
}

//Checks if there's line of sight between objects
function los(%obj1,%obj2,%offset1,%offset2,%mask) {
	if (!%mask)
		%mask = -1;
	%start = pos(%obj1);
	%end = pos(%obj2);
	if (%offset1)
		%start = vectorAdd(%start,realvec(%obj1,%offset1));
	if (%offset2)
		%end = vectorAdd(%end,realvec(%obj2,%offset2));
	%res = containerRayCast(%start,%end,%mask,%obj1);
	return (%res == %obj2);
}


//Returns the closests player to the given location
function closestPlayer(%location) {
	%dis = "";

	if (!ClientGroup.getCount())
		return "";

	%tplayer = "";
	for( %c = 0; %c < ClientGroup.getCount(); %c++ ) {
		%client = ClientGroup.getObject(%c);
		%player = %client.player;
		%pos = pos(%player);
		%dist = vectorDist(%location,%pos);
		if ($MTC_Loaded = true) {
			if (!%dis || %dist < %dis && MTCCleanTarget(%player)) {
				%tplayer = %player;
				%dis = %dist;
			}
		}
		else {
			if (!%dis || %dist < %dis) {
				%tplayer = %player;
				%dis = %dist;
			}
		}
	}
	return %tplayer SPC %dist;
}

//Moderate

//Returns Location information about the location.
function aboveground(%pos,%work,%obj)
       {
        ///1 Give ground under feet
        %mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType;
	%res1 = containerRayCast(%pos, GetWords(%pos,0,1) SPC "-10000", %mask,0);
	if (%res1)
               {
               if (%res1.getClassName() $= TerrainBlock)
                   %ground = 1;
               else
                   %ground = 2;
               }
	else
		%ground = "";

       ///2 Give cieling
       if (%work > 0)
          {
          %res2 = containerRayCast(%pos,vectorAdd(%pos,"0 0 10000"), %mask,0);
        	if (%res2)
                   {
                   if (%res2.getClassName() $= TerrainBlock)
                       %cieling = 1;
                   else
                       %cieling = 2;
                   }
        	else
	               %cieling = "";

           }
        if (%work > 1)
           {
           if (%res1)
               %down = VectorDist(posFromRaycast(%res1),%pos);
           if (%res2)
               %up =  VectorDist(posFromRaycast(%res2),%pos);
           }


/// void = 0
/// terrain = 1
/// Interior = 2
/// Ground-Cieling;

%answer = %ground + %cieling*3;
switch$ (%answer) {
		case 0:
			return "underground" SPC %down SPC %up; //0-0
		case 1:
			return "open" SPC %down SPC %up; //1-0
		case 2:
			return "roof" SPC %down SPC %up; //2-0
		case 3:
			return "underground" SPC %down SPC %up; //0-1
		case 4:
			return "odd-t" SPC %down SPC %up; //1-1
		case 5:
			return "odd-int" SPC %down SPC %up; //2-1
		case 6:
			return "underbuilding" SPC %down SPC %up; //0-2
		case 7:
			return "shadow" SPC %down SPC %up; //1-2
		case 8:
			return "inside" SPC %down SPC %up; //2-2
                }
}


//Returns wetehr or not we can see the top of the object above ground.
function GameBase::seetop(%obj)
{
%res = containerRayCast(vectorAdd(%obj.getWorldboxcenter(),"0 0 1000"),%obj.getWorldboxcenter(),-1,0);
	if (GetWord(%res,0) == %obj)
               return %res;
        else
		return "";
}

/////////////////////////
/////////new since 24-8//
/////////////////////////

///Dfunctions

function MicroAdjust(%pos)
{
%offset = (GetRandom()*0.02 - 0.01) SPC (GetRandom()*0.02 - 0.01) SPC (GetRandom()*0.02 - 0.01);
return vectorAdd(%pos,%offset);
}

function MatrixDot(%vector,%matrix)
{
%count1 = GetWordCount(%vector);
%count2 = GetWordCount(%matrix);
if (%count1 == 2 &&  %count2 == 4)
    return VectorDot(GetWords(%matrix,0,1),%vector) SPC VectorDot(GetWords(%matrix,2,3),%vector);
if (%count1 == 3 &&  %count2 == 9)
    return VectorDot(GetWords(%matrix,0,2),%vector) SPC VectorDot(GetWords(%matrix,3,5),%vector) SPC VectorDot(GetWords(%matrix,6,8),%vector);
}

function MatrixMult(%vector,%matrix)
{
%v1 = vectorScale(GetWords(%matrix,0,2),GetWord(%vector,0));
%v2 = vectorScale(GetWords(%matrix,3,5),GetWord(%vector,1));
%v3 = vectorScale(GetWords(%matrix,6,8),GetWord(%vector,2));
return vectorAdd(%v1,vectorAdd(%v2,%v3));
}

function TransPose(%matrix)
{
%count = GetWordCount(%matrix);
if (%count == 4)
   return GetWord(%matrix,0) SPC GetWord(%matrix,2) SPC GetWord(%matrix,1) SPC GetWord(%matrix,3);
else if (%count == 9)
   return GetWord(%matrix,0) SPC GetWord(%matrix,3) SPC GetWord(%matrix,5) SPC GetWord(%matrix,1) SPC GetWord(%matrix,4) SPC GetWord(%matrix,6) SPC GetWord(%matrix,2) SPC GetWord(%matrix,5) SPC GetWord(%matrix,7);
}


function dCross(%vector,%dir)
{
if (!%dir)
    %dir =1;
return %dir*GetWord(%vector,1) SPC %dir* -1*GetWord(%vector,0);
}


function MatrixfromVector(%vector,%dir)
{
%count = GetWordCount(%vector);
if (%count == 2)
   {
   return %vector SPC dCross(%vector,%dir);
   }
else if (%count == 3)
   {
   %x = GetWord(%vector,0);
   %y = GetWord(%vector,1);
   %z = GetWord(%vector,2);
   %x2 = -1*((%x * %y)/(Mpow(%x,2)+Mpow(%y,2)+Mpow(%z,2)));
   %y2 = (mPow(%x,2) * mPow(%z,2))/(Mpow(%x,2)+Mpow(%y,2)+Mpow(%z,2));
   %z2 = -1*((%y * %z)/(Mpow(%x,2)+Mpow(%y,2)+Mpow(%z,2)));
   %x3 = -1*((%x * %z)/(Mpow(%x,2)+Mpow(%z,2)));
   %z3 = mPow(%x,2)/(Mpow(%x,2)+Mpow(%z,2));
   return %vector SPC %x2 SPC %y2 SPC %z2 SPC %x3 SPC "0" SPC %z3;
   }
}

function Inverse(%matrix)
{
%count = GetWordCount(%matrix);
if (%count == 4)
   {
   %a = GetWord(%matrix,0);
   %b = GetWord(%matrix,1);
   %c = GetWord(%matrix,2);
   %d = GetWord(%matrix,3);
   %prod = (-1*%b * %c + %a * %d);
   return %d/%prod SPC -1*%b/%prod SPC -1*%c / %prod SPC %a / %prod;
   }
else if (%count == 9)
   {
   %a = GetWord(%matrix,0);
   %b = GetWord(%matrix,1);
   %c = GetWord(%matrix,2);
   %e = GetWord(%matrix,3);
   %f = GetWord(%matrix,4);
   %g = GetWord(%matrix,5);
   %h = GetWord(%matrix,6);
   %i = GetWord(%matrix,7);
   %j = GetWord(%matrix,8);
   %prod = -1*%c*%e*%g+%b*%f*%g+%c*%d*%h-%a*%f*%h-%b*%d*%i+%a*%e*%i;
   %a1 = (-1*%f*%h+%e*%i)/%prod;
   %b1 = (-1*%c*%h-%b*%i)/%prod;
   %c1 = (-1*%c*%e+%b*%f)/%prod;
   %d1 = (-1*%f*%g-%d*%i)/%prod;
   %e1 = (-1*%c*%g+%a*%i)/%prod;
   %f1 = (-1*%c*%d-%a*%f)/%prod;
   %g1 = (-1*%e*%g+%d*%h)/%prod;
   %h1 = (-1*%b*%g-%a*%h)/%prod;
   %i1 = (-1*%b*%d+%a*%e)/%prod;
   return %a1 SPC %b1 SPC %c1 SPC %d1 SPC %e1 SPC %f1 SPC %g1 SPC %h1 SPC %i1;
   }
}

function GameBase::GetShapeSize(%obj)
{
return VectorSub(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2));
}

function GameBase::GetRealSize(%obj)
{
%return = VectorMultiply(%obj.getScale(),%obj.getShapeSize());
if (%obj.getdatablock().getname() $="DeployedCrate11")   //for pad swap
    %return = vectorMultiply(%return,0.121951 SPC 0.238095 SPC 0.243902);
return %return;
}

function GameBase::SetRealSize(%obj,%size)
{
%scale = vectordivide(%size,%obj.getShapeSize());
if (%obj.getdatablock().getname() $="DeployedCrate11") //for pad swap
    %scale = vectorMultiply(%scale,8.20002 SPC 4.2 SPC 4.1);
%obj.setScale(%scale);
}

function GameBase::SetWorldBoxCenter(%obj,%location)
{
%obj.setEdge(%location,"0 0 0");
}

function GameBase::SetEdge(%obj,%location,%offset)
{
%VirCenter = vectorScale(vectorAdd(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)),0.5);
%VirOffset = VectorMultiply(vectorScale(%offset,0.5),%obj.getShapeSize());
%realoffset = RealVec(%obj,VectorMultiply(vectorAdd(%VirCenter,%VirOffset),%obj.getScale()));
%pos = vectorAdd(%location,vectorScale(%realoffset,-1));
%obj.setTransform(%pos SPC rot(%obj));
}

function GameBase::GetEdge(%obj,%offset)
{
%VirCenter = vectorScale(vectorAdd(getWords(%obj.getObjectBox(),3,5),getWords(%obj.getObjectBox(),0,2)),0.5);
%VirOffset = VectorMultiply(vectorScale(%offset,0.5),%obj.getShapeSize());
%realoffset = RealVec(%obj,VectorMultiply(vectorAdd(%VirCenter,%VirOffset),%obj.getScale()));
return vectorAdd(GetWords(%obj.getTransform(),0,2),%realoffset);
}


/////////////////////////
/////////new since 1-9//
/////////////////////////

//Replacement function for old calcb
//returns the changes damage instead of the coverage!

function calcBuildingInWay2(%position, %targetObject,%damage,%radius)
        {
	%targetPos = %targetObject.getWorldBoxCenter();
        $SolidCo = 1;
	%sourcePos = %position;

	%mask = $TypeMasks::StaticObjectType;
        %found = containerRayCast(%sourcePos, %targetPos, %mask,%lastfound);
        while (%found && %found != %targetObject && %damage > 0)
                {
      	        //Theoretically this should never happen
		if ((%found.getClassName() $= InteriorInstance) || (%found.getClassName() $= TSStatic))
			return 0;
                %dist = VectorDist(%sourcepos,getWords(%found,1,3));
                %amount = (1.0 - ((%dist / %radius) * 0.88)) * %damage;
                %damage = %amount - (%found.getDamageLeft() * %SolidCo);
                %lastfound = %found;
		%lastsourcepos = GetWords(%found,1,3);
                %found = containerRayCast(%lastsourcePos, %targetPos, %mask,%lastfound);
		}
	return Limit(%damage,0);
}

//Returns the highest value of the vector only

function topvec(%vec) {
	%x = getWord(%vec,0);
	%y = getWord(%vec,1);
	%z = getWord(%vec,2);
	if (mAbs(%x) >= mAbs(%y) && mAbs(%x) >= mAbs(%z))
		return %x SPC "0 0";
	else if (mAbs(%y) >= mAbs(%x) && mAbs(%y) >= mAbs(%z))
		return "0" SPC %y SPC "0";
	else
		return "0 0" SPC %z;
}

//Changed Vector Divide, to be more stable.

function VectorDivide(%vec1,%vec2)
{
%x1 =  getWord(%vec1,0);
%y1 =  getWord(%vec1,1);
%z1 =  getWord(%vec1,2);
%x2 =  getWord(%vec2,0);
%y2 =  getWord(%vec2,1);
%z2 =  getWord(%vec2,2);
%x3 =  0;
%y3 =  0;
%z3 =  0;
if (%x1 != 0||%x2 != 0)
   %x3 = %x1/%x2;
if (%y1 != 0||%y2 != 0)
   %y3 = %y1/%y2;
if (%z1 != 0||%z2 != 0)
   %z3 = %z1/%z2;
return %x3 SPC %y3 SPC %z3;
}


function VirpassVector(%obj,%vec)
{
%virvec = floorvec(vectorNormalize(VirVec(%obj,%vec)),1000);
%mask = floorvec(VectorMultiply(vectorScale(vectorNormalize(%virvec),1/mPow(2,0.5)),%obj.getRealSize()),1000);
%inoutvec = VectorMultiply( vectorNormalize( TopVec( VAbs( VectorDivide( %virvec,%mask ) ))),%obj.getRealSize());
%pass = vectorScale( %virvec,VectorLen( VectorDivide( %inoutvec,%virvec ) ) );
return %pass;
}

function getpassVector(%obj,%vec)
{
return RealVec(%obj,VirpassVector(%obj,%vec));
}

/////////The amout of substance you'd be crossing of an object if you went through the object in %vec direction.
/////////ie. going through the front of a 10 10 1 wall would return 1 going to the side would return 10.

function getpassLength(%obj,%vec)
{
return VectorLen(getpassVector(%obj,%vec));
}

//////// END Dfunctions additon Volume 2
//////// 1-9-2002
