Useful Maths Functions
Some useful functions and operators to fill in some of UnrealScript's gaps. See also:
- Scripting Operators for more information and other examples.
- Global Functions for built-in maths functions
Number functions and operators
divides
This is an operator that returns true if A is a divisor of B: for example:
( 3 divides 5 ) is false ( 3 divides 6 ) is true
static final operator(24) bool divides ( float A , float B ) { if( int( B / A ) == B / A ) return true ; }
sgn
This is a function that crops up in maths from time to time, that has proved useful on occasion in UnrealScript. It returns -1, 0 or +1 depending on the sign of the input.
function float Sgn( float theValue ) { if( theValue == 0 ) return 0; return theValue / Abs(theValue); }
Modulo operator
UnrealScript already has a modulus operator, %
but its behaviour with negative numbers is not consistent with the mathematical definition:
UnrealScript says -8 % 10 = -8
Maths says -8 % 10 = 2
Interestingly enough, this also occurs with C's own % operator, showing the source of the "bug".
static final operator(18) float mod ( float A, float B ) { if( A % B >= 0 ) return A % B ; else return ( A % B ) + B ; }
Log
UnrealScript has an ln (Loge) operator, but no log with a variable base. This function allows that. 10 is the default if 0 or no base is passed:
static final function float Logarithm (float a, optional float Base){ if (Base==0) Base=10; return Loge(a)/Loge(base); }
Trigonometic functions
Unrealscript includes Sin, Cos, Tan, and arcTan functions, defined in the Object class. The sin, cos, and tan assume an angle in radians is passed and aTan will return an angle in radians. Here are some const conversions:
Const RadianToDegree = 57.2957795131; Const DegreeToRadian = 0.01745329252; Const RadianToURot = 10430.3783505; Const URotToRadian = 0.000095873799;
Where URot is an unreal rotation unit (used in rotators).
arcSin function
Inverse Sin function. Pass the sin of an angle, and it returns the angle:
static final function float ASin ( float A ){ if (A>1||A<-1) //outside domain! return 0; if (A==1) //div by 0 checks return Pi/2.0; if (A==-1) return Pi/-2.0; return ATan(A/Sqrt(1-Square(A))); }
arcCos funtion
Inverse Cosine funtion. Pass the cosine of an angle and the angle is returned:
static final function float ACos ( float A ) { if (A>1||A<-1) //outside domain! return 0; if (A==0) //div by 0 check return (Pi/2.0); A=ATan(Sqrt(1.0-Square(A))/A); if (A<0) A+=Pi; Return A; }
aTan2 funtion
ArcTangent2. Pass the adjacent triangle leg as X and the opposite leg as Y (or X compoent, Y compont of a triangle inscribed in a unit circle).:
Note that if Y and X are 0, it will return 0, although in reality there is no answer (no line = no angle). The ratio allows for more exact angles (i.e. anywhere on the unit circle, rather than just 1/2 of it).
final static function float ATan2(float Y,float X) { local float tempang; if(X==0) { //div by 0 checks. if(Y<0) return -pi/2.0; else if(Y>0) return pi/2.0; else return 0; //technically impossible (nothing exists) } tempang=ATan(Y/X); if (X<0) tempang+=pi; //1st/3th quad //normalize (from -pi to pi) if(tempang>pi) tempang-=pi*2.0; if(tempang<-pi) tempang+=pi*2.0; return tempang; }
aSin2 funtion
ArcSin2: a more precise asin. Y=opposite leg, R=radius/hypotenuse. Of course if R is 0, no line exists, so it will return 0. Note that this assumes you put the asin code in your script.
final static function float ASin2(float Y,float Rad) { local float tempang; if(Rad==0) return 0; //technically impossible (no hypotenuse = nothing) tempang=ASin(Y/Rad); if (Rad<0) tempang=pi-tempang; //lower quads return tempang; }
aCos2 funtion
a more precise acos. X=adjecent leg, R=opposite. Other rules are similar to ASin2:
final static function float ACos2(float X,float Rad) { local float tempang; if(Rad==0) return 0; //no possible angle tempang=ACos(X/Rad); if (X<0) tempang*=-1; //left quads return tempang; }
Vector operators
Some simple vector operators, since most operators that you could want for vector have already been defined.
// Extend vector by an unit length static final preoperator vector ++ ( out vector A ) { return A += Normal(A); } // Shrink operator by an unit length static final preoperator vector -- ( out vector A ) { return A -= Normal(A); } // Same thing, but postop static final postoperator vector ++ ( out vector A ) { local vector B; B = A; A += Normal(A); return B; } static final postoperator vector -- ( out vector A ) { local vector B; B = A; A += Normal(A); return B; }
Suggestions: Firstly, don't use <pre></pre>. Indent your code lines by an arbitary amount of blanks instead (two, for instance) – that'll make Wiki automatically format them in a monospaced font and with linebreaks preserved, and it makes the code samples stand out better. Secondly, avoid tabs – there's no standard way for rendering tabs, so you'll be lucky if it comes out as you wish on other people's computers; better use blanks instead. —Mychaeel
thanks these were a straight copy-paste from a posting I made in Buf-Coding – Tarquin
Using <uscript></uscript> is way better now. – Wormbo
Indeed. By the way, as a potentially useful trivia about <uscript>: It expands tabs to spaces in four-character steps because that's the setting I believe Epic's coders used (and UnrealEd's script editor does as well). Best way is to avoid tabs altogether though and indent with spaces... —Mychaeel
Personally, I don't see any use of unary vector operators. Perhaps the author can explain their purpose? (though I admit it serves as a demonstration of proper usage of pre/post operator defining)– UsAaR33
Corran: Does anyone know what the abs() function does? In object.uc it's in the same section as all the trig functions but I can't seem to work out whay it does.
Tarquin: is it abs(float) or abs(vector)? you should move this to Global Function.
Mychaeel: It returns the absolute value of its argument. That is, the positive value of the given number. (And the trigonometric functions only happen to be close to it because they also take a float as their arguments.)