1 /* KJL 12:42:43 29/12/98 - this is effectively Dynamics V4.0. If you think this code looks bad,
2 you should have seen the previous versions. */
3 
4 #include "3dc.h"
5 #include "module.h"
6 #include "inline.h"
7 #include "stratdef.h"
8 #include "gamedef.h"
9 #include "dynblock.h"
10 #include "dynamics.h"
11 
12 #include "bh_types.h"
13 #include "comp_shp.h"
14 #include "avpview.h"
15 #include "pvisible.h"
16 #include "extents.h"
17 
18 #include "bh_marin.h"
19 #include "bh_pred.h"
20 #include "bh_alien.h"
21 #include "showcmds.h"
22 #include "pldghost.h"
23 #include "weapons.h"
24 
25 #include "bh_track.h"
26 #include "bh_fan.h"
27 #include "detaillevels.h"
28 #include "dxlog.h"
29 #include "avp_userprofile.h"
30 #include "pfarlocs.h"
31 #include "particle.h"
32 
33 #define UseLocalAssert Yes
34 #include "ourasert.h"
35 
36 #define TELEPORT_IF_OUTSIDE_ENV 1
37 #define MINIMUM_BOUNDINGBOX_EXTENT 25
38 
39 
40 #define FLOOR_THRESHOLD 30000
41 #define NEARLYFLATFLOOR_THRESHOLD 60000
42 
43 #if 0
44 	extern int GlobalFrameCounter;
45 	#define LogInfo LOGDXFMT
46 #else
47 	#define LogInfo(args) (void)0
48 #endif
49 
50 extern MORPHDISPLAY MorphDisplay;
51 extern VECTORCH MorphedPts[];
52 extern VECTORCH *ShapePointsPtr;
53 extern int *ShapeNormalsPtr;
54 extern int *Shape2NormalsPtr;
55 extern char ShapeIsMorphed;
56 extern int **ItemArrayPtr;
57 extern POLYHEADER *PolyheaderPtr;
58 extern DAMAGE_PROFILE FlechetteDamage;
59 extern DAMAGE_PROFILE FallingDamage;
60 extern DAMAGE_PROFILE PredPistol_FlechetteDamage;
61 
62 #define AccessNextPolygon()\
63 {\
64 	int *itemPtr = *(ItemArrayPtr++);\
65 	PolyheaderPtr = (POLYHEADER *) itemPtr;\
66 }
67 
68 #define GetPolygonVertices(polyPtr)\
69 {\
70 	int *vertexNumberPtr = &PolyheaderPtr->Poly1stPt;\
71 \
72   	(polyPtr)->PolyPoint[0] = *(ShapePointsPtr + *vertexNumberPtr++);\
73     (polyPtr)->PolyPoint[1] = *(ShapePointsPtr + *vertexNumberPtr++);\
74     (polyPtr)->PolyPoint[2] = *(ShapePointsPtr + *vertexNumberPtr++);\
75     \
76 	if (*vertexNumberPtr != Term)\
77 	{\
78 	    (polyPtr)->PolyPoint[3] = *(ShapePointsPtr + *vertexNumberPtr);\
79 	   	(polyPtr)->NumberOfVertices=4; \
80 	}\
81 	else\
82 	{\
83 	   	(polyPtr)->NumberOfVertices=3; \
84 	}\
85 }
86 #define GetPolygonNormal(polyPtr)\
87 {	  \
88 	if (ShapeIsMorphed)\
89 	{\
90 		VECTORCH n1Ptr = *(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);\
91 		VECTORCH n2Ptr = *(VECTORCH*)(Shape2NormalsPtr + PolyheaderPtr->PolyNormalIndex);\
92         \
93 		if( ((n1Ptr.vx == n2Ptr.vx)\
94 		  && (n1Ptr.vy == n2Ptr.vy)\
95 		  && (n1Ptr.vz == n2Ptr.vz))\
96 		  || (MorphDisplay.md_lerp == 0) )\
97 		{\
98 			(polyPtr)->PolyNormal = n1Ptr;\
99 		}\
100 		else if(MorphDisplay.md_lerp == 0xffff)\
101 		{\
102 			(polyPtr)->PolyNormal = n2Ptr;\
103 		}\
104 		else\
105 		{\
106 			VECTORCH *pointPtr[3];\
107  			int *vertexNumPtr = &PolyheaderPtr->Poly1stPt;\
108 \
109 			pointPtr[0] = (ShapePointsPtr + *vertexNumPtr++);\
110 			pointPtr[1] = (ShapePointsPtr + *vertexNumPtr++);\
111 			pointPtr[2] = (ShapePointsPtr + *vertexNumPtr);\
112 \
113 			MakeNormal\
114 			(\
115 				pointPtr[0],\
116 				pointPtr[1],\
117 				pointPtr[2],\
118 				&(polyPtr)->PolyNormal\
119 			);\
120 		}\
121 	}\
122     else /* not morphed */\
123     {\
124      	(polyPtr)->PolyNormal = *(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);\
125     }\
126 }
127 #define PolygonFlag (PolyheaderPtr->PolyFlags)
128 
129 /*KJL****************************************************************************************
130 *                                    P R O T O T Y P E S	                                *
131 ****************************************************************************************KJL*/
132 extern void ObjectDynamics(void);
133 
134 static void InitialiseDynamicObjectsList(void);
135 static void UpdateDisplayBlockData(STRATEGYBLOCK *sbPtr);
136 
137 static void ApplyGravity(DYNAMICSBLOCK *dynPtr);
138 static void AlignObjectToGravityDirection(DYNAMICSBLOCK *dynPtr);
139 static void AlignObjectToStandardGravityDirection(DYNAMICSBLOCK *dynPtr);
140 static void VectorHomingForSurfaceAlign(VECTORCH *currentPtr, VECTORCH *targetPtr, VECTORCH *perpendicularPtr);
141 
142 extern void DynamicallyRotateObject(DYNAMICSBLOCK *dynPtr);
143 
144 static void FindLandscapePolygonsInObjectsPath(STRATEGYBLOCK *sbPtr);
145 static void FindObjectsToRelocateAgainst(STRATEGYBLOCK *sbPtr);
146 static void FindObjectPolygonsInObjectsPath(STRATEGYBLOCK *sbPtr);
147 
148 static void MakeDynamicBoundingBoxForObject(STRATEGYBLOCK *sbPtr, VECTORCH *worldOffsetPtr);
149 static void TestShapeWithDynamicBoundingBox(DISPLAYBLOCK *objectPtr, DYNAMICSBLOCK *mainDynPtr);
150 static void TestObjectWithStaticBoundingBox(DISPLAYBLOCK *objectPtr);
151 static void TestShapeWithParticlesDynamicBoundingBox(DISPLAYBLOCK *objectPtr);
152 
153 
154 static void CreateSphereBBForObject(const STRATEGYBLOCK *sbPtr);
155 static signed int DistanceMovedBeforeSphereHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
156 static int SphereProjectOntoPoly(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, VECTORCH *projectedPosition);
157 static void MakeStaticBoundingBoxForSphere(STRATEGYBLOCK *sbPtr);
158 static int RelocateSphere(STRATEGYBLOCK *sbPtr);
159 
160 
161 static void CreateNRBBForObject(const STRATEGYBLOCK *sbPtr);
162 static signed int DistanceMovedBeforeNRBBHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
163 static int NRBBProjectsOntoPolygon(DYNAMICSBLOCK *dynPtr, int vertexToPlaneDist[], struct ColPolyTag *polyPtr, VECTORCH *projectionDirPtr);
164 static void MakeStaticBoundingBoxForNRBB(STRATEGYBLOCK *sbPtr);
165 static int RelocateNRBB(STRATEGYBLOCK *sbPtr);
166 
167 static void FindLandscapePolygonsInObjectsVicinity(STRATEGYBLOCK *sbPtr);
168 #if 0
169 static signed int DistanceMovedBeforeNRBBHitsNegYPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
170 static signed int DistanceMovedBeforeNRBBHitsPosYPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
171 static signed int DistanceMovedBeforeNRBBHitsNegXPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
172 static signed int DistanceMovedBeforeNRBBHitsPosXPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
173 static signed int DistanceMovedBeforeNRBBHitsNegZPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
174 static signed int DistanceMovedBeforeNRBBHitsPosZPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
175 static void TestForValidMovement(STRATEGYBLOCK *sbPtr);
176 #endif
177 static int MoveObject(STRATEGYBLOCK *sbPtr);
178 static void TestForValidPlayerStandUp(STRATEGYBLOCK *sbPtr);
179 static int SteppingUpIsValid(STRATEGYBLOCK *sbPtr);
180 static void TestShapeWithStaticBoundingBox(DISPLAYBLOCK *objectPtr);
181 static int IsPolygonWithinDynamicBoundingBox(const struct ColPolyTag *polyPtr);
182 static int IsPolygonWithinStaticBoundingBox(const struct ColPolyTag *polyPtr);
183 static int WhichNRBBVertex(DYNAMICSBLOCK *dynPtr, VECTORCH *normalPtr);
184 static int DoesPolygonIntersectNRBB(struct ColPolyTag *polyPtr,VECTORCH *objectVertices);
185 
186 
187 static signed int (*DistanceMovedBeforeObjectHitsPolygon)(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove);
188 static void (*MakeStaticBoundingBoxForObject)(STRATEGYBLOCK *sbPtr);
189 static int (*RelocationIsValid)(STRATEGYBLOCK *sbPtr);
190 
191 static void MovePlatformLift(STRATEGYBLOCK *sbPtr);
192 static void FindLandscapePolygonsInParticlesPath(PARTICLE *particlePtr, VECTORCH *displacementPtr);
193 
194 VECTORCH *GetNearestModuleTeleportPoint(MODULE* thisModulePtr, VECTORCH* positionPtr);
195 
196 /*KJL****************************************************************************************
197 * 										D E F I N E S 										*
198 ****************************************************************************************KJL*/
199 
200 #define	AddVectorToVector(v2,v1)\
201 {				  				\
202 	v1.vx += v2.vx;				\
203 	v1.vy += v2.vy;				\
204 	v1.vz += v2.vz;				\
205 }
206 #define	SubVectorFromVector(v2,v1)\
207 {				  				\
208 	v1.vx -= v2.vx;				\
209 	v1.vy -= v2.vy;				\
210 	v1.vz -= v2.vz;				\
211 }
212 
213 #define AddScaledVectorToVector(v2,s,v1)	\
214 {											\
215 	v1.vx += MUL_FIXED(v2.vx, s);			\
216 	v1.vy += MUL_FIXED(v2.vy, s);			\
217 	v1.vz += MUL_FIXED(v2.vz, s);			\
218 }
219 #define SubScaledVectorFromVector(v2,s,v1)	\
220 {											\
221 	v1.vx -= MUL_FIXED(v2.vx, s);			\
222 	v1.vy -= MUL_FIXED(v2.vy, s);			\
223  	v1.vz -= MUL_FIXED(v2.vz, s);			\
224 }
225 
226 
227 
228 /*KJL****************************************************************************************
229 *  										G L O B A L S 	            					    *
230 ****************************************************************************************KJL*/
231 extern int NumActiveStBlocks;
232 extern STRATEGYBLOCK *ActiveStBlockList[maxstblocks];
233 extern int NormalFrameTime;
234 
235 
236 #define COLLISION_GRANULARITY 10 // 40
237 #define RELOCATION_GRANULARITY 5 // 30
238 #define GRAVITY_DISPLACEMENT (COLLISION_GRANULARITY+1)
239 #define MAXIMUM_NUMBER_OF_COLLISIONPOLYS 3000
240 #define PLAYER_PICKUP_OBJECT_RADIUS 1600
241 
242 
243 static STRATEGYBLOCK *DynamicObjectsList[MAX_NO_OF_DYNAMICS_BLOCKS];
244 static int NumberOfDynamicObjects = 1;
245 
246 static int AccelDueToGravity;
247 static int DistanceToStepUp;
248 static VECTORCH DirectionOfTravel;
249 
250 static struct ColPolyTag CollisionPolysArray[MAXIMUM_NUMBER_OF_COLLISIONPOLYS];
251 static struct ColPolyTag *CollisionPolysPtr;
252 static int NumberOfCollisionPolys;
253 
254 #define MAX_NUMBER_OF_INTERFERENCE_POLYGONS 100
255 static struct ColPolyTag InterferencePolygons[MAX_NUMBER_OF_INTERFERENCE_POLYGONS];
256 static int NumberOfInterferencePolygons = 0;
257 
258 /* global storage of bounding box */
259 static int DBBMinX,DBBMaxX, DBBMinY,DBBMaxY, DBBMinZ,DBBMaxZ;
260 static int SBBMinX,SBBMaxX, SBBMinY,SBBMaxY, SBBMinZ,SBBMaxZ;
261 
262 const static int CuboidVertexList[]={0,1,5,4, 0,4,6,2, 0,2,3,1, 1,3,7,5, 4,5,7,6, 3,2,6,7};
263 int PlanarGravity=1;
264 
265 static int PlayersFallingSpeed;
266 int PlayersMaxHeightWhilstNotInContactWithGround;
267 /*KJL****************************************************************************************
268 *                                     F U N C T I O N S	                                    *
269 ****************************************************************************************KJL*/
270 
271 /* Entry point to dynamics system - this function handles the movement of all objects */
ObjectDynamics(void)272 extern void ObjectDynamics(void)
273 {
274 	int i;
275  /*	textprint("player Impulse at %d,%d,%d\n",
276 	Player->ObStrategyBlock->DynPtr->LinImpulse.vx,
277 	Player->ObStrategyBlock->DynPtr->LinImpulse.vy,
278 	Player->ObStrategyBlock->DynPtr->LinImpulse.vz);
279  */
280 //	if (TICKERTAPE_CHEATMODE)
281 //		PlayerPheromoneTrail();
282 
283 	if (FREEFALL_CHEATMODE)
284 	{
285 		PlanarGravity = 0;
286 	}
287 	else
288 	{
289 		PlanarGravity = 1;
290 	}
291 	/* clear previous frame's collision reports */
292 	InitialiseCollisionReports();
293 
294 	/* create ordered list of dynamic objects */
295 	InitialiseDynamicObjectsList();
296 
297 	{
298 		DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
299 		LogInfo
300 		((
301 			"Dynamics Logging: frame %d\nDL: player's Position %d,%d,%d\nDL: player's Displacement %d,%d,%d\nDL: NormalFrameTime %d\n",
302 			GlobalFrameCounter,
303 			dynPtr->Position.vx,dynPtr->Position.vy,dynPtr->Position.vz,
304 			dynPtr->Displacement.vx,dynPtr->Displacement.vy,dynPtr->Displacement.vz,
305 			NormalFrameTime
306 		));
307 
308 	}
309 
310 	i = NumberOfDynamicObjects;
311 	/* scan through objects */
312 	while(i--)
313 	{
314 		STRATEGYBLOCK *sbPtr = DynamicObjectsList[i];
315 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
316 
317 		GLOBALASSERT(dynPtr->Mass>0);
318 
319 		if (dynPtr->IsNetGhost || (dynPtr->IsPickupObject && !dynPtr->GravityOn))
320 		{
321 			#if 0
322 			dynPtr->Position.vx += MUL_FIXED(dynPtr->LinVelocity.vx, NormalFrameTime);
323 		    dynPtr->Position.vy += MUL_FIXED(dynPtr->LinVelocity.vy, NormalFrameTime);
324 		    dynPtr->Position.vz += MUL_FIXED(dynPtr->LinVelocity.vz, NormalFrameTime);
325 			AlignObjectToStandardGravityDirection(dynPtr);
326 			#endif
327 			UpdateDisplayBlockData(sbPtr);
328 			continue;
329 		}
330 		/* setup function pointers */
331 		switch(dynPtr->DynamicsType)
332 		{
333 			case DYN_TYPE_SPHERE_COLLISIONS:
334 			{
335 				DistanceMovedBeforeObjectHitsPolygon = DistanceMovedBeforeSphereHitsPolygon;
336 				MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForSphere;
337 				RelocationIsValid = RelocateSphere;
338 				break;
339 			}
340 			case DYN_TYPE_NRBB_COLLISIONS:
341 			{
342 				DistanceMovedBeforeObjectHitsPolygon = DistanceMovedBeforeNRBBHitsPolygon;
343 				MakeStaticBoundingBoxForObject = MakeStaticBoundingBoxForNRBB;
344 				RelocationIsValid = RelocateNRBB;
345 				break;
346 			}
347 			default:
348 			{
349 				/* oh dear, invalid collision shape */
350 				GLOBALASSERT(0);
351 				break;
352 			}
353 		}
354 		if ((sbPtr->SBdptr == Player) && dynPtr->RequestsToStandUp)
355 			TestForValidPlayerStandUp(sbPtr);
356 #if 0
357 		if (dynPtr->OnlyCollideWithObjects)
358 		{
359 			/* initialise near polygons array */
360 			CollisionPolysPtr = &CollisionPolysArray[0];
361 		    NumberOfCollisionPolys=0;
362 		}
363 		else
364 		{
365 			/* find which landscape polygons occupy the space
366 		   	through which the object wishes to move */
367 			FindLandscapePolygonsInObjectsPath(sbPtr);
368 		}
369 #endif
370 		if (dynPtr->OnlyCollideWithObjects)
371 		{
372 			/* initialise near polygons array */
373 			CollisionPolysPtr = &CollisionPolysArray[0];
374 			NumberOfCollisionPolys=0;
375 			MovePlatformLift(sbPtr);
376 		}
377 		else if (dynPtr->StopOnCollision)
378 	  	{
379 			if (dynPtr->OnlyCollideWithObjects)
380 			{
381 				/* initialise near polygons array */
382 				CollisionPolysPtr = &CollisionPolysArray[0];
383 			    NumberOfCollisionPolys=0;
384 				FindObjectPolygonsInObjectsPath(sbPtr);
385 			}
386 			else
387 			{
388 				/* find which landscape polygons occupy the space
389 			   	through which the object wishes to move */
390 				FindLandscapePolygonsInObjectsPath(sbPtr);
391 				if (!dynPtr->OnlyCollideWithEnvironment)
392 				{
393 					FindObjectPolygonsInObjectsPath(sbPtr);
394 				}
395 			}
396 			while(dynPtr->DistanceLeftToMove && !MoveObject(sbPtr));
397 		}
398 		else
399 		{
400 		  	int noOfMoves=4;
401 			int maxMoveLimit=10;
402 
403 	   	  	if (dynPtr->OnlyCollideWithObjects)
404 			{
405 				/* initialise near polygons array */
406 				CollisionPolysPtr = &CollisionPolysArray[0];
407 			    NumberOfCollisionPolys=0;
408 				FindObjectPolygonsInObjectsPath(sbPtr);
409 			}
410 			else
411 			{
412 				/* find which landscape polygons occupy the space
413 			   	through which the object wishes to move */
414 				FindLandscapePolygonsInObjectsPath(sbPtr);
415 				if (!dynPtr->OnlyCollideWithEnvironment)
416 				{
417 					FindObjectPolygonsInObjectsPath(sbPtr);
418 				}
419 			}
420 
421 			while (dynPtr->DistanceLeftToMove && noOfMoves && maxMoveLimit)
422 		 	{
423 				int hitSomethingWhileMoving;
424 
425 				if (ShowDebuggingText.Dynamics) PrintDebuggingText("Displacement:%d,%d,%d\n",
426 				dynPtr->Displacement.vx,
427 				dynPtr->Displacement.vy,
428 				dynPtr->Displacement.vz);
429 
430 				hitSomethingWhileMoving = MoveObject(sbPtr);
431 
432 				if(hitSomethingWhileMoving||DistanceToStepUp)
433 				{
434 					if (dynPtr->OnlyCollideWithObjects)
435 					{
436 						/* initialise near polygons array */
437 						CollisionPolysPtr = &CollisionPolysArray[0];
438 					    NumberOfCollisionPolys=0;
439 						FindObjectPolygonsInObjectsPath(sbPtr);
440 					}
441 					else
442 					{
443 						/* find which landscape polygons occupy the space
444 					   	through which the object wishes to move */
445 						FindLandscapePolygonsInObjectsPath(sbPtr);
446 						if (!dynPtr->OnlyCollideWithEnvironment)
447 						{
448 							FindObjectPolygonsInObjectsPath(sbPtr);
449 						}
450 					}
451 				}
452 				if(hitSomethingWhileMoving&&!DistanceToStepUp)
453 				{
454 		     		noOfMoves--;
455 				}
456 
457 				maxMoveLimit--;
458 			}
459 		}
460 
461 		/* friction */
462 		#if 0
463 		if (dynPtr->IsInContactWithFloor)
464 		{
465 			int scale = NormalFrameTime<<1;
466 			if(scale>ONE_FIXED) scale = ONE_FIXED;
467 			scale = ONE_FIXED;
468 	   		dynPtr->LinImpulse.vx -= MUL_FIXED(scale,dynPtr->LinImpulse.vx);
469 	   		dynPtr->LinImpulse.vz -= MUL_FIXED(scale,dynPtr->LinImpulse.vz);
470 		}
471 		#else
472 		if (dynPtr->IsInContactWithFloor)
473 		{
474 			int k = NormalFrameTime<<1;
475 			int dotted = DotProduct(&(dynPtr->LinImpulse),&(dynPtr->GravityDirection));
476 
477 			VECTORCH linParallel,linPerp;
478 
479 			linParallel.vx = MUL_FIXED(dotted,dynPtr->GravityDirection.vx);
480 			linParallel.vy = MUL_FIXED(dotted,dynPtr->GravityDirection.vy);
481 			linParallel.vz = MUL_FIXED(dotted,dynPtr->GravityDirection.vz);
482 
483 			linPerp.vx = dynPtr->LinImpulse.vx - linParallel.vx;
484 			linPerp.vy = dynPtr->LinImpulse.vy - linParallel.vy;
485 			linPerp.vz = dynPtr->LinImpulse.vz - linParallel.vz;
486 
487 			if (dynPtr->IsInContactWithNearlyFlatFloor)
488 			{
489 				if (Approximate3dMagnitude(&linPerp)<3000)
490 				{
491 					k*=16;
492 					if (k>ONE_FIXED) k = ONE_FIXED;
493 				}
494 			}
495 
496 	   		dynPtr->LinImpulse.vx -= MUL_FIXED(k,linPerp.vx);
497 	   		dynPtr->LinImpulse.vy -= MUL_FIXED(k,linPerp.vy);
498 	   		dynPtr->LinImpulse.vz -= MUL_FIXED(k,linPerp.vz);
499 		}
500 		#endif
501 
502 		#if 0
503 		if( (dynPtr->Position.vx != dynPtr->PrevPosition.vx)
504 		  ||(dynPtr->Position.vy != dynPtr->PrevPosition.vy)
505 		  ||(dynPtr->Position.vz != dynPtr->PrevPosition.vz))
506 		#endif
507 		{
508 // 	 		FindObjectsToRelocateAgainst(sbPtr);
509 //			TestForValidMovement(sbPtr);
510 		}
511   //		RelocatedDueToFallout(dynPtr);
512 		UpdateDisplayBlockData(sbPtr);
513 	}
514 	#if TELEPORT_IF_OUTSIDE_ENV
515 	{
516 		extern MODULE *playerPherModule;
517 		DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
518 		MODULE *newModule = (ModuleFromPosition(&(dynPtr->Position), playerPherModule));
519 
520 		if (!newModule)
521 		{
522 			/* hmm, player isn't in a module */
523 			#if 0
524 			if (playerPherModule)
525 			{
526 				dynPtr->Position.vx = playerPherModule->m_world.vx;
527 				dynPtr->Position.vy = playerPherModule->m_world.vy;
528 				dynPtr->Position.vz = playerPherModule->m_world.vz;
529 				PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
530 
531 				dynPtr->PrevPosition = dynPtr->Position;
532 				dynPtr->LinImpulse.vx = 0;
533 				dynPtr->LinImpulse.vy = 0;
534 				dynPtr->LinImpulse.vz = 0;
535 				UpdateDisplayBlockData(Player->ObStrategyBlock);
536 			}
537 			else
538 			#endif
539 			{
540 				if (playerPherModule)
541 				{
542 					VECTORCH newPosition = playerPherModule->m_aimodule->m_world;
543 					VECTORCH *offsetPtr = GetNearestModuleTeleportPoint(playerPherModule, &dynPtr->Position);
544 					if (offsetPtr)
545 					{
546 						newPosition.vx += offsetPtr->vx;
547 						newPosition.vy += offsetPtr->vy;
548 						newPosition.vz += offsetPtr->vz;
549 					}
550 
551 					dynPtr->Position = newPosition;
552 					dynPtr->PrevPosition = newPosition;
553 				}
554 				PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
555 				dynPtr->LinImpulse.vx = 0;
556 				dynPtr->LinImpulse.vy = 0;
557 				dynPtr->LinImpulse.vz = 0;
558 				UpdateDisplayBlockData(Player->ObStrategyBlock);
559 	   			//NewOnScreenMessage("Relocated Player");
560 			}
561 
562 		}
563 	}
564 	#endif
565 	/* KJL 18:50:17 10/11/98 - Falling Damage */
566 	if (AvP.PlayerType==I_Marine)
567 	{
568 		DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
569 		if(dynPtr->IsInContactWithFloor)
570 		{
571 			#if 0
572 			int damage = (PlayersFallingSpeed-15000)*160;
573 			if (damage>0)
574 			{
575 				CauseDamageToObject(Player->ObStrategyBlock,&FallingDamage,damage,NULL);
576 
577 			}
578 			//falling damage may be turned off in network games
579 			BOOL fallingDamageDisabled = (!netGameData.fallingDamage && AvP.Network!=I_No_Network);
580 			int damage = ((dynPtr->Position.vy - PlayersMaxHeightWhilstNotInContactWithGround - 4000))*256
581 			;
582 			if (damage>0 && !fallingDamageDisabled)
583 			{
584 				CauseDamageToObject(Player->ObStrategyBlock,&FallingDamage,damage,NULL);
585 			}
586 			/* CDF 8/4/99 - end of jump sound... */
587 			{
588 				int distanceFallen = (dynPtr->Position.vy - PlayersMaxHeightWhilstNotInContactWithGround);
589 
590 				if ((distanceFallen>500)&&(distanceFallen<4000 || fallingDamageDisabled)) {
591 					/* Make a sound. */
592 	   				Sound_Play(SID_MARINE_SMALLLANDING,"h");
593 					if(AvP.Network!=I_No_Network) netGameData.landingNoise=1;
594 				}
595 			}
596 			#endif
597 			BOOL fallingDamageDisabled = (!netGameData.fallingDamage && AvP.Network!=I_No_Network);
598 			int damage = (PlayersFallingSpeed-15000)*256;
599 			int distanceFallen = (dynPtr->Position.vy - PlayersMaxHeightWhilstNotInContactWithGround);
600 
601 			if (distanceFallen>5000 && damage>ONE_FIXED && !fallingDamageDisabled)
602 			{
603 				CauseDamageToObject(Player->ObStrategyBlock,&FallingDamage,damage,NULL);
604 			}
605 			else if (distanceFallen>1000)
606 			{
607 	   			Sound_Play(SID_MARINE_SMALLLANDING,"h");
608 				if(AvP.Network!=I_No_Network) netGameData.landingNoise=1;
609 			}
610 
611 
612 
613 			PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
614 		}
615 		else
616 		{
617 			if(dynPtr->LinImpulse.vy < 0)
618 			{
619 				PlayersMaxHeightWhilstNotInContactWithGround = 1000000;
620 			}
621 			else if(PlayersMaxHeightWhilstNotInContactWithGround>dynPtr->Position.vy)
622 			{
623 				PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
624 			}
625 		}
626 	} else if (AvP.PlayerType==I_Predator) {
627 		DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
628 
629 		if(dynPtr->IsInContactWithFloor)
630 		{
631 			/* CDF 8/4/99 - end of jump sound... */
632 			{
633 				int distanceFallen = (dynPtr->Position.vy - PlayersMaxHeightWhilstNotInContactWithGround);
634 
635 				if (distanceFallen>1000) {
636 					/* Make a sound. */
637 	   				Sound_Play(SID_PRED_SMALLLANDING,"h");
638 					if(AvP.Network!=I_No_Network) netGameData.landingNoise=1;
639 				}
640 			}
641 			PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
642 		}
643 		else
644 		{
645 			if(dynPtr->LinImpulse.vy < 0)
646 			{
647 				PlayersMaxHeightWhilstNotInContactWithGround = 1000000;
648 			}
649 			else if(PlayersMaxHeightWhilstNotInContactWithGround>dynPtr->Position.vy)
650 			{
651 				PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
652 			}
653 		}
654 	}
655 	/* Check for object pickup */
656 	{
657 		int i = NumberOfDynamicObjects;
658 		DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
659 
660 	    while(i--)
661 		{
662 			STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i];
663 //		  	if((obstaclePtr->I_SBtype == I_BehaviourHierarchicalFragment)||(obstaclePtr->DynPtr->IsPickupObject))
664 		  	if(obstaclePtr->DynPtr->IsPickupObject)
665 			{
666 				VECTORCH disp;
667 				disp.vx = dynPtr->Position.vx-obstaclePtr->DynPtr->Position.vx;
668 				disp.vy = dynPtr->Position.vy-obstaclePtr->DynPtr->Position.vy;
669 				disp.vz = dynPtr->Position.vz-obstaclePtr->DynPtr->Position.vz;
670 				if (Approximate3dMagnitude(&disp)<PLAYER_PICKUP_OBJECT_RADIUS)
671 				{
672 					/* create a report about the collision */
673 					COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
674 					if (reportPtr)
675 					{
676 						reportPtr->ObstacleSBPtr = obstaclePtr;
677 						reportPtr->ObstacleNormal.vx = -dynPtr->GravityDirection.vx;
678 						reportPtr->ObstacleNormal.vy = -dynPtr->GravityDirection.vy;
679 						reportPtr->ObstacleNormal.vz = -dynPtr->GravityDirection.vz;
680 					}
681 				}
682 			}
683 		}
684 	}
685 	#if 0
686 	{
687 		COLLISIONREPORT *reportPtr = Player->ObStrategyBlock->DynPtr->CollisionReportPtr;
688 
689 		if (ShowDebuggingText.Dynamics) PrintDebuggingText("Player Impulse:%d,%d,%d\n",
690 		Player->ObStrategyBlock->DynPtr->LinImpulse.vx,
691 		Player->ObStrategyBlock->DynPtr->LinImpulse.vy,
692 		Player->ObStrategyBlock->DynPtr->LinImpulse.vz);
693 
694 		if (ShowDebuggingText.Dynamics) PrintDebuggingText("Player Position:%d,%d,%d\n",
695 		Player->ObStrategyBlock->DynPtr->Position.vx,
696 		Player->ObStrategyBlock->DynPtr->Position.vy,
697 		Player->ObStrategyBlock->DynPtr->Position.vz);
698 
699 		if (ShowDebuggingText.Dynamics) PrintDebuggingText("InContactWithFloor %d\n",Player->ObStrategyBlock->DynPtr->IsInContactWithFloor);
700 		if (ShowDebuggingText.Dynamics) PrintDebuggingText("Player Gravity Direction:%d,%d,%d\n",
701 			Player->ObStrategyBlock->DynPtr->GravityDirection.vx,
702 			Player->ObStrategyBlock->DynPtr->GravityDirection.vy,
703 			Player->ObStrategyBlock->DynPtr->GravityDirection.vz);
704 
705 		while (reportPtr) /* while there is a valid report */
706 		{
707 			if (ShowDebuggingText.Dynamics) PrintDebuggingText("Col Normal %d %d %d\n",reportPtr->ObstacleNormal.vx,reportPtr->ObstacleNormal.vy,reportPtr->ObstacleNormal.vz);
708 			if (ShowDebuggingText.Dynamics) PrintDebuggingText("strategy ptr %p\n",reportPtr->ObstacleSBPtr);
709 
710 			/* skip to next report */
711 			reportPtr = reportPtr->NextCollisionReportPtr;
712 		}
713 		PrintDebuggingText("���� ���\n");
714 		if(!Player->ObStrategyBlock->DynPtr->IsInContactWithFloor)
715 			NewOnScreenMessage("���� word ��� word ���� word �� word\n");
716 	}
717 	#endif
718 	//NewTrailPoint(Player->ObStrategyBlock->DynPtr);
719 }
720 
InitialiseDynamicObjectsList(void)721 static void InitialiseDynamicObjectsList(void)
722 {
723 	STRATEGYBLOCK *unsortedDynamicObjectsList[MAX_NO_OF_DYNAMICS_BLOCKS];
724 	signed int valueOnWhichToSort[MAX_NO_OF_DYNAMICS_BLOCKS];
725 	AccelDueToGravity = MUL_FIXED(GRAVITY_STRENGTH,NormalFrameTime);
726 
727 	if (UNDERWATER_CHEATMODE)
728 	{
729 		AccelDueToGravity/=2;
730 	}
731 
732 	/* scan through list of strategy blocks looking for ones
733 	   with dynamics blocks and collisions on  */
734 	{
735 		int i = NumActiveStBlocks;
736 		NumberOfDynamicObjects = 0;
737 		while(i)
738 		{
739 			STRATEGYBLOCK *sbPtr = ActiveStBlockList[--i];
740 			DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
741 			DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
742 
743 			if (dynPtr && dispPtr)
744 			{
745 				/* skip static objects */
746 				if(dynPtr->IsStatic)
747 				{
748 					UpdateDisplayBlockData(sbPtr);
749 // 		 			CreateNRBBForObject(sbPtr);
750 				}
751 				/* should object simply move? */
752   				else if (dynPtr->DynamicsType == DYN_TYPE_NO_COLLISIONS)
753 				{
754 					/* Apply gravity */
755 		   			ApplyGravity(dynPtr);
756 
757 					dynPtr->Position.vx +=
758 						MUL_FIXED(dynPtr->LinVelocity.vx+dynPtr->LinImpulse.vx, NormalFrameTime);
759 				    dynPtr->Position.vy +=
760 				    	MUL_FIXED(dynPtr->LinVelocity.vy+dynPtr->LinImpulse.vy, NormalFrameTime);
761 				    dynPtr->Position.vz +=
762      			    	MUL_FIXED(dynPtr->LinVelocity.vz+dynPtr->LinImpulse.vz, NormalFrameTime);
763 					UpdateDisplayBlockData(sbPtr);
764 				}
765 				/* is it just static? */
766 				else /* have to consider it properly */
767 				{
768 					/* Apply gravity */
769 		   	  		ApplyGravity(dynPtr);
770 					AddEffectsOfForceGenerators(&dynPtr->Position,&dynPtr->LinImpulse,dynPtr->Mass);
771 					/* create a bb that surrounds the object */
772 		 //			CreateExtentCuboidForObject(sbPtr);
773 		 			switch(dynPtr->DynamicsType)
774 					{
775 						case DYN_TYPE_SPHERE_COLLISIONS:
776 						{
777 				 			dynPtr->CollisionRadius = 500;
778 
779 				 			CreateSphereBBForObject(sbPtr);
780 							break;
781 						}
782 						case DYN_TYPE_NRBB_COLLISIONS:
783 						{
784 						#if 0
785 							textprint
786 							(
787 								"%d %d, %d %d, %d %d\n"
788 								,sbPtr->SBdptr->ObMaxX,sbPtr->SBdptr->ObMinX
789 								,sbPtr->SBdptr->ObMaxY,sbPtr->SBdptr->ObMinY
790 								,sbPtr->SBdptr->ObMaxZ,sbPtr->SBdptr->ObMinZ
791 							);
792 						#endif
793 				 			CreateNRBBForObject(sbPtr);
794 							break;
795 						}
796 						default:
797 						{
798 							/* oh dear, invalid collision shape */
799 							GLOBALASSERT(0);
800 							break;
801 						}
802 					}
803 
804 					if (!dynPtr->IsNetGhost)
805 					{
806 						/* set previous position datum */
807 						dynPtr->PrevPosition = dynPtr->Position;
808 						//dynPtr->PrevOrientMat = dynPtr->OrientMat;
809 
810 						/* reset floor contact flag */
811 						dynPtr->IsInContactWithFloor = 0;
812 						dynPtr->IsInContactWithNearlyFlatFloor = 0;
813 
814 						/* calculate object's movement vector */
815 						if (!dynPtr->UseDisplacement)
816 						{
817 							dynPtr->Displacement.vx = 0;
818 							dynPtr->Displacement.vy = 0;
819 							dynPtr->Displacement.vz = 0;
820 						}
821 
822 
823 						if (dynPtr->OnlyCollideWithObjects)
824 						{
825 							dynPtr->Displacement.vx += MUL_FIXED(dynPtr->LinVelocity.vx, NormalFrameTime);
826 						    dynPtr->Displacement.vy += MUL_FIXED(dynPtr->LinVelocity.vy, NormalFrameTime);
827 						    dynPtr->Displacement.vz += MUL_FIXED(dynPtr->LinVelocity.vz, NormalFrameTime);
828 						}
829 						else
830 						{
831 							dynPtr->Displacement.vx += MUL_FIXED(dynPtr->LinVelocity.vx+dynPtr->LinImpulse.vx, NormalFrameTime);
832 						    dynPtr->Displacement.vy += MUL_FIXED(dynPtr->LinVelocity.vy+dynPtr->LinImpulse.vy, NormalFrameTime);
833 						    dynPtr->Displacement.vz += MUL_FIXED(dynPtr->LinVelocity.vz+dynPtr->LinImpulse.vz, NormalFrameTime);
834 
835 							/* If moving in direction of gravity, add a little bit to make sure you will make contact
836 							with the ground if your close */
837 							if (dynPtr->GravityOn)
838 							{
839 								if (dynPtr->UseStandardGravity&&PlanarGravity)	/* ie. in direction of +ve Y-axis */
840 								{
841 									if (dynPtr->Displacement.vy > 0)
842 										dynPtr->Displacement.vy += GRAVITY_DISPLACEMENT;
843 								}
844 								else
845 								{
846 									if (DotProduct(&(dynPtr->Displacement),&(dynPtr->GravityDirection)) > 0)
847 										dynPtr->Displacement.vx += MUL_FIXED(dynPtr->GravityDirection.vx, GRAVITY_DISPLACEMENT);
848 									    dynPtr->Displacement.vy += MUL_FIXED(dynPtr->GravityDirection.vy, GRAVITY_DISPLACEMENT);
849 									    dynPtr->Displacement.vz += MUL_FIXED(dynPtr->GravityDirection.vz, GRAVITY_DISPLACEMENT);
850 								}
851 							}
852 
853 							/* KJL 12:00:29 25/11/98 - resolve against last frames normals */
854 							#if 0
855 							{
856 								COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
857 								while (reportPtr)
858 								{
859 									int magOfPerpVel;
860 //									if (! ((reportPtr->ObstacleNormal.vx < 100 && reportPtr->ObstacleNormal.vx > -100)
861 //   										 &&(reportPtr->ObstacleNormal.vz < 100 && reportPtr->ObstacleNormal.vz > -100) ))
862 									if(reportPtr->ObstaclePoint.vx == 0x7fffffff &&
863 									   reportPtr->ObstaclePoint.vy == 0x7fffffff &&
864 									   reportPtr->ObstaclePoint.vz == 0x7fffffff)
865 									{
866 
867 //										reportPtr->ObstacleNormal.vy = 0;
868 //										Normalise(&reportPtr->ObstacleNormal);
869 										magOfPerpVel = MUL_FIXED(66000,DotProduct(&reportPtr->ObstacleNormal,&(dynPtr->Displacement)));
870 
871 	//									SubScaledVectorFromVector(reportPtr->ObstacleNormal, magOfPerpVel, (dynPtr->Displacement));
872 										dynPtr->Displacement.vx -= MUL_FIXED(reportPtr->ObstacleNormal.vx,magOfPerpVel);
873 										dynPtr->Displacement.vy -= MUL_FIXED(reportPtr->ObstacleNormal.vy,magOfPerpVel);
874 										dynPtr->Displacement.vz -= MUL_FIXED(reportPtr->ObstacleNormal.vz,magOfPerpVel);
875 									}
876 									reportPtr = reportPtr->NextCollisionReportPtr;
877 								}
878 							}
879 							#endif
880 
881 						}
882 
883 						dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);
884 
885 						if (dynPtr->DistanceLeftToMove>ONE_FIXED/8)
886 						{
887 							dynPtr->DistanceLeftToMove = ONE_FIXED/8;
888 							Normalise(&dynPtr->Displacement);
889 							dynPtr->Displacement.vx /= 8;
890 							dynPtr->Displacement.vy /= 8;
891 							dynPtr->Displacement.vz /= 8;
892 						}
893 					}
894 
895 					if(dynPtr->OnlyCollideWithObjects || dynPtr->IsNetGhost)
896 					{
897 						valueOnWhichToSort[NumberOfDynamicObjects] = 0x7fffffff;
898 					}
899 					else
900 					{
901 						valueOnWhichToSort[NumberOfDynamicObjects] = dynPtr->DistanceLeftToMove;
902 					}
903 
904 					unsortedDynamicObjectsList[NumberOfDynamicObjects] = sbPtr;
905 					NumberOfDynamicObjects++;
906 
907 					if (dispPtr == Player)
908 					{
909 						PlayersFallingSpeed = (dynPtr->LinVelocity.vy+dynPtr->LinImpulse.vy);
910 					}
911 				}
912 
913 				/* wipe previous collision records */
914 				dynPtr->CollisionReportPtr =0;
915 			}
916 		}
917 	}
918 	/* possibly a good idea to sort objects so that the fastest is moved first */
919 	{
920 		/* extremely simple (and inefficient) selection sort */
921 		int outer = NumberOfDynamicObjects;
922 		while(outer > 0)
923 		{
924 			int inner = NumberOfDynamicObjects;
925 			int highestValueFound = -1;
926 			int indexOfFastestObject =0;
927 			while(inner)
928 			{
929 				if (valueOnWhichToSort[--inner]>highestValueFound)
930 				{
931 					highestValueFound = valueOnWhichToSort[inner];
932 					indexOfFastestObject = inner;
933 				}
934 			}
935 
936 			DynamicObjectsList[--outer] = unsortedDynamicObjectsList[indexOfFastestObject];
937 			valueOnWhichToSort[indexOfFastestObject] = -1;
938 		}
939 	}
940 }
UpdateDisplayBlockData(STRATEGYBLOCK * sbPtr)941 static void UpdateDisplayBlockData(STRATEGYBLOCK *sbPtr)
942 {
943 	/* If the object associated with this strategyblock has a valid displayblock
944 	   then update the data which has been changed by the objects movement. */
945 	DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
946 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
947 
948 	if (dispPtr)
949 	{
950 		dispPtr->ObWorld = dynPtr->Position;
951 
952 		if (dynPtr->CollisionRadius)
953 		{
954 			int radius = dynPtr->CollisionRadius;
955 			dispPtr->ObWorld.vy -= radius;
956 			dispPtr->ObWorld.vx += MUL_FIXED(dynPtr->OrientMat.mat21,radius);
957 			dispPtr->ObWorld.vy += MUL_FIXED(dynPtr->OrientMat.mat22,radius);
958 			dispPtr->ObWorld.vz += MUL_FIXED(dynPtr->OrientMat.mat23,radius);
959 		}
960 		dispPtr->ObMat = dynPtr->OrientMat;
961 		dispPtr->ObEuler = dynPtr->OrientEuler;
962 
963 		if (TICKERTAPE_CHEATMODE)
964 		{
965 			if (sbPtr)
966 			{
967 				if (sbPtr->I_SBtype == I_BehaviourAlien)
968 					PlayerPheromoneTrail(dynPtr);
969 			}
970 		}
971 	}
972 	dynPtr->PrevOrientMat = dynPtr->OrientMat;
973 }
974 
975 
976 
977 
978 
979 
980 
981 
982 /* gravity code */
ApplyGravity(DYNAMICSBLOCK * dynPtr)983 static void ApplyGravity(DYNAMICSBLOCK *dynPtr)
984 {
985 	if (dynPtr->GravityOn)
986 	{
987 		if (dynPtr->UseStandardGravity)
988 		{
989 			if (PlanarGravity)
990 			{
991 				/* ie. in direction of +ve Y-axis */
992 	   			dynPtr->LinImpulse.vy += AccelDueToGravity;
993 
994 				/* KJL 11:47:04 03/26/97 - aliens need to be aligned */
995 				if (dynPtr->ToppleForce == TOPPLE_FORCE_ALIEN)
996 				{
997 					AlignObjectToStandardGravityDirection(dynPtr);
998 				}
999 			}
1000 			/* else if (RadialGravityModel) */
1001 			else
1002 			{
1003 				extern int CloakingPhase;
1004 				dynPtr->GravityDirection.vx = GetSin((CloakingPhase/16)&4095);
1005 				dynPtr->GravityDirection.vy = GetCos((CloakingPhase/16)&4095);
1006 				dynPtr->GravityDirection.vz = GetCos((CloakingPhase/19+400)&4095);
1007 				Normalise(&(dynPtr->GravityDirection));
1008 				AddScaledVectorToVector(dynPtr->GravityDirection,(AccelDueToGravity),dynPtr->LinImpulse);
1009 				AlignObjectToGravityDirection(dynPtr);
1010 			}
1011 		}
1012 		else
1013 		{
1014 			/* KJL 11:47:04 03/26/97 - aliens need to be aligned */
1015 			if (dynPtr->ToppleForce == TOPPLE_FORCE_ALIEN)
1016 			{
1017 				COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
1018 				VECTORCH averageNormal= {0,0,0};
1019 				int normalsFound=0;
1020 
1021 				if(dynPtr->TimeNotInContactWithFloor!=-1)
1022 				{
1023 					while (reportPtr) /* while there is a valid report */
1024 					{
1025 			//			if (reportPtr->ObstacleSBPtr == 0)
1026 						{
1027 							averageNormal.vx -= reportPtr->ObstacleNormal.vx;
1028 							averageNormal.vy -= reportPtr->ObstacleNormal.vy;
1029 							averageNormal.vz -= reportPtr->ObstacleNormal.vz;
1030 							normalsFound++;
1031 						}
1032 						/* skip to next report */
1033 						reportPtr = reportPtr->NextCollisionReportPtr;
1034 					}
1035 				}
1036 				if (normalsFound)
1037 				{
1038 		  	  	  //averageNormal.vx /= normalsFound;
1039 		  		  //averageNormal.vy /= normalsFound;
1040 		 		  //averageNormal.vz /= normalsFound;
1041 					if (averageNormal.vx==0 && averageNormal.vy==0 && averageNormal.vz==0)
1042 					{
1043 						// down boy down
1044 						averageNormal.vy = ONE_FIXED;
1045 					}
1046 					else
1047 					{
1048 						Normalise(&averageNormal);
1049 					}
1050 					dynPtr->GravityDirection = averageNormal;
1051 					dynPtr->TimeNotInContactWithFloor = TIME_BEFORE_GRAVITY_KICKS_IN;
1052 		  		}
1053 				else
1054 				{
1055 					if (dynPtr->TimeNotInContactWithFloor<=0)
1056 					{
1057 						if (PlanarGravity)
1058 						{
1059 							dynPtr->GravityDirection.vx = 0;
1060 							dynPtr->GravityDirection.vy = 65536;
1061 							dynPtr->GravityDirection.vz = 0;
1062 						}
1063 						/* else if (RadialGravityModel) */
1064 						else
1065 						{
1066 							dynPtr->GravityDirection.vx = -dynPtr->Position.vx;
1067 							dynPtr->GravityDirection.vy = -dynPtr->Position.vy;
1068 							dynPtr->GravityDirection.vz = -dynPtr->Position.vz;
1069 							Normalise(&(dynPtr->GravityDirection));
1070 						}
1071 					}
1072 					else if (dynPtr->TimeNotInContactWithFloor == TIME_BEFORE_GRAVITY_KICKS_IN)
1073 					{
1074 						if (dynPtr->LinVelocity.vx==0 && dynPtr->LinVelocity.vy==0 && dynPtr->LinVelocity.vz==0)
1075 						{
1076 //							dynPtr->GravityDirection.vx = 0;
1077 //							dynPtr->GravityDirection.vy = 65536;
1078 //							dynPtr->GravityDirection.vz = 0;
1079 						}
1080 						else
1081 						{
1082 							/* code to enable going round 270 degree corners */
1083 							#if 1
1084 							Normalise(&dynPtr->LinVelocity);
1085 							dynPtr->GravityDirection.vx -= (dynPtr->LinVelocity.vx*3)/4;
1086 							dynPtr->GravityDirection.vy -= (dynPtr->LinVelocity.vy*3)/4;
1087 							dynPtr->GravityDirection.vz -= (dynPtr->LinVelocity.vz*3)/4;
1088 							Normalise(&dynPtr->GravityDirection);
1089 							dynPtr->LinVelocity.vx = 0;
1090 							dynPtr->LinVelocity.vy = 0;
1091 							dynPtr->LinVelocity.vz = 0;
1092 							#endif
1093 						}
1094 					}
1095 					dynPtr->TimeNotInContactWithFloor-=NormalFrameTime;
1096 					if (dynPtr->TimeNotInContactWithFloor<0)
1097 					{
1098 						dynPtr->TimeNotInContactWithFloor = 0;
1099 					}
1100 
1101 				}
1102 				AlignObjectToGravityDirection(dynPtr);
1103 			}
1104 			AddScaledVectorToVector(dynPtr->GravityDirection,AccelDueToGravity,dynPtr->LinImpulse);
1105 		}
1106 	}
1107 }
AlignObjectToGravityDirection(DYNAMICSBLOCK * dynPtr)1108 static void AlignObjectToGravityDirection(DYNAMICSBLOCK *dynPtr)
1109 {
1110 	VECTORCH XVector;
1111 	VECTORCH YVector;
1112 	VECTORCH ZVector;
1113 	int staticAxis;
1114 
1115 	{
1116 		int dotx = Dot((VECTORCH*)&dynPtr->OrientMat.mat11, &dynPtr->GravityDirection);
1117 		int doty = Dot((VECTORCH*)&dynPtr->OrientMat.mat21, &dynPtr->GravityDirection);
1118 		int dotz = Dot((VECTORCH*)&dynPtr->OrientMat.mat31, &dynPtr->GravityDirection);
1119 
1120 		/* Get their absolute values */
1121 		if(dotx < 0) dotx = -dotx;
1122 		if(doty < 0) doty = -doty;
1123 		if(dotz < 0) dotz = -dotz;
1124 
1125 		if (dotx<doty)
1126 		{
1127 			if (dotx<dotz)
1128 			{
1129 				staticAxis = ix;
1130 			}
1131 			else
1132 			{
1133 				staticAxis = iz;
1134 			}
1135 		}
1136 		else
1137 		{
1138 			if (doty<dotz)
1139 			{
1140 				staticAxis = iy;
1141 			}
1142 			else
1143 			{
1144 				staticAxis = iz;
1145 			}
1146 		}
1147 	}
1148  	if (staticAxis == iz)
1149 	{
1150 		ZVector = *((VECTORCH*)&dynPtr->OrientMat.mat31);
1151 	 	YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1152 	  	VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat11));
1153 		CrossProduct(&YVector, &ZVector, &XVector);
1154 	}
1155  	else if (staticAxis == ix)
1156 	{
1157 		XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
1158 	 	YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1159 		VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
1160 		CrossProduct(&XVector, &YVector, &ZVector);
1161 	}
1162 	else if (staticAxis == iy)
1163 	{
1164 		XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
1165 	 	YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1166 		VectorHomingForSurfaceAlign(&YVector, &dynPtr->GravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
1167 		CrossProduct(&XVector, &YVector, &ZVector);
1168 		CrossProduct(&YVector, &ZVector, &XVector);
1169 	}
1170 	Normalise(&XVector);
1171 	Normalise(&YVector);
1172 	Normalise(&ZVector);
1173 
1174 	dynPtr->OrientMat.mat11 = XVector.vx;
1175    	dynPtr->OrientMat.mat12 = XVector.vy;
1176 	dynPtr->OrientMat.mat13 = XVector.vz;
1177 
1178 	dynPtr->OrientMat.mat21 = YVector.vx;
1179 	dynPtr->OrientMat.mat22 = YVector.vy;
1180 	dynPtr->OrientMat.mat23 = YVector.vz;
1181 
1182 	dynPtr->OrientMat.mat31 = ZVector.vx;
1183 	dynPtr->OrientMat.mat32 = ZVector.vy;
1184 	dynPtr->OrientMat.mat33 = ZVector.vz;
1185 
1186 	MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
1187 }
AlignObjectToStandardGravityDirection(DYNAMICSBLOCK * dynPtr)1188 static void AlignObjectToStandardGravityDirection(DYNAMICSBLOCK *dynPtr)
1189 {
1190 	VECTORCH gravityDirection = {0,65536,0};
1191 	VECTORCH XVector,YVector,ZVector;
1192 	int staticAxis;
1193 
1194 	dynPtr->GravityDirection = gravityDirection;
1195 
1196 	{
1197 		int dotx = dynPtr->OrientMat.mat12;
1198 		int doty = dynPtr->OrientMat.mat22;
1199 		int dotz = dynPtr->OrientMat.mat32;
1200 
1201 		/* Get their absolute values */
1202 		if(dotx < 0) dotx = -dotx;
1203 		if(doty < 0) doty = -doty;
1204 		if(dotz < 0) dotz = -dotz;
1205 
1206 		if (dotx<doty)
1207 		{
1208 			if (dotx<dotz)
1209 			{
1210 				staticAxis = ix;
1211 			}
1212 			else
1213 			{
1214 				staticAxis = iz;
1215 			}
1216 		}
1217 		else
1218 		{
1219 			if (doty<dotz)
1220 			{
1221 				staticAxis = iy;
1222 			}
1223 			else
1224 			{
1225 				staticAxis = iz;
1226 			}
1227 		}
1228 	}
1229  	if (staticAxis == iz)
1230 	{
1231 		ZVector = *((VECTORCH*)&dynPtr->OrientMat.mat31);
1232 	 	YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1233 	  	VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat11));
1234 		CrossProduct(&YVector, &ZVector, &XVector);
1235 	}
1236  	else if (staticAxis == ix)
1237 	{
1238 		XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
1239 	 	YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1240 		VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
1241 		CrossProduct(&XVector, &YVector, &ZVector);
1242 	}
1243 	else if (staticAxis == iy)
1244 	{
1245 		XVector = *((VECTORCH*)&dynPtr->OrientMat.mat11);
1246 	 	YVector = *((VECTORCH*)&dynPtr->OrientMat.mat21);
1247 		VectorHomingForSurfaceAlign(&YVector, &gravityDirection,((VECTORCH*)&dynPtr->OrientMat.mat31));
1248 		CrossProduct(&XVector, &YVector, &ZVector);
1249 		CrossProduct(&YVector, &ZVector, &XVector);
1250 	}
1251 	Normalise(&XVector);
1252 	Normalise(&YVector);
1253 	Normalise(&ZVector);
1254 
1255 	dynPtr->OrientMat.mat11 = XVector.vx;
1256    	dynPtr->OrientMat.mat12 = XVector.vy;
1257 	dynPtr->OrientMat.mat13 = XVector.vz;
1258 
1259 	dynPtr->OrientMat.mat21 = YVector.vx;
1260 	dynPtr->OrientMat.mat22 = YVector.vy;
1261 	dynPtr->OrientMat.mat23 = YVector.vz;
1262 
1263 	dynPtr->OrientMat.mat31 = ZVector.vx;
1264 	dynPtr->OrientMat.mat32 = ZVector.vy;
1265 	dynPtr->OrientMat.mat33 = ZVector.vz;
1266 
1267 	MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
1268 }
VectorHomingForSurfaceAlign(VECTORCH * currentPtr,VECTORCH * targetPtr,VECTORCH * perpendicularPtr)1269 static void VectorHomingForSurfaceAlign(VECTORCH *currentPtr, VECTORCH *targetPtr, VECTORCH *perpendicularPtr)
1270 {
1271 	int cos = Dot(currentPtr, targetPtr);
1272 
1273 	if (cos<=-65000)
1274 	{
1275 		int a1 = NormalFrameTime*4;
1276 		if (a1>ONE_FIXED) a1=ONE_FIXED;
1277 		else if (a1<1024) a1=1024;
1278 
1279 		currentPtr->vx = currentPtr->vx+MUL_FIXED(perpendicularPtr->vx-currentPtr->vx, a1);
1280 		currentPtr->vy = currentPtr->vy+MUL_FIXED(perpendicularPtr->vy-currentPtr->vy, a1);
1281 		currentPtr->vz = currentPtr->vz+MUL_FIXED(perpendicularPtr->vz-currentPtr->vz, a1);
1282 		Normalise(currentPtr);
1283 		return;
1284 	}
1285 	else if (cos>=65500)	/* if they're practically parallel just snap currentPtr to targetPtr */
1286 	{
1287 		currentPtr->vx = targetPtr->vx;
1288 		currentPtr->vy = targetPtr->vy;
1289 		currentPtr->vz = targetPtr->vz;
1290 		return;
1291 	}
1292 
1293 	if (cos<32768) cos = 32768;
1294 
1295 	{
1296   		int a1 = MUL_FIXED(cos*8,NormalFrameTime);
1297 //		int a1 = NormalFrameTime*4;
1298 		if (a1>ONE_FIXED) a1=ONE_FIXED;
1299 		else if (a1<1024) a1=1024;
1300 
1301 		currentPtr->vx = currentPtr->vx+MUL_FIXED(targetPtr->vx-currentPtr->vx, a1);
1302 		currentPtr->vy = currentPtr->vy+MUL_FIXED(targetPtr->vy-currentPtr->vy, a1);
1303 		currentPtr->vz = currentPtr->vz+MUL_FIXED(targetPtr->vz-currentPtr->vz, a1);
1304 		Normalise(currentPtr);
1305 	}
1306 	return;
1307 }
1308 
DynamicallyRotateObject(DYNAMICSBLOCK * dynPtr)1309 extern void DynamicallyRotateObject(DYNAMICSBLOCK *dynPtr)
1310 {
1311 	extern int NormalFrameTime;
1312 
1313 	MATRIXCH mat;
1314 	EULER euler;
1315 	euler.EulerX = MUL_FIXED(NormalFrameTime,dynPtr->AngVelocity.EulerX);
1316 	euler.EulerX &= wrap360;
1317 
1318 	euler.EulerY = MUL_FIXED(NormalFrameTime,dynPtr->AngVelocity.EulerY);
1319 	euler.EulerY &= wrap360;
1320 
1321 	euler.EulerZ = MUL_FIXED(NormalFrameTime,dynPtr->AngVelocity.EulerZ);
1322 	euler.EulerZ &= wrap360;
1323 
1324 	CreateEulerMatrix(&euler, &mat);
1325 	TransposeMatrixCH(&mat);
1326 
1327   	MatrixMultiply(&dynPtr->OrientMat,&mat,&dynPtr->OrientMat);
1328  	MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
1329 }
1330 
1331 static int InterferenceAt(int lambda, DYNAMICSBLOCK *dynPtr);
1332 
1333 /* Move an object. At this stage, we have a list of the polygons in the
1334 environment with which the object the may collide. */
MoveObject(STRATEGYBLOCK * sbPtr)1335 static int MoveObject(STRATEGYBLOCK *sbPtr)
1336 {
1337 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1338 
1339 	int lowestBoundary = 0;
1340 	int highestBoundary = ONE_FIXED;
1341 	int testValue = ONE_FIXED;
1342     int hitSomething = 0;
1343 
1344     DirectionOfTravel = dynPtr->Displacement;
1345     Normalise(&DirectionOfTravel);
1346 
1347 	{
1348 		int maxDistanceAllowed=dynPtr->ObjectVertices[0].vz-dynPtr->ObjectVertices[7].vz;
1349 		if (maxDistanceAllowed>dynPtr->ObjectVertices[0].vx-dynPtr->ObjectVertices[7].vx)
1350 			maxDistanceAllowed=dynPtr->ObjectVertices[0].vx-dynPtr->ObjectVertices[7].vx;
1351 		if (maxDistanceAllowed>dynPtr->ObjectVertices[0].vy-dynPtr->ObjectVertices[7].vy)
1352 			maxDistanceAllowed=dynPtr->ObjectVertices[0].vy-dynPtr->ObjectVertices[7].vy;
1353 
1354 		if (maxDistanceAllowed<10)
1355 		{
1356 			LOCALASSERT("Object's bounding box is too small. Suspicious."==0);
1357 		}
1358 
1359 		if (dynPtr->DistanceLeftToMove>maxDistanceAllowed)
1360 		{
1361 			testValue = DIV_FIXED(maxDistanceAllowed,dynPtr->DistanceLeftToMove);
1362 			highestBoundary = testValue;
1363 		}
1364 	}
1365 
1366 	if (InterferenceAt(testValue,dynPtr))
1367 	{
1368 		testValue /= 2;
1369 		do
1370 		{
1371 			if (InterferenceAt(testValue,dynPtr))
1372 			{
1373 				highestBoundary = testValue;
1374 				testValue = (lowestBoundary+highestBoundary)/2;
1375 			}
1376 			else
1377 			{
1378 				lowestBoundary = testValue;
1379 				testValue = (lowestBoundary+highestBoundary)/2;
1380 			}
1381 			if (MUL_FIXED(highestBoundary-lowestBoundary,dynPtr->DistanceLeftToMove)<=16)
1382 			{
1383 				InterferenceAt(highestBoundary,dynPtr);
1384 				break;
1385 			}
1386 		}
1387 		while(1);
1388 		testValue = lowestBoundary;
1389 		hitSomething = 1;
1390 	}
1391 
1392 	{
1393 		VECTORCH displacement;
1394 		displacement.vx = MUL_FIXED(dynPtr->Displacement.vx,testValue);
1395 		displacement.vy = MUL_FIXED(dynPtr->Displacement.vy,testValue);
1396 		displacement.vz = MUL_FIXED(dynPtr->Displacement.vz,testValue);
1397 
1398 		AddVectorToVector(displacement, dynPtr->Position);
1399 		SubVectorFromVector(displacement, dynPtr->Displacement);
1400 		{
1401 			VECTORCH *vertexPtr = dynPtr->ObjectVertices;
1402 			int i=8;
1403 			do
1404 			{
1405 			  	vertexPtr->vx += displacement.vx;
1406 				vertexPtr->vy += displacement.vy;
1407 				vertexPtr->vz += displacement.vz;
1408 				vertexPtr++;
1409 			}
1410 			while(--i);
1411 		}
1412 
1413     }
1414 
1415 	if (hitSomething)
1416     {
1417 		int wentUpStep = 0;
1418 		VECTORCH obstacleNormal = {0,0,0};
1419 		int n = NumberOfInterferencePolygons;
1420 		VECTORCH objectCentre = {0,0,0};
1421 		int leastSoFar = 1000000;
1422 		struct ColPolyTag *polygonPtr=0;
1423 
1424 		{
1425 			if (DirectionOfTravel.vx>0)
1426 			{
1427 				objectCentre.vx = dynPtr->ObjectVertices[0].vx-COLLISION_GRANULARITY;
1428 			}
1429 			else if (DirectionOfTravel.vx<0)
1430 			{
1431 				objectCentre.vx = dynPtr->ObjectVertices[7].vx+COLLISION_GRANULARITY;
1432 			}
1433 			else
1434 			{
1435 				objectCentre.vx = (dynPtr->ObjectVertices[0].vx+dynPtr->ObjectVertices[7].vx)/2;
1436 			}
1437 			#if 1
1438 			if (DirectionOfTravel.vy>0)
1439 			{
1440 				objectCentre.vy = dynPtr->ObjectVertices[0].vy-COLLISION_GRANULARITY;
1441 			}
1442 			else if (DirectionOfTravel.vy<0)
1443 			{
1444 				objectCentre.vy = dynPtr->ObjectVertices[7].vy+COLLISION_GRANULARITY;
1445 			}
1446 			else
1447 			#endif
1448 			{
1449 				objectCentre.vy = (dynPtr->ObjectVertices[0].vy+dynPtr->ObjectVertices[7].vy)/2;
1450 			}
1451 			if (DirectionOfTravel.vz>0)
1452 			{
1453 				objectCentre.vz = dynPtr->ObjectVertices[0].vz-COLLISION_GRANULARITY;
1454 			}
1455 			else if (DirectionOfTravel.vz<0)
1456 			{
1457 				objectCentre.vz = dynPtr->ObjectVertices[7].vz+COLLISION_GRANULARITY;
1458 			}
1459 			else
1460 			{
1461 				objectCentre.vz = (dynPtr->ObjectVertices[0].vz+dynPtr->ObjectVertices[7].vz)/2;
1462 			}
1463 
1464 		}
1465 		#if 0
1466 		PrintDebuggingText("Test point %d,%d,%d\n",objectCentre.vx,objectCentre.vy,objectCentre.vz);
1467 		#endif
1468 		while(n--)
1469 		{
1470 			#if 1
1471 			VECTORCH r;
1472 			int d;
1473 
1474    			r.vx = objectCentre.vx - InterferencePolygons[n].PolyPoint[0].vx;
1475    			r.vy = objectCentre.vy - InterferencePolygons[n].PolyPoint[0].vy;
1476    			r.vz = objectCentre.vz - InterferencePolygons[n].PolyPoint[0].vz;
1477 			d = DotProduct(&r,&InterferencePolygons[n].PolyNormal);
1478 
1479 			if (d<0) d+=1000000;
1480 			{
1481 				if (d<leastSoFar)
1482 				{
1483 					obstacleNormal = InterferencePolygons[n].PolyNormal;
1484 					leastSoFar = d;
1485 					polygonPtr = &InterferencePolygons[n];
1486 				}
1487 			}
1488 			#else
1489 			VECTORCH r;
1490 			int d;
1491 
1492 			d = DotProduct(&DirectionOfTravel,&InterferencePolygons[n].PolyNormal);
1493 
1494 			if (d<0)
1495 			{
1496 				if (d<leastSoFar)
1497 				{
1498 					obstacleNormal = InterferencePolygons[n].PolyNormal;
1499 					leastSoFar = d;
1500 					polygonPtr = &InterferencePolygons[n];
1501 				}
1502 			}
1503 			#endif
1504 
1505 		}
1506 		#if 0
1507 		if (obstacleNormal.vx==0 && obstacleNormal.vy==0 && obstacleNormal.vz==0)
1508 		{
1509 			obstacleNormal.vy = -ONE_FIXED;
1510 		}
1511 		else
1512 		{
1513 			Normalise(&obstacleNormal);
1514 		}
1515 		#endif
1516 		if(!polygonPtr)
1517 		{
1518 			dynPtr->DistanceLeftToMove = 0;
1519 			LOCALASSERT(0);
1520 			return 0;
1521 		}
1522 		else
1523 		{
1524 			#if 0
1525 			PrintDebuggingText("POLY NORMAL IS %d %d %d\n",(polygonPtr->PolyNormal).vx,(polygonPtr->PolyNormal).vy,(polygonPtr->PolyNormal).vz);
1526 			PrintDebuggingText("POLY NO OF VERTICES %d\n",(polygonPtr->NumberOfVertices));
1527 			PrintDebuggingText("POLY POINT[0] IS %d %d %d\n",(polygonPtr->PolyPoint[0]).vx,(polygonPtr->PolyPoint[0]).vy,(polygonPtr->PolyPoint[0]).vz);
1528 			PrintDebuggingText("POLY POINT[1] IS %d %d %d\n",(polygonPtr->PolyPoint[1]).vx,(polygonPtr->PolyPoint[1]).vy,(polygonPtr->PolyPoint[1]).vz);
1529 			PrintDebuggingText("POLY POINT[2] IS %d %d %d\n",(polygonPtr->PolyPoint[2]).vx,(polygonPtr->PolyPoint[2]).vy,(polygonPtr->PolyPoint[2]).vz);
1530 			#endif
1531 		}
1532 		/* test for a 'step' in front of object */
1533     	if ( (dynPtr->CanClimbStairs)
1534 		/* check to see that polygon is vertical */
1535 		  &&(polygonPtr->PolyNormal.vy>-250)
1536 		  &&(polygonPtr->PolyNormal.vy<250) )
1537 		{
1538 	        int heightOfStep,topOfStep;
1539 	        {
1540 		    	int vertexNum=polygonPtr->NumberOfVertices-1;
1541 
1542 		    	topOfStep = polygonPtr->PolyPoint[0].vy;
1543 		        do
1544 		        {
1545 					int y = polygonPtr->PolyPoint[vertexNum].vy;
1546 
1547 		        	if (y < topOfStep) topOfStep = y;
1548 		        }
1549 	            while(--vertexNum);
1550 			}
1551 
1552 	        heightOfStep = dynPtr->ObjectVertices[0].vy - topOfStep;  /* y-axis is +ve downwards, remember */
1553 	 		//textprint("found step %d\n",heightOfStep);
1554 	        if (heightOfStep>0 && heightOfStep < MAXIMUM_STEP_HEIGHT) /* we've hit a 'step' - move player upwards */
1555 	        {
1556 		   		DistanceToStepUp=heightOfStep+COLLISION_GRANULARITY;
1557 	         	wentUpStep = SteppingUpIsValid(sbPtr);
1558 				#if 0
1559 				if (wentUpStep)
1560 				{
1561 					PrintDebuggingText("Found a valid step.\n");
1562 				}
1563 				else
1564 				{
1565 					PrintDebuggingText("Found a step but couldn't go up it.\n");
1566 				}
1567 				#endif
1568 
1569 			}
1570 		}
1571 
1572 		if (!wentUpStep)
1573 		{
1574 			STRATEGYBLOCK *obstacleSBPtr = 0;
1575 
1576 			if (polygonPtr->ParentObject)
1577                 if (polygonPtr->ParentObject->ObStrategyBlock)
1578                 {
1579                     obstacleSBPtr = polygonPtr->ParentObject->ObStrategyBlock;
1580                 }
1581 
1582 			DistanceToStepUp = 0;
1583 
1584         	/* resolve player's movement vector against the collision plane */
1585 			/* awkward problem here to do with non-exact normals */
1586 			{
1587 		   //     int magOfPerpVel = DotProduct(&obstacleNormal,&(dynPtr->Displacement));
1588 		        int magOfPerpVel = MUL_FIXED(66000,DotProduct(&obstacleNormal,&(dynPtr->Displacement)));
1589 		   		SubScaledVectorFromVector(obstacleNormal, magOfPerpVel, (dynPtr->Displacement));
1590 			}
1591 
1592     		/* collision - elasticity */
1593 			{
1594 				int magOfPerpImp =	MUL_FIXED
1595 									(
1596 										DotProduct(&obstacleNormal,&dynPtr->LinImpulse),
1597 										65536 + dynPtr->Elasticity
1598 									);
1599 				SubScaledVectorFromVector(obstacleNormal, magOfPerpImp, dynPtr->LinImpulse);
1600 			}
1601 			/* momentum test */
1602 			/* OnlyCollideWithObjects flag indicates a platform lift etc. which should not be involved with momentum transfer */
1603 			if (obstacleSBPtr && (obstacleSBPtr->DynPtr))
1604 			if (!(dynPtr->OnlyCollideWithObjects
1605 				||obstacleSBPtr->DynPtr->OnlyCollideWithObjects
1606 				||obstacleSBPtr->DynPtr->IsStatic
1607 				||dynPtr->IsInanimate
1608 				||obstacleSBPtr->DynPtr->IsInanimate))
1609 			{
1610 				DYNAMICSBLOCK *obsDynPtr = obstacleSBPtr->DynPtr;
1611 				int totalMass = (obsDynPtr->Mass + dynPtr->Mass)*4;
1612 				int diffMass = (dynPtr->Mass-obsDynPtr->Mass)/2;
1613 
1614 				obsDynPtr->LinImpulse.vx +=
1615 					WideMulNarrowDiv
1616 					(
1617 						dynPtr->LinImpulse.vx + dynPtr->LinVelocity.vx,
1618 						dynPtr->Mass,
1619 						totalMass
1620 					);
1621 				obsDynPtr->LinImpulse.vy +=
1622 					WideMulNarrowDiv
1623 					(
1624 						dynPtr->LinImpulse.vy + dynPtr->LinVelocity.vy,
1625 						dynPtr->Mass,
1626 						totalMass
1627 					);
1628 				obsDynPtr->LinImpulse.vz +=
1629 					WideMulNarrowDiv
1630 					(
1631 						dynPtr->LinImpulse.vz + dynPtr->LinVelocity.vz,
1632 						dynPtr->Mass,
1633 						totalMass
1634 					);
1635 
1636 				dynPtr->LinImpulse.vx +=
1637 					WideMulNarrowDiv
1638 					(
1639 						dynPtr->LinImpulse.vx + dynPtr->LinVelocity.vx,
1640 						diffMass,
1641 						totalMass
1642 					);
1643 				dynPtr->LinImpulse.vy +=
1644 					WideMulNarrowDiv
1645 					(
1646 						dynPtr->LinImpulse.vy + dynPtr->LinVelocity.vy,
1647 						diffMass,
1648 						totalMass
1649 					);
1650 				dynPtr->LinImpulse.vz +=
1651 					WideMulNarrowDiv
1652 					(
1653 						dynPtr->LinImpulse.vz + dynPtr->LinVelocity.vz,
1654 						diffMass,
1655 						totalMass
1656 					);
1657 
1658 			}
1659 			/* see if object has hit the 'floor' */
1660 			if (dynPtr->GravityOn)
1661 			{
1662 				if (dynPtr->UseStandardGravity&&PlanarGravity)
1663 				{
1664 					if (obstacleNormal.vy < -FLOOR_THRESHOLD)
1665 					{
1666 						dynPtr->IsInContactWithFloor = 1;
1667 						if (obstacleNormal.vy < -NEARLYFLATFLOOR_THRESHOLD) dynPtr->IsInContactWithNearlyFlatFloor = 1;
1668 					}
1669 				}
1670 				else
1671 				{
1672 					int angle = DotProduct(&obstacleNormal,&dynPtr->GravityDirection);
1673 					if (angle < -FLOOR_THRESHOLD)
1674 					{
1675 						/* we've hit something that's against the direction of gravity */
1676 						dynPtr->IsInContactWithFloor = 1;
1677 						if (angle < -NEARLYFLATFLOOR_THRESHOLD) dynPtr->IsInContactWithNearlyFlatFloor = 1;
1678 					}
1679 				}
1680 			}
1681 
1682 			/* create a report about the collision */
1683 			{
1684 				{
1685 					COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
1686 					if (reportPtr)
1687 					{
1688 						reportPtr->ObstacleSBPtr = obstacleSBPtr;
1689 						reportPtr->ObstacleNormal = obstacleNormal;
1690 						reportPtr->ObstaclePoint = dynPtr->Position;
1691 					}
1692 				}
1693 				if (obstacleSBPtr&&obstacleSBPtr->DynPtr)
1694 				{
1695 					COLLISIONREPORT *reportPtr = AllocateCollisionReport(obstacleSBPtr->DynPtr);
1696 					if (reportPtr)
1697 					{
1698 						reportPtr->ObstacleSBPtr = sbPtr;
1699 						reportPtr->ObstacleNormal.vx = -obstacleNormal.vx;
1700 						reportPtr->ObstacleNormal.vy = -obstacleNormal.vy;
1701 						reportPtr->ObstacleNormal.vz = -obstacleNormal.vz;
1702 						reportPtr->ObstaclePoint = dynPtr->Position;
1703 					}
1704 				}
1705 			}
1706 		}
1707 		dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);
1708 		if (dynPtr->DistanceLeftToMove<=16)
1709 		{
1710 			dynPtr->DistanceLeftToMove = 0;
1711 		}
1712 		return 1;
1713     }
1714     else
1715     {
1716 		dynPtr->DistanceLeftToMove = Magnitude(&dynPtr->Displacement);
1717 		if (dynPtr->DistanceLeftToMove<=16)
1718 		{
1719 			dynPtr->DistanceLeftToMove = 0;
1720 		}
1721 		return 0;
1722    	}
1723 
1724 }
1725 
InterferenceAt(int lambda,DYNAMICSBLOCK * dynPtr)1726 static int InterferenceAt(int lambda, DYNAMICSBLOCK *dynPtr)
1727 {
1728     VECTORCH objectVertices[8];
1729     int polysLeft;
1730     struct ColPolyTag *polyPtr;
1731 
1732 	{
1733     	int vertexNum=8;
1734 
1735     	VECTORCH disp;
1736 		disp.vx = MUL_FIXED(dynPtr->Displacement.vx,lambda);
1737 		disp.vy = MUL_FIXED(dynPtr->Displacement.vy,lambda);
1738 		disp.vz = MUL_FIXED(dynPtr->Displacement.vz,lambda);
1739 
1740 		do
1741         {
1742 			vertexNum--;
1743 			objectVertices[vertexNum] = dynPtr->ObjectVertices[vertexNum];
1744 			objectVertices[vertexNum].vx += disp.vx;
1745 			objectVertices[vertexNum].vy += disp.vy;
1746 			objectVertices[vertexNum].vz += disp.vz;
1747 	    }
1748         while(vertexNum);
1749 	}
1750 
1751 	polysLeft = NumberOfCollisionPolys;
1752     polyPtr = CollisionPolysArray;
1753 
1754 	NumberOfInterferencePolygons = 0;
1755 
1756     while(polysLeft)
1757 	{
1758 		{
1759 			if(DotProduct(&DirectionOfTravel,&polyPtr->PolyNormal)<0)
1760 			if (DoesPolygonIntersectNRBB(polyPtr,objectVertices))
1761 			{
1762 				InterferencePolygons[NumberOfInterferencePolygons++] = *polyPtr;
1763 				if (NumberOfInterferencePolygons==MAX_NUMBER_OF_INTERFERENCE_POLYGONS) break;
1764 			}
1765 		}
1766         polyPtr++;
1767 		polysLeft--;
1768 	}
1769 	return NumberOfInterferencePolygons;
1770 }
1771 
1772 
1773 
1774 
1775 
1776 
MovePlatformLift(STRATEGYBLOCK * sbPtr)1777 static void MovePlatformLift(STRATEGYBLOCK *sbPtr)
1778 {
1779 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1780     int polysLeft;
1781     struct ColPolyTag *nearPolysPtr;
1782     int distanceToMove;
1783 
1784 	VECTORCH obstacleNormal;
1785 	STRATEGYBLOCK *obstacleSBPtr = 0;
1786 
1787     DirectionOfTravel = dynPtr->Displacement;
1788     Normalise(&DirectionOfTravel);
1789 
1790     /* ugh */
1791     distanceToMove = dynPtr->DistanceLeftToMove;
1792 
1793 	/* make list of platform's polygons */
1794 	{
1795 		VECTORCH zero = {0,0,0};
1796 		MakeDynamicBoundingBoxForObject(sbPtr, &(dynPtr->Position));
1797 		TestShapeWithDynamicBoundingBox(sbPtr->SBdptr,dynPtr);
1798 		MakeDynamicBoundingBoxForObject(sbPtr, &zero);
1799 	}
1800 
1801 //	textprint("polys on lift %d\n",NumberOfCollisionPolys);
1802     DirectionOfTravel.vx = -DirectionOfTravel.vx;
1803     DirectionOfTravel.vy = -DirectionOfTravel.vy;
1804     DirectionOfTravel.vz = -DirectionOfTravel.vz;
1805 	{
1806 		int i = NumberOfDynamicObjects;
1807 	    while(i--)
1808 		{
1809 
1810 			STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i];
1811 
1812 			/* check whether collision is even possible */
1813 			{
1814 			   	if (sbPtr==obstaclePtr)
1815 					continue;
1816 				{
1817 					VECTORCH *objectVerticesPtr = obstaclePtr->DynPtr->ObjectVertices;
1818 				   	if (!( ( (DBBMaxX >= objectVerticesPtr[7].vx) && (DBBMinX <= objectVerticesPtr[0].vx) )
1819 				   	     &&( (DBBMaxY >= objectVerticesPtr[7].vy) && (DBBMinY <= objectVerticesPtr[0].vy) )
1820 				         &&( (DBBMaxZ >= objectVerticesPtr[7].vz) && (DBBMinZ <= objectVerticesPtr[0].vz) ) ))
1821 						continue;
1822 				}
1823 			}
1824 
1825 			//textprint("found an object\n");
1826 
1827 			polysLeft = NumberOfCollisionPolys;
1828 			nearPolysPtr = CollisionPolysArray;
1829 
1830 		    distanceToMove = dynPtr->DistanceLeftToMove;
1831 
1832 			/* check against the landscape */
1833 		    while(polysLeft)
1834 			{
1835 				signed int distanceToObstacle;
1836 
1837 				distanceToObstacle = DistanceMovedBeforeObjectHitsPolygon(obstaclePtr->DynPtr,nearPolysPtr,distanceToMove);
1838 
1839 				if (distanceToObstacle>=0)
1840 		        {
1841 
1842 			       	distanceToMove = distanceToObstacle;
1843 				   	obstacleNormal = nearPolysPtr->PolyNormal;
1844 					obstacleSBPtr =	obstaclePtr;
1845 				}
1846 		        nearPolysPtr++;
1847 				polysLeft--;
1848 			}
1849 
1850 			if (distanceToMove!=dynPtr->DistanceLeftToMove)
1851 			{
1852 				if (dynPtr->Displacement.vy<0)
1853 				{
1854 					VECTORCH displacement;
1855 //					displacement.vx = -MUL_FIXED(DirectionOfTravel.vx, dynPtr->DistanceLeftToMove-distanceToMove+COLLISION_GRANULARITY);
1856 					displacement.vx = displacement.vz = 0;
1857 					displacement.vy = -(dynPtr->DistanceLeftToMove-distanceToMove+COLLISION_GRANULARITY);
1858 //					displacement.vz = -MUL_FIXED(DirectionOfTravel.vz, dynPtr->DistanceLeftToMove-distanceToMove+COLLISION_GRANULARITY);
1859 					AddVectorToVector(displacement, obstaclePtr->DynPtr->Position);
1860 					obstaclePtr->DynPtr->PrevPosition = obstaclePtr->DynPtr->Position;
1861 					{
1862 						VECTORCH *vertexPtr = obstaclePtr->DynPtr->ObjectVertices;
1863 						int i=8;
1864 						do
1865 						{
1866 							vertexPtr->vy += displacement.vy;
1867 							vertexPtr++;
1868 						}
1869 						while(--i);
1870 					}
1871 					if (obstaclePtr->SBdptr == Player)
1872 					{
1873 						/* look for polygons inside this volume */
1874 						FindLandscapePolygonsInObjectsVicinity(obstaclePtr);
1875 						FindObjectsToRelocateAgainst(obstaclePtr);
1876 
1877 						{
1878 							int polysLeft;
1879 						    struct ColPolyTag *polyPtr;
1880 
1881 						    polysLeft = NumberOfCollisionPolys;
1882 						    polyPtr = CollisionPolysArray;
1883 
1884 							while(polysLeft)
1885 							{
1886 						        if(DoesPolygonIntersectNRBB(polyPtr,obstaclePtr->DynPtr->ObjectVertices))
1887 						        {
1888 							   		int greatestDistance;
1889 
1890 							    	{
1891 							    		VECTORCH vertex = obstaclePtr->DynPtr->ObjectVertices[WhichNRBBVertex(obstaclePtr->DynPtr,&(polyPtr->PolyNormal))];
1892 										vertex.vx -= polyPtr->PolyPoint[0].vx;
1893 										vertex.vy -= polyPtr->PolyPoint[0].vy;
1894 										vertex.vz -= polyPtr->PolyPoint[0].vz;
1895 										greatestDistance = -DotProduct(&vertex,&(polyPtr->PolyNormal));
1896 									}
1897 
1898 									if (greatestDistance>0)
1899 									{
1900 										/* sorry, no room! */
1901 										SubVectorFromVector(displacement, obstaclePtr->DynPtr->Position);
1902 										obstaclePtr->DynPtr->PrevPosition = obstaclePtr->DynPtr->Position;
1903 										{
1904 											VECTORCH *vertexPtr = obstaclePtr->DynPtr->ObjectVertices;
1905 											int i=8;
1906 											do
1907 											{
1908 												vertexPtr->vy -= displacement.vy;
1909 												vertexPtr++;
1910 											}
1911 											while(--i);
1912 										}
1913 
1914 										return;
1915 									}
1916 						        }
1917 						        polyPtr++;
1918 								polysLeft--;
1919 							}
1920 
1921 						}
1922 					}
1923 					if (obstaclePtr->DynPtr->Displacement.vy>0)
1924 					{
1925 						obstaclePtr->DynPtr->Displacement.vy=0;
1926 						obstaclePtr->DynPtr->DistanceLeftToMove = Magnitude(&obstaclePtr->DynPtr->Displacement);
1927 					}
1928 					if (obstaclePtr->DynPtr->LinImpulse.vy>0)
1929 					{
1930 						obstaclePtr->DynPtr->LinImpulse.vy=0;
1931 					}
1932 
1933 				}
1934 				{
1935 					COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
1936 
1937 					if (reportPtr)
1938 					{
1939 						reportPtr->ObstacleSBPtr = obstacleSBPtr;
1940 						reportPtr->ObstacleNormal.vx = -obstacleNormal.vx;
1941 						reportPtr->ObstacleNormal.vy = -obstacleNormal.vy;
1942 						reportPtr->ObstacleNormal.vz = -obstacleNormal.vz;
1943 					}
1944 				}
1945 				if (obstacleSBPtr) //&& !(obstacleSBPtr->DynPtr->StopOnCollision))
1946 				 /* give obstacle a report too */
1947 				{
1948 					COLLISIONREPORT *reportPtr = AllocateCollisionReport(obstacleSBPtr->DynPtr);
1949 
1950 					if (reportPtr)
1951 					{
1952 						reportPtr->ObstacleSBPtr = sbPtr;
1953 						reportPtr->ObstacleNormal.vx = obstacleNormal.vx;
1954 						reportPtr->ObstacleNormal.vy = obstacleNormal.vy;
1955 						reportPtr->ObstacleNormal.vz = obstacleNormal.vz;
1956 					}
1957 				    /* see if object has hit the 'floor' */
1958 					if (obstacleSBPtr->DynPtr->GravityOn)
1959 					{
1960 						if (obstacleSBPtr->DynPtr->UseStandardGravity&&PlanarGravity)
1961 						{
1962 							if (obstacleNormal.vy < -FLOOR_THRESHOLD)
1963 							{
1964 								obstacleSBPtr->DynPtr->IsInContactWithFloor = 1;
1965 								if (obstacleNormal.vy < -NEARLYFLATFLOOR_THRESHOLD) obstacleSBPtr->DynPtr->IsInContactWithNearlyFlatFloor = 1;
1966 							}
1967 						}
1968 						else
1969 						{
1970 							int angle = DotProduct(&obstacleNormal,&obstacleSBPtr->DynPtr->GravityDirection);
1971 							if (angle < -FLOOR_THRESHOLD)
1972 							{
1973 								/* we've hit something that's against the direction of gravity */
1974 								obstacleSBPtr->DynPtr->IsInContactWithFloor = 1;
1975 								if (angle < -NEARLYFLATFLOOR_THRESHOLD) obstacleSBPtr->DynPtr->IsInContactWithNearlyFlatFloor = 1;
1976 							}
1977 						}
1978 					}
1979 
1980 				}
1981 			}
1982 	   	}
1983 //   	textprint("moving %d out of %d\n",distanceToMove,dynPtr->DistanceLeftToMove);
1984 
1985    	/* move object */
1986 
1987  //		textprint("disp %d %d %d\n",displacement.vx,displacement.vy,displacement.vz);
1988 
1989     }
1990 	if (dynPtr->Displacement.vy>0 && dynPtr->CollisionReportPtr)
1991 	{
1992 	}
1993 	else
1994 	{
1995 		AddVectorToVector(dynPtr->Displacement, dynPtr->Position);
1996 	}
1997 
1998 	#if 0
1999     if (distanceToMove!=dynPtr->DistanceLeftToMove)
2000     {
2001 		/* create a report about the collision */
2002 		{
2003 			COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
2004 
2005 			if (reportPtr)
2006 			{
2007 				reportPtr->ObstacleSBPtr = obstacleSBPtr;
2008 				reportPtr->ObstacleNormal.vx = -obstacleNormal.vx;
2009 				reportPtr->ObstacleNormal.vy = -obstacleNormal.vy;
2010 				reportPtr->ObstacleNormal.vz = -obstacleNormal.vz;
2011 			}
2012 		}
2013 
2014 		if (obstacleSBPtr) //&& !(obstacleSBPtr->DynPtr->StopOnCollision))
2015 		 /* give obstacle a report too */
2016 		{
2017 			COLLISIONREPORT *reportPtr = AllocateCollisionReport(obstacleSBPtr->DynPtr);
2018 
2019 			if (reportPtr)
2020 			{
2021 				reportPtr->ObstacleSBPtr = sbPtr;
2022 				reportPtr->ObstacleNormal.vx = obstacleNormal.vx;
2023 				reportPtr->ObstacleNormal.vy = obstacleNormal.vy;
2024 				reportPtr->ObstacleNormal.vz = obstacleNormal.vz;
2025 			}
2026 		}
2027 	}
2028 	#endif
2029 
2030 
2031 }
2032 
2033 
2034 
2035 
2036 
TestForValidPlayerStandUp(STRATEGYBLOCK * sbPtr)2037 static void TestForValidPlayerStandUp(STRATEGYBLOCK *sbPtr)
2038 {
2039 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2040 
2041 	/* make a collision volume corresponding to a standing character */
2042 	{
2043 		COLLISION_EXTENTS *extentsPtr = 0;
2044 
2045 		switch(AvP.PlayerType)
2046 		{
2047 			default:
2048 				LOCALASSERT(0);
2049 				/* if no debug then fall through to marine */
2050 			case I_Marine:
2051 				extentsPtr = &CollisionExtents[CE_MARINE];
2052 				break;
2053 
2054 			case I_Alien:
2055 				extentsPtr = &CollisionExtents[CE_ALIEN];
2056 				break;
2057 
2058 			case I_Predator:
2059 				extentsPtr = &CollisionExtents[CE_PREDATOR];
2060 				break;
2061 
2062 		}
2063 
2064 		/* max X */
2065 		dynPtr->ObjectVertices[0].vx = extentsPtr->CollisionRadius;
2066 		dynPtr->ObjectVertices[1].vx = extentsPtr->CollisionRadius;
2067 		dynPtr->ObjectVertices[2].vx = extentsPtr->CollisionRadius;
2068 		dynPtr->ObjectVertices[3].vx = extentsPtr->CollisionRadius;
2069 
2070 		/* max Z */
2071 		dynPtr->ObjectVertices[0].vz = extentsPtr->CollisionRadius;
2072 	    dynPtr->ObjectVertices[2].vz = extentsPtr->CollisionRadius;
2073 	    dynPtr->ObjectVertices[4].vz = extentsPtr->CollisionRadius;
2074 	    dynPtr->ObjectVertices[6].vz = extentsPtr->CollisionRadius;
2075 
2076 		/* min X */
2077 		dynPtr->ObjectVertices[4].vx = -extentsPtr->CollisionRadius;
2078 		dynPtr->ObjectVertices[5].vx = -extentsPtr->CollisionRadius;
2079 		dynPtr->ObjectVertices[6].vx = -extentsPtr->CollisionRadius;
2080 		dynPtr->ObjectVertices[7].vx = -extentsPtr->CollisionRadius;
2081 
2082 		/* min Z */
2083 		dynPtr->ObjectVertices[1].vz = -extentsPtr->CollisionRadius;
2084 		dynPtr->ObjectVertices[3].vz = -extentsPtr->CollisionRadius;
2085 		dynPtr->ObjectVertices[5].vz = -extentsPtr->CollisionRadius;
2086 		dynPtr->ObjectVertices[7].vz = -extentsPtr->CollisionRadius;
2087 
2088 		/* max Y */
2089 	   	dynPtr->ObjectVertices[0].vy = extentsPtr->Bottom;
2090 	    dynPtr->ObjectVertices[1].vy = extentsPtr->Bottom;
2091 	    dynPtr->ObjectVertices[4].vy = extentsPtr->Bottom;
2092 	    dynPtr->ObjectVertices[5].vy = extentsPtr->Bottom;
2093 
2094 		/* min Y */
2095 	   	dynPtr->ObjectVertices[2].vy = extentsPtr->StandingTop;
2096 	    dynPtr->ObjectVertices[3].vy = extentsPtr->StandingTop;
2097 	    dynPtr->ObjectVertices[6].vy = extentsPtr->StandingTop;
2098 	    dynPtr->ObjectVertices[7].vy = extentsPtr->StandingTop;
2099 
2100 		/* translate cuboid into world space */
2101 		{
2102 			VECTORCH *vertexPtr = dynPtr->ObjectVertices;
2103 
2104 	        int vertexNum=8;
2105 	        do
2106 	        {
2107 	        	vertexPtr->vx += dynPtr->Position.vx;
2108 	        	vertexPtr->vy += dynPtr->Position.vy;
2109 	        	vertexPtr->vz += dynPtr->Position.vz;
2110 	        	vertexPtr++;
2111 	        }
2112 	        while(--vertexNum);
2113 		}
2114 
2115 	}
2116 
2117 	/* look for polygons inside this volume */
2118 	FindLandscapePolygonsInObjectsVicinity(sbPtr);
2119 	FindObjectsToRelocateAgainst(sbPtr);
2120 
2121 
2122 	{
2123 
2124 		int polysLeft;
2125 	    struct ColPolyTag *polyPtr;
2126 
2127 	    polysLeft = NumberOfCollisionPolys;
2128 	    polyPtr = CollisionPolysArray;
2129 
2130 		while(polysLeft)
2131 		{
2132 	        if(DoesPolygonIntersectNRBB(polyPtr,dynPtr->ObjectVertices))
2133 	        {
2134 		   		int greatestDistance;
2135 
2136 		    	{
2137 		    		VECTORCH vertex = dynPtr->ObjectVertices[WhichNRBBVertex(dynPtr,&(polyPtr->PolyNormal))];
2138 					vertex.vx -= polyPtr->PolyPoint[0].vx;
2139 					vertex.vy -= polyPtr->PolyPoint[0].vy;
2140 					vertex.vz -= polyPtr->PolyPoint[0].vz;
2141 					greatestDistance = -DotProduct(&vertex,&(polyPtr->PolyNormal));
2142 				}
2143 
2144 				if (greatestDistance>0)
2145 				{
2146 					/* sorry, no standing room */
2147 		 			CreateNRBBForObject(sbPtr);
2148 					return;
2149 				}
2150 	        }
2151 	        polyPtr++;
2152 			polysLeft--;
2153 		}
2154 
2155 	}
2156 
2157 	/* standing up is ok */
2158 	{
2159 		PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
2160 
2161 		/* set player state */
2162 		playerStatusPtr->ShapeState = PMph_Standing;
2163 
2164 		/* if player is an alien, cancel his ability to walk on walls */
2165 		if (AvP.PlayerType == I_Alien)
2166 		{
2167 			dynPtr->UseStandardGravity=1;
2168 		}
2169 	}
2170 
2171 }
SteppingUpIsValid(STRATEGYBLOCK * sbPtr)2172 static int SteppingUpIsValid(STRATEGYBLOCK *sbPtr)
2173 {
2174 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2175 	VECTORCH displacement;
2176 
2177 	displacement.vx = MUL_FIXED(DirectionOfTravel.vx, COLLISION_GRANULARITY*2);
2178 	displacement.vy = - DistanceToStepUp;
2179 	displacement.vz = MUL_FIXED(DirectionOfTravel.vz, COLLISION_GRANULARITY*2);
2180 
2181 
2182 
2183 	{
2184 		int i=8;
2185 		VECTORCH *vertexPtr = dynPtr->ObjectVertices;
2186 		do
2187 		{
2188 			vertexPtr->vx += displacement.vx;
2189 			vertexPtr->vy += displacement.vy;
2190 			vertexPtr->vz += displacement.vz;
2191 			vertexPtr++;
2192 		}
2193 		while(--i);
2194 		dynPtr->Position.vx += displacement.vx;
2195 		dynPtr->Position.vy += displacement.vy;
2196 		dynPtr->Position.vz += displacement.vz;
2197 	}
2198 
2199 	/* look for polygons inside this volume */
2200 	FindLandscapePolygonsInObjectsVicinity(sbPtr);
2201 	FindObjectsToRelocateAgainst(sbPtr);
2202 
2203 
2204 	{
2205 
2206 		int polysLeft;
2207 	    struct ColPolyTag *polyPtr;
2208 
2209 	    polysLeft = NumberOfCollisionPolys;
2210 	    polyPtr = CollisionPolysArray;
2211 
2212 		while(polysLeft)
2213 		{
2214 	        if(DoesPolygonIntersectNRBB(polyPtr,dynPtr->ObjectVertices))
2215 	        {
2216 		   		#if 0
2217 		   		int greatestDistance;
2218 
2219 		    	{
2220 		    		VECTORCH vertex = dynPtr->ObjectVertices[WhichNRBBVertex(dynPtr,&(polyPtr->PolyNormal))];
2221 					vertex.vx -= polyPtr->PolyPoint[0].vx;
2222 					vertex.vy -= polyPtr->PolyPoint[0].vy;
2223 					vertex.vz -= polyPtr->PolyPoint[0].vz;
2224 					greatestDistance = -DotProduct(&vertex,&(polyPtr->PolyNormal));
2225 				}
2226 
2227 				if (greatestDistance>0)
2228 				#endif
2229 				{
2230 					/* sorry, there's a polygon in the way */
2231 					//textprint("no step %d\n",greatestDistance);
2232 					{
2233 						int i=8;
2234 						VECTORCH *vertexPtr = dynPtr->ObjectVertices;
2235 						do
2236 						{
2237 							vertexPtr->vx -= displacement.vx;
2238 							vertexPtr->vy -= displacement.vy;
2239 							vertexPtr->vz -= displacement.vz;
2240 							vertexPtr++;
2241 						}
2242 						while(--i);
2243 						dynPtr->Position.vx -= displacement.vx;
2244 						dynPtr->Position.vy -= displacement.vy;
2245 						dynPtr->Position.vz -= displacement.vz;
2246 					}
2247 					return 0;
2248 				}
2249 	        }
2250 	        polyPtr++;
2251 			polysLeft--;
2252 		}
2253 
2254 	}
2255 
2256 	/* steping up is ok */
2257 	{
2258 		//textprint("step ok\n");
2259 		return 1;
2260 	}
2261 
2262 }
2263 
FindLandscapePolygonsInObjectsPath(STRATEGYBLOCK * sbPtr)2264 static void FindLandscapePolygonsInObjectsPath(STRATEGYBLOCK *sbPtr)
2265 {
2266 	extern int NumActiveBlocks;
2267     extern DISPLAYBLOCK *ActiveBlockList[];
2268 
2269 	/* initialise near polygons array */
2270 	CollisionPolysPtr = &CollisionPolysArray[0];
2271     NumberOfCollisionPolys=0;
2272 
2273    	/* scan through ActiveBlockList for modules */
2274 	{
2275 	   	int numberOfObjects = NumActiveBlocks;
2276 	   	while(numberOfObjects)
2277 	   	{
2278 	   		DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
2279 	   		char isStaticObject=0;
2280 
2281 	   		GLOBALASSERT(objectPtr);
2282 			if(objectPtr->ObStrategyBlock)
2283 				if(objectPtr->ObStrategyBlock->DynPtr)
2284 				{
2285 					if(((objectPtr->ObStrategyBlock->DynPtr->IsStatic)
2286 			  		||(objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithObjects))
2287 			  		&&(!objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithEnvironment))
2288 						isStaticObject=1;
2289 				}
2290 
2291 	   		if (objectPtr->ObMyModule)
2292 	    	{
2293 				MakeDynamicBoundingBoxForObject(sbPtr, &(objectPtr->ObWorld));
2294 
2295 			    /* if the bounding box intersects with the object, investigate */
2296 			   	if (( (DBBMaxX >= objectPtr->ObMinX) && (DBBMinX <= objectPtr->ObMaxX) )
2297 			      &&( (DBBMaxY >= objectPtr->ObMinY) && (DBBMinY <= objectPtr->ObMaxY) )
2298  			      &&( (DBBMaxZ >= objectPtr->ObMinZ) && (DBBMinZ <= objectPtr->ObMaxZ) ))
2299 			       	TestShapeWithDynamicBoundingBox(objectPtr,sbPtr->DynPtr);
2300 	        }
2301 	   		else if (isStaticObject)
2302 	    	{
2303 				MakeDynamicBoundingBoxForObject(sbPtr, &(objectPtr->ObWorld));
2304 
2305 			    /* if the bounding box intersects with the object, investigate */
2306 			   	if (( (DBBMaxX >= -objectPtr->ObRadius) && (DBBMinX <= objectPtr->ObRadius) )
2307 			      &&( (DBBMaxY >= -objectPtr->ObRadius) && (DBBMinY <= objectPtr->ObRadius) )
2308  			      &&( (DBBMaxZ >= -objectPtr->ObRadius) && (DBBMinZ <= objectPtr->ObRadius) ))
2309 			       	TestShapeWithDynamicBoundingBox(objectPtr,sbPtr->DynPtr);
2310 	        }
2311 	    }
2312   	}
2313 }
FindObjectPolygonsInObjectsPath(STRATEGYBLOCK * sbPtr)2314 static void FindObjectPolygonsInObjectsPath(STRATEGYBLOCK *sbPtr)
2315 {
2316 	DYNAMICSBLOCK *dynPtr=sbPtr->DynPtr;
2317 	/* check against other objects */
2318 	{
2319 		VECTORCH zero = {0,0,0};
2320 		int i = NumberOfDynamicObjects;
2321 		MakeDynamicBoundingBoxForObject(sbPtr, &zero);
2322 	    while(i--)
2323 		{
2324 
2325 			STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i];
2326 			VECTORCH *objectVerticesPtr = obstaclePtr->DynPtr->ObjectVertices;
2327 
2328 			/* check whether collision is even possible */
2329 			{
2330 			   	if (sbPtr==obstaclePtr)
2331 					continue;
2332 
2333 				/* can it be seen? */
2334 				if(obstaclePtr->SBdptr->ObFlags&ObFlag_NotVis) continue;
2335 
2336 				/* two sprites */
2337 				if((dynPtr->DynamicsType == DYN_TYPE_SPRITE_COLLISIONS)
2338 			     &&(obstaclePtr->DynPtr->DynamicsType == DYN_TYPE_SPRITE_COLLISIONS) )
2339 					continue;
2340 
2341 				if ( (dynPtr->IgnoreSameObjectsAsYou || obstaclePtr->DynPtr->IgnoreSameObjectsAsYou)
2342 				 &&(sbPtr->I_SBtype == obstaclePtr->I_SBtype) )
2343 					continue;
2344 
2345 				if (obstaclePtr->DynPtr->OnlyCollideWithObjects)
2346 					continue;
2347 
2348 				if (obstaclePtr->DynPtr->OnlyCollideWithEnvironment)
2349 					continue;
2350 
2351 				if ( ((obstaclePtr->SBdptr == Player) && dynPtr->IgnoreThePlayer)
2352 				   ||((sbPtr->SBdptr == Player) && obstaclePtr->DynPtr->IgnoreThePlayer) )
2353 					continue;
2354 
2355 				if( (sbPtr->SBdptr==Player)
2356 				  &&( (obstaclePtr->I_SBtype == I_BehaviourHierarchicalFragment)
2357 				    ||(obstaclePtr->DynPtr->IsPickupObject))
2358 				  )
2359 				{
2360 					continue;
2361 				}
2362 
2363 			   	if (!( ( (DBBMaxX >= objectVerticesPtr[7].vx) && (DBBMinX <= objectVerticesPtr[0].vx) )
2364 			   	     &&( (DBBMaxY >= objectVerticesPtr[7].vy) && (DBBMinY <= objectVerticesPtr[0].vy) )
2365 			         &&( (DBBMaxZ >= objectVerticesPtr[7].vz) && (DBBMinZ <= objectVerticesPtr[0].vz) ) ))
2366 					continue;
2367 			}
2368 
2369 			{
2370 				const int *vertexIndexPtr=&CuboidVertexList[0];
2371 				int face=6;
2372 
2373 				do
2374 				{
2375 					struct ColPolyTag poly;
2376 					poly.NumberOfVertices=4;
2377 					poly.ParentObject = obstaclePtr->SBdptr;
2378 
2379 					poly.PolyPoint[0]=objectVerticesPtr[*vertexIndexPtr++];
2380 					poly.PolyPoint[1]=objectVerticesPtr[*vertexIndexPtr++];
2381 					poly.PolyPoint[2]=objectVerticesPtr[*vertexIndexPtr++];
2382 					poly.PolyPoint[3]=objectVerticesPtr[*vertexIndexPtr++];
2383 
2384 
2385 					if (IsPolygonWithinDynamicBoundingBox(&poly))
2386 	 				{
2387 						{
2388 							switch(face)
2389 							{
2390 								case 6: /* all points are on max y face */
2391 								{
2392 								    poly.PolyNormal.vx = 0;
2393 								    poly.PolyNormal.vy = ONE_FIXED;
2394 								    poly.PolyNormal.vz = 0;
2395 									break;
2396 								}
2397 								case 5: /* all points are on max z face */
2398 								{
2399 								    poly.PolyNormal.vx = 0;
2400 								    poly.PolyNormal.vy = 0;
2401 								    poly.PolyNormal.vz = ONE_FIXED;
2402 									break;
2403 								}
2404 								case 4: /* all points are on max x face */
2405 								{
2406 								    poly.PolyNormal.vx = ONE_FIXED;
2407 								    poly.PolyNormal.vy = 0;
2408 								    poly.PolyNormal.vz = 0;
2409 									break;
2410 								}
2411 								case 3: /* all points are on min z face */
2412 								{
2413 								    poly.PolyNormal.vx = 0;
2414 								    poly.PolyNormal.vy = 0;
2415 								    poly.PolyNormal.vz = -ONE_FIXED;
2416 									break;
2417 								}
2418 								case 2: /* all points are on min x face */
2419 								{
2420 								    poly.PolyNormal.vx = -ONE_FIXED;
2421 								    poly.PolyNormal.vy = 0;
2422 								    poly.PolyNormal.vz = 0;
2423 									break;
2424 								}
2425 								case 1: /* all points are on min y face */
2426 								{
2427 								    poly.PolyNormal.vx = 0;
2428 								    poly.PolyNormal.vy = -ONE_FIXED;
2429 								    poly.PolyNormal.vz = 0;
2430 									break;
2431 								}
2432 							}
2433 						}
2434 
2435 						#if 0
2436 						polyDistance = DistanceMovedBeforeObjectHitsPolygon(dynPtr,&poly,distanceToMove);
2437 						if (polyDistance>=0)
2438 				        {
2439 							/* If the player moves into a weapon/ammo/etc, report the collision but
2440 							don't stop the player. (ie. let him walk through it) */
2441 							if( (sbPtr->SBdptr==Player)
2442 							  &&( (obstaclePtr->I_SBtype == I_BehaviourHierarchicalFragment)
2443 							    ||(obstaclePtr->DynPtr->IsPickupObject))
2444 							  )
2445 							{
2446 								/* create a report about the collision */
2447 								COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
2448 								if (reportPtr)
2449 								{
2450 									reportPtr->ObstacleSBPtr = obstaclePtr;
2451 									reportPtr->ObstacleNormal = poly.PolyNormal;
2452 								}
2453 							}
2454 							else
2455 							{
2456 					       	   	distanceToMove = polyDistance;
2457 							   	obstacleNormal = poly.PolyNormal;
2458 								obstaclePoint = poly.PolyPoint[0];
2459 								obstacleSBPtr =	obstaclePtr;
2460 								LOCALASSERT(obstaclePtr);
2461 								topOfStep = -2000000000;
2462 							}
2463 						}
2464 						#endif
2465 						*CollisionPolysPtr = poly;
2466 
2467 						CollisionPolysPtr++;
2468 				    	NumberOfCollisionPolys++;
2469 
2470 					}
2471 					face--;
2472 				}
2473 				while(face);
2474 
2475 			}
2476 		}
2477 	}
2478 }
2479 
FindLandscapePolygonsInObjectsVicinity(STRATEGYBLOCK * sbPtr)2480 static void FindLandscapePolygonsInObjectsVicinity(STRATEGYBLOCK *sbPtr)
2481 {
2482 	extern int NumActiveBlocks;
2483     extern DISPLAYBLOCK *ActiveBlockList[];
2484 
2485 	/* intialise near polygons array */
2486 	CollisionPolysPtr = &CollisionPolysArray[0];
2487     NumberOfCollisionPolys=0;
2488 
2489    	/* scan through ActiveBlockList for modules */
2490 	{
2491 	   	int numberOfObjects = NumActiveBlocks;
2492 	   	while(numberOfObjects)
2493 	   	{
2494 	   		DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
2495 	   		char isStaticObject=0;
2496 
2497 	   		GLOBALASSERT(objectPtr);
2498 			if(objectPtr->ObStrategyBlock)
2499 				if(objectPtr->ObStrategyBlock->DynPtr)
2500 				{
2501 					if(((objectPtr->ObStrategyBlock->DynPtr->IsStatic)
2502 					||(objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithObjects))
2503 			  		&&(!objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithEnvironment))
2504 						isStaticObject=1;
2505 				}
2506 
2507 	   		if (objectPtr->ObMyModule) /* is object a module or static? */
2508 	    	{
2509 				MakeStaticBoundingBoxForObject(sbPtr);
2510 
2511 				/* translate SBB into space of landscape module */
2512 				SBBMinX -= objectPtr->ObWorld.vx;
2513 				SBBMaxX -= objectPtr->ObWorld.vx;
2514 
2515 				SBBMinY -= objectPtr->ObWorld.vy;
2516 				SBBMaxY -= objectPtr->ObWorld.vy;
2517 
2518 				SBBMinZ -= objectPtr->ObWorld.vz;
2519 				SBBMaxZ -= objectPtr->ObWorld.vz;
2520 
2521 			    /* if the bounding box intersects with the object, investigate */
2522 			   	if (( (SBBMaxX >= objectPtr->ObMinX) && (SBBMinX <= objectPtr->ObMaxX) )
2523 			      &&( (SBBMaxY >= objectPtr->ObMinY) && (SBBMinY <= objectPtr->ObMaxY) )
2524  			      &&( (SBBMaxZ >= objectPtr->ObMinZ) && (SBBMinZ <= objectPtr->ObMaxZ) ))
2525 			       	TestShapeWithStaticBoundingBox(objectPtr);
2526 	        }
2527 			else if (isStaticObject)
2528 			{
2529 				MakeStaticBoundingBoxForObject(sbPtr);
2530 
2531 				/* translate SBB into space of landscape module */
2532 				SBBMinX -= objectPtr->ObWorld.vx;
2533 				SBBMaxX -= objectPtr->ObWorld.vx;
2534 
2535 				SBBMinY -= objectPtr->ObWorld.vy;
2536 				SBBMaxY -= objectPtr->ObWorld.vy;
2537 
2538 				SBBMinZ -= objectPtr->ObWorld.vz;
2539 				SBBMaxZ -= objectPtr->ObWorld.vz;
2540 
2541 			    /* if the bounding box intersects with the object, investigate */
2542 			   	if (( (SBBMaxX >= objectPtr->ObMinX) && (SBBMinX <= objectPtr->ObMaxX) )
2543 			      &&( (SBBMaxY >= objectPtr->ObMinY) && (SBBMinY <= objectPtr->ObMaxY) )
2544  			      &&( (SBBMaxZ >= objectPtr->ObMinZ) && (SBBMinZ <= objectPtr->ObMaxZ) ))
2545 			       	TestShapeWithStaticBoundingBox(objectPtr);
2546 			}
2547 
2548 	    }
2549   	}
2550 }
2551 
FindObjectsToRelocateAgainst(STRATEGYBLOCK * sbPtr)2552 static void FindObjectsToRelocateAgainst(STRATEGYBLOCK *sbPtr)
2553 {
2554 	MakeStaticBoundingBoxForObject(sbPtr);
2555 	{
2556 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2557 		int i = NumberOfDynamicObjects;
2558 	    while(i--)
2559 		{
2560 			STRATEGYBLOCK *obstaclePtr = DynamicObjectsList[i];
2561 
2562 			/* check whether collision is even possible */
2563 			if (sbPtr==obstaclePtr)
2564 				continue;
2565 
2566 			/* ignore platform lifts */
2567 		 	if(obstaclePtr->DynPtr->OnlyCollideWithObjects)
2568 		 		continue;
2569 
2570 			/* ignore things that only collide with environment */
2571 			if (obstaclePtr->DynPtr->OnlyCollideWithEnvironment)
2572 				continue;
2573 
2574 			/* don't relocate against ammo and stuff */
2575 			if (sbPtr->SBdptr==Player)
2576 			{
2577 				if(obstaclePtr->DynPtr->IsPickupObject)
2578 				{
2579 						continue;
2580 				}
2581 			}
2582 
2583 			/* two sprites */
2584 			if((dynPtr->DynamicsType == DYN_TYPE_SPRITE_COLLISIONS)
2585 			   &&(obstaclePtr->DynPtr->DynamicsType == DYN_TYPE_SPRITE_COLLISIONS) )
2586 				continue;
2587 
2588 			if (dynPtr->IgnoreSameObjectsAsYou
2589 			 &&(sbPtr->I_SBtype == obstaclePtr->I_SBtype) )
2590 				continue;
2591 
2592 			TestObjectWithStaticBoundingBox(obstaclePtr->SBdptr);
2593 		}
2594 	}
2595 }
2596 
MakeDynamicBoundingBoxForObject(STRATEGYBLOCK * sbPtr,VECTORCH * worldOffsetPtr)2597 static void MakeDynamicBoundingBoxForObject(STRATEGYBLOCK *sbPtr, VECTORCH *worldOffsetPtr)
2598 {
2599 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2600 
2601 	DBBMaxX = dynPtr->ObjectVertices[0].vx - worldOffsetPtr->vx + COLLISION_GRANULARITY;
2602 	DBBMinX = dynPtr->ObjectVertices[7].vx - worldOffsetPtr->vx - COLLISION_GRANULARITY;
2603 
2604 	DBBMaxY = dynPtr->ObjectVertices[0].vy - worldOffsetPtr->vy + COLLISION_GRANULARITY;
2605 	DBBMinY = dynPtr->ObjectVertices[7].vy - worldOffsetPtr->vy - COLLISION_GRANULARITY;
2606 
2607 	DBBMaxZ = dynPtr->ObjectVertices[0].vz - worldOffsetPtr->vz + COLLISION_GRANULARITY;
2608 	DBBMinZ = dynPtr->ObjectVertices[7].vz - worldOffsetPtr->vz - COLLISION_GRANULARITY;
2609 
2610 	if (dynPtr->Displacement.vx > 0)
2611 	{
2612 		DBBMaxX += dynPtr->Displacement.vx;
2613 	}
2614 	else
2615 	{
2616 	    DBBMinX += dynPtr->Displacement.vx;
2617 	}
2618 
2619 	if (dynPtr->Displacement.vy > 0)
2620 	{
2621 		DBBMaxY += dynPtr->Displacement.vy;
2622 	}
2623 	else
2624 	{
2625 	    DBBMinY += dynPtr->Displacement.vy;
2626 	}
2627 
2628 	if (dynPtr->Displacement.vz > 0)
2629 	{
2630 		DBBMaxZ += dynPtr->Displacement.vz;
2631 	}
2632 	else
2633 	{
2634 	    DBBMinZ += dynPtr->Displacement.vz;
2635 	}
2636 
2637 }
2638 
MakeStaticBoundingBoxForSphere(STRATEGYBLOCK * sbPtr)2639 static void MakeStaticBoundingBoxForSphere(STRATEGYBLOCK *sbPtr)
2640 {
2641 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2642 	int objectSize = dynPtr->CollisionRadius+COLLISION_GRANULARITY;
2643 
2644     SBBMinX = dynPtr->Position.vx - objectSize;
2645 	SBBMaxX = dynPtr->Position.vx + objectSize;
2646     SBBMinY = dynPtr->Position.vy - objectSize;
2647 	SBBMaxY = dynPtr->Position.vy + objectSize;
2648     SBBMinZ = dynPtr->Position.vz - objectSize;
2649 	SBBMaxZ = dynPtr->Position.vz + objectSize;
2650 }
MakeStaticBoundingBoxForNRBB(STRATEGYBLOCK * sbPtr)2651 static void MakeStaticBoundingBoxForNRBB(STRATEGYBLOCK *sbPtr)
2652 {
2653 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
2654     SBBMinX = dynPtr->ObjectVertices[7].vx - COLLISION_GRANULARITY*16;
2655 	SBBMaxX = dynPtr->ObjectVertices[0].vx + COLLISION_GRANULARITY*16;
2656 
2657     SBBMinY = dynPtr->ObjectVertices[7].vy - COLLISION_GRANULARITY*16;
2658 	SBBMaxY = dynPtr->ObjectVertices[0].vy + COLLISION_GRANULARITY*16;
2659 
2660     SBBMinZ = dynPtr->ObjectVertices[7].vz - COLLISION_GRANULARITY*16;
2661 	SBBMaxZ = dynPtr->ObjectVertices[0].vz + COLLISION_GRANULARITY*16;
2662 }
2663 
TestShapeWithDynamicBoundingBox(DISPLAYBLOCK * objectPtr,DYNAMICSBLOCK * mainDynPtr)2664 static void TestShapeWithDynamicBoundingBox(DISPLAYBLOCK *objectPtr, DYNAMICSBLOCK *mainDynPtr)
2665 {
2666 	int numberOfItems;
2667     int needToRotate = 0;
2668 
2669     /* KJL 10:58:22 24/11/98 - If the object is a static object rather than a module,
2670 	we'll need to rotate the polygons into world-space */
2671    	if (objectPtr->ObStrategyBlock)
2672 	{
2673 		DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
2674 
2675 		if (dynPtr)
2676 		{
2677 			if (dynPtr->IsStatic)
2678 			{
2679 				needToRotate = 1;
2680 			}
2681 		}
2682 	}
2683 
2684 
2685     /* okay, let's setup the shape's data and access the first poly */
2686 	numberOfItems = SetupPolygonAccess(objectPtr);
2687 
2688     /* go through polys looking for those which intersect with the bounding box */
2689   	while(numberOfItems--)
2690 	{
2691 		AccessNextPolygon();
2692 
2693 		if (mainDynPtr->IgnoresNotVisPolys && (PolygonFlag & iflag_notvis) && !(PolygonFlag & iflag_mirror)) continue;
2694 
2695 		GetPolygonVertices(CollisionPolysPtr);
2696 
2697        	if (needToRotate)
2698 		{
2699 			int i = CollisionPolysPtr->NumberOfVertices;
2700         	VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
2701 
2702 
2703            	do
2704            	{
2705 				RotateVector(polyVertexPtr,&objectPtr->ObMat);
2706 				polyVertexPtr++;
2707         	}
2708 			while(--i);
2709         }
2710 
2711 		{
2712 			VECTORCH *vertices = CollisionPolysPtr->PolyPoint;
2713 			if (CollisionPolysPtr->NumberOfVertices==4)
2714 			{
2715 		    	if (vertices[0].vy < DBBMinY)
2716 		        	if (vertices[1].vy < DBBMinY)
2717 			      		if (vertices[2].vy < DBBMinY)
2718 			      			if (vertices[3].vy < DBBMinY)
2719 		          				continue;
2720 
2721 		    	if (vertices[0].vx < DBBMinX)
2722 		    		if (vertices[1].vx < DBBMinX)
2723 		    			if (vertices[2].vx < DBBMinX)
2724 		    				if (vertices[3].vx < DBBMinX)
2725 		          				continue;
2726 
2727 		    	if (vertices[0].vx > DBBMaxX)
2728 			    	if (vertices[1].vx > DBBMaxX)
2729 			      		if (vertices[2].vx > DBBMaxX)
2730 			    			if (vertices[3].vx > DBBMaxX)
2731 		          				continue;
2732 
2733 		    	if (vertices[0].vz < DBBMinZ)
2734 			    	if (vertices[1].vz < DBBMinZ)
2735 			      		if (vertices[2].vz < DBBMinZ)
2736 			      			if (vertices[3].vz < DBBMinZ)
2737 		          				continue;
2738 
2739 		    	if (vertices[0].vz > DBBMaxZ)
2740 			    	if (vertices[1].vz > DBBMaxZ)
2741 			    		if (vertices[2].vz > DBBMaxZ)
2742 			    			if (vertices[3].vz > DBBMaxZ)
2743 			    				continue;
2744 
2745 		    	if (vertices[0].vy > DBBMaxY)
2746 			    	if (vertices[1].vy > DBBMaxY)
2747 			    		if (vertices[2].vy > DBBMaxY)
2748 			    			if (vertices[3].vy > DBBMaxY)
2749 		        			  	continue;
2750 
2751 		    }
2752 		    else
2753 			{
2754 		    	if (vertices[0].vy < DBBMinY)
2755 		        	if (vertices[1].vy < DBBMinY)
2756 			    		if (vertices[2].vy < DBBMinY)
2757 		          			continue;
2758 
2759 		    	if (vertices[0].vx < DBBMinX)
2760 			    	if (vertices[1].vx < DBBMinX)
2761 			    		if (vertices[2].vx < DBBMinX)
2762 		        		  	continue;
2763 
2764 		    	if (vertices[0].vx > DBBMaxX)
2765 			    	if (vertices[1].vx > DBBMaxX)
2766 			   			if (vertices[2].vx > DBBMaxX)
2767 				          	continue;
2768 
2769 		    	if (vertices[0].vz < DBBMinZ)
2770 			  		if (vertices[1].vz < DBBMinZ)
2771 			   			if (vertices[2].vz < DBBMinZ)
2772 		          			continue;
2773 
2774 		    	if (vertices[0].vz > DBBMaxZ)
2775 			    	if (vertices[1].vz > DBBMaxZ)
2776 			   			if (vertices[2].vz > DBBMaxZ)
2777 			    			continue;
2778 
2779 		    	if (vertices[0].vy > DBBMaxY)
2780 			    	if (vertices[1].vy > DBBMaxY)
2781 			    		if (vertices[2].vy > DBBMaxY)
2782 		          			continue;
2783 
2784 		    }
2785 		}
2786 
2787     	/* add object's world space coords to vertices */
2788 		{
2789 			int i = CollisionPolysPtr->NumberOfVertices;
2790         	VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
2791 
2792 
2793            	do
2794            	{
2795 			    polyVertexPtr->vx += objectPtr->ObWorld.vx;
2796     	        polyVertexPtr->vy += objectPtr->ObWorld.vy;
2797         	    polyVertexPtr->vz += objectPtr->ObWorld.vz;
2798 				polyVertexPtr++;
2799         	}
2800 			while(--i);
2801         }
2802 
2803         /* get the poly's normal */
2804     	GetPolygonNormal(CollisionPolysPtr);
2805        	if (needToRotate)
2806 		{
2807 			RotateVector(&CollisionPolysPtr->PolyNormal,&objectPtr->ObMat);
2808 		}
2809 		CollisionPolysPtr->ParentObject = objectPtr;
2810 
2811     	CollisionPolysPtr++;
2812     	NumberOfCollisionPolys++;
2813 		/* ran out of space? */
2814 		LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
2815 
2816         if (PolygonFlag & iflag_no_bfc)
2817         {
2818 	    	CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
2819 			if(CollisionPolysPtr->NumberOfVertices==3)
2820 			{
2821 				CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
2822 				CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
2823 				CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
2824 			}
2825 			else
2826 			{
2827 				CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
2828 				CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
2829 				CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
2830 				CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
2831 			}
2832 
2833 			CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
2834 			CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
2835 			CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
2836 			CollisionPolysPtr->ParentObject = objectPtr;
2837 
2838 			CollisionPolysPtr++;
2839 	    	NumberOfCollisionPolys++;
2840 			/* ran out of space? */
2841 			LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
2842         }
2843 	}
2844 
2845     return;
2846 }
TestShapeWithParticlesDynamicBoundingBox(DISPLAYBLOCK * objectPtr)2847 static void TestShapeWithParticlesDynamicBoundingBox(DISPLAYBLOCK *objectPtr)
2848 {
2849 	int numberOfItems;
2850     int needToRotate = 0;
2851 
2852     /* KJL 10:58:22 24/11/98 - If the object is a static object rather than a module,
2853 	we'll need to rotate the polygons into world-space */
2854    	if (objectPtr->ObStrategyBlock)
2855 	{
2856 		DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
2857 
2858 		if (dynPtr)
2859 		{
2860 			if (dynPtr->IsStatic)
2861 			{
2862 				needToRotate = 1;
2863 			}
2864 		}
2865 	}
2866 
2867 
2868     /* okay, let's setup the shape's data and access the first poly */
2869 	numberOfItems = SetupPolygonAccess(objectPtr);
2870 
2871     /* go through polys looking for those which intersect with the bounding box */
2872   	while(numberOfItems--)
2873 	{
2874 		AccessNextPolygon();
2875 
2876         if (PolygonFlag & iflag_notvis) continue;
2877 
2878 		GetPolygonVertices(CollisionPolysPtr);
2879        	if (needToRotate)
2880 		{
2881 			int i = CollisionPolysPtr->NumberOfVertices;
2882         	VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
2883 
2884 
2885            	do
2886            	{
2887 				RotateVector(polyVertexPtr,&objectPtr->ObMat);
2888 				polyVertexPtr++;
2889         	}
2890 			while(--i);
2891         }
2892 
2893 		{
2894 			VECTORCH *vertices = CollisionPolysPtr->PolyPoint;
2895 			if (CollisionPolysPtr->NumberOfVertices==4)
2896 			{
2897 		    	if (vertices[0].vy < DBBMinY)
2898 		        	if (vertices[1].vy < DBBMinY)
2899 			      		if (vertices[2].vy < DBBMinY)
2900 			      			if (vertices[3].vy < DBBMinY)
2901 		          				continue;
2902 
2903 		    	if (vertices[0].vx < DBBMinX)
2904 		    		if (vertices[1].vx < DBBMinX)
2905 		    			if (vertices[2].vx < DBBMinX)
2906 		    				if (vertices[3].vx < DBBMinX)
2907 		          				continue;
2908 
2909 		    	if (vertices[0].vx > DBBMaxX)
2910 			    	if (vertices[1].vx > DBBMaxX)
2911 			      		if (vertices[2].vx > DBBMaxX)
2912 			    			if (vertices[3].vx > DBBMaxX)
2913 		          				continue;
2914 
2915 		    	if (vertices[0].vz < DBBMinZ)
2916 			    	if (vertices[1].vz < DBBMinZ)
2917 			      		if (vertices[2].vz < DBBMinZ)
2918 			      			if (vertices[3].vz < DBBMinZ)
2919 		          				continue;
2920 
2921 		    	if (vertices[0].vz > DBBMaxZ)
2922 			    	if (vertices[1].vz > DBBMaxZ)
2923 			    		if (vertices[2].vz > DBBMaxZ)
2924 			    			if (vertices[3].vz > DBBMaxZ)
2925 			    				continue;
2926 
2927 		    	if (vertices[0].vy > DBBMaxY)
2928 			    	if (vertices[1].vy > DBBMaxY)
2929 			    		if (vertices[2].vy > DBBMaxY)
2930 			    			if (vertices[3].vy > DBBMaxY)
2931 		        			  	continue;
2932 
2933 		    }
2934 		    else
2935 			{
2936 		    	if (vertices[0].vy < DBBMinY)
2937 		        	if (vertices[1].vy < DBBMinY)
2938 			    		if (vertices[2].vy < DBBMinY)
2939 		          			continue;
2940 
2941 		    	if (vertices[0].vx < DBBMinX)
2942 			    	if (vertices[1].vx < DBBMinX)
2943 			    		if (vertices[2].vx < DBBMinX)
2944 		        		  	continue;
2945 
2946 		    	if (vertices[0].vx > DBBMaxX)
2947 			    	if (vertices[1].vx > DBBMaxX)
2948 			   			if (vertices[2].vx > DBBMaxX)
2949 				          	continue;
2950 
2951 		    	if (vertices[0].vz < DBBMinZ)
2952 			  		if (vertices[1].vz < DBBMinZ)
2953 			   			if (vertices[2].vz < DBBMinZ)
2954 		          			continue;
2955 
2956 		    	if (vertices[0].vz > DBBMaxZ)
2957 			    	if (vertices[1].vz > DBBMaxZ)
2958 			   			if (vertices[2].vz > DBBMaxZ)
2959 			    			continue;
2960 
2961 		    	if (vertices[0].vy > DBBMaxY)
2962 			    	if (vertices[1].vy > DBBMaxY)
2963 			    		if (vertices[2].vy > DBBMaxY)
2964 		          			continue;
2965 
2966 		    }
2967 		}
2968 
2969     	/* add object's world space coords to vertices */
2970 		{
2971 			int i = CollisionPolysPtr->NumberOfVertices;
2972         	VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
2973 
2974            	do
2975            	{
2976 	            polyVertexPtr->vx += objectPtr->ObWorld.vx;
2977     	        polyVertexPtr->vy += objectPtr->ObWorld.vy;
2978         	    polyVertexPtr->vz += objectPtr->ObWorld.vz;
2979 				polyVertexPtr++;
2980         	}
2981 			while(--i);
2982         }
2983 
2984         /* get the poly's normal */
2985     	GetPolygonNormal(CollisionPolysPtr);
2986        	if (needToRotate)
2987 		{
2988 			RotateVector(&CollisionPolysPtr->PolyNormal,&objectPtr->ObMat);
2989 		}
2990 		CollisionPolysPtr->ParentObject = objectPtr;
2991 
2992     	CollisionPolysPtr++;
2993     	NumberOfCollisionPolys++;
2994 		/* ran out of space? */
2995 		LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
2996 
2997         if (PolygonFlag & iflag_no_bfc)
2998         {
2999 	    	CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
3000 			if(CollisionPolysPtr->NumberOfVertices==3)
3001 			{
3002 				CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
3003 				CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
3004 				CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
3005 			}
3006 			else
3007 			{
3008 				CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
3009 				CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
3010 				CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
3011 				CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
3012 			}
3013 
3014 			CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
3015 			CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
3016 			CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
3017 			CollisionPolysPtr->ParentObject = objectPtr;
3018 
3019 			CollisionPolysPtr++;
3020 	    	NumberOfCollisionPolys++;
3021 			/* ran out of space? */
3022 			LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
3023         }
3024 	}
3025 
3026     return;
3027 }
3028 
TestShapeWithStaticBoundingBox(DISPLAYBLOCK * objectPtr)3029 static void TestShapeWithStaticBoundingBox(DISPLAYBLOCK *objectPtr)
3030 {
3031 	int numberOfItems;
3032     int needToRotate = 0;
3033 
3034     /* KJL 10:58:22 24/11/98 - If the object is a static object rather than a module,
3035 	we'll need to rotate the polygons into world-space */
3036    	if (objectPtr->ObStrategyBlock)
3037 	{
3038 		DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
3039 
3040 		if (dynPtr)
3041 		{
3042 			if (dynPtr->IsStatic)
3043 			{
3044 				needToRotate = 1;
3045 			}
3046 		}
3047 	}
3048 
3049     /* okay, let's setup the shape's data and access the first poly */
3050 	numberOfItems = SetupPolygonAccess(objectPtr);
3051 
3052     /* go through polys looking for those which intersect with the bounding box */
3053   	while(numberOfItems--)
3054 	{
3055 		AccessNextPolygon();
3056 
3057   //      if (PolygonFlag & iflag_notvis) continue;
3058 
3059 		GetPolygonVertices(CollisionPolysPtr);
3060     	if (needToRotate)
3061 		{
3062 			int i = CollisionPolysPtr->NumberOfVertices;
3063         	VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
3064 
3065 
3066            	do
3067            	{
3068 				RotateVector(polyVertexPtr,&objectPtr->ObMat);
3069 				polyVertexPtr++;
3070         	}
3071 			while(--i);
3072         }
3073 
3074         if(IsPolygonWithinStaticBoundingBox(CollisionPolysPtr))
3075         {
3076         	/* add object's world space coords to vertices */
3077 			{
3078 				int i = CollisionPolysPtr->NumberOfVertices;
3079             	VECTORCH *polyVertexPtr = CollisionPolysPtr->PolyPoint;
3080 
3081 				do
3082 	           	{
3083 		            polyVertexPtr->vx += objectPtr->ObWorld.vx;
3084 	    	        polyVertexPtr->vy += objectPtr->ObWorld.vy;
3085 	        	    polyVertexPtr->vz += objectPtr->ObWorld.vz;
3086 					polyVertexPtr++;
3087             	}
3088 				while(--i);
3089             }
3090 
3091             /* get the poly's normal */
3092         	GetPolygonNormal(CollisionPolysPtr);
3093 	       	if (needToRotate)
3094 			{
3095 				RotateVector(&CollisionPolysPtr->PolyNormal,&objectPtr->ObMat);
3096 			}
3097 
3098         	CollisionPolysPtr++;
3099         	NumberOfCollisionPolys++;
3100 
3101 			/* ran out of space? */
3102 			LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
3103 	        if (PolygonFlag & iflag_no_bfc)
3104 	        {
3105 		    	CollisionPolysPtr->NumberOfVertices = (CollisionPolysPtr-1)->NumberOfVertices;
3106 				if(CollisionPolysPtr->NumberOfVertices==3)
3107 				{
3108 					CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[2];
3109 					CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[1];
3110 					CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[0];
3111 				}
3112 				else
3113 				{
3114 					CollisionPolysPtr->PolyPoint[0] = (CollisionPolysPtr-1)->PolyPoint[3];
3115 					CollisionPolysPtr->PolyPoint[1] = (CollisionPolysPtr-1)->PolyPoint[2];
3116 					CollisionPolysPtr->PolyPoint[2] = (CollisionPolysPtr-1)->PolyPoint[1];
3117 					CollisionPolysPtr->PolyPoint[3] = (CollisionPolysPtr-1)->PolyPoint[0];
3118 				}
3119 
3120 				CollisionPolysPtr->PolyNormal.vx = -(CollisionPolysPtr-1)->PolyNormal.vx;
3121 				CollisionPolysPtr->PolyNormal.vy = -(CollisionPolysPtr-1)->PolyNormal.vy;
3122 				CollisionPolysPtr->PolyNormal.vz = -(CollisionPolysPtr-1)->PolyNormal.vz;
3123 
3124 				CollisionPolysPtr++;
3125 		    	NumberOfCollisionPolys++;
3126 				/* ran out of space? */
3127 				LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
3128 	        }
3129         }
3130 
3131 	}
3132 
3133     return;
3134 }
TestObjectWithStaticBoundingBox(DISPLAYBLOCK * objectPtr)3135 static void TestObjectWithStaticBoundingBox(DISPLAYBLOCK *objectPtr)
3136 {
3137 
3138 	DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
3139 //	VECTORCH *objectPositionPtr = &(dynPtr->Position);
3140     /* if the bounding box does not intersect with the object at all just return */
3141 	VECTORCH *objectVerticesPtr = dynPtr->ObjectVertices;
3142 
3143    	if (!( ( (SBBMaxX >= objectVerticesPtr[7].vx) && (SBBMinX <= objectVerticesPtr[0].vx) )
3144    	     &&( (SBBMaxY >= objectVerticesPtr[7].vy) && (SBBMinY <= objectVerticesPtr[0].vy) )
3145          &&( (SBBMaxZ >= objectVerticesPtr[7].vz) && (SBBMinZ <= objectVerticesPtr[0].vz) ) ))
3146        	return;
3147 
3148     /* okay, let's access the objects polys */
3149 	{
3150 		const int *vertexIndexPtr=&CuboidVertexList[0];
3151 		int face=6;
3152 
3153 		do
3154 		{
3155 			CollisionPolysPtr->NumberOfVertices = 4;
3156 			CollisionPolysPtr->PolyPoint[0]=objectVerticesPtr[*vertexIndexPtr++];
3157 			CollisionPolysPtr->PolyPoint[1]=objectVerticesPtr[*vertexIndexPtr++];
3158 			CollisionPolysPtr->PolyPoint[2]=objectVerticesPtr[*vertexIndexPtr++];
3159 			CollisionPolysPtr->PolyPoint[3]=objectVerticesPtr[*vertexIndexPtr++];
3160 
3161 	        if(IsPolygonWithinStaticBoundingBox(CollisionPolysPtr))
3162 			{
3163 				if(dynPtr->DynamicsType == DYN_TYPE_CUBOID_COLLISIONS)
3164 				{
3165 					switch(face)
3166 					{
3167 						case 6: /* all points are on max y face */
3168 						{
3169 						    CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat21;
3170 						    CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat22;
3171 						    CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat23;
3172 							break;
3173 						}
3174 						case 5: /* all points are on max z face */
3175 						{
3176 						    CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat31;
3177 						    CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat32;
3178 						    CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat33;
3179 							break;
3180 						}
3181 						case 4: /* all points are on max x face */
3182 						{
3183 						    CollisionPolysPtr->PolyNormal.vx = dynPtr->OrientMat.mat11;
3184 						    CollisionPolysPtr->PolyNormal.vy = dynPtr->OrientMat.mat12;
3185 						    CollisionPolysPtr->PolyNormal.vz = dynPtr->OrientMat.mat13;
3186 							break;
3187 						}
3188 						case 3: /* all points are on min z face */
3189 						{
3190 						    CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat31;
3191 						    CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat32;
3192 						    CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat33;
3193 							break;
3194 						}
3195 						case 2: /* all points are on min x face */
3196 						{
3197 						    CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat11;
3198 						    CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat12;
3199 						    CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat13;
3200 							break;
3201 						}
3202 						case 1: /* all points are on min y face */
3203 						{
3204 						    CollisionPolysPtr->PolyNormal.vx = -dynPtr->OrientMat.mat21;
3205 						    CollisionPolysPtr->PolyNormal.vy = -dynPtr->OrientMat.mat22;
3206 						    CollisionPolysPtr->PolyNormal.vz = -dynPtr->OrientMat.mat23;
3207 							break;
3208 						}
3209 					}
3210 				}
3211 				else
3212 				{
3213 					switch(face)
3214 					{
3215 						case 6: /* all points are on max y face */
3216 						{
3217 						    CollisionPolysPtr->PolyNormal.vx = 0;
3218 						    CollisionPolysPtr->PolyNormal.vy = ONE_FIXED;
3219 						    CollisionPolysPtr->PolyNormal.vz = 0;
3220 							break;
3221 						}
3222 						case 5: /* all points are on max z face */
3223 						{
3224 						    CollisionPolysPtr->PolyNormal.vx = 0;
3225 						    CollisionPolysPtr->PolyNormal.vy = 0;
3226 						    CollisionPolysPtr->PolyNormal.vz = ONE_FIXED;
3227 							break;
3228 						}
3229 						case 4: /* all points are on max x face */
3230 						{
3231 						    CollisionPolysPtr->PolyNormal.vx = ONE_FIXED;
3232 						    CollisionPolysPtr->PolyNormal.vy = 0;
3233 						    CollisionPolysPtr->PolyNormal.vz = 0;
3234 							break;
3235 						}
3236 						case 3: /* all points are on min z face */
3237 						{
3238 						    CollisionPolysPtr->PolyNormal.vx = 0;
3239 						    CollisionPolysPtr->PolyNormal.vy = 0;
3240 						    CollisionPolysPtr->PolyNormal.vz = -ONE_FIXED;
3241 							break;
3242 						}
3243 						case 2: /* all points are on min x face */
3244 						{
3245 						    CollisionPolysPtr->PolyNormal.vx = -ONE_FIXED;
3246 						    CollisionPolysPtr->PolyNormal.vy = 0;
3247 						    CollisionPolysPtr->PolyNormal.vz = 0;
3248 							break;
3249 						}
3250 						case 1: /* all points are on min y face */
3251 						{
3252 						    CollisionPolysPtr->PolyNormal.vx = 0;
3253 						    CollisionPolysPtr->PolyNormal.vy = -ONE_FIXED;
3254 						    CollisionPolysPtr->PolyNormal.vz = 0;
3255 							break;
3256 						}
3257 					}
3258 				}
3259 	        	CollisionPolysPtr++;
3260 	        	NumberOfCollisionPolys++;
3261 
3262 				/* ran out of space? */
3263 				LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
3264 			}
3265 		}
3266 		while(--face);
3267 
3268 	}
3269     return;
3270 }
3271 
3272 
IsPolygonWithinDynamicBoundingBox(const struct ColPolyTag * polyPtr)3273 static int IsPolygonWithinDynamicBoundingBox(const struct ColPolyTag *polyPtr)
3274 {
3275 	VECTORCH *vertices = polyPtr->PolyPoint;
3276 
3277 	if (polyPtr->NumberOfVertices==4)
3278 	{
3279     	if (vertices[0].vy < DBBMinY)
3280         	if (vertices[1].vy < DBBMinY)
3281 	      		if (vertices[2].vy < DBBMinY)
3282 	      			if (vertices[3].vy < DBBMinY)
3283           				return 0;
3284 
3285     	if (vertices[0].vx < DBBMinX)
3286     		if (vertices[1].vx < DBBMinX)
3287     			if (vertices[2].vx < DBBMinX)
3288     				if (vertices[3].vx < DBBMinX)
3289           				return 0;
3290 
3291     	if (vertices[0].vx > DBBMaxX)
3292 	    	if (vertices[1].vx > DBBMaxX)
3293 	      		if (vertices[2].vx > DBBMaxX)
3294 	    			if (vertices[3].vx > DBBMaxX)
3295           				return 0;
3296 
3297     	if (vertices[0].vz < DBBMinZ)
3298 	    	if (vertices[1].vz < DBBMinZ)
3299 	      		if (vertices[2].vz < DBBMinZ)
3300 	      			if (vertices[3].vz < DBBMinZ)
3301           				return 0;
3302 
3303     	if (vertices[0].vz > DBBMaxZ)
3304 	    	if (vertices[1].vz > DBBMaxZ)
3305 	    		if (vertices[2].vz > DBBMaxZ)
3306 	    			if (vertices[3].vz > DBBMaxZ)
3307 	    				return 0;
3308 
3309     	if (vertices[0].vy > DBBMaxY)
3310 	    	if (vertices[1].vy > DBBMaxY)
3311 	    		if (vertices[2].vy > DBBMaxY)
3312 	    			if (vertices[3].vy > DBBMaxY)
3313         			  	return 0;
3314 
3315     }
3316     else
3317 	{
3318     	if (vertices[0].vy < DBBMinY)
3319         	if (vertices[1].vy < DBBMinY)
3320 	    		if (vertices[2].vy < DBBMinY)
3321           			return 0;
3322 
3323     	if (vertices[0].vx < DBBMinX)
3324 	    	if (vertices[1].vx < DBBMinX)
3325 	    		if (vertices[2].vx < DBBMinX)
3326         		  	return 0;
3327 
3328     	if (vertices[0].vx > DBBMaxX)
3329 	    	if (vertices[1].vx > DBBMaxX)
3330 	   			if (vertices[2].vx > DBBMaxX)
3331 		          	return 0;
3332 
3333     	if (vertices[0].vz < DBBMinZ)
3334 	  		if (vertices[1].vz < DBBMinZ)
3335 	   			if (vertices[2].vz < DBBMinZ)
3336           			return 0;
3337 
3338     	if (vertices[0].vz > DBBMaxZ)
3339 	    	if (vertices[1].vz > DBBMaxZ)
3340 	   			if (vertices[2].vz > DBBMaxZ)
3341 	    			return 0;
3342 
3343     	if (vertices[0].vy > DBBMaxY)
3344 	    	if (vertices[1].vy > DBBMaxY)
3345 	    		if (vertices[2].vy > DBBMaxY)
3346           			return 0;
3347 
3348     }
3349 
3350 
3351     return 1;
3352 }
3353 
IsPolygonWithinStaticBoundingBox(const struct ColPolyTag * polyPtr)3354 static int IsPolygonWithinStaticBoundingBox(const struct ColPolyTag *polyPtr)
3355 {
3356 	VECTORCH *vertices = polyPtr->PolyPoint;
3357 
3358 	if (polyPtr->NumberOfVertices==4)
3359 	{
3360     	if (vertices[0].vy < SBBMinY)
3361         	if (vertices[1].vy < SBBMinY)
3362 	      		if (vertices[2].vy < SBBMinY)
3363 	      			if (vertices[3].vy < SBBMinY)
3364           				return 0;
3365 
3366     	if (vertices[0].vx < SBBMinX)
3367     		if (vertices[1].vx < SBBMinX)
3368     			if (vertices[2].vx < SBBMinX)
3369     				if (vertices[3].vx < SBBMinX)
3370           				return 0;
3371 
3372     	if (vertices[0].vx > SBBMaxX)
3373 	    	if (vertices[1].vx > SBBMaxX)
3374 	      		if (vertices[2].vx > SBBMaxX)
3375 	    			if (vertices[3].vx > SBBMaxX)
3376           				return 0;
3377 
3378     	if (vertices[0].vz < SBBMinZ)
3379 	    	if (vertices[1].vz < SBBMinZ)
3380 	      		if (vertices[2].vz < SBBMinZ)
3381 	      			if (vertices[3].vz < SBBMinZ)
3382           				return 0;
3383 
3384     	if (vertices[0].vz > SBBMaxZ)
3385 	    	if (vertices[1].vz > SBBMaxZ)
3386 	    		if (vertices[2].vz > SBBMaxZ)
3387 	    			if (vertices[3].vz > SBBMaxZ)
3388 	    				return 0;
3389 
3390     	if (vertices[0].vy > SBBMaxY)
3391 	    	if (vertices[1].vy > SBBMaxY)
3392 	    		if (vertices[2].vy > SBBMaxY)
3393 	    			if (vertices[3].vy > SBBMaxY)
3394         			  	return 0;
3395 
3396     }
3397     else
3398 	{
3399     	if (vertices[0].vy < SBBMinY)
3400         	if (vertices[1].vy < SBBMinY)
3401 	    		if (vertices[2].vy < SBBMinY)
3402           			return 0;
3403 
3404     	if (vertices[0].vx < SBBMinX)
3405 	    	if (vertices[1].vx < SBBMinX)
3406 	    		if (vertices[2].vx < SBBMinX)
3407         		  	return 0;
3408 
3409     	if (vertices[0].vx > SBBMaxX)
3410 	    	if (vertices[1].vx > SBBMaxX)
3411 	   			if (vertices[2].vx > SBBMaxX)
3412 		          	return 0;
3413 
3414     	if (vertices[0].vz < SBBMinZ)
3415 	  		if (vertices[1].vz < SBBMinZ)
3416 	   			if (vertices[2].vz < SBBMinZ)
3417           			return 0;
3418 
3419     	if (vertices[0].vz > SBBMaxZ)
3420 	    	if (vertices[1].vz > SBBMaxZ)
3421 	   			if (vertices[2].vz > SBBMaxZ)
3422 	    			return 0;
3423 
3424     	if (vertices[0].vy > SBBMaxY)
3425 	    	if (vertices[1].vy > SBBMaxY)
3426 	    		if (vertices[2].vy > SBBMaxY)
3427           			return 0;
3428 
3429     }
3430 
3431 
3432     return 1;
3433 }
3434 
3435 
3436 
3437 
3438 
3439 
3440 
3441 
3442 
3443 
3444 /*KJL****************************************************************************
3445 * A function which takes a plane's normal and decides which axis to ignore when *
3446 * projecting points on the plane into a 2D space.                               *
3447 ****************************************************************************KJL*/
AxisToIgnore(VECTORCH * normal)3448 static int AxisToIgnore(VECTORCH *normal)
3449 {
3450 	VECTORCH absNormal = *normal;
3451 	if (absNormal.vx<0) absNormal.vx=-absNormal.vx;
3452 	if (absNormal.vy<0) absNormal.vy=-absNormal.vy;
3453 	if (absNormal.vz<0) absNormal.vz=-absNormal.vz;
3454 
3455 	if (absNormal.vx > absNormal.vy)
3456 	{
3457 		if (absNormal.vx > absNormal.vz)
3458 		{
3459 			return ix;
3460 		}
3461 		else
3462 		{
3463 			return iz;
3464 		}
3465 	}
3466 	else
3467 	{
3468 		if (absNormal.vy > absNormal.vz)
3469 		{
3470 			return iy;
3471 		}
3472 		else
3473 		{
3474 			return iz;
3475 		}
3476 	}
3477 }
3478 
3479 #if 0
3480 static void TestForValidMovement(STRATEGYBLOCK *sbPtr)
3481 {
3482 	#if 1
3483 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
3484 
3485 	/* I'm a platform lift - leave me alone */
3486 	if(dynPtr->OnlyCollideWithObjects)
3487 		return;
3488 
3489 	if(RelocationIsValid(sbPtr))
3490 	{
3491 		/* movement ok */
3492 	}
3493 	else
3494 	{
3495 		/* cancel movement */
3496 		//PrintDebuggingText("Relocate!");
3497 		dynPtr->Position=dynPtr->PrevPosition;
3498 		dynPtr->LinVelocity.vx = 0;
3499 		dynPtr->LinVelocity.vy = 0;
3500 		dynPtr->LinVelocity.vz = 0;
3501 	}
3502 	#endif
3503 }
3504 #endif
3505 
RelocateSphere(STRATEGYBLOCK * sbPtr)3506 static int RelocateSphere(STRATEGYBLOCK *sbPtr)
3507 {
3508 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
3509     VECTORCH objectPosition = dynPtr->Position;
3510     VECTORCH objectVertices[8];
3511 
3512     int polysLeft;
3513     struct ColPolyTag *polyPtr;
3514 
3515     polysLeft = NumberOfCollisionPolys;
3516    	polyPtr = CollisionPolysArray;
3517 
3518 	{
3519     	int vertexNum=8;
3520 		do
3521         {
3522 			vertexNum--;
3523 			objectVertices[vertexNum] = dynPtr->ObjectVertices[vertexNum];
3524 	    }
3525         while(vertexNum);
3526 	}
3527 
3528 	/* first pass relocate */
3529     while(polysLeft)
3530 	{
3531 	   	VECTORCH planeNormal = polyPtr->PolyNormal;
3532         VECTORCH pointOnPlane = polyPtr->PolyPoint[0];
3533         int distance;
3534 
3535         {
3536         	VECTORCH planeToObject;
3537 
3538 			planeToObject.vx = objectPosition.vx - pointOnPlane.vx;
3539 			planeToObject.vy = objectPosition.vy - pointOnPlane.vy;
3540 			planeToObject.vz = objectPosition.vz - pointOnPlane.vz;
3541 
3542     	    distance = dynPtr->CollisionRadius - Dot(&planeToObject,&planeNormal);
3543         }
3544 
3545 		if (distance>0 && DoesPolygonIntersectNRBB(polyPtr,objectVertices))
3546 		{
3547 			VECTORCH displacement;
3548 
3549 			displacement.vx = MUL_FIXED(planeNormal.vx,distance+RELOCATION_GRANULARITY);
3550 			displacement.vy = MUL_FIXED(planeNormal.vy,distance+RELOCATION_GRANULARITY);
3551 			displacement.vz = MUL_FIXED(planeNormal.vz,distance+RELOCATION_GRANULARITY);
3552 
3553 			AddVectorToVector(displacement,objectPosition);
3554 			{
3555 		    	int vertexNum=8;
3556 				VECTORCH *vertexPtr = objectVertices;
3557 
3558 		        do
3559 		        {
3560 					vertexPtr->vx += displacement.vx;
3561 					vertexPtr->vy += displacement.vy;
3562 					vertexPtr->vz += displacement.vz;
3563 					vertexPtr++;
3564 			    }
3565 		        while(--vertexNum);
3566 			}
3567 
3568 		}
3569 
3570         polyPtr++;
3571 		polysLeft--;
3572 	}
3573 
3574 	/* did we move at all? */
3575 	if ( (objectPosition.vx == dynPtr->Position.vx)
3576 	   &&(objectPosition.vy == dynPtr->Position.vy)
3577 	   &&(objectPosition.vz == dynPtr->Position.vz) )
3578 	   return 1;
3579 
3580  	/* pass test if okay */
3581 	polysLeft = NumberOfCollisionPolys;
3582 	polyPtr = CollisionPolysArray;
3583 
3584 	{
3585 		int stillIntersectingSomething = 0;
3586 		while(polysLeft)
3587 		{
3588 			{
3589 			   	VECTORCH planeNormal = polyPtr->PolyNormal;
3590 	    	    VECTORCH pointOnPlane = polyPtr->PolyPoint[0];
3591 	        	int distance;
3592 
3593 		        {
3594 		        	VECTORCH planeToObject;
3595 
3596 					planeToObject.vx = objectPosition.vx - pointOnPlane.vx;
3597 					planeToObject.vy = objectPosition.vy - pointOnPlane.vy;
3598 					planeToObject.vz = objectPosition.vz - pointOnPlane.vz;
3599 
3600 		    	    distance = dynPtr->CollisionRadius - Dot(&planeToObject,&planeNormal);
3601 		        }
3602 
3603 				if (distance>0 && DoesPolygonIntersectNRBB(polyPtr,objectVertices))
3604 				{
3605 					stillIntersectingSomething = 1;
3606 				}
3607 	        }
3608 	        polyPtr++;
3609 			polysLeft--;
3610 		}
3611 
3612 		if (stillIntersectingSomething)
3613 		{
3614 			return 0;
3615 		}
3616 		else
3617 		{
3618 	    	int vertexNum=8;
3619 			do
3620 	        {
3621 				vertexNum--;
3622 				dynPtr->ObjectVertices[vertexNum] = objectVertices[vertexNum];
3623 		    }
3624 	        while(vertexNum);
3625 			dynPtr->Position = objectPosition;
3626 			return 1;
3627 		}
3628 	}
3629 }
3630 
RelocateNRBB(STRATEGYBLOCK * sbPtr)3631 static int RelocateNRBB(STRATEGYBLOCK *sbPtr)
3632 {
3633 	int noProblems = 1;
3634 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
3635     VECTORCH objectPosition = dynPtr->Position;
3636     VECTORCH objectVertices[8];
3637     int polysLeft;
3638     struct ColPolyTag *polyPtr;
3639 
3640 	polysLeft = NumberOfCollisionPolys;
3641     polyPtr = CollisionPolysArray;
3642 
3643 	{
3644     	int vertexNum=8;
3645 		do
3646         {
3647 			vertexNum--;
3648 			objectVertices[vertexNum] = dynPtr->ObjectVertices[vertexNum];
3649 	    }
3650         while(vertexNum);
3651 	}
3652 
3653     while(polysLeft)
3654 	{
3655 	   	VECTORCH planeNormal = polyPtr->PolyNormal;
3656         VECTORCH pointOnPlane = polyPtr->PolyPoint[0];
3657 
3658         {
3659         	VECTORCH planeToObject;
3660 
3661 			planeToObject.vx = objectPosition.vx - pointOnPlane.vx;
3662 			planeToObject.vy = objectPosition.vy - pointOnPlane.vy;
3663 			planeToObject.vz = objectPosition.vz - pointOnPlane.vz;
3664 
3665     	    if (DotProduct(&planeToObject,&planeNormal) < 0)
3666     	    {
3667 		        polyPtr++;
3668 				polysLeft--;
3669     	    	continue;
3670 			}
3671         }
3672         {
3673 			int greatestDistance;
3674 
3675 	    	{
3676 	    		VECTORCH vertex = objectVertices[WhichNRBBVertex(dynPtr,&planeNormal)];
3677 				vertex.vx -= pointOnPlane.vx;
3678 				vertex.vy -= pointOnPlane.vy;
3679 				vertex.vz -= pointOnPlane.vz;
3680 				greatestDistance = -DotProduct(&vertex,&planeNormal);
3681 			}
3682 
3683 			if ((greatestDistance>0) && DoesPolygonIntersectNRBB(polyPtr,objectVertices))
3684 			{
3685 				#if 0
3686 				VECTORCH displacement;
3687 
3688 				displacement.vx = MUL_FIXED(planeNormal.vx,greatestDistance+RELOCATION_GRANULARITY);
3689 				displacement.vy = MUL_FIXED(planeNormal.vy,greatestDistance+RELOCATION_GRANULARITY);
3690 				displacement.vz = MUL_FIXED(planeNormal.vz,greatestDistance+RELOCATION_GRANULARITY);
3691 
3692 				AddVectorToVector(displacement,objectPosition);
3693 		    	{
3694 		        	int vertexNum=8;
3695 		    		VECTORCH *vertexPtr = objectVertices;
3696 
3697 		            do
3698 		            {
3699 						vertexPtr->vx += displacement.vx;
3700 						vertexPtr->vy += displacement.vy;
3701 						vertexPtr->vz += displacement.vz;
3702 						vertexPtr++;
3703 				    }
3704 		            while(--vertexNum);
3705 				}
3706 				#endif
3707 				/* create a report about the collision */
3708 				{
3709 					COLLISIONREPORT *reportPtr = AllocateCollisionReport(dynPtr);
3710 
3711 					if (reportPtr)
3712 					{
3713 						reportPtr->ObstacleSBPtr = 0;//obstacleSBPtr;
3714 						reportPtr->ObstacleNormal = planeNormal;
3715 
3716 						reportPtr->ObstaclePoint = pointOnPlane;
3717 					   //	reportPtr->ObstaclePoint.vx = 0x7fffffff;
3718 					   //	reportPtr->ObstaclePoint.vy = 0x7fffffff;
3719 					   //	reportPtr->ObstaclePoint.vz = 0x7fffffff;
3720 					}
3721 				}
3722 	   			noProblems = 0;
3723 
3724 			}
3725 		}
3726         polyPtr++;
3727 		polysLeft--;
3728 	}
3729 	#if 0
3730 	/* did we move at all? */
3731 	if ( (objectPosition.vx == dynPtr->Position.vx)
3732 	   &&(objectPosition.vy == dynPtr->Position.vy)
3733 	   &&(objectPosition.vz == dynPtr->Position.vz) )
3734 	   return noProblems;
3735 
3736 
3737  	/* pass test if okay */
3738     polysLeft = NumberOfCollisionPolys;
3739     polyPtr = CollisionPolysArray;
3740 
3741 	{
3742 		while(polysLeft)
3743 		{
3744 	        if(DoesPolygonIntersectNRBB(polyPtr,objectVertices))
3745 	        {
3746 			   	VECTORCH planeNormal = polyPtr->PolyNormal;
3747 		        VECTORCH pointOnPlane = polyPtr->PolyPoint[0];
3748 				int greatestDistance;
3749 
3750 		    	{
3751 		    		VECTORCH vertex = objectVertices[WhichNRBBVertex(dynPtr,&planeNormal)];
3752 					vertex.vx -= pointOnPlane.vx;
3753 					vertex.vy -= pointOnPlane.vy;
3754 					vertex.vz -= pointOnPlane.vz;
3755 					greatestDistance = -DotProduct(&vertex,&planeNormal);
3756 				}
3757 
3758 				if (greatestDistance>0)
3759 				{
3760 					/* still intersecting something */
3761 					return noProblems;
3762 				}
3763 	        }
3764 	        polyPtr++;
3765 			polysLeft--;
3766 		}
3767 
3768 		{
3769 	    	int vertexNum=8;
3770 			do
3771 	        {
3772 				vertexNum--;
3773 				dynPtr->ObjectVertices[vertexNum] = objectVertices[vertexNum];
3774 		    }
3775 	        while(vertexNum);
3776 			dynPtr->Position = objectPosition;
3777 			return 1;
3778 		}
3779 	}
3780 	#endif
3781 	if (!noProblems) PrintDebuggingText("RECOMMEND RELOCATE\n");
3782 	return noProblems;
3783 }
3784 
3785 
DoesPolygonIntersectNRBB(struct ColPolyTag * polyPtr,VECTORCH * objectVertices)3786 static int DoesPolygonIntersectNRBB(struct ColPolyTag *polyPtr,VECTORCH *objectVertices)
3787 {
3788 	VECTORCH *minVertexPtr = &objectVertices[7];
3789 	VECTORCH *vertices = polyPtr->PolyPoint;
3790 
3791   	/* trivial rejection tests */
3792 	if (polyPtr->NumberOfVertices==4)
3793 	{
3794     	if (vertices[0].vx < minVertexPtr->vx)
3795     		if (vertices[1].vx < minVertexPtr->vx)
3796     			if (vertices[2].vx < minVertexPtr->vx)
3797     				if (vertices[3].vx < minVertexPtr->vx)
3798           				return 0;
3799 
3800     	if (vertices[0].vz < minVertexPtr->vz)
3801 	    	if (vertices[1].vz < minVertexPtr->vz)
3802 	      		if (vertices[2].vz < minVertexPtr->vz)
3803 	      			if (vertices[3].vz < minVertexPtr->vz)
3804           				return 0;
3805 
3806     	if (vertices[0].vy < minVertexPtr->vy)
3807         	if (vertices[1].vy < minVertexPtr->vy)
3808 	      		if (vertices[2].vy < minVertexPtr->vy)
3809 	      			if (vertices[3].vy < minVertexPtr->vy)
3810           				return 0;
3811 
3812 
3813     	if (vertices[0].vx > objectVertices->vx)
3814 	    	if (vertices[1].vx > objectVertices->vx)
3815 	      		if (vertices[2].vx > objectVertices->vx)
3816 	    			if (vertices[3].vx > objectVertices->vx)
3817           				return 0;
3818 
3819     	if (vertices[0].vz > objectVertices->vz)
3820 	    	if (vertices[1].vz > objectVertices->vz)
3821 	    		if (vertices[2].vz > objectVertices->vz)
3822 	    			if (vertices[3].vz > objectVertices->vz)
3823 	    				return 0;
3824 
3825     	if (vertices[0].vy > objectVertices->vy)
3826 	    	if (vertices[1].vy > objectVertices->vy)
3827 	    		if (vertices[2].vy > objectVertices->vy)
3828 	    			if (vertices[3].vy > objectVertices->vy)
3829         			  	return 0;
3830 
3831     }
3832     else
3833 	{
3834     	if (vertices[0].vx < minVertexPtr->vx)
3835     		if (vertices[1].vx < minVertexPtr->vx)
3836     			if (vertices[2].vx < minVertexPtr->vx)
3837           				return 0;
3838 
3839     	if (vertices[0].vz < minVertexPtr->vz)
3840 	    	if (vertices[1].vz < minVertexPtr->vz)
3841 	      		if (vertices[2].vz < minVertexPtr->vz)
3842           				return 0;
3843 
3844     	if (vertices[0].vy < minVertexPtr->vy)
3845         	if (vertices[1].vy < minVertexPtr->vy)
3846 	      		if (vertices[2].vy < minVertexPtr->vy)
3847           				return 0;
3848 
3849 
3850     	if (vertices[0].vx > objectVertices->vx)
3851 	    	if (vertices[1].vx > objectVertices->vx)
3852 	      		if (vertices[2].vx > objectVertices->vx)
3853           				return 0;
3854 
3855     	if (vertices[0].vz > objectVertices->vz)
3856 	    	if (vertices[1].vz > objectVertices->vz)
3857 	    		if (vertices[2].vz > objectVertices->vz)
3858 	    				return 0;
3859 
3860     	if (vertices[0].vy > objectVertices->vy)
3861 	    	if (vertices[1].vy > objectVertices->vy)
3862 	    		if (vertices[2].vy > objectVertices->vy)
3863         			  	return 0;
3864     }
3865 
3866    	/* are any of the poly's vertices inside the object's bounding box? */
3867 	{
3868     	if (vertices[0].vy >= minVertexPtr->vy)
3869 			if (vertices[0].vy <= objectVertices->vy)
3870     			if (vertices[0].vx >= minVertexPtr->vx)
3871 		  			if (vertices[0].vx <= objectVertices->vx)
3872 	    				if (vertices[0].vz >= minVertexPtr->vz)
3873 				    		if (vertices[0].vz <= objectVertices->vz)
3874        								return 1;
3875     	if (vertices[1].vy >= minVertexPtr->vy)
3876 			if (vertices[1].vy <= objectVertices->vy)
3877     			if (vertices[1].vx >= minVertexPtr->vx)
3878 		  			if (vertices[1].vx <= objectVertices->vx)
3879 	    				if (vertices[1].vz >= minVertexPtr->vz)
3880 				    		if (vertices[1].vz <= objectVertices->vz)
3881        								return 1;
3882     	if (vertices[2].vy >= minVertexPtr->vy)
3883 			if (vertices[2].vy <= objectVertices->vy)
3884     			if (vertices[2].vx >= minVertexPtr->vx)
3885 		  			if (vertices[2].vx <= objectVertices->vx)
3886 	    				if (vertices[2].vz >= minVertexPtr->vz)
3887 				    		if (vertices[2].vz <= objectVertices->vz)
3888        								return 1;
3889     }
3890 	if (polyPtr->NumberOfVertices==4)
3891 	{
3892     	if (vertices[3].vy >= minVertexPtr->vy)
3893 			if (vertices[3].vy <= objectVertices->vy)
3894     			if (vertices[3].vx >= minVertexPtr->vx)
3895 		  			if (vertices[3].vx <= objectVertices->vx)
3896 	    				if (vertices[3].vz >= minVertexPtr->vz)
3897 				    		if (vertices[3].vz <= objectVertices->vz)
3898        								return 1;
3899     }
3900 
3901 	/* okay, it's not that simple then. Let's see if any of the poly's edges
3902 	   intersect the objects bounding box */
3903 	{
3904 	    int vertexA = polyPtr->NumberOfVertices;
3905 		do
3906 		{
3907 			VECTORCH alpha,beta;
3908 			int vertexB;
3909 			vertexA--;
3910 			vertexB = (vertexA+1)%(polyPtr->NumberOfVertices);
3911 
3912 			alpha = vertices[vertexA];
3913 			beta.vx = vertices[vertexB].vx - alpha.vx;
3914 			beta.vy = vertices[vertexB].vy - alpha.vy;
3915 			beta.vz = vertices[vertexB].vz - alpha.vz;
3916 
3917 			/* edge is the line segment 'alpha + lambda*beta' where lambda is between 0 and 1 */
3918 			if (beta.vy!=0)
3919 			{
3920 				{
3921 					/* box edge 1:  y=minVertexPtr->vy; normal is (0,-1,0) */
3922 				   	int lambda;
3923 
3924 					f2i(lambda,(float)(minVertexPtr->vy - alpha.vy)/(float)beta.vy*65536.0f);
3925 
3926 					/* eliminate the divides? */
3927 					if (lambda>=0 && lambda <= 65536)
3928 					{
3929 						int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
3930 						if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
3931 						{
3932 							int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
3933 							if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
3934 								return 1;
3935 						}
3936 					}
3937 				}
3938 				{
3939 					/* box edge 2:  y=objectVertices->vy; normal is (0,1,0) */
3940 					int lambda;// = DIV_FIXED(objectVertices->vy - (alpha.vy),(beta.vy) );
3941 					f2i(lambda,(float)(objectVertices->vy - alpha.vy)/(float)beta.vy*65536.0f);
3942 					/* eliminate the divides? */
3943 					if (lambda>=0 && lambda <= 65536)
3944 					{
3945 						int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
3946 						if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
3947 						{
3948 							int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
3949 							if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
3950 								return 1;
3951 						}
3952 					}
3953 				}
3954 			}
3955 			if (beta.vx!=0)
3956 			{
3957 				{
3958 					/* box edge 3:  x=minVertexPtr->vx; normal is (-1,0,0) */
3959 					int lambda;// = DIV_FIXED(minVertexPtr->vx - (alpha.vx),(beta.vx) );
3960 					f2i(lambda,(float)(minVertexPtr->vx - alpha.vx)/(float)beta.vx*65536.0f);
3961 					/* eliminate the divides? */
3962 					if (lambda>=0 && lambda <= 65536)
3963 					{
3964 						int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
3965 						if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
3966 						{
3967 							int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
3968 							if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
3969 								return 1;
3970 						}
3971 					}
3972 				}
3973 				{
3974 					/* box edge 4:  x=objectVertices->vx; normal is (1,0,0) */
3975 					int lambda;// = DIV_FIXED(objectVertices->vx - (alpha.vx),(beta.vx) );
3976 					f2i(lambda,(float)(objectVertices->vx - alpha.vx)/(float)beta.vx*65536.0f);
3977 					/* eliminate the divides? */
3978 					if (lambda>=0 && lambda <= 65536)
3979 					{
3980 						int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
3981 						if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
3982 						{
3983 							int intersectionZ = alpha.vz + MUL_FIXED(lambda,beta.vz);
3984 							if (intersectionZ >= minVertexPtr->vz && intersectionZ <= objectVertices->vz)
3985 								return 1;
3986 						}
3987 					}
3988 				}
3989 			}
3990 			if (beta.vz!=0)
3991 			{
3992 				{
3993 					/* box edge 5:  z=minVertexPtr->vz; normal is (0,0,-1) */
3994 					int lambda;// = DIV_FIXED(minVertexPtr->vz - (alpha.vz),(beta.vz));
3995 					f2i(lambda,(float)(minVertexPtr->vz - alpha.vz)/(float)beta.vz*65536.0f);
3996 					/* eliminate the divides? */
3997 					if (lambda>=0 && lambda <= 65536)
3998 					{
3999 						int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
4000 						if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
4001 						{
4002 							int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
4003 							if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
4004 								return 1;
4005 						}
4006 					}
4007 				}
4008 				{
4009 					/* box edge 6:  z=objectVertices->vz; normal is (0,0,1) */
4010 					int lambda;// = DIV_FIXED(objectVertices->vz - (alpha.vz),(beta.vz));
4011 					f2i(lambda,(float)(objectVertices->vz - alpha.vz)/(float)beta.vz*65536.0f);
4012 					/* eliminate the divides? */
4013 					if (lambda>=0 && lambda <= 65536)
4014 					{
4015 						int intersectionY = alpha.vy + MUL_FIXED(lambda,beta.vy);
4016 						if (intersectionY >= minVertexPtr->vy && intersectionY <= objectVertices->vy)
4017 						{
4018 							int intersectionX = alpha.vx + MUL_FIXED(lambda,beta.vx);
4019 							if (intersectionX >= minVertexPtr->vx && intersectionX <= objectVertices->vx)
4020 								return 1;
4021 						}
4022 					}
4023 				}
4024 			}
4025 
4026 		}
4027 		while(vertexA);
4028 	}
4029 	/* Still here? Damn. Okay, we'll have to check to see if a cuboid's diagonal intersect the polygon */
4030 	{
4031 		VECTORCH alpha,beta;
4032 		int dottedNormals;
4033 		int lambda;
4034 
4035 		if ((polyPtr->PolyNormal).vx > 0)
4036 		{
4037 			alpha.vx = minVertexPtr->vx;
4038 			beta.vx = objectVertices->vx - alpha.vx;
4039 		}
4040 		else
4041 		{
4042 			alpha.vx = objectVertices->vx;
4043 			beta.vx = minVertexPtr->vx - alpha.vx;
4044 		}
4045 
4046 		if ((polyPtr->PolyNormal).vy > 0)
4047 		{
4048 			alpha.vy = minVertexPtr->vy;
4049 			beta.vy = objectVertices->vy - alpha.vy;
4050 		}
4051 		else
4052 		{
4053 			alpha.vy = objectVertices->vy;
4054 			beta.vy = minVertexPtr->vy - alpha.vy;
4055 		}
4056 
4057 		if ((polyPtr->PolyNormal).vz > 0)
4058 		{
4059 			alpha.vz = minVertexPtr->vz;
4060 			beta.vz = objectVertices->vz - alpha.vz;
4061 		}
4062 		else
4063 		{
4064 			alpha.vz = objectVertices->vz;
4065 			beta.vz = minVertexPtr->vz - alpha.vz;
4066 		}
4067 
4068 		dottedNormals = DotProduct(&(polyPtr->PolyNormal),&beta);
4069 		#if 1//debug
4070 		if (!dottedNormals)
4071 		{
4072 			#if 0
4073 			char buffer[200];
4074 			sprintf(buffer,"POLY NORMAL IS %d %d %d\n",(polyPtr->PolyNormal).vx,(polyPtr->PolyNormal).vy,(polyPtr->PolyNormal).vz);
4075 			NewOnScreenMessage(buffer);
4076 			sprintf(buffer,"POLY NO OF VERTICES %d\n",(polyPtr->NumberOfVertices));
4077 			NewOnScreenMessage(buffer);
4078 			sprintf(buffer,"POLY POINT IS %d %d %d\n",(polyPtr->PolyPoint[0]).vx,(polyPtr->PolyPoint[0]).vy,(polyPtr->PolyPoint[0]).vz);
4079 			NewOnScreenMessage(buffer);
4080 			#endif
4081 			LOGDXFMT(( "POLY NORMAL IS %d %d %d\n",(polyPtr->PolyNormal).vx,(polyPtr->PolyNormal).vy,(polyPtr->PolyNormal).vz));
4082 			LOGDXFMT(( "POLY NO OF VERTICES %d\n",polyPtr->NumberOfVertices));
4083 			LOGDXFMT(( "POLY POINT IS %d %d %d\n",(polyPtr->PolyPoint[0]).vx,(polyPtr->PolyPoint[0]).vy,(polyPtr->PolyPoint[0]).vz ));
4084 			LOCALASSERT("Found normal which may be incorrect"==0);
4085 			return 0;
4086 		}
4087 		#endif
4088 		{
4089 			VECTORCH cornerToPlane;
4090 			cornerToPlane.vx = vertices[0].vx - alpha.vx;
4091 			cornerToPlane.vy = vertices[0].vy - alpha.vy;
4092 			cornerToPlane.vz = vertices[0].vz - alpha.vz;
4093 			lambda = DIV_FIXED
4094 			(
4095 				DotProduct(&(polyPtr->PolyNormal),&cornerToPlane),
4096 				dottedNormals
4097 			);
4098 	  	}
4099 
4100 		if (lambda >= 0 && lambda <= 65536)
4101 		{
4102 			int axis1,axis2;
4103 			/* decide which 2d plane to project onto */
4104 			{
4105 				VECTORCH absNormal = (polyPtr->PolyNormal);
4106 				if (absNormal.vx<0) absNormal.vx=-absNormal.vx;
4107 				if (absNormal.vy<0) absNormal.vy=-absNormal.vy;
4108 				if (absNormal.vz<0) absNormal.vz=-absNormal.vz;
4109 
4110 				if (absNormal.vx > absNormal.vy)
4111 				{
4112 					if (absNormal.vx > absNormal.vz)
4113 					{
4114 						axis1=iy;
4115 						axis2=iz;
4116 					}
4117 					else
4118 					{
4119 						axis1=ix;
4120 						axis2=iy;
4121 					}
4122 				}
4123 				else
4124 				{
4125 					if (absNormal.vy > absNormal.vz)
4126 					{
4127 						axis1=ix;
4128 						axis2=iz;
4129 					}
4130 					else
4131 					{
4132 						axis1=ix;
4133 						axis2=iy;
4134 					}
4135 				}
4136 			}
4137 
4138 
4139 			{
4140 				int projectedPolyVertex[20];
4141 				int projectedPointOnPlane[2];
4142 
4143 				projectedPointOnPlane[0]=*((int*)&alpha+axis1) + MUL_FIXED(lambda,*((int*)&beta+axis1));
4144 			 	projectedPointOnPlane[1]=*((int*)&alpha+axis2) + MUL_FIXED(lambda,*((int*)&beta+axis2));
4145 
4146 			 	{
4147 			 		VECTORCH *vertexPtr = &vertices[0];
4148 			 		int *projectedVertexPtr= &projectedPolyVertex[0];
4149 					int noOfVertices = polyPtr->NumberOfVertices;
4150 
4151 					do
4152 					{
4153 			 			*projectedVertexPtr++ = *((int*)vertexPtr + axis1);
4154 			 			*projectedVertexPtr++ = *((int*)vertexPtr + axis2);
4155 
4156 		 	 		   	vertexPtr++;
4157 			 		}
4158 	                while(--noOfVertices);
4159 
4160 			 	}
4161 
4162 
4163 				if (PointInPolygon(&projectedPointOnPlane[0],&projectedPolyVertex[0],polyPtr->NumberOfVertices,2))
4164 					return 1;
4165 			}
4166 		}
4167 	}
4168 	/* after all that we can be sure that the polygon isn't intersecting the object */
4169     return 0;
4170 }
4171 
4172 
WhichNRBBVertex(DYNAMICSBLOCK * dynPtr,VECTORCH * normalPtr)4173 static int WhichNRBBVertex(DYNAMICSBLOCK *dynPtr, VECTORCH *normalPtr)
4174 {
4175 	VECTORCH dir;
4176 
4177 	dir.vx = -normalPtr->vx;
4178 	dir.vy = -normalPtr->vy;
4179 	dir.vz = -normalPtr->vz;
4180 
4181 	if (dir.vx>=0)
4182 	{
4183 		if (dir.vy>=0)
4184 		{
4185 			if (dir.vz>=0)
4186 			{
4187 				/* +ve x +ve y +ve z */
4188 				return 0;
4189 			}
4190 			else
4191 			{
4192 				/* +ve x +ve y -ve z */
4193 				return 1;
4194 			}
4195 		}
4196 		else
4197 		{
4198 			if (dir.vz>=0)
4199 			{
4200 				/* +ve x -ve y +ve z */
4201 				return 2;
4202 			}
4203 			else
4204 			{
4205 				/* +ve x -ve y -ve z */
4206 				return 3;
4207 			}
4208 		}
4209 	}
4210 	else
4211 	{
4212 		if (dir.vy>=0)
4213 		{
4214 			if (dir.vz>=0)
4215 			{
4216 				/* -ve x +ve y +ve z */
4217 				return 4;
4218 			}
4219 			else
4220 			{
4221 				/* -ve x +ve y -ve z */
4222 				return 5;
4223 			}
4224 		}
4225 		else
4226 		{
4227 			if (dir.vz>=0)
4228 			{
4229 				/* -ve x -ve y +ve z */
4230 				return 6;
4231 			}
4232 			else
4233 			{
4234 				/* -ve x -ve y -ve z */
4235 				return 7;
4236 			}
4237 		}
4238 	}
4239 }
4240 
4241 
4242 
4243 
4244 
4245 
4246 
DistanceMovedBeforeSphereHitsPolygon(DYNAMICSBLOCK * dynPtr,struct ColPolyTag * polyPtr,int distanceToMove)4247 static signed int DistanceMovedBeforeSphereHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4248 {
4249     int dottedNormals;
4250 	int sphereToPolyDist;
4251 
4252 	LOCALASSERT(polyPtr);
4253 
4254     dottedNormals = -DotProduct(&DirectionOfTravel,&(polyPtr->PolyNormal));
4255 
4256 	/* reject if polygon does not face against direction of sphere's travel */
4257 	if (dottedNormals<=0)
4258 	{
4259 		return -1;
4260 	}
4261 
4262     /* calculate distance each vertex is from poly's plane along direction of motion */
4263     {
4264 		VECTORCH sphereToPoly;
4265 
4266 		sphereToPoly.vx = dynPtr->Position.vx - polyPtr->PolyPoint[0].vx;
4267 		sphereToPoly.vy = dynPtr->Position.vy - polyPtr->PolyPoint[0].vy;
4268 		sphereToPoly.vz = dynPtr->Position.vz - polyPtr->PolyPoint[0].vz;
4269 
4270 	    sphereToPolyDist = DotProduct(&sphereToPoly,&(polyPtr->PolyNormal))-dynPtr->CollisionRadius;
4271 	}
4272 	/* reject if polygon is 'behind' sphere */
4273 	if (sphereToPolyDist<0)
4274 	{
4275 		#if 0
4276 		if (sphereToPolyDist>-dynPtr->CollisionRadius)
4277 		{
4278 			VECTORCH projectedPosition;
4279 
4280 		   	projectedPosition.vx = dynPtr->Position.vx + MUL_FIXED(sphereToPolyDist,polyPtr->PolyNormal.vx);
4281 		   	projectedPosition.vy = dynPtr->Position.vy + MUL_FIXED(sphereToPolyDist,polyPtr->PolyNormal.vy);
4282 		   	projectedPosition.vz = dynPtr->Position.vz + MUL_FIXED(sphereToPolyDist,polyPtr->PolyNormal.vz);
4283 
4284 		 	if (DoesSphereProjectOntoPoly(dynPtr, polyPtr, &projectedPosition))
4285 			{
4286 		  		textprint("RELOCATION CASE\n");
4287 			}
4288 		}
4289 		#endif
4290 		return -2;
4291 	}
4292 
4293   	/* calculate distance along direction of travel */
4294 
4295 	sphereToPolyDist = DIV_FIXED(sphereToPolyDist,dottedNormals);
4296 
4297 	if (sphereToPolyDist>=distanceToMove)
4298 	{
4299 		return -4;
4300 	}
4301 
4302 	/* test if sphere's projected path intersect polygon */
4303 	{
4304 		VECTORCH projectedPosition;
4305 	   	projectedPosition.vx = dynPtr->Position.vx + MUL_FIXED(DirectionOfTravel.vx, sphereToPolyDist) - MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vx);
4306 	   	projectedPosition.vy = dynPtr->Position.vy + MUL_FIXED(DirectionOfTravel.vy, sphereToPolyDist) - MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vy);
4307 	   	projectedPosition.vz = dynPtr->Position.vz + MUL_FIXED(DirectionOfTravel.vz, sphereToPolyDist) - MUL_FIXED(dynPtr->CollisionRadius,polyPtr->PolyNormal.vz);
4308 
4309 
4310 		if (SphereProjectOntoPoly(dynPtr, polyPtr, &projectedPosition))
4311 		{
4312 			return sphereToPolyDist;
4313 		}
4314 	}
4315 	/* polygon not in way of sphere */
4316 	return -5;
4317 }
4318 
4319 
SphereProjectOntoPoly(DYNAMICSBLOCK * dynPtr,struct ColPolyTag * polyPtr,VECTORCH * projectedPosition)4320 static int SphereProjectOntoPoly(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, VECTORCH *projectedPosition)
4321 {
4322 	/* decide which 2d plane to project onto */
4323 	int axisToIgnore = AxisToIgnore(&polyPtr->PolyNormal);
4324 
4325     if (axisToIgnore!=ix)
4326     {
4327     	int polyMax,polyMin;
4328 
4329     	/* search x-coords of poly vertices for min and max */
4330         {
4331 	    	int vertexNum=polyPtr->NumberOfVertices;
4332 
4333 	    	polyMax = polyMin = polyPtr->PolyPoint[0].vx;
4334 			do
4335 			{
4336 	        	int x;
4337 				vertexNum--;
4338 	        	x = polyPtr->PolyPoint[vertexNum].vx;
4339 	        	if (x > polyMax) polyMax = x;
4340 	        	else if (x < polyMin) polyMin = x;
4341 	        }
4342             while(vertexNum);
4343 		}
4344 
4345         /* test to see if object & polygon overlap */
4346         if (projectedPosition->vx+dynPtr->CollisionRadius < polyMin || projectedPosition->vx-dynPtr->CollisionRadius > polyMax)
4347         	return 0;
4348     }
4349     if (axisToIgnore!=iz)
4350     {
4351     	int polyMax,polyMin;
4352 
4353     	/* search z-coords of poly vertices for min and max */
4354         {
4355 	    	int vertexNum=polyPtr->NumberOfVertices;
4356 
4357 	    	polyMax = polyMin = polyPtr->PolyPoint[0].vz;
4358 	        do
4359 	        {
4360 	        	int z;
4361 				vertexNum--;
4362 	        	z = polyPtr->PolyPoint[vertexNum].vz;
4363 	        	if (z > polyMax) polyMax = z;
4364 	        	else if (z < polyMin) polyMin = z;
4365 	        }
4366             while(vertexNum);
4367 		}
4368 
4369         /* test to see if object & polygon overlap */
4370         if (projectedPosition->vz+dynPtr->CollisionRadius < polyMin || projectedPosition->vz-dynPtr->CollisionRadius > polyMax)
4371         	return 0;
4372     }
4373     if (axisToIgnore!=iy)
4374     {
4375     	int polyMax,polyMin;
4376 
4377     	/* search y-coords of poly vertices for min and max */
4378         {
4379 	    	int vertexNum=polyPtr->NumberOfVertices;
4380 
4381 	    	polyMax = polyMin = polyPtr->PolyPoint[0].vy;
4382 	        do
4383 	        {
4384 				int y;
4385 				vertexNum--;
4386 
4387 				y = polyPtr->PolyPoint[vertexNum].vy;
4388 	        	if (y > polyMax) polyMax = y;
4389 	        	else if (y < polyMin) polyMin = y;
4390 	        }
4391             while(vertexNum);
4392 		}
4393 
4394         /* test to see if object & polygon overlap */
4395         if (projectedPosition->vy+dynPtr->CollisionRadius < polyMin || projectedPosition->vy-dynPtr->CollisionRadius > polyMax)
4396         	return 0;
4397 
4398 		#if 1
4399     	/* test for a 'step' in front of object */
4400         {
4401 	        int heightOfStep = projectedPosition->vy+dynPtr->CollisionRadius - polyMin;  /* y-axis is +ve downwards, remember */
4402 	        if (heightOfStep < MAXIMUM_STEP_HEIGHT) /* we've hit a 'step' - move player upwards */
4403 	        {
4404 	   			DistanceToStepUp=heightOfStep+COLLISION_GRANULARITY;
4405 		        LOCALASSERT(heightOfStep>0);
4406 	        }
4407 		}
4408 		#endif
4409     }
4410 
4411 
4412     return 1;
4413 }
4414 
4415 
DistanceMovedBeforeNRBBHitsPolygon(DYNAMICSBLOCK * dynPtr,struct ColPolyTag * polyPtr,int distanceToMove)4416 static signed int DistanceMovedBeforeNRBBHitsPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4417 {
4418   	VECTORCH polyNormal;
4419     int dottedNormals;
4420 	int obstacleDistance= 0x7fffffff;
4421     int vertexToPlaneDist[8];
4422 
4423 	LOCALASSERT(polyPtr);
4424 
4425 	polyNormal = polyPtr->PolyNormal;
4426 
4427 	#if 0
4428 	if (polyNormal.vy<=-65500)
4429 		return DistanceMovedBeforeNRBBHitsNegYPolygon(dynPtr, polyPtr, distanceToMove);
4430 	else if (polyNormal.vy>=65500)
4431 		return DistanceMovedBeforeNRBBHitsPosYPolygon(dynPtr, polyPtr, distanceToMove);
4432 	else if (polyNormal.vx>=65500)
4433 		return DistanceMovedBeforeNRBBHitsPosXPolygon(dynPtr, polyPtr, distanceToMove);
4434 	else if (polyNormal.vx<=-65500)
4435 		return DistanceMovedBeforeNRBBHitsNegXPolygon(dynPtr, polyPtr, distanceToMove);
4436 	else if (polyNormal.vz>=65500)
4437 		return DistanceMovedBeforeNRBBHitsPosZPolygon(dynPtr, polyPtr, distanceToMove);
4438 	else if (polyNormal.vz<=-65500)
4439 		return DistanceMovedBeforeNRBBHitsNegZPolygon(dynPtr, polyPtr, distanceToMove);
4440 	#endif
4441 
4442     dottedNormals = -DotProduct(&DirectionOfTravel,&polyNormal);
4443 	if (dottedNormals<=0) return -1; /* reject poly */
4444 
4445     /* calculate distance each vertex is from poly's plane along direction of motion */
4446     {
4447 		VECTORCH polyPoint = polyPtr->PolyPoint[0];
4448 	    int originToPlaneDist = DotProduct(&polyPoint,&polyNormal);
4449 
4450     	{
4451         	int vertexNum=8;
4452             do
4453             {
4454             	vertexNum--;
4455 
4456 	        	vertexToPlaneDist[vertexNum] =
4457 	        		DotProduct(&dynPtr->ObjectVertices[vertexNum],&polyNormal) - originToPlaneDist;
4458 
4459 				if (vertexToPlaneDist[vertexNum] < 0) return -1;
4460 	        }
4461 			while(vertexNum);
4462 	    }
4463 
4464 
4465 		{
4466         	int vertexNum=8;
4467 			int *distancePtr = vertexToPlaneDist;
4468             do
4469             {
4470 				*distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4471 
4472 				if(*distancePtr < obstacleDistance)
4473 					obstacleDistance = *distancePtr;
4474 
4475 				distancePtr++;
4476 		    }
4477             while(--vertexNum);
4478 
4479 		}
4480 	}
4481 	if (obstacleDistance>=distanceToMove)
4482 		return -2;
4483 
4484 	/* test if any vertices projected paths intersect polygons */
4485 	if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4486 	{
4487 		return obstacleDistance;
4488 	}
4489 
4490 	return -3;
4491 }
4492 #if 0
4493 static signed int DistanceMovedBeforeNRBBHitsNegYPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4494 {
4495     int dottedNormals;
4496 	int obstacleDistance= 0x7fffffff;
4497     int vertexToPlaneDist[8];
4498 
4499 	LOCALASSERT(polyPtr);
4500 
4501     dottedNormals = DirectionOfTravel.vy;
4502 	if (dottedNormals<=0) return -1; /* reject poly */
4503 
4504     /* calculate distance each vertex is from poly's plane along direction of motion */
4505     {
4506 	    int originToPlaneDist = -polyPtr->PolyPoint[0].vy;
4507 
4508     	{
4509         	int vertexNum=8;
4510             do
4511             {
4512             	vertexNum--;
4513 
4514 	        	vertexToPlaneDist[vertexNum] = -dynPtr->ObjectVertices[vertexNum].vy - originToPlaneDist;
4515 
4516 				if (vertexToPlaneDist[vertexNum] < 0)
4517 				{
4518 					return -1;
4519 				}
4520 	        }
4521 			while(vertexNum);
4522 	    }
4523 
4524 
4525 		{
4526         	int vertexNum=8;
4527 			int *distancePtr = vertexToPlaneDist;
4528             do
4529             {
4530 				*distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4531 
4532 				if(*distancePtr < obstacleDistance)
4533 					obstacleDistance = *distancePtr;
4534 
4535 				distancePtr++;
4536 		    }
4537             while(--vertexNum);
4538 
4539 		}
4540 	}
4541 	if (obstacleDistance>=distanceToMove)
4542 		return -2;
4543 
4544 	/* test if any vertices projected paths intersect polygons */
4545 	if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4546 	{
4547 		return obstacleDistance;
4548 	}
4549 
4550 	return -3;
4551 }
4552 
4553 static signed int DistanceMovedBeforeNRBBHitsPosYPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4554 {
4555     int dottedNormals;
4556 	int obstacleDistance= 0x7fffffff;
4557     int vertexToPlaneDist[8];
4558 
4559 	LOCALASSERT(polyPtr);
4560 
4561     dottedNormals = -DirectionOfTravel.vy;
4562 	if (dottedNormals<=0) return -1; /* reject poly */
4563 
4564     /* calculate distance each vertex is from poly's plane along direction of motion */
4565     {
4566 	    int originToPlaneDist = polyPtr->PolyPoint[0].vy;
4567 
4568     	{
4569         	int vertexNum=8;
4570             do
4571             {
4572             	vertexNum--;
4573 
4574 	        	vertexToPlaneDist[vertexNum] = dynPtr->ObjectVertices[vertexNum].vy - originToPlaneDist;
4575 
4576 				if (vertexToPlaneDist[vertexNum] < 0)
4577 				{
4578 					return -1;
4579 				}
4580 	        }
4581 			while(vertexNum);
4582 	    }
4583 
4584 		{
4585         	int vertexNum=8;
4586 			int *distancePtr = vertexToPlaneDist;
4587             do
4588             {
4589 				*distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4590 
4591 				if(*distancePtr < obstacleDistance)
4592 					obstacleDistance = *distancePtr;
4593 
4594 				distancePtr++;
4595 		    }
4596             while(--vertexNum);
4597 
4598 		}
4599 	}
4600 	if (obstacleDistance>=distanceToMove)
4601 		return -2;
4602 
4603 	/* test if any vertices projected paths intersect polygons */
4604 	if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4605 	{
4606 		return obstacleDistance;
4607 	}
4608 
4609 	return -3;
4610 }
4611 static signed int DistanceMovedBeforeNRBBHitsPosXPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4612 {
4613     int dottedNormals;
4614 	int obstacleDistance= 0x7fffffff;
4615     int vertexToPlaneDist[8];
4616 
4617 	LOCALASSERT(polyPtr);
4618 
4619     dottedNormals = -DirectionOfTravel.vx;
4620 	if (dottedNormals<=0) return -1; /* reject poly */
4621 
4622     /* calculate distance each vertex is from poly's plane along direction of motion */
4623     {
4624 	    int originToPlaneDist = polyPtr->PolyPoint[0].vx;
4625 
4626     	{
4627         	int vertexNum=8;
4628             do
4629             {
4630             	vertexNum--;
4631 
4632 	        	vertexToPlaneDist[vertexNum] = dynPtr->ObjectVertices[vertexNum].vx - originToPlaneDist;
4633 
4634 				if (vertexToPlaneDist[vertexNum] < 0) return -1;
4635 	        }
4636 			while(vertexNum);
4637 	    }
4638 
4639 
4640 		{
4641         	int vertexNum=8;
4642 			int *distancePtr = vertexToPlaneDist;
4643             do
4644             {
4645 				*distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4646 
4647 				if(*distancePtr < obstacleDistance)
4648 					obstacleDistance = *distancePtr;
4649 
4650 				distancePtr++;
4651 		    }
4652             while(--vertexNum);
4653 
4654 		}
4655 	}
4656 	if (obstacleDistance>=distanceToMove)
4657 		return -2;
4658 
4659 	/* test if any vertices projected paths intersect polygons */
4660 	if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4661 	{
4662 		return obstacleDistance;
4663 	}
4664 
4665 	return -3;
4666 }
4667 static signed int DistanceMovedBeforeNRBBHitsNegXPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4668 {
4669     int dottedNormals;
4670 	int obstacleDistance= 0x7fffffff;
4671     int vertexToPlaneDist[8];
4672 
4673 	LOCALASSERT(polyPtr);
4674 
4675     dottedNormals = DirectionOfTravel.vx;
4676 	if (dottedNormals<=0) return -1; /* reject poly */
4677 
4678     /* calculate distance each vertex is from poly's plane along direction of motion */
4679     {
4680 	    int originToPlaneDist = -polyPtr->PolyPoint[0].vx;
4681 
4682     	{
4683         	int vertexNum=8;
4684             do
4685             {
4686             	vertexNum--;
4687 
4688 	        	vertexToPlaneDist[vertexNum] = -dynPtr->ObjectVertices[vertexNum].vx - originToPlaneDist;
4689 
4690 				if (vertexToPlaneDist[vertexNum] < 0) return -1;
4691 	        }
4692 			while(vertexNum);
4693 	    }
4694 
4695 		{
4696         	int vertexNum=8;
4697 			int *distancePtr = vertexToPlaneDist;
4698             do
4699             {
4700 				*distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4701 
4702 				if(*distancePtr < obstacleDistance)
4703 					obstacleDistance = *distancePtr;
4704 
4705 				distancePtr++;
4706 		    }
4707             while(--vertexNum);
4708 
4709 		}
4710 	}
4711 	if (obstacleDistance>=distanceToMove)
4712 		return -2;
4713 
4714 	/* test if any vertices projected paths intersect polygons */
4715 	if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4716 	{
4717 		return obstacleDistance;
4718 	}
4719 
4720 	return -3;
4721 }
4722 static signed int DistanceMovedBeforeNRBBHitsPosZPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4723 {
4724     int dottedNormals;
4725 	int obstacleDistance= 0x7fffffff;
4726     int vertexToPlaneDist[8];
4727 
4728 	LOCALASSERT(polyPtr);
4729 
4730     dottedNormals = -DirectionOfTravel.vz;
4731 	if (dottedNormals<=0) return -1; /* reject poly */
4732 
4733     /* calculate distance each vertex is from poly's plane along direction of motion */
4734     {
4735 	    int originToPlaneDist = polyPtr->PolyPoint[0].vz;
4736 
4737     	{
4738         	int vertexNum=8;
4739             do
4740             {
4741             	vertexNum--;
4742 
4743 	        	vertexToPlaneDist[vertexNum] = dynPtr->ObjectVertices[vertexNum].vz - originToPlaneDist;
4744 
4745 				if (vertexToPlaneDist[vertexNum] < 0) return -1;
4746 	        }
4747 			while(vertexNum);
4748 	    }
4749 
4750 		{
4751         	int vertexNum=8;
4752 			int *distancePtr = vertexToPlaneDist;
4753             do
4754             {
4755 				*distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4756 
4757 				if(*distancePtr < obstacleDistance)
4758 					obstacleDistance = *distancePtr;
4759 
4760 				distancePtr++;
4761 		    }
4762             while(--vertexNum);
4763 
4764 		}
4765 	}
4766 	if (obstacleDistance>=distanceToMove)
4767 		return -2;
4768 
4769 	/* test if any vertices projected paths intersect polygons */
4770 	if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4771 	{
4772 		return obstacleDistance;
4773 	}
4774 
4775 	return -3;
4776 }
4777 static signed int DistanceMovedBeforeNRBBHitsNegZPolygon(DYNAMICSBLOCK *dynPtr, struct ColPolyTag *polyPtr, int distanceToMove)
4778 {
4779     int dottedNormals;
4780 	int obstacleDistance= 0x7fffffff;
4781     int vertexToPlaneDist[8];
4782 
4783 	LOCALASSERT(polyPtr);
4784 
4785     dottedNormals = DirectionOfTravel.vz;
4786 	if (dottedNormals<=0) return -1; /* reject poly */
4787 
4788     /* calculate distance each vertex is from poly's plane along direction of motion */
4789     {
4790 	    int originToPlaneDist = -polyPtr->PolyPoint[0].vz;
4791 
4792     	{
4793         	int vertexNum=8;
4794             do
4795             {
4796             	vertexNum--;
4797 
4798 	        	vertexToPlaneDist[vertexNum] = -dynPtr->ObjectVertices[vertexNum].vz - originToPlaneDist;
4799 
4800 				if (vertexToPlaneDist[vertexNum] < 0) return -1;
4801 	        }
4802 			while(vertexNum);
4803 	    }
4804 
4805 
4806 		{
4807         	int vertexNum=8;
4808 			int *distancePtr = vertexToPlaneDist;
4809             do
4810             {
4811 				*distancePtr = DIV_FIXED(*distancePtr,dottedNormals);
4812 
4813 				if(*distancePtr < obstacleDistance)
4814 					obstacleDistance = *distancePtr;
4815 
4816 				distancePtr++;
4817 		    }
4818             while(--vertexNum);
4819 
4820 		}
4821 	}
4822 	if (obstacleDistance>=distanceToMove)
4823 		return -2;
4824 
4825 	/* test if any vertices projected paths intersect polygons */
4826 	if (NRBBProjectsOntoPolygon(dynPtr,vertexToPlaneDist,polyPtr,&DirectionOfTravel))
4827 	{
4828 		return obstacleDistance;
4829 	}
4830 
4831 	return -3;
4832 }
4833 #endif
NRBBProjectsOntoPolygon(DYNAMICSBLOCK * dynPtr,int vertexToPlaneDist[],struct ColPolyTag * polyPtr,VECTORCH * projectionDirPtr)4834 static int NRBBProjectsOntoPolygon(DYNAMICSBLOCK *dynPtr, int vertexToPlaneDist[], struct ColPolyTag *polyPtr, VECTORCH *projectionDirPtr)
4835 {
4836 	/* decide which 2d plane to project onto */
4837 	int axisToIgnore = AxisToIgnore(&polyPtr->PolyNormal);
4838     int objMaxX,objMinX,objMaxY,objMinY,objMaxZ,objMinZ;
4839 
4840     if (axisToIgnore!=ix)
4841     {
4842     	int polyMax,polyMin;
4843 
4844     	/* search x-coords of poly vertices for min and max */
4845         {
4846 	    	int vertexNum=polyPtr->NumberOfVertices;
4847 
4848 	    	polyMax = polyMin = polyPtr->PolyPoint[0].vx;
4849 			do
4850 			{
4851    	        	int x;
4852 				vertexNum--;
4853 	        	x = polyPtr->PolyPoint[vertexNum].vx;
4854 	        	if (x > polyMax) polyMax = x;
4855 	        	else if (x < polyMin) polyMin = x;
4856 	        }
4857             while(vertexNum);
4858 		}
4859         /* search x-coords of object vertices for min and max */
4860         {
4861 			int i=7; /* 8 vertices in a cuboid */
4862 
4863         	objMaxX = objMinX = dynPtr->ObjectVertices[0].vx + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vx);
4864 			do
4865 	        {
4866 	        	int x;
4867 	        	x = dynPtr->ObjectVertices[i].vx + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vx);
4868 	        	if (x > objMaxX) objMaxX = x;
4869 	        	else if (x < objMinX) objMinX = x;
4870 	        	i--;
4871 	        }
4872 			while(i);
4873 		}
4874 
4875         /* test to see if object & polygon overlap */
4876         if (objMaxX < polyMin || objMinX > polyMax)
4877         	return 0;
4878     }
4879     if (axisToIgnore!=iz)
4880     {
4881     	int polyMax,polyMin;
4882 
4883     	/* search z-coords of poly vertices for min and max */
4884         {
4885 	    	int vertexNum=polyPtr->NumberOfVertices;
4886 
4887 	    	polyMax = polyMin = polyPtr->PolyPoint[0].vz;
4888 	        do
4889 	        {
4890 	        	int z;
4891 				vertexNum--;
4892 	        	z = polyPtr->PolyPoint[vertexNum].vz;
4893 	        	if (z > polyMax) polyMax = z;
4894 	        	else if (z < polyMin) polyMin = z;
4895 	        }
4896             while(vertexNum);
4897 		}
4898         /* search z-coords of object vertices for min and max */
4899         {
4900 			int i=7; /* 8 vertices in a cuboid */
4901 
4902         	objMaxZ = objMinZ = dynPtr->ObjectVertices[0].vz + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vz);
4903 			do
4904 	        {
4905 	        	int z;
4906 	        	z = dynPtr->ObjectVertices[i].vz + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vz);
4907 	        	if (z > objMaxZ) objMaxZ = z;
4908 	        	else if (z < objMinZ) objMinZ = z;
4909 	        	i--;
4910 	        }
4911 			while(i);
4912 		}
4913 
4914         /* test to see if object & polygon overlap */
4915         if (objMaxZ < polyMin || objMinZ > polyMax)
4916         	return 0;
4917     }
4918     if (axisToIgnore!=iy)
4919     {
4920     	int polyMax,polyMin;
4921 
4922     	/* search y-coords of poly vertices for min and max */
4923         {
4924 	    	int vertexNum=polyPtr->NumberOfVertices;
4925 
4926 	    	polyMax = polyMin = polyPtr->PolyPoint[0].vy;
4927 	        do
4928 	        {
4929 				int y;
4930 				vertexNum--;
4931 
4932 				y = polyPtr->PolyPoint[vertexNum].vy;
4933 	        	if (y > polyMax) polyMax = y;
4934 	        	else if (y < polyMin) polyMin = y;
4935 	        }
4936             while(vertexNum);
4937 		}
4938         /* search y-coords of object vertices for min and max */
4939         {
4940 			int i=7; /* 8 vertices in a cuboid */
4941 
4942         	objMaxY = objMinY = dynPtr->ObjectVertices[0].vy + MUL_FIXED(vertexToPlaneDist[0],projectionDirPtr->vy);
4943 			do
4944 	        {
4945 	        	int y;
4946 
4947 	        	y = dynPtr->ObjectVertices[i].vy + MUL_FIXED(vertexToPlaneDist[i],projectionDirPtr->vy);
4948 	        	if (y > objMaxY) objMaxY = y;
4949 	        	else if (y < objMinY) objMinY = y;
4950 	        	i--;
4951 	        }
4952 			while(i);
4953 		}
4954 
4955         /* test to see if object & polygon overlap */
4956         if (objMaxY < polyMin || objMinY > polyMax)
4957         	return 0;
4958 
4959     }
4960 
4961 	/* test for triangle/rectangle overlap */
4962 	/* traingle vertices are stored anticlockwise! */
4963 	if (polyPtr->NumberOfVertices == 3)
4964 	{
4965 		if(axisToIgnore==ix)
4966 		{
4967 			VECTORCH n;
4968 
4969 			n.vy = (polyPtr->PolyPoint[1].vz-polyPtr->PolyPoint[0].vz);
4970 			n.vz = -(polyPtr->PolyPoint[1].vy-polyPtr->PolyPoint[0].vy);
4971 			if(polyPtr->PolyNormal.vx<0)
4972 			{
4973 				n.vy = -n.vy;
4974 				n.vz = -n.vz;
4975 			}
4976 			{
4977 				int d1,d2,d3,d4;
4978 				d1 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
4979 				d2 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
4980 				d3 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
4981 				d4 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
4982 
4983 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
4984 			}
4985 
4986 			n.vy = (polyPtr->PolyPoint[2].vz-polyPtr->PolyPoint[1].vz);
4987 			n.vz = -(polyPtr->PolyPoint[2].vy-polyPtr->PolyPoint[1].vy);
4988 			if(polyPtr->PolyNormal.vx<0)
4989 			{
4990 				n.vy = -n.vy;
4991 				n.vz = -n.vz;
4992 			}
4993 			{
4994 				int d1,d2,d3,d4;
4995 				d1 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
4996 				d2 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
4997 				d3 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
4998 				d4 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
4999 
5000 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5001 			}
5002 
5003 			n.vy = (polyPtr->PolyPoint[0].vz-polyPtr->PolyPoint[2].vz);
5004 			n.vz = -(polyPtr->PolyPoint[0].vy-polyPtr->PolyPoint[2].vy);
5005 			if(polyPtr->PolyNormal.vx<0)
5006 			{
5007 				n.vy = -n.vy;
5008 				n.vz = -n.vz;
5009 			}
5010 			{
5011 				int d1,d2,d3,d4;
5012 				d1 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5013 				d2 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5014 				d3 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5015 				d4 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5016 
5017 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5018 			}
5019 
5020 		}
5021 	    else if(axisToIgnore==iy)
5022 		{
5023 			VECTORCH n;
5024 
5025 			n.vx = (polyPtr->PolyPoint[1].vz-polyPtr->PolyPoint[0].vz);
5026 			n.vz = -(polyPtr->PolyPoint[1].vx-polyPtr->PolyPoint[0].vx);
5027 			if(polyPtr->PolyNormal.vy>0)
5028 			{
5029 				n.vx = -n.vx;
5030 				n.vz = -n.vz;
5031 			}
5032 			{
5033 				int d1,d2,d3,d4;
5034 				d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5035 				d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5036 				d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5037 				d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5038 
5039 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5040 			}
5041 
5042 			n.vx = (polyPtr->PolyPoint[2].vz-polyPtr->PolyPoint[1].vz);
5043 			n.vz = -(polyPtr->PolyPoint[2].vx-polyPtr->PolyPoint[1].vx);
5044 			if(polyPtr->PolyNormal.vy>0)
5045 			{
5046 				n.vx = -n.vx;
5047 				n.vz = -n.vz;
5048 			}
5049 			{
5050 				int d1,d2,d3,d4;
5051 				d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5052 				d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5053 				d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5054 				d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5055 
5056 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5057 			}
5058 
5059 			n.vx = (polyPtr->PolyPoint[0].vz-polyPtr->PolyPoint[2].vz);
5060 			n.vz = -(polyPtr->PolyPoint[0].vx-polyPtr->PolyPoint[2].vx);
5061 			if(polyPtr->PolyNormal.vy>0)
5062 			{
5063 				n.vx = -n.vx;
5064 				n.vz = -n.vz;
5065 			}
5066 			{
5067 				int d1,d2,d3,d4;
5068 				d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5069 				d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5070 				d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5071 				d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5072 
5073 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5074 			}
5075 		}
5076 		else if(axisToIgnore==iz)
5077 		{
5078 			VECTORCH n;
5079 
5080 			n.vx = (polyPtr->PolyPoint[1].vy-polyPtr->PolyPoint[0].vy);
5081 			n.vy = -(polyPtr->PolyPoint[1].vx-polyPtr->PolyPoint[0].vx);
5082 			if(polyPtr->PolyNormal.vz<0)
5083 			{
5084 				n.vx = -n.vx;
5085 				n.vy = -n.vy;
5086 			}
5087 			{
5088 				int d1,d2,d3,d4;
5089 				d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
5090 				d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
5091 				d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
5092 				d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
5093 
5094 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5095 			}
5096 
5097 			n.vx = (polyPtr->PolyPoint[2].vy-polyPtr->PolyPoint[1].vy);
5098 			n.vy = -(polyPtr->PolyPoint[2].vx-polyPtr->PolyPoint[1].vx);
5099 			if(polyPtr->PolyNormal.vz<0)
5100 			{
5101 				n.vx = -n.vx;
5102 				n.vy = -n.vy;
5103 			}
5104 			{
5105 				int d1,d2,d3,d4;
5106 				d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
5107 				d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
5108 				d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
5109 				d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
5110 
5111 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5112 			}
5113 
5114 			n.vx = (polyPtr->PolyPoint[0].vy-polyPtr->PolyPoint[2].vy);
5115 			n.vy = -(polyPtr->PolyPoint[0].vx-polyPtr->PolyPoint[2].vx);
5116 			if(polyPtr->PolyNormal.vz<0)
5117 			{
5118 				n.vx = -n.vx;
5119 				n.vy = -n.vy;
5120 			}
5121 			{
5122 				int d1,d2,d3,d4;
5123 				d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
5124 				d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
5125 				d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
5126 				d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
5127 
5128 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5129 			}
5130 		}
5131 	}
5132 	else
5133 	{
5134 		if(axisToIgnore==ix)
5135 		{
5136 			VECTORCH n;
5137 
5138 			n.vy = (polyPtr->PolyPoint[1].vz-polyPtr->PolyPoint[0].vz);
5139 			n.vz = -(polyPtr->PolyPoint[1].vy-polyPtr->PolyPoint[0].vy);
5140 			if(polyPtr->PolyNormal.vx<0)
5141 			{
5142 				n.vy = -n.vy;
5143 				n.vz = -n.vz;
5144 			}
5145 			{
5146 				int d1,d2,d3,d4;
5147 				d1 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5148 				d2 = (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5149 				d3 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5150 				d4 = (objMinY-polyPtr->PolyPoint[0].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5151 
5152 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5153 			}
5154 
5155 			n.vy = (polyPtr->PolyPoint[2].vz-polyPtr->PolyPoint[1].vz);
5156 			n.vz = -(polyPtr->PolyPoint[2].vy-polyPtr->PolyPoint[1].vy);
5157 			if(polyPtr->PolyNormal.vx<0)
5158 			{
5159 				n.vy = -n.vy;
5160 				n.vz = -n.vz;
5161 			}
5162 			{
5163 				int d1,d2,d3,d4;
5164 				d1 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5165 				d2 = (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5166 				d3 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5167 				d4 = (objMinY-polyPtr->PolyPoint[1].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5168 
5169 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5170 			}
5171 
5172 			n.vy = (polyPtr->PolyPoint[3].vz-polyPtr->PolyPoint[2].vz);
5173 			n.vz = -(polyPtr->PolyPoint[3].vy-polyPtr->PolyPoint[2].vy);
5174 			if(polyPtr->PolyNormal.vx<0)
5175 			{
5176 				n.vy = -n.vy;
5177 				n.vz = -n.vz;
5178 			}
5179 			{
5180 				int d1,d2,d3,d4;
5181 				d1 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5182 				d2 = (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5183 				d3 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5184 				d4 = (objMinY-polyPtr->PolyPoint[2].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5185 
5186 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5187 			}
5188 
5189 			n.vy = (polyPtr->PolyPoint[0].vz-polyPtr->PolyPoint[3].vz);
5190 			n.vz = -(polyPtr->PolyPoint[0].vy-polyPtr->PolyPoint[3].vy);
5191 			if(polyPtr->PolyNormal.vx<0)
5192 			{
5193 				n.vy = -n.vy;
5194 				n.vz = -n.vz;
5195 			}
5196 			{
5197 				int d1,d2,d3,d4;
5198 				d1 = (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
5199 				d2 = (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
5200 				d3 = (objMinY-polyPtr->PolyPoint[3].vy)*n.vy + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
5201 				d4 = (objMinY-polyPtr->PolyPoint[3].vy)*n.vy + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
5202 
5203 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5204 			}
5205 		}
5206 	    else if(axisToIgnore==iy)
5207 		{
5208 			VECTORCH n;
5209 
5210 			n.vx = (polyPtr->PolyPoint[1].vz-polyPtr->PolyPoint[0].vz);
5211 			n.vz = -(polyPtr->PolyPoint[1].vx-polyPtr->PolyPoint[0].vx);
5212 			if(polyPtr->PolyNormal.vy>0)
5213 			{
5214 				n.vx = -n.vx;
5215 				n.vz = -n.vz;
5216 			}
5217 			{
5218 				int d1,d2,d3,d4;
5219 				d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5220 				d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5221 				d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[0].vz)*n.vz;
5222 				d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[0].vz)*n.vz;
5223 
5224 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5225 			}
5226 
5227 			n.vx = (polyPtr->PolyPoint[2].vz-polyPtr->PolyPoint[1].vz);
5228 			n.vz = -(polyPtr->PolyPoint[2].vx-polyPtr->PolyPoint[1].vx);
5229 			if(polyPtr->PolyNormal.vy>0)
5230 			{
5231 				n.vx = -n.vx;
5232 				n.vz = -n.vz;
5233 			}
5234 			{
5235 				int d1,d2,d3,d4;
5236 				d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5237 				d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5238 				d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[1].vz)*n.vz;
5239 				d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[1].vz)*n.vz;
5240 
5241 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5242 			}
5243 
5244 			n.vx = (polyPtr->PolyPoint[3].vz-polyPtr->PolyPoint[2].vz);
5245 			n.vz = -(polyPtr->PolyPoint[3].vx-polyPtr->PolyPoint[2].vx);
5246 			if(polyPtr->PolyNormal.vy>0)
5247 			{
5248 				n.vx = -n.vx;
5249 				n.vz = -n.vz;
5250 			}
5251 			{
5252 				int d1,d2,d3,d4;
5253 				d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5254 				d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5255 				d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[2].vz)*n.vz;
5256 				d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[2].vz)*n.vz;
5257 
5258 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5259 			}
5260 
5261 			n.vx = (polyPtr->PolyPoint[0].vz-polyPtr->PolyPoint[3].vz);
5262 			n.vz = -(polyPtr->PolyPoint[0].vx-polyPtr->PolyPoint[3].vx);
5263 			if(polyPtr->PolyNormal.vy>0)
5264 			{
5265 				n.vx = -n.vx;
5266 				n.vz = -n.vz;
5267 			}
5268 			{
5269 				int d1,d2,d3,d4;
5270 				d1 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
5271 				d2 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
5272 				d3 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxZ-polyPtr->PolyPoint[3].vz)*n.vz;
5273 				d4 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinZ-polyPtr->PolyPoint[3].vz)*n.vz;
5274 
5275 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5276 			}
5277 
5278 		}
5279 		else if(axisToIgnore==iz)
5280 		{
5281 			VECTORCH n;
5282 
5283 			n.vx = (polyPtr->PolyPoint[1].vy-polyPtr->PolyPoint[0].vy);
5284 			n.vy = -(polyPtr->PolyPoint[1].vx-polyPtr->PolyPoint[0].vx);
5285 			if(polyPtr->PolyNormal.vz<0)
5286 			{
5287 				n.vx = -n.vx;
5288 				n.vy = -n.vy;
5289 			}
5290 			{
5291 				int d1,d2,d3,d4;
5292 				d1 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
5293 				d2 = (objMaxX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
5294 				d3 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[0].vy)*n.vy;
5295 				d4 = (objMinX-polyPtr->PolyPoint[0].vx)*n.vx + (objMinY-polyPtr->PolyPoint[0].vy)*n.vy;
5296 
5297 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5298 			}
5299 
5300 			n.vx = (polyPtr->PolyPoint[2].vy-polyPtr->PolyPoint[1].vy);
5301 			n.vy = -(polyPtr->PolyPoint[2].vx-polyPtr->PolyPoint[1].vx);
5302 			if(polyPtr->PolyNormal.vz<0)
5303 			{
5304 				n.vx = -n.vx;
5305 				n.vy = -n.vy;
5306 			}
5307 			{
5308 				int d1,d2,d3,d4;
5309 				d1 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
5310 				d2 = (objMaxX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
5311 				d3 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[1].vy)*n.vy;
5312 				d4 = (objMinX-polyPtr->PolyPoint[1].vx)*n.vx + (objMinY-polyPtr->PolyPoint[1].vy)*n.vy;
5313 
5314 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5315 			}
5316 
5317 			n.vx = (polyPtr->PolyPoint[3].vy-polyPtr->PolyPoint[2].vy);
5318 			n.vy = -(polyPtr->PolyPoint[3].vx-polyPtr->PolyPoint[2].vx);
5319 			if(polyPtr->PolyNormal.vz<0)
5320 			{
5321 				n.vx = -n.vx;
5322 				n.vy = -n.vy;
5323 			}
5324 			{
5325 				int d1,d2,d3,d4;
5326 				d1 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
5327 				d2 = (objMaxX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
5328 				d3 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[2].vy)*n.vy;
5329 				d4 = (objMinX-polyPtr->PolyPoint[2].vx)*n.vx + (objMinY-polyPtr->PolyPoint[2].vy)*n.vy;
5330 
5331 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5332 			}
5333 
5334 			n.vx = (polyPtr->PolyPoint[0].vy-polyPtr->PolyPoint[3].vy);
5335 			n.vy = -(polyPtr->PolyPoint[0].vx-polyPtr->PolyPoint[3].vx);
5336 			if(polyPtr->PolyNormal.vz<0)
5337 			{
5338 				n.vx = -n.vx;
5339 				n.vy = -n.vy;
5340 			}
5341 			{
5342 				int d1,d2,d3,d4;
5343 				d1 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy;
5344 				d2 = (objMaxX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinY-polyPtr->PolyPoint[3].vy)*n.vy;
5345 				d3 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMaxY-polyPtr->PolyPoint[3].vy)*n.vy;
5346 				d4 = (objMinX-polyPtr->PolyPoint[3].vx)*n.vx + (objMinY-polyPtr->PolyPoint[3].vy)*n.vy;
5347 
5348 				if (d1>0 && d2>0 && d3>0 && d4>0) return 0;
5349 			}
5350 		}
5351 	}
5352     return 1;
5353 }
5354 
CreateNRBBForObject(const STRATEGYBLOCK * sbPtr)5355 static void CreateNRBBForObject(const STRATEGYBLOCK *sbPtr)
5356 {
5357 	VECTORCH *objectVertices = sbPtr->DynPtr->ObjectVertices;
5358 	COLLISION_EXTENTS *extentsPtr = 0;
5359 	int objectIsCrouching = 0;
5360 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5361 
5362 	dynPtr->CollisionRadius = 0;
5363 
5364 
5365 	switch (sbPtr->I_SBtype)
5366 	{
5367    		case I_BehaviourMarinePlayer:
5368 		{
5369 			PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
5370 
5371 			/* set player state */
5372 			objectIsCrouching = (playerStatusPtr->ShapeState != PMph_Standing);
5373 
5374 			switch(AvP.PlayerType)
5375 			{
5376 				case I_Marine:
5377 					extentsPtr = &CollisionExtents[CE_MARINE];
5378 					dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5379 					break;
5380 
5381 				case I_Alien:
5382 					extentsPtr = &CollisionExtents[CE_ALIEN];
5383 					dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5384 					break;
5385 
5386 				case I_Predator:
5387 					extentsPtr = &CollisionExtents[CE_PREDATOR];
5388 					dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5389 					break;
5390 			}
5391 			break;
5392 		}
5393 
5394    		case I_BehaviourAlien:
5395 		{
5396 			ALIEN_STATUS_BLOCK *alienStatusPtr = (ALIEN_STATUS_BLOCK *)sbPtr->SBdataptr;
5397 			objectIsCrouching = alienStatusPtr->IAmCrouched;
5398 
5399 			extentsPtr = &CollisionExtents[CE_ALIEN];
5400 			dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5401 			sbPtr->SBdptr->ObRadius = 2000;
5402 			break;
5403 		}
5404 		case I_BehaviourPredator:
5405 		{
5406 			PREDATOR_STATUS_BLOCK *predatorStatusPtr = (PREDATOR_STATUS_BLOCK *)sbPtr->SBdataptr;
5407 			objectIsCrouching = predatorStatusPtr->IAmCrouched;
5408 
5409 			sbPtr->SBdptr->ObRadius = 2000;
5410 			extentsPtr = &CollisionExtents[CE_PREDATOR];
5411 //			dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5412 			break;
5413 		}
5414 		case I_BehaviourMarine:
5415 		{
5416 			MARINE_STATUS_BLOCK *marineStatusPtr = (MARINE_STATUS_BLOCK *)sbPtr->SBdataptr;
5417 			objectIsCrouching = marineStatusPtr->IAmCrouched;
5418 
5419 			sbPtr->SBdptr->ObRadius = 2000;
5420 			extentsPtr = &CollisionExtents[CE_MARINE];
5421 //			dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5422 			break;
5423 		}
5424 		case I_BehaviourFaceHugger:
5425 		{
5426 			extentsPtr = &CollisionExtents[CE_FACEHUGGER];
5427 			dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5428 			break;
5429 		}
5430 		case I_BehaviourXenoborg:
5431 		{
5432 			extentsPtr = &CollisionExtents[CE_XENOBORG];
5433 			break;
5434 		}
5435 		case I_BehaviourPredatorAlien:
5436 		{
5437 			extentsPtr = &CollisionExtents[CE_PREDATORALIEN];
5438 			break;
5439 		}
5440 
5441 		case I_BehaviourQueenAlien:
5442 			extentsPtr = &CollisionExtents[CE_QUEEN];
5443 			break;
5444 		case I_BehaviourSeal:
5445 			extentsPtr = &CollisionExtents[CE_MARINE];
5446 			break;
5447 
5448 		case I_BehaviourNetCorpse:
5449 			extentsPtr = &CollisionExtents[CE_CORPSE];
5450 			sbPtr->SBdptr->ObRadius = 700;
5451 			break;
5452 
5453 		case I_BehaviourNetGhost:
5454 		{
5455 			NETGHOSTDATABLOCK *ghostData;
5456 
5457 			ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
5458 			LOCALASSERT(ghostData);
5459 
5460 			switch(ghostData->type)
5461 			{
5462 		   		case I_BehaviourAlienPlayer:
5463 				{
5464 					extentsPtr = &CollisionExtents[CE_ALIEN];
5465 					dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5466 					sbPtr->SBdptr->ObRadius = 700;
5467 					break;
5468 				}
5469 				case I_BehaviourPredatorPlayer:
5470 				{
5471 					extentsPtr = &CollisionExtents[CE_PREDATOR];
5472 					sbPtr->SBdptr->ObRadius = 700;
5473 					break;
5474 				}
5475 				case I_BehaviourMarinePlayer:
5476 				{
5477 					extentsPtr = &CollisionExtents[CE_MARINE];
5478 					sbPtr->SBdptr->ObRadius = 700;
5479 					break;
5480 				}
5481 
5482 		   		case I_BehaviourAlien:
5483 				{
5484 					#if 0
5485 					ALIEN_STATUS_BLOCK *alienStatusPtr = (ALIEN_STATUS_BLOCK *)sbPtr->SBdataptr;
5486 					objectIsCrouching = alienStatusPtr->IAmCrouched;
5487 					#endif
5488 					extentsPtr = &CollisionExtents[CE_ALIEN];
5489 					dynPtr->CollisionRadius = extentsPtr->CollisionRadius;
5490 					sbPtr->SBdptr->ObRadius = 2000;
5491 					break;
5492 				}
5493 
5494 				case I_BehaviourNetCorpse:
5495 					extentsPtr = &CollisionExtents[CE_MARINE];
5496 					sbPtr->SBdptr->ObRadius = 700;
5497 					break;
5498 				default:
5499 					break;
5500 			}
5501 		}
5502 
5503 		default:
5504 			break;
5505 	}
5506 
5507 	if (extentsPtr)
5508 	{
5509 		/* max X */
5510 		objectVertices[0].vx = extentsPtr->CollisionRadius;
5511 		objectVertices[1].vx = extentsPtr->CollisionRadius;
5512 		objectVertices[2].vx = extentsPtr->CollisionRadius;
5513 		objectVertices[3].vx = extentsPtr->CollisionRadius;
5514 
5515 		/* max Z */
5516 		objectVertices[0].vz = extentsPtr->CollisionRadius;
5517 	    objectVertices[2].vz = extentsPtr->CollisionRadius;
5518 	    objectVertices[4].vz = extentsPtr->CollisionRadius;
5519 	    objectVertices[6].vz = extentsPtr->CollisionRadius;
5520 
5521 		/* min X */
5522 		objectVertices[4].vx = -extentsPtr->CollisionRadius;
5523 		objectVertices[5].vx = -extentsPtr->CollisionRadius;
5524 		objectVertices[6].vx = -extentsPtr->CollisionRadius;
5525 		objectVertices[7].vx = -extentsPtr->CollisionRadius;
5526 
5527 		/* min Z */
5528 		objectVertices[1].vz = -extentsPtr->CollisionRadius;
5529 		objectVertices[3].vz = -extentsPtr->CollisionRadius;
5530 		objectVertices[5].vz = -extentsPtr->CollisionRadius;
5531 		objectVertices[7].vz = -extentsPtr->CollisionRadius;
5532 
5533 		/* max Y */
5534 	   	objectVertices[0].vy = extentsPtr->Bottom;
5535 	    objectVertices[1].vy = extentsPtr->Bottom;
5536 	    objectVertices[4].vy = extentsPtr->Bottom;
5537 	    objectVertices[5].vy = extentsPtr->Bottom;
5538 
5539 		/* min Y */
5540 		if(objectIsCrouching)
5541 		{
5542 		   	objectVertices[2].vy = extentsPtr->CrouchingTop;
5543 		    objectVertices[3].vy = extentsPtr->CrouchingTop;
5544 		    objectVertices[6].vy = extentsPtr->CrouchingTop;
5545 		    objectVertices[7].vy = extentsPtr->CrouchingTop;
5546 		}
5547 		else
5548 		{
5549 		   	objectVertices[2].vy = extentsPtr->StandingTop;
5550 		    objectVertices[3].vy = extentsPtr->StandingTop;
5551 		    objectVertices[6].vy = extentsPtr->StandingTop;
5552 		    objectVertices[7].vy = extentsPtr->StandingTop;
5553 	    }
5554 	}
5555 	else
5556 	/* make a cuboid from the shape's extent data */
5557 	{
5558 	    {
5559 	   		int shapeMaxX = sbPtr->SBdptr->ObMaxX;
5560 			if (shapeMaxX < MINIMUM_BOUNDINGBOX_EXTENT) shapeMaxX = MINIMUM_BOUNDINGBOX_EXTENT;
5561 	        objectVertices[0].vx = shapeMaxX;
5562 	        objectVertices[1].vx = shapeMaxX;
5563 	        objectVertices[2].vx = shapeMaxX;
5564 	        objectVertices[3].vx = shapeMaxX;
5565 	    }
5566 	    {
5567 	   		int shapeMinX = sbPtr->SBdptr->ObMinX;
5568 			if (shapeMinX > -MINIMUM_BOUNDINGBOX_EXTENT) shapeMinX = -MINIMUM_BOUNDINGBOX_EXTENT;
5569 	        objectVertices[4].vx = shapeMinX;
5570 	        objectVertices[5].vx = shapeMinX;
5571 	        objectVertices[6].vx = shapeMinX;
5572 	        objectVertices[7].vx = shapeMinX;
5573 	    }
5574 	    {
5575 	   		int shapeMaxY = sbPtr->SBdptr->ObMaxY;
5576 			if (shapeMaxY < MINIMUM_BOUNDINGBOX_EXTENT) shapeMaxY = MINIMUM_BOUNDINGBOX_EXTENT;
5577 	        objectVertices[0].vy = shapeMaxY;
5578 	        objectVertices[1].vy = shapeMaxY;
5579 	        objectVertices[4].vy = shapeMaxY;
5580 	        objectVertices[5].vy = shapeMaxY;
5581 	    }
5582 	    {
5583 	   		int shapeMinY = sbPtr->SBdptr->ObMinY;
5584 			if (shapeMinY > -MINIMUM_BOUNDINGBOX_EXTENT) shapeMinY = -MINIMUM_BOUNDINGBOX_EXTENT;
5585 	        objectVertices[2].vy = shapeMinY;
5586 	        objectVertices[3].vy = shapeMinY;
5587 	        objectVertices[6].vy = shapeMinY;
5588 	        objectVertices[7].vy = shapeMinY;
5589 	    }
5590 	    {
5591 	   		int shapeMaxZ = sbPtr->SBdptr->ObMaxZ;
5592 			if (shapeMaxZ < MINIMUM_BOUNDINGBOX_EXTENT) shapeMaxZ = MINIMUM_BOUNDINGBOX_EXTENT;
5593 			objectVertices[0].vz = shapeMaxZ;
5594 	        objectVertices[2].vz = shapeMaxZ;
5595 	        objectVertices[4].vz = shapeMaxZ;
5596 	        objectVertices[6].vz = shapeMaxZ;
5597 		}
5598 		{
5599 	   		int shapeMinZ = sbPtr->SBdptr->ObMinZ;
5600 			if (shapeMinZ > -MINIMUM_BOUNDINGBOX_EXTENT) shapeMinZ = -MINIMUM_BOUNDINGBOX_EXTENT;
5601 		    objectVertices[1].vz = shapeMinZ;
5602 	        objectVertices[3].vz = shapeMinZ;
5603 	        objectVertices[5].vz = shapeMinZ;
5604 	        objectVertices[7].vz = shapeMinZ;
5605 	    }
5606 	}
5607 
5608 	/* translate cuboid into world space */
5609 	{
5610 		VECTORCH *vertexPtr = objectVertices;
5611         VECTORCH objectPosition = sbPtr->DynPtr->Position;
5612 
5613         int vertexNum=8;
5614         do
5615         {
5616         	vertexPtr->vx += objectPosition.vx;
5617         	vertexPtr->vy += objectPosition.vy;
5618         	vertexPtr->vz += objectPosition.vz;
5619         	vertexPtr++;
5620         }
5621         while(--vertexNum);
5622 
5623 	}
5624 }
CreateSphereBBForObject(const STRATEGYBLOCK * sbPtr)5625 static void CreateSphereBBForObject(const STRATEGYBLOCK *sbPtr)
5626 {
5627 	VECTORCH *objectVertices = sbPtr->DynPtr->ObjectVertices;
5628 	/* make a cuboid from the sphere's radius */
5629 	{
5630 		int radius = sbPtr->DynPtr->CollisionRadius;
5631 
5632         objectVertices[0].vx = radius;
5633         objectVertices[1].vx = radius;
5634         objectVertices[2].vx = radius;
5635         objectVertices[3].vx = radius;
5636         objectVertices[0].vy = radius;
5637         objectVertices[1].vy = radius;
5638         objectVertices[4].vy = radius;
5639         objectVertices[5].vy = radius;
5640 		objectVertices[0].vz = radius;
5641         objectVertices[2].vz = radius;
5642         objectVertices[4].vz = radius;
5643         objectVertices[6].vz = radius;
5644 
5645 		radius = -radius;
5646 
5647         objectVertices[4].vx = radius;
5648         objectVertices[5].vx = radius;
5649         objectVertices[6].vx = radius;
5650         objectVertices[7].vx = radius;
5651         objectVertices[2].vy = radius;
5652         objectVertices[3].vy = radius;
5653         objectVertices[6].vy = radius;
5654         objectVertices[7].vy = radius;
5655 	    objectVertices[1].vz = radius;
5656         objectVertices[3].vz = radius;
5657         objectVertices[5].vz = radius;
5658         objectVertices[7].vz = radius;
5659 	}
5660 
5661 	/* translate cuboid into world space */
5662 	{
5663 		VECTORCH *vertexPtr = objectVertices;
5664         VECTORCH objectPosition = sbPtr->DynPtr->Position;
5665 
5666         int vertexNum=8;
5667         do
5668         {
5669         	vertexPtr->vx += objectPosition.vx;
5670         	vertexPtr->vy += objectPosition.vy;
5671         	vertexPtr->vz += objectPosition.vz;
5672         	vertexPtr++;
5673         }
5674         while(--vertexNum);
5675 
5676 	}
5677 }
5678 
5679 
5680 
5681 
5682 #if 0
5683 static int RelocatedDueToFallout(DYNAMICSBLOCK *dynPtr)
5684 {
5685 	/* If the object is outside ALL of the modules in the
5686 	ActiveBlockList, move it back to its previous position. */
5687 
5688 	{
5689 		extern int NumActiveBlocks;
5690 	    extern DISPLAYBLOCK *ActiveBlockList[];
5691 
5692 	   	/* scan through modules and stop if object is inside any of them */
5693 		{
5694 			int objectInsideSomething = 0;
5695 
5696 		   	int numberOfObjects = NumActiveBlocks;
5697 		   	while(numberOfObjects)
5698 		   	{
5699 		   		DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
5700 		   		GLOBALASSERT(objectPtr);
5701 		   		if (objectPtr->ObMyModule) /* is object a module ? */
5702 		    	{
5703 					VECTORCH position = dynPtr->Position;
5704 					position.vx -= objectPtr->ObWorld.vx;
5705 					position.vy -= objectPtr->ObWorld.vy;
5706 					position.vz -= objectPtr->ObWorld.vz;
5707 
5708 					if (position.vx >= objectPtr->ObMinX)
5709 				    	if (position.vx <= objectPtr->ObMaxX)
5710 						    if (position.vz >= objectPtr->ObMinZ)
5711 							    if (position.vz <= objectPtr->ObMaxZ)
5712 								    if (position.vy >= objectPtr->ObMinY)
5713 									    if (position.vy <= objectPtr->ObMaxY)
5714 										{
5715 											objectInsideSomething = 1;
5716 											break;
5717 										}
5718 		        }
5719 		    }
5720 
5721 			if (!objectInsideSomething)
5722 			{
5723 				dynPtr->Position=dynPtr->PrevPosition;
5724 //				NewOnScreenMessage("DEBUG: WENT OUTSIDE ENV");
5725 			}
5726 
5727 			return !objectInsideSomething;
5728 	  	}
5729 	}
5730 
5731 }
5732 #endif
5733 
5734 
5735 
5736 
5737 
5738 
5739 /* KJL 10:43:28 8/20/97 - stuff to add to bh_near.c */
5740 #if 0
5741 
5742 	textprint("alien vel %d %d %d\n",sbPtr->DynPtr->LinVelocity.vx,sbPtr->DynPtr->LinVelocity.vy,sbPtr->DynPtr->LinVelocity.vz);
5743 	#if 1
5744 	if(alienStatusPtr->IAmCrouched)
5745 	{
5746 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5747 		LOCALASSERT(dynPtr);
5748 
5749 		dynPtr->DynamicsType = DYN_TYPE_SPHERE_COLLISIONS;
5750 	}
5751 	else
5752 	{
5753 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5754 		LOCALASSERT(dynPtr);
5755 
5756 		dynPtr->DynamicsType = DYN_TYPE_NRBB_COLLISIONS;
5757 	}
5758 	#endif
5759 #endif
5760 
5761 static signed int DistanceMovedBeforeParticleHitsPolygon(PARTICLE *particlePtr, struct ColPolyTag *polyPtr, int distanceToMove);
5762 
5763 #if 1
5764 
5765 /*KJL****************
5766 * PARTICLE DYNAMICS *
5767 ****************KJL*/
5768 
ParticleDynamics(PARTICLE * particlePtr,VECTORCH * obstacleNormalPtr,int * moduleIndexPtr)5769 int ParticleDynamics(PARTICLE *particlePtr, VECTORCH *obstacleNormalPtr, int *moduleIndexPtr)
5770 {
5771 	VECTORCH prevPosition = particlePtr->Position;
5772 	DISPLAYBLOCK *hitModule = 0;
5773     int polysLeft;
5774     struct ColPolyTag *nearPolysPtr;
5775 	int distanceToMove;
5776     VECTORCH displacement;
5777 	int hitObstacle=0;
5778 
5779 	displacement.vx = MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
5780 	displacement.vy = MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
5781 	displacement.vz = MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
5782 	distanceToMove = Magnitude(&displacement);
5783 
5784 	if (distanceToMove<COLLISION_GRANULARITY) return 0;
5785 
5786 	DirectionOfTravel = particlePtr->Velocity;
5787 	Normalise(&DirectionOfTravel);
5788 
5789 	if (!LocalDetailLevels.BloodCollidesWithEnvironment
5790 		&&(particlePtr->ParticleID==PARTICLE_ALIEN_BLOOD
5791 		 ||particlePtr->ParticleID==PARTICLE_HUMAN_BLOOD
5792 		 ||particlePtr->ParticleID==PARTICLE_PREDATOR_BLOOD))
5793 	{
5794 		CollisionPolysPtr = &CollisionPolysArray[0];
5795     	NumberOfCollisionPolys=0;
5796 	}
5797 	else
5798 	{
5799 	   	FindLandscapePolygonsInParticlesPath(particlePtr, &displacement);
5800 	}
5801 
5802     polysLeft = NumberOfCollisionPolys;
5803     nearPolysPtr = CollisionPolysArray;
5804 
5805 	/* check against selected polys */
5806     while(polysLeft)
5807 	{
5808 		signed int distanceToObstacle;
5809 
5810 		distanceToObstacle = DistanceMovedBeforeParticleHitsPolygon(particlePtr,nearPolysPtr,distanceToMove);
5811 
5812 		if (distanceToObstacle>=0)
5813         {
5814 	       	hitObstacle=1;
5815 	       	distanceToMove = distanceToObstacle;
5816 		   	*obstacleNormalPtr = nearPolysPtr->PolyNormal;
5817 			if ( (nearPolysPtr->ParentObject)
5818 			   &&(nearPolysPtr->ParentObject->ObMyModule) )
5819 			{
5820 				*moduleIndexPtr = nearPolysPtr->ParentObject->ObMyModule->m_index;
5821 				hitModule = nearPolysPtr->ParentObject;
5822 			}
5823 			else
5824 			{
5825 				*moduleIndexPtr = -1;
5826 				hitModule=0;
5827 				if (particlePtr->ParticleID==PARTICLE_FLECHETTE && nearPolysPtr->ParentObject)
5828 				{
5829 					if (nearPolysPtr->ParentObject->ObStrategyBlock)
5830 					{
5831 						CauseDamageToObject(nearPolysPtr->ParentObject->ObStrategyBlock,&FlechetteDamage,ONE_FIXED,&(particlePtr->Velocity));
5832 					}
5833 				} else if (particlePtr->ParticleID==PARTICLE_PREDPISTOL_FLECHETTE && nearPolysPtr->ParentObject)
5834 				{
5835 					if (nearPolysPtr->ParentObject->ObStrategyBlock)
5836 					{
5837 						CauseDamageToObject(nearPolysPtr->ParentObject->ObStrategyBlock,&PredPistol_FlechetteDamage,ONE_FIXED,&(particlePtr->Velocity));
5838 					}
5839 				}
5840 
5841 			}
5842 		}
5843         nearPolysPtr++;
5844 		polysLeft--;
5845 	}
5846 
5847 
5848 	if (distanceToMove>COLLISION_GRANULARITY)
5849 	{
5850 		distanceToMove-=COLLISION_GRANULARITY;
5851 		particlePtr->Position.vx += MUL_FIXED(DirectionOfTravel.vx,distanceToMove);
5852 		particlePtr->Position.vy += MUL_FIXED(DirectionOfTravel.vy,distanceToMove);
5853 		particlePtr->Position.vz += MUL_FIXED(DirectionOfTravel.vz,distanceToMove);
5854 	}
5855 
5856 	if (hitObstacle)
5857 	{
5858 		int magOfPerpImp = DotProduct(obstacleNormalPtr,&(particlePtr->Velocity));
5859 		int magnitude = Magnitude(&particlePtr->Velocity);
5860 		particlePtr->Velocity.vx -= MUL_FIXED(obstacleNormalPtr->vx, magOfPerpImp);
5861 		particlePtr->Velocity.vy -= MUL_FIXED(obstacleNormalPtr->vy, magOfPerpImp);
5862 		particlePtr->Velocity.vz -= MUL_FIXED(obstacleNormalPtr->vz, magOfPerpImp);
5863 		if(particlePtr->Velocity.vx || particlePtr->Velocity.vy || particlePtr->Velocity.vz)
5864 		{
5865 			Normalise(&particlePtr->Velocity);
5866 			particlePtr->Velocity.vx = MUL_FIXED(particlePtr->Velocity.vx,magnitude/2);
5867 			particlePtr->Velocity.vy = MUL_FIXED(particlePtr->Velocity.vy,magnitude/2);
5868 			particlePtr->Velocity.vz = MUL_FIXED(particlePtr->Velocity.vz,magnitude/2);
5869 		}
5870 	}
5871 
5872 	/* test to see if you've hit any objects */
5873 	{
5874 		int i = NumberOfDynamicObjects;
5875 	   	{
5876 			if (prevPosition.vx > particlePtr->Position.vx)
5877 			{
5878 			    DBBMinX = particlePtr->Position.vx;
5879 				DBBMaxX = prevPosition.vx;
5880 			}
5881 			else
5882 			{
5883 			    DBBMinX = prevPosition.vx;
5884 				DBBMaxX = particlePtr->Position.vx;
5885 			}
5886 
5887 			if (prevPosition.vy > particlePtr->Position.vy)
5888 			{
5889 			    DBBMinY = particlePtr->Position.vy;
5890 				DBBMaxY = prevPosition.vy;
5891 			}
5892 			else
5893 			{
5894 			    DBBMinY = prevPosition.vy;
5895 				DBBMaxY = particlePtr->Position.vy;
5896 			}
5897 
5898 			if (prevPosition.vz > particlePtr->Position.vz)
5899 			{
5900 			    DBBMinZ = particlePtr->Position.vz;
5901 				DBBMaxZ = prevPosition.vz;
5902 			}
5903 			else
5904 			{
5905 			    DBBMinZ = prevPosition.vz;
5906 				DBBMaxZ = particlePtr->Position.vz;
5907 			}
5908 
5909 		}
5910 		/* scan through objects */
5911 		while(i--)
5912 		{
5913 			STRATEGYBLOCK *sbPtr = DynamicObjectsList[i];
5914 			DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5915 			DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
5916 
5917 			if (dispPtr)
5918 			if (DBBMinX<dynPtr->ObjectVertices[0].vx && DBBMaxX>dynPtr->ObjectVertices[7].vx)
5919 			if (DBBMinY<dynPtr->ObjectVertices[0].vy && DBBMaxY>dynPtr->ObjectVertices[7].vy)
5920 			if (DBBMinZ<dynPtr->ObjectVertices[0].vz && DBBMaxZ>dynPtr->ObjectVertices[7].vz)
5921 			{
5922 				/* blam! particle hit something */
5923 				if (particlePtr->ParticleID==PARTICLE_ALIEN_BLOOD)
5924 				{
5925 					if ((dispPtr==Player)||(sbPtr->I_SBtype==I_BehaviourMarine)) {
5926 						CauseDamageToObject(sbPtr,&TemplateAmmo[AMMO_ALIEN_FRAG].MaxDamage[AvP.Difficulty], NormalFrameTime,NULL);
5927 					}
5928 				}
5929 				else if (particlePtr->ParticleID==PARTICLE_FLAME
5930 				       ||particlePtr->ParticleID==PARTICLE_PARGEN_FLAME
5931 				       ||particlePtr->ParticleID==PARTICLE_MOLOTOVFLAME)
5932 				{
5933 					BOOL ignoreDamage = FALSE;
5934 					if ((dispPtr==Player)||(dispPtr->HModelControlBlock))
5935 					{
5936 
5937 						if(AvP.Network != I_No_Network)
5938 						{
5939 							//If friendly fire has been disabled , we may need to ignore this option
5940 							if(particlePtr->ParticleID==PARTICLE_FLAME)
5941 							{
5942 								if (netGameData.disableFriendlyFire && (netGameData.gameType==NGT_CoopDeathmatch || netGameData.gameType==NGT_Coop))
5943 								{
5944 									//okay , friendly fire is off , so flamethrower particles , can't harm
5945 									//marines.
5946 									//in coop games it shouldn't harm predators either
5947 									if(sbPtr->I_SBtype==I_BehaviourNetGhost)
5948 									{
5949 										NETGHOSTDATABLOCK *ghostData=(NETGHOSTDATABLOCK *) sbPtr->SBdataptr;
5950 										GLOBALASSERT(ghostData);
5951 										if (ghostData->type==I_BehaviourMarinePlayer)
5952 										{
5953 											ignoreDamage = TRUE;
5954 										}
5955 										else if (ghostData->type==I_BehaviourPredatorPlayer && netGameData.gameType==NGT_Coop)
5956 										{
5957 											ignoreDamage = TRUE;
5958 										}
5959 									}
5960 									if(dispPtr==Player)
5961 									{
5962 										if(AvP.PlayerType == I_Marine)
5963 										{
5964 											ignoreDamage = TRUE;
5965 										}
5966 										else if (AvP.PlayerType == I_Predator && netGameData.gameType==NGT_Coop)
5967 										{
5968 											ignoreDamage = TRUE;
5969 										}
5970 									}
5971 
5972 								}
5973 							}
5974 
5975 							if(!ignoreDamage)
5976 							{
5977 								if(dispPtr==Player)
5978 								{
5979 									extern DPID myIgniterId;
5980 									myIgniterId=0; //the player hasn't been set alight by a network opponent
5981 								}
5982 								else if(sbPtr->I_SBtype==I_BehaviourAlien)
5983 								{
5984 									//note that the alien has been set on fire locally
5985 									ALIEN_STATUS_BLOCK *alienStatus = (ALIEN_STATUS_BLOCK *)sbPtr->SBdataptr;
5986 									if(particlePtr->ParticleID==PARTICLE_FLAME)
5987 									{
5988 										extern DPID AVPDPNetID;
5989 										alienStatus->aliensIgniterId=AVPDPNetID;
5990 									}
5991 									else
5992 									{
5993 										//no credit for aliens killed by molotov particles , or
5994 										//particle generator particles.
5995 										alienStatus->aliensIgniterId=0;
5996 									}
5997 								}
5998 							}
5999 						}
6000 						if(!ignoreDamage)
6001 						{
6002 							if(sbPtr->I_SBtype==I_BehaviourNetGhost)
6003 							{
6004 
6005 								/*
6006 								Don't let molotov particles damage netghosts. Each machine in a net game will be generating
6007 								its own molotov particles.
6008 								Similary for PARTICLE_PARGEN_FLAME
6009 								*/
6010 								if(particlePtr->ParticleID==PARTICLE_FLAME)
6011 								{
6012 									NETGHOSTDATABLOCK *ghostData=(NETGHOSTDATABLOCK *) sbPtr->SBdataptr;
6013 									GLOBALASSERT(ghostData);
6014 
6015 
6016 									//just add up the number of particles that have hit the ghost
6017 									//so the damage message can be sent in one block
6018 									ghostData->FlameHitCount++;
6019 									sbPtr->SBDamageBlock.IsOnFire = 1;
6020 								}
6021 							}
6022 							else
6023 							{
6024 								CauseDamageToObject(sbPtr,&TemplateAmmo[AMMO_FLAMETHROWER].MaxDamage[AvP.Difficulty], ONE_FIXED/400,NULL);
6025 								sbPtr->SBDamageBlock.IsOnFire = 1;
6026 							}
6027 						}
6028 					}
6029 					if (dispPtr==Player && !ignoreDamage)
6030 					{
6031 						PlayerStatusPtr->fireTimer=PLAYER_ON_FIRE_TIME;
6032 					}
6033 		 		}
6034 				else if (particlePtr->ParticleID==PARTICLE_FLECHETTE)
6035 				{
6036 					if(sbPtr->I_SBtype==I_BehaviourNetGhost)
6037 					{
6038 						//for net ghosts add up all the flechettes that hit it this frame , and send as one
6039 						//damage message
6040 						NETGHOSTDATABLOCK *ghostData=(NETGHOSTDATABLOCK *) sbPtr->SBdataptr;
6041 						GLOBALASSERT(ghostData);
6042 						ghostData->FlechetteHitCount++;
6043 
6044 					}
6045 					else
6046 					{
6047 						CauseDamageToObject(sbPtr,&FlechetteDamage,ONE_FIXED,&(particlePtr->Velocity));
6048 					}
6049 				}
6050 				else if (particlePtr->ParticleID==PARTICLE_PREDPISTOL_FLECHETTE)
6051 				{
6052 					CauseDamageToObject(sbPtr,&PredPistol_FlechetteDamage,particlePtr->LifeTime,&(particlePtr->Velocity));
6053 				}
6054 			}
6055 		}
6056 	}
6057 
6058 	if (*moduleIndexPtr != -1)
6059 	{
6060 		if(hitModule)
6061 		{
6062 			char stickWhereYouAre = 0;
6063 
6064 			if (hitModule->ObStrategyBlock)
6065 			{
6066 				if (hitModule->ObMyModule && (!hitModule->ObMorphCtrl))
6067 				{
6068 					stickWhereYouAre=1;
6069 				}
6070 			}
6071 			else
6072 			{
6073 				stickWhereYouAre = 1;
6074 			}
6075 
6076 			if (!stickWhereYouAre) *moduleIndexPtr = -1;
6077 
6078 			return hitObstacle;
6079 		}
6080 		return hitObstacle;
6081 	}
6082 	else return 0;
6083 }
6084 
FindLandscapePolygonsInParticlesPath(PARTICLE * particlePtr,VECTORCH * displacementPtr)6085 static void FindLandscapePolygonsInParticlesPath(PARTICLE *particlePtr, VECTORCH *displacementPtr)
6086 {
6087 	extern int NumActiveBlocks;
6088     extern DISPLAYBLOCK *ActiveBlockList[];
6089 
6090 	/* initialise near polygons array */
6091 	CollisionPolysPtr = &CollisionPolysArray[0];
6092     NumberOfCollisionPolys=0;
6093 
6094    	/* scan through ActiveBlockList for modules */
6095 	{
6096 	   	int numberOfObjects = NumActiveBlocks;
6097 	   	while(numberOfObjects)
6098 	   	{
6099 	   		DISPLAYBLOCK* objectPtr = ActiveBlockList[--numberOfObjects];
6100 	   		char isStaticObject=0;
6101 
6102 	   		GLOBALASSERT(objectPtr);
6103 			if(objectPtr->ObStrategyBlock)
6104 				if(objectPtr->ObStrategyBlock->DynPtr)
6105 				{
6106 					if(((objectPtr->ObStrategyBlock->DynPtr->IsStatic)
6107 					||(objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithObjects))
6108 			  		&&(!objectPtr->ObStrategyBlock->DynPtr->OnlyCollideWithEnvironment))
6109 						isStaticObject=1;
6110 				}
6111 
6112 	   		if (objectPtr->ObMyModule) /* is object a module or static? */
6113 	    	{
6114 				{
6115 					DBBMaxX = particlePtr->Position.vx - objectPtr->ObWorld.vx + COLLISION_GRANULARITY;
6116 					DBBMinX = particlePtr->Position.vx - objectPtr->ObWorld.vx - COLLISION_GRANULARITY;
6117 
6118 					DBBMaxY = particlePtr->Position.vy - objectPtr->ObWorld.vy + COLLISION_GRANULARITY;
6119 					DBBMinY = particlePtr->Position.vy - objectPtr->ObWorld.vy - COLLISION_GRANULARITY;
6120 
6121 					DBBMaxZ = particlePtr->Position.vz - objectPtr->ObWorld.vz + COLLISION_GRANULARITY;
6122 					DBBMinZ = particlePtr->Position.vz - objectPtr->ObWorld.vz - COLLISION_GRANULARITY;
6123 
6124 					if (displacementPtr->vx > 0)
6125 					{
6126 						DBBMaxX += displacementPtr->vx;
6127 					}
6128 					else
6129 					{
6130 					    DBBMinX += displacementPtr->vx;
6131 					}
6132 
6133 					if (displacementPtr->vy > 0)
6134 					{
6135 						DBBMaxY += displacementPtr->vy;
6136 					}
6137 					else
6138 					{
6139 					    DBBMinY += displacementPtr->vy;
6140 					}
6141 
6142 					if (displacementPtr->vz > 0)
6143 					{
6144 						DBBMaxZ += displacementPtr->vz;
6145 					}
6146 					else
6147 					{
6148 					    DBBMinZ += displacementPtr->vz;
6149 					}
6150 
6151 				}
6152 				LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
6153 
6154 				/* if the bounding box intersects with the object, investigate */
6155 			   	if (( (DBBMaxX >= objectPtr->ObMinX) && (DBBMinX <= objectPtr->ObMaxX) )
6156 			      &&( (DBBMaxY >= objectPtr->ObMinY) && (DBBMinY <= objectPtr->ObMaxY) )
6157  			      &&( (DBBMaxZ >= objectPtr->ObMinZ) && (DBBMinZ <= objectPtr->ObMaxZ) ))
6158 			       	TestShapeWithParticlesDynamicBoundingBox(objectPtr);
6159 	        }
6160 			else if (isStaticObject)
6161 			{
6162 				{
6163 					DBBMaxX = particlePtr->Position.vx - objectPtr->ObWorld.vx + COLLISION_GRANULARITY;
6164 					DBBMinX = particlePtr->Position.vx - objectPtr->ObWorld.vx - COLLISION_GRANULARITY;
6165 
6166 					DBBMaxY = particlePtr->Position.vy - objectPtr->ObWorld.vy + COLLISION_GRANULARITY;
6167 					DBBMinY = particlePtr->Position.vy - objectPtr->ObWorld.vy - COLLISION_GRANULARITY;
6168 
6169 					DBBMaxZ = particlePtr->Position.vz - objectPtr->ObWorld.vz + COLLISION_GRANULARITY;
6170 					DBBMinZ = particlePtr->Position.vz - objectPtr->ObWorld.vz - COLLISION_GRANULARITY;
6171 
6172 					if (displacementPtr->vx > 0)
6173 					{
6174 						DBBMaxX += displacementPtr->vx;
6175 					}
6176 					else
6177 					{
6178 					    DBBMinX += displacementPtr->vx;
6179 					}
6180 
6181 					if (displacementPtr->vy > 0)
6182 					{
6183 						DBBMaxY += displacementPtr->vy;
6184 					}
6185 					else
6186 					{
6187 					    DBBMinY += displacementPtr->vy;
6188 					}
6189 
6190 					if (displacementPtr->vz > 0)
6191 					{
6192 						DBBMaxZ += displacementPtr->vz;
6193 					}
6194 					else
6195 					{
6196 					    DBBMinZ += displacementPtr->vz;
6197 					}
6198 
6199 				}
6200 				LOCALASSERT(NumberOfCollisionPolys < MAXIMUM_NUMBER_OF_COLLISIONPOLYS);
6201 
6202 				/* if the bounding box intersects with the object, investigate */
6203 			   	if (( (DBBMaxX >= -objectPtr->ObRadius) && (DBBMinX <= objectPtr->ObRadius) )
6204 			      &&( (DBBMaxY >= -objectPtr->ObRadius) && (DBBMinY <= objectPtr->ObRadius) )
6205  			      &&( (DBBMaxZ >= -objectPtr->ObRadius) && (DBBMinZ <= objectPtr->ObRadius) ))
6206 			       	TestShapeWithParticlesDynamicBoundingBox(objectPtr);
6207 
6208 			}
6209 	    }
6210   	}
6211 }
6212 
DistanceMovedBeforeParticleHitsPolygon(PARTICLE * particlePtr,struct ColPolyTag * polyPtr,int distanceToMove)6213 static signed int DistanceMovedBeforeParticleHitsPolygon(PARTICLE *particlePtr, struct ColPolyTag *polyPtr, int distanceToMove)
6214 {
6215 	VECTORCH pointOnPlane;
6216 	int lambda;
6217 	int axis1;
6218 	int axis2;
6219 
6220 	{
6221 		int normDotBeta = DotProduct(&(polyPtr->PolyNormal),&DirectionOfTravel);
6222 
6223 		/* trivial rejection of poly if it is not facing LOS */
6224    		if (normDotBeta>-500)
6225    		{
6226    			return -1;
6227 		}
6228 
6229 		/* calculate coords of plane-line intersection */
6230 		{
6231 			int d;
6232 			{
6233 				/* get a pt in the poly */
6234 				VECTORCH pop=polyPtr->PolyPoint[0];
6235 				pop.vx -= particlePtr->Position.vx;
6236 				pop.vy -= particlePtr->Position.vy;
6237 				pop.vz -= particlePtr->Position.vz;
6238 
6239 			  	d = DotProduct(&(polyPtr->PolyNormal),&pop);
6240 			}
6241 			if (d>=0)
6242 			{
6243 				return -1;
6244 			}
6245 		  	lambda = DIV_FIXED(d,normDotBeta);
6246 			if (lambda>=distanceToMove)
6247 			{
6248 				return -1;
6249 			}
6250 	   		pointOnPlane.vx	= particlePtr->Position.vx + MUL_FIXED(lambda,DirectionOfTravel.vx);
6251 		   	pointOnPlane.vy	= particlePtr->Position.vy + MUL_FIXED(lambda,DirectionOfTravel.vy);
6252 	   		pointOnPlane.vz	= particlePtr->Position.vz + MUL_FIXED(lambda,DirectionOfTravel.vz);
6253 
6254   		}
6255 
6256 		/* decide which 2d plane to project onto */
6257 
6258 		{
6259 			VECTORCH absNormal = (polyPtr->PolyNormal);
6260 			if (absNormal.vx<0) absNormal.vx=-absNormal.vx;
6261 			if (absNormal.vy<0) absNormal.vy=-absNormal.vy;
6262 			if (absNormal.vz<0) absNormal.vz=-absNormal.vz;
6263 
6264 			if (absNormal.vx > absNormal.vy)
6265 			{
6266 				if (absNormal.vx > absNormal.vz)
6267 				{
6268 					axis1=iy;
6269 					axis2=iz;
6270 				}
6271 				else
6272 				{
6273 					axis1=ix;
6274 					axis2=iy;
6275 				}
6276 			}
6277 			else
6278 			{
6279 				if (absNormal.vy > absNormal.vz)
6280 				{
6281 					axis1=ix;
6282 					axis2=iz;
6283 				}
6284 				else
6285 				{
6286 					axis1=ix;
6287 					axis2=iy;
6288 				}
6289 			}
6290 		}
6291 
6292 	}
6293 	{
6294 		int projectedPolyVertex[20];
6295 		int projectedPointOnPlane[2];
6296 		int *popPtr = &pointOnPlane.vx;
6297 
6298 		projectedPointOnPlane[0]=*(popPtr+axis1);
6299 	 	projectedPointOnPlane[1]=*(popPtr+axis2);
6300 
6301 	 	{
6302 	 		VECTORCH *vertexPtr = polyPtr->PolyPoint;
6303 	 		int *projectedVertexPtr= projectedPolyVertex;
6304 			int noOfVertices = polyPtr->NumberOfVertices;
6305 
6306 			do
6307 			{
6308 	 			*projectedVertexPtr++ = *((int*)vertexPtr + axis1);
6309 	 			*projectedVertexPtr++ = *((int*)vertexPtr + axis2);
6310 
6311  	 		   	vertexPtr++;
6312 	 			noOfVertices--;
6313 	 		}
6314             while(noOfVertices);
6315 
6316 	 	}
6317 
6318 
6319 		if (PointInPolygon(&projectedPointOnPlane[0],&projectedPolyVertex[0],polyPtr->NumberOfVertices,2))
6320 		{
6321 		    return lambda;
6322 		}
6323 	}
6324 
6325 	return -1;
6326 }
6327 
AddEffectsOfForceGenerators(VECTORCH * positionPtr,VECTORCH * impulsePtr,int mass)6328 void AddEffectsOfForceGenerators(VECTORCH *positionPtr, VECTORCH *impulsePtr, int mass)
6329 {
6330 	extern int NumActiveBlocks;
6331 	extern DISPLAYBLOCK *ActiveBlockList[];
6332 	int numOfObjects = NumActiveBlocks;
6333 	while(numOfObjects)
6334 	{
6335 		DISPLAYBLOCK *objectPtr = ActiveBlockList[--numOfObjects];
6336 		STRATEGYBLOCK *sbPtr = objectPtr->ObStrategyBlock;
6337 
6338 		if (sbPtr && sbPtr->I_SBtype==I_BehaviourFan)
6339 		{
6340 		 	FAN_BEHAV_BLOCK *fanPtr;
6341 			fanPtr = (FAN_BEHAV_BLOCK*)sbPtr->SBdataptr;
6342 
6343 			if (fanPtr->wind_speed)
6344 			{
6345 				int mag;
6346 				VECTORCH disp = sbPtr->DynPtr->Position;
6347 				disp.vx -= positionPtr->vx;
6348 				disp.vy -= positionPtr->vy;
6349 				disp.vz -= positionPtr->vz;
6350 
6351 				mag = 16384 - Approximate3dMagnitude(&disp);
6352 
6353 				if (mag<0) continue;
6354 				if(MagnitudeOfCrossProduct(&disp,&fanPtr->fan_wind_direction)>objectPtr->ObRadius+200) continue;
6355 				mag=MUL_FIXED(MUL_FIXED(mag*32*4*32,fanPtr->wind_speed),NormalFrameTime)/mass;
6356 
6357 				impulsePtr->vx += MUL_FIXED(fanPtr->fan_wind_direction.vx,mag);
6358 				impulsePtr->vy += MUL_FIXED(fanPtr->fan_wind_direction.vy,mag);
6359 				impulsePtr->vz += MUL_FIXED(fanPtr->fan_wind_direction.vz,mag);
6360 			}
6361 //			PrintDebuggingText("Fan acting upon object %d\n",fanPtr->wind_speed);
6362 		}
6363 	}
6364 }
6365 
6366 #endif
6367 
6368 
6369 
GetNearestModuleTeleportPoint(MODULE * thisModulePtr,VECTORCH * positionPtr)6370 VECTORCH *GetNearestModuleTeleportPoint(MODULE* thisModulePtr, VECTORCH* positionPtr)
6371 {
6372 	extern FARENTRYPOINTSHEADER *FALLP_EntryPoints;
6373 	int numEps;
6374 	FARENTRYPOINT *epList;
6375 	FARENTRYPOINT *thisEp = (FARENTRYPOINT *)0;
6376 	int tmIndex = thisModulePtr->m_aimodule->m_index;
6377 	int distance = 0x7fffffff;
6378 
6379 	numEps = FALLP_EntryPoints[tmIndex].numEntryPoints;
6380 	epList = FALLP_EntryPoints[tmIndex].entryPointsList;
6381 
6382 	while((numEps>0))
6383 	{
6384 		VECTORCH p = *positionPtr;
6385 		int d;
6386 
6387 		p.vx -= thisModulePtr->m_aimodule->m_world.vx + epList->position.vx;
6388 		p.vy -= thisModulePtr->m_aimodule->m_world.vy + epList->position.vy;
6389 		p.vz -= thisModulePtr->m_aimodule->m_world.vz + epList->position.vz;
6390 
6391 		d = Approximate3dMagnitude(&p);
6392 
6393 		if (d<distance)
6394 		{
6395 			distance = d;
6396 			thisEp = epList;
6397 		}
6398 
6399 		epList++;
6400 		numEps--;
6401 	}
6402 
6403 	if(!thisEp)
6404 	{
6405 		return 0;
6406 	}
6407 	else
6408 	{
6409 		return &(thisEp->position);
6410 	}
6411 }
6412