View difference between Paste ID: NPHTYFgv and JqiQLiB6
SHOW: | | - or go back to the newest paste.
1
//-----------------------------------------------------------------------------
2
// Torque Game Engine 
3
// Copyright (C) GarageGames.com, Inc.
4
//-----------------------------------------------------------------------------
5
6
//----------------------------------------------------------------------------------------------------------------
7
// Library Functions v2.1
8
//----------------------------------------------------------------------------------------------------------------
9
// These are nifty lil functions that are usefull for other things then solely supporting the functions they
10
// were written to help.
11
12
//*************************************************************************************
13
//torque engine tidbits
14
//
15
// The rotation value returned for the z axis of an object in torque, is specified by
16
// the last 2 words.(it can be made a single value by: getWord(%rot, 2) * getWord(%rot, 3))
17
// This value will remain positive until the angle is larger than 4.18879 radians OR 240
18
// degrees, any angle larger than this will revert to a negative value.
19
// GOing clockwise around the torque compass there are the following degree values...
20
//
21
// North -  0 deg, 0 Rad
22
// East  - 90 deg, 1.5707963 rad
23
// South- 180 deg, 3.1415926 rad
24
//        240 deg, 4.18879 rad (changeover point, 30 degrees past south)
25
// West - 270 deg, -1.5707963 rad (the negative value for due east)
26
//
27
//  pi = 3.1415926 (3.14159265358979323846)
28
// 2pi = 6.2831853 (6.28318530717958647692)
29
//
30
// Table X degrees = X radians
31
//  1d = 0.0174532
32
//  5d = 0.0872664
33
// 10d = 0.1745329
34
// 45d = 0.785398
35
// 60d = 1.0471974
36
// 90d = 1.5707963
37
//180d = 3.1415926
38
//
39
// when getting a rotation via an objects ID.rotation, the final word of the rotation
40
// is in degrees, NOT radians!
41
// ID.rotation = x y z amount(in degrees)
42
43
44
// getWorldBox returns box.min.x, box.min.y, box.min.z, box.max.x, box.max.y, box.max.z
45
// which are two diagonaly opposiing corners of the box
46
47
// Just thought someone might find this usefull :D  -Founder
48
//*************************************************************************************
49
50
//-------------------------------------------------------------------------------------
51
// Rotations, positions, vectors, and Matricies OH MY!
52
//-------------------------------------------------------------------------------------
53
//set some usefull globals
54
$Pi = 3.14159;
55
$TwoPi = 6.28319;
56
57
$North   = 0;
58
$NE      = 0.785398; //45
59
$East    = 1.5708;   //90
60
$SE      = 2.35619;  //135
61
$South   = $Pi;      //180
62
$SW      = 3.92699;  //225
63
$West    = 4.71239;  //270
64
$NW      = 5.49779;  //315
65
66
//----Vectors----
67
68
//this function serves a similar purpose to vectorScale, except instead of scaling it
69
//makes the specified vector.length equal to the number provided
70
function setVectorLength(%vec, %desiredLength)
71
{
72
   error("setVectorLength vec:" SPC %vec SPC "desiredLength" SPC %desiredLength);
73
   //this only works if we start with a unit vector so we have the relative valuse for x y and z
74
   %vecNorm = vectorLen(%vec) > 1 ? vectorNormalize(%vec) : %vec;
75
76
   // x + y + z = the number to devide the length by in order to get the proper scale by which to
77
   //multiply the vector elements
78
   %nl = mAbs(getWord(%vecNorm, 0)) + mAbs(getWord(%vecNorm, 1)) + mAbs(getWord(%vecNorm, 2));
79
   %scale = %desiredLength / %nl;
80
   //now vector scale it and send it back
81
   %newVec = vectorScale(%vecNorm, %scale);
82
   error("finalVec:" SPC %newVec);
83
   return %newVec;
84
}
85
86
//----common transform utilities----
87
function posFromRaycast(%transform)
88
{
89
   // the 2nd, 3rd, and 4th words returned from a successful raycast call are the position of the point
90
   %position = getWord(%transform, 1) SPC getWord(%transform, 2) SPC getWord(%transform, 3);
91
   return %position;
92
}
93
94
function normalFromRaycast(%transform)
95
{
96
   // the	5th,	6th and 7th words returned from a successful	raycast call are the normal of the	surface
97
   %norm = getWord(%transform, 4) SPC getWord(%transform, 5) SPC getWord(%transform, 6);
98
   return %norm;
99
}
100
101
// these stay, since having to type %rot = %obj.rotFromTransform(%transform); after already having the transform is
102
// just way too much.
103
function posFromTransform(%transform)
104
{
105
   // the first three words of an object's transform are the object's position
106
   %position = getWord(%transform, 0) SPC getWord(%transform, 1) SPC getWord(%transform, 2);
107
   return %position;
108
}
109
110
function rotFromTransform(%transform)
111
{
112
   // the last four words of an object's transform are the object's rotation
113
   %rotation = getWord(%transform, 3) SPC getWord(%transform, 4) SPC getWord(%transform, 5) SPC getWord(%transform, 6);
114
   return %rotation;
115
}
116
117
//if we are going to make these inherited functions, might as welllet them get the transform as well
118
function SceneObject::posFromTransform(%obj, %transform)
119
{
120
   if(%transform $= "")
121
      %transform = %obj.getTransForm();
122
   // the first three words of an object's transform are the object's position
123
   %position = getWord(%transform, 0) SPC getWord(%transform, 1) SPC getWord(%transform, 2);
124
   return %position;
125
}
126
127
function SceneObject::rotFromTransform(%obj, %transform)
128
{
129
   if(%transform $= "")
130
      %transform = %obj.getTransForm();
131
   // the last four words of an object's transform are the object's rotation
132
   %rotation = getWord(%transform, 3) SPC getWord(%transform, 4) SPC getWord(%transform, 5) SPC getWord(%transform, 6);
133
   return %rotation;
134
}
135
136
//this finds the terrain height for the position and sets it x meters above the terrain
137
function bumpZ(%pos, %heightMod)
138
{
139
   %x = getword(%pos, 0);
140
   %y = getword(%pos, 1);
141
   %height = getTerrainHeight(%x SPC %y);
142
143
   return %x SPC %y SPC %height + %heightMod;
144
}
145
146
//this function merely zeroes the z of a pos, not used anymore
147
function gimpPosition(%pos)
148
{
149
   return getword(%pos, 0) SPC getword(%pos, 1) SPC "0";
150
}
151
152
function getAngleDifferance(%angleOne, %angleTwo)
153
{
154
   //we need the smallest angle from angle one to angle two
155
156
   //First ensure both angles are positive
157
   %angleOne = %angleOne < 0 ? $TwoPi + %angleOne : %angleOne;
158
   %angleTwo = %angleTwo < 0 ? $TwoPi + %angleTwo : %angleTwo;
159
160
   %diff = %angleTwo - %angleOne;
161
162
   %diff = %diff > $Pi ? $TwoPi - %diff : %diff;
163
   %diff = %diff < -$Pi ? -$TwoPi - %diff : %diff;
164
165
   return %diff;
166
}
167
168
//---Directional (compass) functions----
169
170
function getClosestCompassTick(%angle)
171
{
172
   %value = "";
173
174
   %angle = %angle < 0 ? $TwoPi + %angle : %angle;
175
176
   if(%angle >= mDegToRad(337.5) || %angle < mDegToRad(22.5))
177
      %value = "North" SPC $North;
178
   else if(%angle >= mDegToRad(22.5) && %angle < mDegToRad(67.5))
179
      %value = "NorthEast" SPC $NE;
180
   else if(%angle >= mDegToRad(67.5) && %angle < mDegToRad(112.5))
181
      %value = "East" SPC $East;
182
   else if(%angle >= mDegToRad(112.5) && %angle < mDegToRad(157.5))
183
      %value = "SouthEast" SPC $SE;
184
   else if(%angle >= mDegToRad(157.5) && %angle < mDegToRad(202.5))
185
      %value = "South" SPC $South;
186
   else if(%angle >= mDegToRad(202.5) && %angle < mDegToRad(247.5))
187
      %value = "SouthWest" SPC $SW;
188
   else if(%angle >= mDegToRad(247.5) && %angle < mDegToRad(292.5))
189
      %value = "West" SPC $West;
190
   else if(%angle >= mDegToRad(292.5) && %angle < mDegToRad(337.5))
191
      %value = "NorthWest" SPC $NW;
192
193
   return %value;
194
}
195
196
function getClosestCardinal(%angle)
197
{
198
   %value = "";
199
200
   %angle = %angle < 0 ? $TwoPi + %angle : %angle;
201
   %angle = %angle > $TwoPi ? %angle - $TwoPi : %angle;
202
203
   if(%angle >= mDegToRad(315) || %angle < mDegToRad(45))
204
      %value = "North" SPC $North;
205
   else if(%angle >= mDegToRad(45) && %angle < mDegToRad(135))
206
      %value = "East" SPC $East;
207
   else if(%angle >= mDegToRad(135) && %angle < mDegToRad(225))
208
      %value = "South" SPC $South;
209
   else if(%angle >= mDegToRad(225) && %angle < mDegToRad(315))
210
      %value = "West" SPC $West;
211
212
213
   //error("getClosestCardinal Value:" SPC %value);
214
   return %value;
215
}
216
217
//----angles and rotations----
218
219
function invertDegAngle(%angle)
220
{
221
   if(%angle > 0)
222
      %angle = -(180 - %angle);
223
   else
224
      %angle = mAbs(%angle + 180);
225
226
   return %angle;
227
}
228
229
function invertAngle(%angle)
230
{
231
   //add pi, then cap
232
   %angle += $PI;
233
   %angle = %angle > $TwoPi ? %angle - $TwoPi : %angle;
234
235
   return %angle;
236
}
237
238
function getAnglefromRot(%rot)
239
{
240
   //return a positive z angle in radians
241
   %angle = getWord(%rot, 2) * getWord(%rot, 3);
242
   %angle = %angle < 0 ? $TwoPi + %angle : %angle;
243
   return %angle;
244
}
245
246
function getDegAnglefromRot(%rot)
247
{
248
   //return the rot's z angle in positive degrees
249
   %angleOne = mRadtoDeg(getWord(%rot, 2) * getWord(%rot, 3));
250
   %angle = %angleOne < 0 ? 360 + %angleOne : %angleOne;
251
   return %angle;
252
}
253
254
function getZangle(%posOne, %posTwo)
255
{
256
   %vec = VectorSub(%posTwo, %posOne);
257
   //get the angle
258
   %rotAngleZ = mATan( firstWord(%vec), getWord(%vec, 1) );
259
   //add pi to the angle
260
   //%rotAngleZ += $Pi;
261
262
   //make this rotation a proper torque game value, anything more than 240 degrees is negative
263
   //if(%rotAngleZ > 4.18879)
264
      //subtract 2pi from the value, then make sure its positive
265
     // %rotAngleZ = -(mAbs(%rotAngleZ - $TwoPi));
266
267
   return %rotAngleZ;
268
}
269
270
function absRot(%rot)
271
{
272
   %rot = %rot < 0 ? %rot + $TwoPi : %rot;
273
274
   return %rot;
275
}
276
277
function adjustRot(%rot, %rotAdjust)
278
{
279
   %angle = getWord(%rot, 2) * getWord(%rot, 3);
280
   //%rotAdjust = ((%rotAdjust >= 4.18879) ? (($TwoPi - %rotAdjust) * -1) : %rotAdjust);
281
282
   %rotAdjust = %rotAdjust < 0 ? $TwoPi + %rotAdjust : %rotAdjust;
283
284
   //now add the angle adjustment to the refrence rot
285
   %adjust = %angle + %rotAdjust;
286
   //bring in back in line with the torque world
287
   %adjust = ((%adjust >= 4.18879) ? (%adjust - $TwoPi) : %adjust);
288
   //if it's negative we'll stuff it into the vector and leave the angle value unchanged
289
   %rotZ = ((%adjust >= 0) ? 1 : (-1));
290
   %adjust = mAbs(%adjust);
291
   %rot = getWord(%rot, 0) SPC getWord(%rot, 1)  SPC %rotZ SPC %adjust;
292
   return %rot;
293
}
294
295
// This lil function generates the rotation required for an object at PosOne to point at PosTwo (z rot only)
296
function pointToXYPos(%posOne, %posTwo)
297
{
298
   %vec = VectorSub(%posOne, %posTwo);
299
   //get the angle
300
   %rotAngleZ = mATan( firstWord(%vec), getWord(%vec, 1) );
301
   //add pi to the angle
302
   %rotAngleZ += $Pi;
303
304
   //make this rotation a proper torque game value, anything more than 240 degrees is negative
305
   if(%rotAngleZ > 4.18879)
306
   {
307
      //the rotation scale is seldom negative, instead make the axis value negative
308
      %modifier = -1;
309
      //subtract 2pi from the value, then make sure its positive
310
      %rotAngleZ = mAbs(%rotAngleZ - $TwoPi);
311
      //sigh, if only this were all true
312
   }
313
   else
314
      %modifier = 1;
315
316
   //assemble the rotation and send it back
317
   return "0 0" SPC %modifier SPC %rotAngleZ;
318
}
319
320
// And this lil function generates the rotation required for an object at posOne to
321
// point at PosTwo for X, Y And Z axis.
322
function pointToPos(%posOne, %posTwo)
323
{
324
   //sub the two positions so we get a vector pointing from the origin in the direction we want our object to face
325
   %vec = VectorSub(%posTwo, %posOne);
326
327
   // pull the values out of the vector
328
   %x = firstWord(%vec);
329
   %y = getWord(%vec, 1);
330
   %z = getWord(%vec, 2);
331
332
   //this finds the distance from origin to our point
333
   %len = vectorLen(%vec);
334
335
   //---------X-----------------
336
   //given the rise and length of our vector this will give us the angle in radians
337
   %rotAngleX = mATan( %z, %len );
338
339
   //---------Z-----------------
340
   //get the angle for the z axis
341
   %rotAngleZ = mATan( %x, %y );
342
343
   //create 2 matrices, one for the z rotation, the other for the x rotation
344
   %matrix = MatrixCreateFromEuler("0 0" SPC %rotAngleZ * -1);
345
   %matrix2 = MatrixCreateFromEuler(%rotAngleX SPC "0 0");
346
347
   //now multiply them together so we end up with the rotation we want
348
   %finalMat = MatrixMultiply(%matrix, %matrix2);
349
350
   //we're done, send the proper numbers back
351
   return getWords(%finalMat, 3, 6);
352
}
353
354
function getXYAngle(%posOne, %posTwo)
355
{
356
   //sub the two positions so we get a vector pointing from the origin in the direction we want our object to face
357
   %vec = VectorSub(%posTwo, %posOne);
358
359
   // pull the values out of the vector
360
   %x = firstWord(%vec);
361
   %y = getWord(%vec, 1);
362
   %z = getWord(%vec, 2);
363
364
   //this finds the distance from origin to our point
365
   %len = vectorLen(%vec);
366
367
   //---------XY-----------------
368
   //given the rise and length of our vector this will give us the angle in radians
369
   %rotAngleXY = mATan( %z, %len );
370
   //%rotAngleXY+=$Pi;
371
   return %rotAngleXY;
372
}
373
374
function getXYangleFromRot(%rot)
375
{
376
   %a = getWord(%rot, 3);
377
378
   %x = firstWord(%rot) * %a;
379
   %y = getWord(%rot, 1) * %a;
380
   %z = getWord(%rot, 2) * %a;
381
382
383
   %xy = mSqrt((%x * %x) + (%y * %y));
384
   %rotAngleXY = mATan( %xy, mAbs(%z) );
385
   return %rotAngleXY;
386
}
387
388
function getZrise(%rot, %posOne, %posTwo)
389
{
390
   %XYAngle = getXYangleFromRot(%rot);
391
392
   %vec = VectorSub(%posTwo, %posOne);
393
394
    //this finds the distance from origin to our point
395
   %len = vectorLen(%vec);
396
397
   //pythagorian theroem says right triangle sides: a squared + b squared = c squared
398
   //we need to find the rise amount based on the angle and length
399
   // c^2 - a^2 = b^2
400
   //the height of the right triangle equals the tangent of the angle times the length of the base
401
   //%zmod = mTan(%XYAngle + $Pi) * (%len + $Pi);
402
   %zmod = mTan(%XYAngle) * (%len - $Pi);
403
   return %zmod;
404
}
405
406
//--------------------------------------------------------------------------------------------
407
// Spline functions
408
//--------------------------------------------------------------------------------------------
409
410
// These functions draw a curve from the first point to the last point, going near any middle points at time t.
411
// t represents the percentage of distance between the first and last point that you want the curve point for
412
// They can be used to draw a 3-d spline when all three axis are run through the function.
413
414
// %t = (position Of Desired Spline Point) / (distance Between First And Last Points)
415
// %curvePoint1.x = get3PointCurveValue(%point1.x, %point2.x, %point3.x, %t)
416
// %curvePoint1.y = get3PointCurveValue(%point1.y, %point2.y, %point3.y, %t)
417
// %curvePoint1.z = get3PointCurveValue(%point1.z, %point2.z, %point3.z, %t)
418
419
// this lil guy doesn't actually draw a curve, but rather a line, however it is very usefull for mixing
420
// two values together based on a percentage of time or distance
421
function get2PointLineValue(%point1, %point2, %t)
422
{
423
   %pd = ( %point1 * (1-%t)) + (%point2 * %t);
424
   return %pd;
425
}
426
427
function get3PointCurveValue(%point1, %point2, %point3, %t)
428
{
429
   %step1 = %point1 * ((1-%t) * (1-%t));
430
   %step2 = %point2 * 2 * %t * (1 - %t);
431
   %step3 = %point3 * (%t * %t);
432
   %pd = %step1 + %step2 + %step3;
433
   return %pd;
434
}
435
436
function get4PointCurveValue(%point1, %point2, %point3, %point4, %t)
437
{
438
   %step1 = %point1 * ( (1 - %t)*(1 - %t)*(1 - %t) );
439
   %step2 = %point2 * 3 * %t * ( (1 - %t)*(1 - %t) );
440
   %step3 = %point3 * 3 * (%t * %t) * (1 - %t);
441
   %step4 = %point4 * (%t * %t * %t);
442
   %pd = %step1 + %step2 + %step3 + %step4;
443
   return %pd;
444
}
445
446
//---------------------------------------------------------------------------------------------------------------
447
// functions dealing with terrain
448
//---------------------------------------------------------------------------------------------------------------
449
450
//this takes the provided position, and sets it to the position of the earest terrain vertex
451
function findNearestTerrainPoint(%pos)
452
{
453
   %x = findGridPoint(firstWord(%pos));
454
   %y = findGridPoint(getWord(%pos, 1));
455
   %z = getWord(%pos, 2);
456
457
   return(%x SPC %y SPC %z);
458
}
459
460
function findGridPoint(%axis)
461
{
462
   if(%axis == 0)
463
      return 0;
464
   %axis = mFloor(%axis);
465
   %remainder = %axis % Terrain.squareSize;
466
467
   if(%remainder >= (Terrain.squareSize / 2))
468
   {
469
      while(%axis % Terrain.squareSize != 0)
470
         %axis++;
471
   }
472
   else
473
   {
474
      while(%axis % Terrain.squareSize != 0)
475
         %axis--;
476
   }
477
   return %axis;
478
}
479
480
//Takes the pos provided, and sets the z value to the surface height
481
function getTerrainSurfacePoint(%pos)
482
{
483
   %x = getword(%pos, 0);
484
   %y = getword(%pos, 1);
485
   %height = getTerrainHeight(%x SPC %y);
486
   return %x SPC %y SPC %height;
487
}
488
489
//in a box with the given max and min x and y extents, this will find the average height value
490
function getAverageTerrainHeight(%minX, %maxX, %minY, %maxY, %squareSize)
491
{
492
   %total = 0;
493
   %count = 0;
494
   for(%x = %minX; %x <= %maxX; %x += %squareSize)
495
   {
496
      //we are already looping through x, so loop through Y while we're at it
497
      for(%y = %minY; %y <= %maxY; %y += %squareSize)
498
      {
499
         %total += getTerrainHeight(%x SPC %y);
500
         %count++;
501
      }
502
   }
503
   return %total / %count;
504
}
505
506
function getTerrainAngle(%point)
507
{
508
   %angleRad = mACos(vectorDot(%point, "0 0 1"));
509
   %angleDeg = mRadtoDeg(%angleRad);
510
   return %angleDeg;
511
}
512
513
function getTerrainLevel(%pos, %rad)
514
{
515
   while(%retries < 500)
516
   {
517
      %x = getWord(%pos, 0) + mFloor(getRandom(%rad * 2) - %rad);
518
      %y = getWord(%pos, 1) + mFloor(getRandom(%rad * 2) - %rad);
519
      %z = getWord(%pos, 2) + mFloor(getRandom(%rad * 2) - %rad);
520
521
      %start = %x @ " " @ %y @ " 5000";
522
      %end = %x @ " " @ %y @ " -1";
523
      %ground = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0);
524
      %z = getWord(%ground, 3);
525
526
      %z += 3.5;
527
      %position = %x @ " " @ %y @ " " @ %z;
528
529
      %mask = ( $TypeMasks::ShapeBaseObjectType | $TypeMasks::MoveableObjectType |
530
                $TypeMasks::StaticShapeObjectType | $TypeMasks::WaterObjectType | 
531
                $TypeMasks::InteriorObjectType );
532
533
      InitContainerRadiusSearch( %position, 3.5, %mask );
534
      if(containerSearchNext() == 0)
535
      {
536
         //error ("Position Is Good");
537
         return %position;
538
      }
539
      else
540
         %retries++;
541
   }
542
   return( %pos );
543
}
544
545
//---------------------------------------------------------------------------------------------------------------
546
// Functions for moving objects
547
//---------------------------------------------------------------------------------------------------------------
548
function SceneObject::setOnTerrain(%obj, %pos, %calcOnly)
549
{
550
   if(%pos $= "")
551
      %pos = %obj.position;
552
   %terHeight = getTerrainHeight(%pos);
553
   %offset = %obj.GetHeightOffset();
554
   %newPos = firstWord(%pos) SPC getWord(%pos, 1) SPC %terHeight + %offset;
555
   if(%calcOnly)
556
      return %newPos;
557
   else
558
      %obj.setTransform(%newPos SPC %obj.rotFromTransform());
559
}
560
561
function SceneObject::alignTransforms(%obj, %pos, %rot, %rotAdjust, %xAngle, %yRadius, %zMod, %invert, %calc)
562
{
563
   //rotation hack - these rots just aren't natural!
564
   if(%rot $= "0 0 1 0" || %rot $= "0 1 0 0"  || %rot $= "1 0 0 0")
565
      %rot = "0.0001 0.00001 0.99 0.001";
566
567
   //get the angle of the refrence object(rot) so we know what direction to go to find the new position
568
   %angle = getWord(%rot, 2) * getWord(%rot, 3);
569
570
   //this is the angle to find the position at, relative to the refrence point
571
   %xAngle = mDegToRad(%xAngle);
572
   //now adjust it to be compatible with the refrence rotation
573
   %xAngleMod = ((%angle < 0) ? (-1 * %xAngle) : %xAngle);
574
575
   //generate a vector to the adjusted position
576
   %matrix = VectorOrthoBasis(getXYangleFromRot(%rot) SPC getWords(%rot,1,2) SPC getWord(%rot, 3) + %xAngleMod);
577
   //%matrix = VectorOrthoBasis(getWords(%rot,0,2) SPC getWord(%rot, 3) + %xAngleMod);
578
   %yRot = getWords(%matrix, 3, 5);
579
580
   //now scale from our current position the yRadius amount to get our new position
581
   %zPos = vectorAdd(%pos, vectorScale(%yRot, %yRadius));
582
   %bPos = firstWord(%zPos) SPC getWord(%zPos, 1) SPC (getWord(%zPos, 2) + %zMod);
583
584
   //right now our new position is on the horizontal plane of world space, if the refrence rot is tilted
585
   //we need to move the pos up or down to account for it.
586
   //do wee need to adjust the Z hieght position to account for objects rotated on an x or y axis?
587
   %XYAngle = getXYangleFromRot(%rot);
588
   //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)
589
   if(mAbs(%XYAngle) > 0.0174533)
590
   {
591
      %zRise = getZrise(%rot, %bpos, %pos);// + $Pi;
592
      %bPos = getWords(%bPos, 0, 1) SPC getword(%bPos, 2) + %zRise;
593
   }
594
595
   //lets try using the trusty ole matrix to take care of any tilt
596
   //so first thing is to subtract the target position from the ref position.
597
598
599
600
   //it would probably more accurate to calculate this on the surface of a shpere instead of a circle then adjusting
601
   //the hieght, but since I don't know how to do that just now we'll go this route, which is plenty damned acurate
602
603
   //if the generated position needs to point in a certain direction relative to the refrence, then generate it's rot
604
   if(%rotAdjust !$= "" && %rotAdjust != 0)
605
   {
606
      //convert the adjustment to radians, then make it a valid torque world angle
607
      %rotAdjust = mDegToRad(%rotAdjust);
608
      %rotAdjust = ((%rotAdjust >= 4.18879) ? (($TwoPi - %rotAdjust) * -1) : %rotAdjust);
609
610
      //now add the angle adjustment to the refrence rot
611
      %adjust = %angle + %rotAdjust;
612
      //bring in back in line with the torque world
613
      %adjust = ((%adjust >= 4.18879) ? (%adjust - $TwoPi) : %adjust);
614
      //if it's negative we'll stuff it into the vector and leave the angle value unchanged
615
      %rotZ = ((%adjust >= 0) ? 1 : (-1));
616
      %adjust = mAbs(%adjust);
617
      %rot = getWord(%rot, 0) SPC getWord(%rot, 1)  SPC %rotZ SPC %adjust;
618
      %angle = getWord(%rot, 2) * getWord(%rot, 3);
619
   }
620
   if(%invert)
621
   {
622
      //this is for turning the generated position upside down, wonder if this and the above are broken
623
      //for tilted refrence rotations?
624
      %angleR = -1 * %angle;
625
      %Mrot = MatrixCreateFromEuler("0 3.14" SPC %angleR);
626
      %rot = getWord(%Mrot, 3) SPC getWord(%Mrot, 4) SPC getWord(%Mrot, 5) SPC getWord(%Mrot, 6);
627
   }
628
629
   //we're done, get the hell outta here!
630
   %transForm = %bPos SPC %rot;
631
   if(%calc)
632
      return %transForm;
633
   else
634
   {
635
      %obj.setTransform(%transForm);
636
      return;
637
   }
638
}
639
640
//--------------------------------------------------------------------------------------------
641
//
642
//	SceneObject::alignTransforms() -by Founder
643
//
644
//--------------------------------------------------------------------------------------------
645
// Here it is!! THE mother of all functions!! AMAZING!!
646
//
647
// usage: %objectID.alignTransforms(%pos, %rot, %rotAdjust, %xAngle, %yRadius, %zMod, %invert, %calc);
648
//
649
//	%pos is the position of the object(or point) around which to move the (%objectID)
650
//	%rot is the final rotation you want %objectID to face
651
//	%rotAdjust is for making a rotational offset of %objectID relative to the provided %rot
652
//		valid values go from 0 to 360; going clockwise from north(0), east(90)
653
//		south(180), west(270) etc. 360 will work, but I don't know what kind of
654
//		dumbass would rotate an object by 360 degrees in the z.
655
//	%xAngle and %yRadius are vars for adjusting %objectID's position relative to %pos
656
//		%yRadius describes a circle of (%yRadius) in size, along which you wish %objectID to be
657
//		placed. %xAngle is the relative angle in degrees (0 - 360) from %pos. Where this
658
//		angle intersects the circle is the position the object will be placed.
659
//
660
//	%zMod is how far up you want to move the object relative to %pos
661
//	%invert is weather or not you want to turn %objectID upside down.
662
//		true and 1 will invert it, 0, false, or giveing it no value will not.
663
//	%calc will have the function return the calculated transform instead of actually moving
664
//		the object.
665
// if for any option you do not want to make an adjustment fill the spot with a 0(zero)
666
// negative values will subtract from x y and z axis, but negative values are not valid for
667
// the %rotAdjust value
668
// examples:
669
//              %deplObj.alignTransforms(%pos, %rot, 270, 0, 0, 8, true);
670
//              %deplObj.alignTransforms(%dPos, %rot, 0, 0, 0.7, -0.05);
671
//
672
//
673
//
674
//                               --
675
//                          -          X
676
//                         -            -
677
//                               P
678
//                         -            -
679
//                          -          -
680
//                               --
681
//
682
//
683
//  In the diagram above, P equals the position of the player or the position generated by the
684
//  deploy code or the postion of the reference object. The circle made up of (-)'s represents
685
//  a %yRadius of 5 meters. Or if you prefer, a circle which represents the distance
686
//  away from P that you want this object to be. X represents the object for whom we are
687
//  generating the new position, and where we want it. X is at an approximately 45 degree angle
688
//  from P, which is the northEast tick on the Torque compass. In order to keep X's position relative
689
//  to P, no matter what direction P faces you would use the following line of code:
690
//         %ObjectID.alignTransforms(%pos(of P), %rot(of P), 0, 45, 5, 0);
691
//--------------------------------------------------------------------------------------------
692
693
function SceneObject::alignGroupRot(%obj, %pos, %rot, %rotAdjust, %xAngle, %yRadius, %zMod, %invert, %calc)
694
{
695
   %vAngle = getWord(%rot, 3);
696
   %angle = getWord(%rot, 2) * getWord(%rot, 3);
697
   %xAngle = mDegToRad(%xAngle);
698
   %xAngleMod = ((%angle < 0) ? (-1 * %xAngle) : %xAngle);
699
   %vRot =  getWords(%rot,0,2);
700
   %matrix = VectorOrthoBasis(%vRot SPC %vAngle + %xAngleMod);
701
   %yRot = getWords(%matrix, 3, 5);
702
   %zPos = vectorAdd(%pos, vectorScale(%yRot, %yRadius));
703
   %bPos = firstWord(%zPos) SPC getWord(%zPos, 1) SPC (getWord(%zPos, 2) + %zMod);
704
   if(%rotAdjust !$= "" && %rotAdjust != 0)
705
   {
706
      %deg = mRadtoDeg(%angle);
707
      %rotAdjust = ((%rotAdjust >= 240) ? ((360 - %rotAdjust) * -1) : %rotAdjust);
708
      %adjust = %deg + %rotAdjust;
709
      %adjust = ((%adjust >= 240) ? (%adjust - 360) : %adjust);
710
      %rotZ = ((%adjust >= 0) ? 1 : (-1));
711
      %adjust = mAbs(%adjust);
712
      %finAngle = mDegToRad(%adjust);
713
      %rot = getWord(%rot, 0) SPC getWord(%rot, 1)  SPC %rotZ SPC %finAngle;
714
      %angle = getWord(%rot, 2) * getWord(%rot, 3);
715
   }
716
   if(%invert)
717
   {
718
      %angleR = -1 * %angle;
719
      %Mrot = MatrixCreateFromEuler("0 3.14" SPC %angleR);
720
      %rot = getWord(%Mrot, 3) SPC getWord(%Mrot, 4) SPC getWord(%Mrot, 5) SPC getWord(%Mrot, 6);
721
   }
722
   %transForm = %bPos SPC %rot;
723
   if(%calc)
724
      return %transForm;
725
   else
726
   {
727
      %obj.setTransform(%transForm);
728
      return;
729
   }
730
}
731
732
function SceneObject::StartMoveObject(%obj, %endpos, %time, %smoothness, %delay)
733
{
734
   if(isObject(%obj))
735
   {
736
      %startpos = %obj.getTransform();
737
      %diff = VectorSub(%endpos, %startpos);
738
      %numsteps = (%time/1000) * %smoothness;
739
      %interval = 1000 / %smoothness;
740
      %stepvec = VectorScale(%diff, (1/%numsteps));
741
      %numstepsleft = %numsteps;
742
      %currpos = %startpos;
743
      %obj.MoveObject(%startpos, %endpos, %numsteps, %numstepsleft, %stepvec, %currpos, %interval, %delay);
744
   }
745
}
746
747
function SceneObject::MoveObject(%obj, %startpos, %endpos, %numsteps, %numstepsleft, %stepvec, %currpos, %interval, %delay)
748
{
749
   %rot = rotFromTransform(%obj.getTransform());
750
   %currpos = VectorAdd(%currpos, %stepvec);
751
752
   %obj.setTransForm(%currpos SPC %rot);
753
   %numstepsleft--;
754
   if(%numstepsleft < 1)
755
      return;
756
   else
757
      %obj.schedule(%interval, "MoveObject", %startpos, %endpos, %numsteps, %numstepsleft, %stepvec, %currpos, %interval, %delay);
758
}
759
760
function getObjectTypeMask(%obj)
761
{
762
   if(%obj.getType() & $TypeMasks::StaticObjectType)
763
    error("\c4Type is: $TypeMasks::StaticObjectType");
764
   else if(%obj.getType() & $TypeMasks::EnvironmentObjectType)
765
    error("\c4Type is: $TypeMasks::EnvironmentObjectType");
766
   else if(%obj.getType() & $TypeMasks::TerrainObjectType)
767
    error("\c4Type is: $TypeMasks::TerrainObjectType");
768
   else if(%obj.getType() & $TypeMasks::InteriorObjectType)
769
    error("\c4Type is: $TypeMasks::InteriorObjectType");
770
   else if(%obj.getType() & $TypeMasks::WaterObjectType)
771
    error("\c4Type is: $TypeMasks::WaterObjectType");
772
   else if(%obj.getType() & $TypeMasks::TriggerObjectType)
773
    error("\c4Type is: $TypeMasks::TriggerObjectType");
774
   else if(%obj.getType() & $TypeMasks::MarkerObjectType)
775
    error("\c4Type is: $TypeMasks::MarkerObjectType");
776
   else if(%obj.getType() & $TypeMasks::GameBaseObjectType)
777
    error("\c4Type is: $TypeMasks::GameBaseObjectType");
778
   else if(%obj.getType() & $TypeMasks::ShapeBaseObjectType)
779
    error("\c4Type is: $TypeMasks::ShapeBaseObjectType");
780
   else if(%obj.getType() & $TypeMasks::CameraObjectType)
781
    error("\c4Type is: $TypeMasks::CameraObjectType");
782
   else if(%obj.getType() & $TypeMasks::StaticShapeObjectType)
783
    error("\c4Type is: $TypeMasks::StaticShapeObjectType");
784
   else if(%obj.getType() & $TypeMasks::PlayerObjectType)
785
    error("\c4Type is: $TypeMasks::PlayerObjectType");
786
   else if(%obj.getType() & $TypeMasks::ItemObjectType)
787
    error("\c4Type is: $TypeMasks::ItemObjectType");
788
   else if(%obj.getType() & $TypeMasks::VehicleObjectType)
789
    error("\c4Type is: $TypeMasks::VehicleObjectType");
790
   else if(%obj.getType() & $TypeMasks::VehicleBlockerObjectType)
791
    error("\c4Type is: $TypeMasks::VehicleBlockerObjectType");
792
   else if(%obj.getType() & $TypeMasks::ProjectileObjectType)
793
    error("\c4Type is: $TypeMasks::ProjectileObjectType");
794
   else if(%obj.getType() & $TypeMasks::ExplosionObjectType)
795
    error("\c4Type is: $TypeMasks::ExplosionObjectType");
796
   else if(%obj.getType() & $TypeMasks::CorpseObjectType)
797
    error("\c4Type is: $TypeMasks::CorpseObjectType");
798
   else if(%obj.getType() & $TypeMasks::DebrisObjectType)
799
    error("\c4Type is: $TypeMasks::DebrisObjectType");
800
   else if(%obj.getType() & $TypeMasks::PhysicalZoneObjectType)
801
    error("\c4Type is: $TypeMasks::PhysicalZoneObjectType");
802
   else if(%obj.getType() & $TypeMasks::StaticTSObjectType)
803
    error("\c4Type is: $TypeMasks::StaticTSObjectType");
804
   else if(%obj.getType() & $TypeMasks::StaticRenderedObjectType)
805
    error("\c4Type is: $TypeMasks::StaticRenderedObjectType");
806
   else if(%obj.getType() & $TypeMasks::DamagableItemObjectType)
807
    error("\c4Type is: $TypeMasks::DamagableItemObjectType");
808
   else
809
      error("\c4Object type is: UNKNOWN");
810
}
811
812
// Founder: Apply kickbak to anything
813
function SceneObject::applyKickback(%obj, %kick)
814
{
815
   %dir = %obj.getVectorFromTransform( %obj.getTransform(), "reverse" );
816
   %force = vectorScale( %dir, %kick );
817
   %obj.applyImpulse( %obj.posFromTransform(), %force );
818
}
819
820
// ZOD: Modified version of above to allow different directions
821
function SceneObject::applyKick(%obj, %amt, %velCap, %dir)
822
{
823
   %vec = %obj.getVectorFromTransform( %obj.getTransform(), %dir );
824
   %data = %obj.getDataBlock();
825
   %pos = %obj.posFromTransform();
826
   %velocity = %obj.getVelocity();
827
   %normal = VectorDot( %velocity, VectorNormalize( %velocity ) );
828
829
   if( %velCap != 0 && %normal > %velCap) // Whatever cap we wish..
830
   {
831
      %kick = %amt / %Normal; // Reduce impulse.
832
      //retrun; // Or apply no impulse at all and exit out.
833
   }
834
   else
835
      %kick = %amt;
836
837
   %impulse = VectorScale( %vec, %data.mass * %kick );
838
   %obj.applyImpulse(%pos, %impulse);
839
}
840
841
//--------------------------------------------------------------------------------------------
842
// Taken from Harold Paul /*Wedge*/ DElia's post in the GG mod forums
843
// http://www.garagegames.com/mg/forums/result.thread.php?qt=50109
844
function SceneObject::getVectorFromTransform(%obj, %transform, %vector)
845
{
846
   %aa = getWords(%transform, 3, 6);   
847
   %tmat = VectorOrthoBasis(%aa);
848
849
   %rv = getWords(%tMat, 0, 2);
850
   %fv = getWords(%tMat, 3, 5);
851
   %uv = getWords(%tMat, 6, 8);
852
853
   if(%vector $= "up")
854
      return %uv;
855
856
   if(%vector $= "down")
857
      return VectorScale(%uv, -1);
858
859
   if(%vector $= "left")
860
      return VectorScale(%rv, -1);
861
862
   if(%vector $= "right")
863
      return %rv;
864
865
   if(%vector $= "forward")
866
      return %fv;
867
868
   if(%vector $= "reverse")
869
     return VectorScale(%fv, -1);
870
}
871
872
//--------------------------------------------------------------------------------------------
873
874
function stripTaggedVar(%var)
875
{
876
   return stripChars( detag( getTaggedString( %var ) ), "\cp\co\c6\c7\c8\c9" );
877
}
878
879
//------------------------------------------------------------------------------------
880
// Object Box functions
881
//------------------------------------------------------------------------------------
882
//box = min.x min.y min.z max.x max.y max.z
883
884
//parse out a particular element
885
function getBoxMinX(%box){ return getWord(%box, 0); }
886
function getBoxMinY(%box){ return getWord(%box, 1); }
887
function getBoxMinZ(%box){ return getWord(%box, 2); }
888
function getBoxMaxX(%box){ return getWord(%box, 3); }
889
function getBoxMaxY(%box){ return getWord(%box, 4); }
890
function getBoxMaxZ(%box){ return getWord(%box, 5); }
891
892
function SceneObject::getWorldBoxMin(%obj)
893
{
894
   %box = %obj.getObjectBox();
895
   %matrix = %obj.getTransForm();
896
   return MatrixMulPoint(%matrix, getWords(%box, 0, 2));
897
}
898
899
function SceneObject::getWorldBoxMax(%obj)
900
{
901
   %box = %obj.getObjectBox();
902
   %matrix = %obj.getTransForm();
903
   return MatrixMulPoint(%matrix, getWords(%box, 3, 5));
904
}
905
906
function SceneObject::getWorldBoxMinX(%obj) { return getWord(%obj.getWorldBoxMin(), 0); }
907
function SceneObject::getWorldBoxMinY(%obj) { return getWord(%obj.getWorldBoxMin(), 1); }
908
function SceneObject::getWorldBoxMinZ(%obj) { return getWord(%obj.getWorldBoxMin(), 2); }
909
function SceneObject::getWorldBoxMaxX(%obj) { return getWord(%obj.getWorldBoxMax(), 0); }
910
function SceneObject::getWorldBoxMaxY(%obj) { return getWord(%obj.getWorldBoxMax(), 1); }
911
function SceneObject::getWorldBoxMaxZ(%obj) { return getWord(%obj.getWorldBoxMax(), 2); }
912
913
914
//return a box dimension
915
function SceneObject::GetBoxWidth(%obj)
916
{
917
   %box = %obj.getObjectBox();
918
   return mAbs(getBoxMaxX(%box)) + mAbs(getBoxMinX(%box));
919
}
920
921
function SceneObject::GetBoxLength(%obj)
922
{
923
   %box = %obj.getObjectBox();
924
   return mAbs(getBoxMaxY(%box)) + mAbs(getBoxMinY(%box));
925
}
926
927
function SceneObject::GetBoxHeight(%obj)
928
{
929
   %box = %obj.getObjectBox();
930
   return mAbs(getBoxMaxZ(%box)) + mAbs(getBoxMinZ(%box));
931
}
932
933
function SceneObject::GetBoxCenter(%obj)
934
{
935
   //box center by default will be 0 0 0, so use a lil matrix math, get it's current world position
936
   %matrix = %obj.getTransForm();
937
   %box = %obj.getObjectBox();
938
   %newBox = MatrixMulPoint(%matrix, getWords(%box, 0, 2));
939
   %newBox = %newBox SPC MatrixMulPoint(%matrix, getWords(%box, 3, 5));
940
   %centerX = (getBoxMinX(%newBox) + getBoxMaxX(%newBox)) * 0.5;
941
   %centerY = (getBoxMinY(%newBox) + getBoxMaxY(%newBox)) * 0.5;
942
   %centerZ = (getBoxMinZ(%newBox) + getBoxMaxZ(%newBox)) * 0.5;
943
   return %centerX SPC %centerY SPC %centerZ;
944
}
945
946
function SceneObject::GetHeightOffset(%obj)
947
{
948
   return mAbs(getWord(%obj.position, 2) - %obj.getWorldBoxMinZ());
949
}
950
951
//------------------------------------------------------------------------------------
952
// Other functionality
953
//------------------------------------------------------------------------------------
954
955
956
function getValidSpawnSurface(%pos, %rad)
957
{
958
   while(%retries < 500)
959
   {
960
      %x = getWord(%pos, 0) + mFloor(getRandom(%rad * 2) - %rad);
961
      %y = getWord(%pos, 1) + mFloor(getRandom(%rad * 2) - %rad);
962
963
      %start = %x SPC %y SPC VectorAdd(getWord(%pos, 2), 3.5);
964
      %end = %x SPC %y SPC "-1";
965
      %surface = containerRayCast(%start, %end, $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType, 0);
966
 
967
      %z = getWord(%surface, 3);
968
      %position = %x SPC %y SPC %z;
969
970
      %mask = ( $TypeMasks::ShapeBaseObjectType | $TypeMasks::MoveableObjectType |
971
                $TypeMasks::StaticShapeObjectType | $TypeMasks::WaterObjectType );
972
973
      InitContainerRadiusSearch( %position, 3.5, %mask );
974
      if ( containerSearchNext() == 0 )
975
      {
976
         //error("Random Position Is Good");
977
         return %position;
978
      }
979
      else
980
         %retries++;
981
982
   }
983
   //error("Random Position Is Bad");
984
   return( %pos );
985
}
986
987
988
//--------------------------------------------------------------------------------
989
//a lil function to mark a position with an object and a default object to use as marker
990
991
datablock StaticShapeData(markerObject)
992
{
993
   category = "Misc";
994
   shapeFile = "~/data/shapes/markers/octahedron.dts";
995
   dynamicType = $TypeMasks::StaticShapeObjectType;
996
};
997
998
function markPoint(%pos, %rot, %block, %type, %name)
999
{
1000
   if(%block $= "" && %type $= "")
1001
   {
1002
      %type = StaticShape;
1003
      %block = markerObject;
1004
   }
1005
1006
   %obj = new (%type)(%name) {
1007
      dataBlock = %block;
1008
   };
1009
   MissionCleanup.add(%obj);
1010
1011
   %obj.setTransform(%pos SPC %rot);
1012
}
1013
1014
function markPointArray(%array)
1015
{
1016
   %count = %array.count();
1017
   for(%i = 0; %i < %count; %i++)
1018
   {
1019
      markPoint(%array.getValue(%i));
1020
   }
1021
}
1022
//--------------------------------------------------------------------------------------------
1023
// String functions
1024
//--------------------------------------------------------------------------------------------
1025
1026
// Returns true if a string passed to it consists of nothing but digits and/or decimals.
1027
// Passes false for strings with more than one decimal, or with a +
1028
// or - as anything but the first character (+ or - are only allowed as the first character in the string)
1029
function isCleanNumber(%string)
1030
{
1031
   %dot = 0;
1032
   for(%i = 0; (%char = getSubStr(%string, %i, 1)) !$= ""; %i++)
1033
   {
1034
      switch$(%char)
1035
      {
1036
         case "0" or "1" or "2" or "3" or "4" or "5" or "6" or "7" or "8" or "9":
1037
            continue;
1038
1039
         case ".":
1040
            if(%dot > 1)
1041
               return false;
1042
1043
            %dot++;
1044
            continue;
1045
1046
         case "-":
1047
            if(%i) // only valid as first character
1048
               return false;
1049
1050
            continue;
1051
1052
         case "+":
1053
            if(%i) // only valid as first character
1054
               return false;
1055
1056
            continue;
1057
1058
         default:
1059
            return false;
1060
        }
1061
    }
1062
    // %text passed the test
1063
    return true;
1064
}
1065
1066
//this function takes a pathed filename (common/missions/blah.mis) and takes out everything excpet the name (blah)
1067
function cropToName(%filePAth)
1068
{
1069
   %name = "";
1070
  %length = strlen(%filePAth);
1071
   %dot = 0;
1072
1073
   for(%i = 0; %i < %length; %i++)
1074
   {
1075
      if(getSubStr(%filePAth, %i, 1) $= "/")
1076
         %lastDir = %i;
1077
      if(getSubStr(%filePAth, %i, 1) $= ".")
1078
         %dot = %i;
1079
   }
1080
1081
   if(%dot > 0)
1082
   {
1083
      if(%lastDir $= "")
1084
         %name = getSubStr(%filePAth, 0, %dot - 1);
1085
      else
1086
         %name = getSubStr(%filePAth, %lastDir + 1, %dot - 1);
1087
   }
1088
1089
   else
1090
      %name = getSubStr(%filePAth, %lastDir + 1, %length);
1091
1092
  return %name;
1093
1094
}
1095
1096
function cropDecimal(%num)
1097
{
1098
  %length = strlen(%num);
1099
  %dot = 0;
1100
1101
   for(%i = 0; %i < %length; %i++)
1102
   {
1103
      if(getSubStr(%num, %i, 1) $= ".")
1104
         %dot = %i;
1105
   }
1106
1107
   if(%dot > 0)
1108
     %name = getSubStr(%num, 0, %dot);
1109
   else
1110
      %name = %num;
1111
1112
  return %name;
1113
}
1114
1115
function messageTest()
1116
{
1117
   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');
1118
   echo("\c0test \c1test \c2test \c3test \c4test \c5test \c6test \c7test \c8test \c9test");
1119
}
1120
1121
//--------------------------------------------------------------------------------------------
1122
// Taken from Harold "LabRat" Brown's .plan
1123
// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=10202
1124
function dec2hex(%val)
1125
{
1126
   // Converts a decimal number into a 2 digit HEX number
1127
   %digits ="0123456789ABCDEF"; //HEX digit table
1128
	
1129
   // To get the first number we divide by 16 and then round down, using 
1130
   // that number as a lookup into our HEX table.
1131
   %firstDigit = getSubStr(%digits,mFloor(%val/16),1);
1132
	
1133
   // To get the second number we do a MOD 16 and using that number as a
1134
   // lookup into our HEX table.
1135
   %secDigit = getSubStr(%digits,%val % 16,1);
1136
	
1137
   // return our two digit HEX number
1138
   return %firstDigit @ %secDigit;
1139
}
1140
1141
function chrValue(%chr)
1142
{
1143
   // So we don't have to do any C++ changes we approximate the function
1144
   // to return ASCII Values for a character.  This ignores the first 31
1145
   // characters and the last 128.
1146
	
1147
   // Setup our Character Table.  Starting with ASCII character 32 (SPACE)
1148
   %charTable = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~\t\n\r";
1149
	
1150
   //Find the position in the string for the Character we are looking for the value of
1151
   %value = strpos(%charTable,%chr);
1152
1153
   // Add 32 to the value to get the true ASCII value
1154
   %value = %value + 32;
1155
	
1156
   //HACK:  Encode TAB, New Line and Carriage Return
1157
   if (%value >= 127)
1158
   {
1159
      if(%value == 127)
1160
         %value = 9;
1161
      if(%value == 128)
1162
         %value = 10;
1163
      if(%value == 129)
1164
         %value = 13;
1165
   }
1166
   //return the value of the character
1167
   return %value;
1168
}
1169
1170
function URLEncode(%rawString)
1171
{
1172
   // Encode strings to be HTTP safe for URL use
1173
1174
   // Table of characters that are valid in an HTTP URL
1175
   %validChars = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz:/.?=_-$(){}~&";
1176
1177
   // If the string we are encoding has text... start encoding
1178
   if (strlen(%rawString) > 0)
1179
   {
1180
      // Loop through each character in the string
1181
      for(%i=0;%i<strlen(%rawString);%i++)
1182
      {
1183
         // Grab the character at our current index location
1184
         %chrTemp = getSubStr(%rawString,%i,1);
1185
1186
         //  If the character is not valid for an HTTP URL... Encode it
1187
         if (strstr(%validChars,%chrTemp) == -1)
1188
         {
1189
            //Get the HEX value for the character
1190
            %chrTemp = dec2hex(chrValue(%chrTemp));
1191
1192
            // Is it a space?  Change it to a "+" symbol
1193
            if (%chrTemp $= "20")
1194
            {
1195
               %chrTemp = "+";
1196
            }
1197
            else
1198
            {
1199
               // It's not a space, prepend the HEX value with a %
1200
               %chrTemp = "%" @ %chrTemp;
1201
            }
1202
         }
1203
         // Build our encoded string
1204
         %encodeString = %encodeString @ %chrTemp;
1205
      }
1206
   }
1207
   // Return the encoded string value
1208
   return %encodeString;
1209
}
1210
1211
//--------------------------------------------------------------------------------------------
1212
// Zod: A default raycast function
1213
function ShapeBase::doRaycast(%this, %range, %mask)
1214
{
1215
   // get the eye vector and eye transform of the player
1216
   %eyeVec   = %this.getEyeVector();
1217
   %eyeTrans = %this.getEyeTransform();
1218
1219
   // extract the position of the player's camera from the eye transform (first 3 words)
1220
   %eyePos = posFromTransform(%eyeTrans);
1221
1222
   // normalize the eye vector
1223
   %nEyeVec = VectorNormalize(%eyeVec);
1224
1225
   // scale (lengthen) the normalized eye vector according to the search range
1226
   %scEyeVec = VectorScale(%nEyeVec, %range);
1227
1228
   // add the scaled & normalized eye vector to the position of the camera
1229
   %eyeEnd = VectorAdd(%eyePos, %scEyeVec);
1230
1231
   // see if anything gets hit
1232
   %searchResult = containerRayCast(%eyePos, %eyeEnd, %mask, %this);
1233
1234
   return %searchResult;
1235
}