1 /*------------------------Patrick 2/7/97-----------------------------
2   Source file for Marine and Seal AI behaviour functions....
3   --------------------------------------------------------------------*/
4 #include "3dc.h"
5 
6 #include "inline.h"
7 #include "module.h"
8 
9 #include "stratdef.h"
10 #include "gamedef.h"
11 #include "bh_types.h"
12 #include "comp_shp.h"
13 #include "dynblock.h"
14 #include "dynamics.h"
15 #include "lighting.h"
16 
17 #include "pfarlocs.h"
18 #include "pvisible.h"
19 #include "pheromon.h"
20 #include "bh_gener.h"
21 #include "bh_far.h"
22 #include "bh_pred.h"
23 #include "bh_marin.h"
24 #include "bh_weap.h"
25 #include "bh_debri.h"
26 #include "bh_alien.h"
27 #include "psnd.h"
28 #include "weapons.h"
29 #include "load_shp.h"
30 #include "particle.h"
31 #include "sfx.h"
32 #include "huddefs.h"
33 #include "pldghost.h"
34 #include "pldnet.h"
35 #include "psndplat.h"
36 #include "ai_sight.h"
37 #include "los.h"
38 #include "bh_corpse.h"
39 #include "bh_dummy.h"
40 #include "scream.h"
41 #include "targeting.h"
42 
43 #include "dxlog.h"
44 
45 #define UseLocalAssert Yes
46 #include "ourasert.h"
47 
48 #include "sequnces.h"
49 #include "showcmds.h"
50 #include "extents.h"
51 #include "avp_userprofile.h"
52 #include "hud.h"
53 
54 #define ALL_PULSERIFLES 0
55 #define MOTIONTRACKERS 0
56 #define ANARCHY 0
57 #define PISTOL_CLIP_SIZE 8
58 #define SENTRY_SENSITIVITY 1500
59 #define MARINE_AUTODETECT_RANGE	2500
60 
61 #define SUSPECT_SENSITIVITY 2100
62 /* Ten centimetres.  It can make a lot of difference. */
63 
64 #define ALL_NEW_AVOIDANCE	(1)
65 #define TWO_PISTOL_GUY		(1)
66 
67 /* external global variables used in this file */
68 extern int ModuleArraySize;
69 extern char *ModuleCurrVisArray;
70 extern int NormalFrameTime;
71 extern unsigned char Null_Name[8];
72 extern ACTIVESOUNDSAMPLE ActiveSounds[];
73 extern int CurrentLightAtPlayer;
74 
75 extern int AIModuleArraySize;
76 extern AIMODULE *AIModuleArray;
77 extern DAMAGE_PROFILE FallingDamage;
78 
79 extern enum PARTICLE_ID GetBloodType(STRATEGYBLOCK *sbPtr);
80 extern HIERARCHY_SHAPE_REPLACEMENT* GetHierarchyAlternateShapeSetFromLibrary(const char* rif_name,const char* shape_set_name);
81 extern HIERARCHY_VARIANT_DATA* GetHierarchyAlternateShapeSetCollectionFromLibrary(const char* rif_name,int collection_index);
82 extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
83 extern STRATEGYBLOCK* CreateRocketKernel(VECTORCH *position, MATRIXCH *orient,int fromplayer);
84 extern STRATEGYBLOCK* CreateFrisbeeKernel(VECTORCH *position, MATRIXCH *orient, int fromplayer);
85 extern int AlienPCIsCurrentlyVisible(int checktime,STRATEGYBLOCK *sbPtr);
86 extern int SBIsEnvironment(STRATEGYBLOCK *sbPtr);
87 void Marine_SwitchExpression(STRATEGYBLOCK *sbPtr,int state);
88 
89 extern void PrintSpottedNumber(void);
90 
91 /* prototypes for this file */
92 static STATE_RETURN_CONDITION Execute_MFS_Wait(STRATEGYBLOCK *sbPtr);
93 #if 0
94 static STATE_RETURN_CONDITION Execute_MFS_Hunt(STRATEGYBLOCK *sbPtr);
95 static STATE_RETURN_CONDITION Execute_MNS_DischargeGL(STRATEGYBLOCK *sbPtr);
96 static STATE_RETURN_CONDITION Execute_MNS_Hunt(STRATEGYBLOCK *sbPtr);
97 #endif
98 static STATE_RETURN_CONDITION Execute_MFS_Wander(STRATEGYBLOCK *sbPtr);
99 static STATE_RETURN_CONDITION Execute_MFS_Approach(STRATEGYBLOCK *sbPtr);
100 static STATE_RETURN_CONDITION Execute_MFS_Firing(STRATEGYBLOCK *sbPtr);
101 static STATE_RETURN_CONDITION Execute_MFS_Return(STRATEGYBLOCK *sbPtr);
102 static STATE_RETURN_CONDITION Execute_MFS_Pathfinder(STRATEGYBLOCK *sbPtr);
103 static STATE_RETURN_CONDITION Execute_MFS_Avoidance(STRATEGYBLOCK *sbPtr);
104 static STATE_RETURN_CONDITION Execute_MFS_SentryMode(STRATEGYBLOCK *sbPtr);
105 
106 static STATE_RETURN_CONDITION Execute_MNS_Approach(STRATEGYBLOCK *sbPtr);
107 static STATE_RETURN_CONDITION Execute_MNS_Avoidance(STRATEGYBLOCK *sbPtr);
108 static STATE_RETURN_CONDITION Execute_MNS_Wander(STRATEGYBLOCK *sbPtr);
109 static STATE_RETURN_CONDITION Execute_MNS_Wait(STRATEGYBLOCK *sbPtr);
110 static STATE_RETURN_CONDITION Execute_MNS_DischargeLOSWeapon(STRATEGYBLOCK *sbPtr);
111 static STATE_RETURN_CONDITION Execute_MNS_DischargeShotgun(STRATEGYBLOCK *sbPtr);
112 static STATE_RETURN_CONDITION Execute_MNS_DischargePistol(STRATEGYBLOCK *sbPtr);
113 static STATE_RETURN_CONDITION Execute_MNS_DischargeSADAR(STRATEGYBLOCK *sbPtr);
114 static STATE_RETURN_CONDITION Execute_MNS_DischargeFlamethrower(STRATEGYBLOCK *sbPtr);
115 static STATE_RETURN_CONDITION Execute_MNS_ThrowMolotov(STRATEGYBLOCK *sbPtr);
116 static STATE_RETURN_CONDITION Execute_MNS_DischargeMinigun(STRATEGYBLOCK *sbPtr);
117 static STATE_RETURN_CONDITION Execute_MNS_SentryMode(STRATEGYBLOCK *sbPtr);
118 static STATE_RETURN_CONDITION Execute_MNS_Respond(STRATEGYBLOCK *sbPtr);
119 static STATE_RETURN_CONDITION Execute_MNS_Retreat(STRATEGYBLOCK *sbPtr);
120 static STATE_RETURN_CONDITION Execute_MNS_Return(STRATEGYBLOCK *sbPtr);
121 static STATE_RETURN_CONDITION Execute_MNS_Pathfinder(STRATEGYBLOCK *sbPtr);
122 static STATE_RETURN_CONDITION Execute_MNS_Taunting(STRATEGYBLOCK *sbPtr);
123 static STATE_RETURN_CONDITION Execute_MNS_Reloading(STRATEGYBLOCK *sbPtr);
124 static STATE_RETURN_CONDITION Execute_MNS_GetWeapon(STRATEGYBLOCK *sbPtr);
125 static STATE_RETURN_CONDITION Execute_MNS_NewDischargeGL(STRATEGYBLOCK *sbPtr);
126 static STATE_RETURN_CONDITION Execute_MNS_DischargeSmartgun(STRATEGYBLOCK *sbPtr);
127 static STATE_RETURN_CONDITION Execute_MNS_PanicReloading(STRATEGYBLOCK *sbPtr);
128 static STATE_RETURN_CONDITION Execute_MNS_DischargeTwoPistols(STRATEGYBLOCK *sbPtr);
129 static STATE_RETURN_CONDITION Execute_MNS_DischargeSkeeter(STRATEGYBLOCK *sbPtr);
130 static STATE_RETURN_CONDITION Execute_MNS_AcidAvoidance(STRATEGYBLOCK *sbPtr);
131 
132 static void MarineMisfireFlameThrower(SECTION_DATA *muzzle, int *timer);
133 static STATE_RETURN_CONDITION Execute_MNS_NullPanicFire(STRATEGYBLOCK *sbPtr);
134 static STATE_RETURN_CONDITION Execute_MNS_PanicFireLOSWeapon(STRATEGYBLOCK *sbPtr);
135 static STATE_RETURN_CONDITION Execute_MNS_PanicFireFlamethrower(STRATEGYBLOCK *sbPtr);
136 static STATE_RETURN_CONDITION Execute_MNS_PanicFireGL(STRATEGYBLOCK *sbPtr);
137 static STATE_RETURN_CONDITION Execute_MNS_PanicFireMinigun(STRATEGYBLOCK *sbPtr);
138 static STATE_RETURN_CONDITION Execute_MNS_PanicFirePistol(STRATEGYBLOCK *sbPtr);
139 static STATE_RETURN_CONDITION Execute_MNS_PanicFireShotgun(STRATEGYBLOCK *sbPtr);
140 static STATE_RETURN_CONDITION Execute_MNS_PanicFireUnarmed(STRATEGYBLOCK *sbPtr);
141 
142 void NPC_Maintain_Minigun(STRATEGYBLOCK *sbPtr, DELTA_CONTROLLER *mgd);
143 void Marine_AssumePanicExpression(STRATEGYBLOCK *sbPtr);
144 static STATE_RETURN_CONDITION Execute_MFS_Respond(STRATEGYBLOCK *sbPtr);
145 static STATE_RETURN_CONDITION Execute_MNS_PumpAction(STRATEGYBLOCK *sbPtr);
146 static STATE_RETURN_CONDITION Execute_MFS_Retreat(STRATEGYBLOCK *sbPtr);
147 
148 static void Execute_Dying(STRATEGYBLOCK *sbPtr); /* used for near and far */
149 
150 static void ProcessFarMarineTargetModule(STRATEGYBLOCK *sbPtr, AIMODULE* targetModule);
151 static void LobAGrenade(STRATEGYBLOCK *sbPtr);
152 static void CreateMarineGunFlash(STRATEGYBLOCK *sbPtr);
153 
154 static void MarineFireFlameThrower(STRATEGYBLOCK *sbPtr);
155 
156 static void	Marine_ConsiderFallingDamage(STRATEGYBLOCK *sbPtr);
157 static void	Marine_MirrorSuspectPoint(STRATEGYBLOCK *sbPtr);
158 static int MarineCanSeeTarget(STRATEGYBLOCK *sbPtr);
159 static int MarineCanSeeObject(STRATEGYBLOCK *sbPtr,STRATEGYBLOCK *target);
160 static int MarineIsAwareOfTarget(STRATEGYBLOCK *sbPtr);
161 static int MarineShouldBeCrawling(STRATEGYBLOCK *sbPtr);
162 static int MarineRetreatsInTheFaceOfDanger(STRATEGYBLOCK *sbPtr);
163 static void SetMarineAnimationSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweening);
164 static void SetMarineAnimationSequence_Null(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweening);
165 void Marine_Enter_Respond_State(STRATEGYBLOCK *sbPtr);
166 
167 int SpeedRangeMods(VECTORCH *range,VECTORCH *speed);
168 STRATEGYBLOCK *Marine_GetNewTarget(VECTORCH *marinepos, STRATEGYBLOCK *me);
169 void FakeTrackerWheepGenerator(VECTORCH *marinepos, STRATEGYBLOCK *me);
170 
171 void InitMission(STRATEGYBLOCK *sbPtr,MARINE_MISSION mission);
172 
173 void WanderMission_Control(STRATEGYBLOCK *sbPtr);
174 void PathfinderMission_Control(STRATEGYBLOCK *sbPtr);
175 void GuardMission_Control(STRATEGYBLOCK *sbPtr);
176 void LocalGuardMission_Control(STRATEGYBLOCK *sbPtr);
177 void LoiterMission_Control(STRATEGYBLOCK *sbPtr);
178 void RunAroundOnFireMission_Control(STRATEGYBLOCK *sbPtr);
179 
180 void WanderMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result);
181 void PathfinderMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result);
182 void GuardMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result);
183 void LocalGuardMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result);
184 void LoiterMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result);
185 
186 void Marine_Enter_SentryMode_State(STRATEGYBLOCK *sbPtr);
187 void Marine_Enter_Wait_State(STRATEGYBLOCK *sbPtr);
188 void Marine_Enter_Firing_State(STRATEGYBLOCK *sbPtr);
189 void Marine_Enter_Avoidance_State(STRATEGYBLOCK *sbPtr);
190 void Marine_Enter_Wander_State(STRATEGYBLOCK *sbPtr);
191 void Marine_Enter_Approach_State(STRATEGYBLOCK *sbPtr);
192 void Marine_Enter_Hunt_State(STRATEGYBLOCK *sbPtr);
193 void Marine_Enter_Retreat_State(STRATEGYBLOCK *sbPtr);
194 void Marine_Enter_Return_State(STRATEGYBLOCK *sbPtr);
195 void Marine_Enter_Pathfinder_State(STRATEGYBLOCK *sbPtr);
196 void Marine_Enter_Taunt_State(STRATEGYBLOCK *sbPtr);
197 void Marine_Enter_PanicFire_State(STRATEGYBLOCK *sbPtr);
198 void Marine_Enter_Reload_State(STRATEGYBLOCK *sbPtr);
199 void Marine_Enter_PumpAction_State(STRATEGYBLOCK *sbPtr);
200 void Marine_Enter_PullPistol_State(STRATEGYBLOCK *sbPtr);
201 void Marine_Enter_OneArmShotgun_State(STRATEGYBLOCK *sbPtr);
202 void Marine_Enter_OneArmPistol_State(STRATEGYBLOCK *sbPtr);
203 void Marine_Enter_PanicReload_State(STRATEGYBLOCK *sbPtr);
204 
205 void Marine_Activate_AcidAvoidance_State(STRATEGYBLOCK *sbPtr, VECTORCH *incidence);
206 
207 void Marine_QueueNeutralExpression(STRATEGYBLOCK *sbPtr);
208 void Marine_QueueGrimaceExpression(STRATEGYBLOCK *sbPtr);
209 void Marine_QueuePanicExpression(STRATEGYBLOCK *sbPtr);
210 void Marine_QueueWink1Expression(STRATEGYBLOCK *sbPtr);
211 void Marine_QueueWink2Expression(STRATEGYBLOCK *sbPtr);
212 int Marine_HasHisMouthOpen(STRATEGYBLOCK *sbPtr);
213 void Marine_UpdateFace(STRATEGYBLOCK *sbPtr);
214 
215 void Marine_MuteVoice(STRATEGYBLOCK *sbPtr);
216 void Marine_WoundedScream(STRATEGYBLOCK *sbPtr);
217 void Marine_AcidScream(STRATEGYBLOCK *sbPtr);
218 void Marine_BurningScream(STRATEGYBLOCK *sbPtr);
219 void Marine_DeathScream(STRATEGYBLOCK *sbPtr);
220 void Marine_ElectrocutionScream(STRATEGYBLOCK *sbPtr);
221 void Marine_BurningDeathScream(STRATEGYBLOCK *sbPtr);
222 void Marine_AngryScream(STRATEGYBLOCK *sbPtr);
223 void Marine_PanicScream(STRATEGYBLOCK *sbPtr);
224 void Marine_OoophSound(STRATEGYBLOCK *sbPtr);
225 void Marine_SurpriseSound(STRATEGYBLOCK *sbPtr);
226 void Marine_Sobbing(STRATEGYBLOCK *sbPtr);
227 void Marine_TauntShout(STRATEGYBLOCK *sbPtr);
228 
229 void NPC_GetBimbleTarget(STRATEGYBLOCK *sbPtr,VECTORCH *output);
230 void CreateMarineBot(VECTORCH *Position,int weapon);
231 void Convert_To_RunningOnFire(STRATEGYBLOCK *sbPtr);
232 void GetPointToFaceMarineTowards(STRATEGYBLOCK *sbPtr,VECTORCH *output);
233 void DoMarineHearing(STRATEGYBLOCK *sbPtr);
234 
235 static void HandleWaitingAnimations(STRATEGYBLOCK *sbPtr);
236 static void HandleMovingAnimations(STRATEGYBLOCK *sbPtr);
237 int MakeModifiedTargetNum(int targetnum,int dist);
238 
239 
240 /* Console Variables */
241 
242 int Marine_Skill=20000;
243 int Marine_Terminal_Velocity=20000;
244 
245 /* Console Variables */
246 
247 MARINE_WEAPON_DATA NPC_Marine_Weapons[] = {
248 	{
249 		MNPCW_PulseRifle,					/* ID */
250 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
251 
252 		Execute_MNS_DischargeLOSWeapon,		/* Func. */
253 		NULL,								/* Misfire func. */
254 		Execute_MNS_PanicFireLOSWeapon,		/* WeaponPanicFireFunction */
255 		"hnpcmarine",						/* Riffname */
256 		"marine with pulse rifle", 			/* HierarchyName */
257 		"dum flash",						/* GunflashName */
258 		"pulse rifle",						/* ElevationSection */
259 		"marine with pulse rifle", 			/* HitLocationTableName */
260 		"Template",							/* TemplateName */
261 		"pulse mag",						/* ClipName */
262 		0,									/* MinRange (Don't fire when closer) */
263 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
264 		-1,									/* MaxRange (Don't fire if further) */
265 		0,									/* Accuracy */
266 		1000*65536/60,						/* Firing Rate */
267 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
268 		10,									/* MinimumBurstSize */
269 		AMMO_10MM_CULW_NPC,						/* Ammo profile */
270 		99,									/* clip_size */
271 		MSSS_Reload,						/* Reload_Sequence */
272 		300,								/* TargetCallibrationShift */
273 		SID_NOSOUND,						/* StartSound */
274 		SID_PULSE_LOOP,						/* LoopSound */
275 		SID_NOSOUND,						/* EndSound */
276 		1,									/* Enable Grenades */
277 		1,									/* UseElevation */
278 		1,									/* EnableTracker */
279 		1,									/* ARealMarine */
280 		0,									/* Android */
281 	},
282 	{
283 		MNPCW_Flamethrower,					/* ID */
284 		SFX_NONE,							/* enum SFX_ID SfxID; */
285 		Execute_MNS_DischargeFlamethrower,	/* Func. */
286 		MarineMisfireFlameThrower,			/* Misfire func. */
287 		Execute_MNS_PanicFireFlamethrower,	/* WeaponPanicFireFunction */
288 		"hnpcmarine",						/* Riffname */
289 		"marine with flame thrower",		/* HierarchyName */
290 		"dum flash",						/* GunflashName */
291 		"flamer",							/* ElevationSection */
292 		"marine with flame thrower",		/* HitLocationTableName */
293 		"Template",							/* TemplateName */
294 		"flamer mag",						/* ClipName */
295 		0,									/* MinRange (Don't fire when closer) */
296 		5000,								/* ForceFireRange (Fire if closer) */
297 		10000,								/* MaxRange (Don't fire if further) */
298 		ONE_FIXED,							/* Accuracy */
299 		200,								/* Firing Rate */
300 		MARINE_NEAR_FIRE_TIME<<2,			/* Firing Time */
301 		0,									/* MinimumBurstSize */
302 		AMMO_FLAMETHROWER,					/* Ammo profile */
303 		(ONE_FIXED*3),						/* clip_size */
304 		MSSS_Reload,						/* Reload_Sequence */
305 		0,									/* TargetCallibrationShift */
306 		SID_INCIN_START,					/* StartSound */
307 		SID_INCIN_LOOP,						/* LoopSound */
308 		SID_INCIN_END,						/* EndSound */
309 		0,									/* Enable Grenades */
310 		1,									/* UseElevation */
311 		1,									/* EnableTracker */
312 		1,									/* ARealMarine */
313 		0,									/* Android */
314 	},
315 	{
316 		MNPCW_Smartgun,						/* ID */
317 		SFX_MUZZLE_FLASH_SMARTGUN,			/* enum SFX_ID SfxID; */
318 		Execute_MNS_DischargeSmartgun,		/* Func.  Changed from DischargeLOSWeapon! */
319 		NULL,								/* Misfire func. */
320 		Execute_MNS_PanicFireLOSWeapon,		/* WeaponPanicFireFunction */
321 		"hnpcmarine",						/* Riffname */
322 		"marine with smart gun",			/* HierarchyName */
323 		"dum flash",						/* GunflashName */
324 		"smart gun",						/* ElevationSection */
325 		"marine with smart gun", 			/* HitLocationTableName */
326 		"Template",							/* TemplateName */
327 		"smart mag",						/* ClipName */
328 		0,									/* MinRange (Don't fire when closer) */
329 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
330 		36000,								/* MaxRange (Don't fire if further) */
331 		ONE_FIXED,							/* Accuracy */
332 		50*65536,							/* Firing Rate */
333 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
334 		50,									/* MinimumBurstSize */
335 		AMMO_SMARTGUN_NPC,						/* Ammo profile */
336 		300,								/* clip_size */
337 		MSSS_Reload,						/* Reload_Sequence */
338 		0,									/* TargetCallibrationShift */
339 		SID_NOSOUND,						/* StartSound */
340 		SID_SMART1, 						/* LoopSound */
341 		SID_NOSOUND,						/* EndSound */
342 		0,									/* Enable Grenades */
343 		1,									/* UseElevation */
344 		1,									/* EnableTracker */
345 		1,									/* ARealMarine */
346 		0,									/* Android */
347 	},
348 	{
349 		MNPCW_SADAR,						/* ID */
350 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
351 
352 		Execute_MNS_DischargeSADAR,			/* Func. */
353 		NULL,								/* Misfire func. */
354 		Execute_MNS_NullPanicFire,			/* WeaponPanicFireFunction */
355 		"hnpcmarine",						/* Riffname */
356 		"marine with SADAR",				/* HierarchyName */
357 		"dum flame",						/* GunflashName */
358 		"SADAR Tube",						/* ElevationSection */
359 		"marine with pulse rifle", 			/* HitLocationTableName */
360 		"Template",							/* TemplateName */
361 		"SADAR",							/* ClipName */
362 		5000,								/* MinRange (Don't fire when closer) */
363 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
364 		-1,									/* MaxRange (Don't fire if further) */
365 		0,									/* Accuracy */
366 		1000*65536/60,						/* Firing Rate */
367 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
368 		0,									/* MinimumBurstSize */
369 		AMMO_10MM_CULW,						/* Ammo profile */
370 		1,									/* clip_size */
371 		MSSS_Reload,						/* Reload_Sequence */
372 		300,								/* TargetCallibrationShift */
373 		SID_ROCKFIRE,						/* StartSound */
374 		SID_NOSOUND,						/* LoopSound */
375 		SID_NOSOUND,						/* EndSound */
376 		1,									/* Enable Grenades */
377 		1,									/* UseElevation */
378 		1,									/* EnableTracker */
379 		1,									/* ARealMarine */
380 		0,									/* Android */
381 	},
382 	{
383 		MNPCW_GrenadeLauncher,				/* ID */
384 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
385 
386 		Execute_MNS_NewDischargeGL,			/* Func. */
387 		NULL,								/* Misfire func. */
388 		Execute_MNS_PanicFireGL,			/* WeaponPanicFireFunction */
389 		"hnpcmarine",						/* Riffname */
390 		"marine + grenade launcher",		/* HierarchyName */
391 		"dum flash",						/* GunflashName */
392 		"gren stock",						/* ElevationSection */
393 		"marine with pulse rifle", 			/* HitLocationTableName */
394 		"Template",							/* TemplateName */
395 		"gren mag",							/* ClipName */
396 		9000,								/* MinRange (Don't fire when closer) */
397 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
398 		-1,									/* MaxRange (Don't fire if further) */
399 		0,									/* Accuracy */
400 		1000*65536/60,						/* Firing Rate */
401 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
402 		0,									/* MinimumBurstSize */
403 		AMMO_10MM_CULW,						/* Ammo profile */
404 		6,									/* clip_size */
405 		MSSS_Reload,  						/* Reload_Sequence */
406 		0,									/* TargetCallibrationShift */
407 		SID_ROCKFIRE,						/* StartSound */
408 		SID_NOSOUND,						/* LoopSound */
409 		SID_NOSOUND,						/* EndSound */
410 		1,									/* Enable Grenades */
411 		1,									/* UseElevation */
412 		1,									/* EnableTracker */
413 		1,									/* ARealMarine */
414 		0,									/* Android */
415 	},
416 	{
417 		MNPCW_Minigun,						/* ID */
418 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
419 
420 		Execute_MNS_DischargeMinigun,		/* Func. */
421 		NULL,								/* Misfire func. */
422 		Execute_MNS_PanicFireMinigun,		/* WeaponPanicFireFunction */
423 		"hnpcmarine",						/* Riffname */
424 		"Marine with Mini Gun", 			/* HierarchyName */
425 		"dum flash",						/* GunflashName */
426 		"mini gun",							/* ElevationSection */
427 		"marine with pulse rifle", 			/* HitLocationTableName */
428 		"Template",							/* TemplateName */
429 		"mini mag",							/* ClipName */
430 		0,									/* MinRange (Don't fire when closer) */
431 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
432 		-1,									/* MaxRange (Don't fire if further) */
433 		0,									/* Accuracy */
434 		100*65536,							/* Firing Rate */
435 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
436 		MINIGUN_MINIMUM_BURST,				/* MinimumBurstSize */
437 		AMMO_MINIGUN_NPC,						/* Ammo profile */
438 		500,								/* clip_size */
439 		MSSS_Reload,						/* Reload_Sequence */
440 		0,									/* TargetCallibrationShift */
441 		SID_NOSOUND,						/* StartSound */
442 		SID_MINIGUN_LOOP,					/* LoopSound */
443 		SID_MINIGUN_END, 					/* EndSound */
444 		0,									/* Enable Grenades */
445 		1,									/* UseElevation */
446 		1,									/* EnableTracker */
447 		1,									/* ARealMarine */
448 		0,									/* Android */
449 	},
450 	{
451 		MNPCW_PistolMarine,					/* ID */
452 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
453 
454 		Execute_MNS_DischargePistol,		/* Func. */
455 		NULL,								/* Misfire func. */
456 		Execute_MNS_PanicFirePistol,		/* WeaponPanicFireFunction */
457 		"hnpcmarine",						/* Riffname */
458 		"PISTOL",			 				/* HierarchyName */
459 		"dum flash",						/* GunflashName */
460 		"Rbicep",							/* ElevationSection */
461 		"marine with pulse rifle", 			/* HitLocationTableName */
462 		"Template",							/* TemplateName */
463 		NULL,								/* ClipName */
464 		0,									/* MinRange (Don't fire when closer) */
465 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
466 		-1,									/* MaxRange (Don't fire if further) */
467 		30000,	  							/* Accuracy */
468 		1,									/* Firing Rate */
469 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
470 		0,									/* MinimumBurstSize */
471 		AMMO_MARINE_PISTOL,					/* Ammo profile */
472 		12,									/* clip_size */
473 		MSSS_Reload,						/* Reload_Sequence */
474 		250,								/* TargetCallibrationShift */
475 		SID_SHOTGUN,						/* StartSound */
476 		SID_NOSOUND,						/* LoopSound */
477 		SID_NOSOUND,						/* EndSound */
478 		0,									/* Enable Grenades */
479 		1,									/* UseElevation */
480 		0,									/* EnableTracker */
481 		1,									/* ARealMarine */
482 		0,									/* Android */
483 	},
484 	{
485 		MNPCW_MShotgun,						/* ID */
486 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
487 
488 		Execute_MNS_DischargeShotgun,		/* Func. */
489 		NULL,								/* Misfire func. */
490 		Execute_MNS_PanicFireShotgun,		/* WeaponPanicFireFunction */
491 		"hnpc_civvie",						/* Riffname */
492 		"male_shotgun",		 				/* HierarchyName */
493 		"flash dummy",						/* GunflashName */
494 		"shot gun",							/* ElevationSection */
495 		"male civvie",		 				/* HitLocationTableName */
496 		"TEMPLATE",							/* TemplateName */
497 		NULL,								/* ClipName */
498 		0,									/* MinRange (Don't fire when closer) */
499 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
500 		-1,									/* MaxRange (Don't fire if further) */
501 		0,									/* Accuracy */
502 		1,									/* Firing Rate */
503 		-1,									/* Firing Time */
504 		0,									/* MinimumBurstSize */
505 		AMMO_SHOTGUN,						/* Ammo profile */
506 		8,									/* clip_size */
507 		MSSS_Reload,						/* Reload_Sequence */
508 		0,									/* TargetCallibrationShift */
509 		SID_SHOTGUN,						/* StartSound */
510 		SID_NOSOUND,						/* LoopSound */
511 		SID_NOSOUND,						/* EndSound */
512 		0,									/* Enable Grenades */
513 		1,									/* UseElevation */
514 		0,									/* EnableTracker */
515 		0,									/* ARealMarine */
516 		0,									/* Android */
517 	},
518 	{
519 		MNPCW_MPistol,						/* ID */
520 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
521 
522 		Execute_MNS_DischargePistol,		/* Func. */
523 		NULL,								/* Misfire func. */
524 		Execute_MNS_PanicFirePistol,		/* WeaponPanicFireFunction */
525 		"hnpc_civvie",						/* Riffname */
526 		"male_pistol",		 				/* HierarchyName */
527 		"flash dummy",						/* GunflashName */
528 		"male right bicep",					/* ElevationSection */
529 		"male civvie",		 				/* HitLocationTableName */
530 		"TEMPLATE",							/* TemplateName */
531 		NULL,								/* ClipName */
532 		0,									/* MinRange (Don't fire when closer) */
533 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
534 		-1,									/* MaxRange (Don't fire if further) */
535 		10000,	  							/* Accuracy */
536 		1,									/* Firing Rate */
537 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
538 		0,									/* MinimumBurstSize */
539 		AMMO_10MM_CULW_NPC,						/* Ammo profile */
540 		PISTOL_CLIP_SIZE,					/* clip_size */
541 		MSSS_Reload,						/* Reload_Sequence */
542 		0,									/* TargetCallibrationShift */
543 		SID_SHOTGUN,						/* StartSound */
544 		SID_NOSOUND,						/* LoopSound */
545 		SID_NOSOUND,						/* EndSound */
546 		0,									/* Enable Grenades */
547 		1,									/* UseElevation */
548 		0,									/* EnableTracker */
549 		0,									/* ARealMarine */
550 		0,									/* Android */
551 	},
552 	{
553 		MNPCW_MFlamer,						/* ID */
554 		SFX_NONE,							/* enum SFX_ID SfxID; */
555 		Execute_MNS_DischargeFlamethrower,	/* Func. */
556 		MarineMisfireFlameThrower,			/* Misfire func. */
557 		Execute_MNS_PanicFireFlamethrower,	/* WeaponPanicFireFunction */
558 		"hnpc_civvie",						/* Riffname */
559 		"male_flamer",		 				/* HierarchyName */
560 		"flash dummy",						/* GunflashName */
561 		"male right bicep",					/* ElevationSection */
562 		"male civvie",		 				/* HitLocationTableName */
563 		"TEMPLATE",							/* TemplateName */
564 		"flame canaster",					/* ClipName */
565 		0,									/* MinRange (Don't fire when closer) */
566 		5000,								/* ForceFireRange (Fire if closer) */
567 		10000,								/* MaxRange (Don't fire if further) */
568 		ONE_FIXED,							/* Accuracy */
569 		200,								/* Firing Rate */
570 		MARINE_NEAR_FIRE_TIME<<2,			/* Firing Time */
571 		0,									/* MinimumBurstSize */
572 		AMMO_FLAMETHROWER,					/* Ammo profile */
573 		(ONE_FIXED*2),						/* clip_size */
574 		MSSS_Reload, 						/* Reload_Sequence */
575 		0,									/* TargetCallibrationShift */
576 		SID_INCIN_START,					/* StartSound */
577 		SID_INCIN_LOOP,						/* LoopSound */
578 		SID_INCIN_END,						/* EndSound */
579 		0,									/* Enable Grenades */
580 		1,									/* UseElevation */
581 		0,									/* EnableTracker */
582 		0,									/* ARealMarine */
583 		0,									/* Android */
584 	},
585 	{
586 		MNPCW_MUnarmed,						/* ID */
587 		SFX_NONE,							/* enum SFX_ID SfxID; */
588 
589 		NULL,								/* Func. */
590 		NULL,								/* Misfire func. */
591 		Execute_MNS_PanicFireUnarmed,		/* WeaponPanicFireFunction */
592 		"hnpc_civvie", 						/* Riffname */
593 		"male_unarmed",			 			/* HierarchyName */
594 		NULL,								/* GunflashName */
595 		NULL,								/* ElevationSection */
596 		"male civvie",		 				/* HitLocationTableName */
597 		"TEMPLATE",							/* TemplateName */
598 		NULL,								/* ClipName */
599 		0,									/* MinRange (Don't fire when closer) */
600 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
601 		-1,									/* MaxRange (Don't fire if further) */
602 		0,									/* Accuracy */
603 		1,									/* Firing Rate */
604 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
605 		0,									/* MinimumBurstSize */
606 		AMMO_NONE,							/* Ammo profile */
607 		-1,									/* clip_size */
608 		MSSS_Standard,							/* Reload_Sequence */
609 		0,									/* TargetCallibrationShift */
610 		SID_NOSOUND,						/* StartSound */
611 		SID_NOSOUND,						/* LoopSound */
612 		SID_NOSOUND,						/* EndSound */
613 		0,									/* Enable Grenades */
614 		0,									/* UseElevation */
615 		0,									/* EnableTracker */
616 		0,									/* ARealMarine */
617 		0,									/* Android */
618 	},
619 	{
620 		MNPCW_MMolotov,						/* ID */
621 		SFX_NONE,							/* enum SFX_ID SfxID; */
622 
623 		Execute_MNS_ThrowMolotov,			/* Func. */
624 		NULL,								/* Misfire func. */
625 		Execute_MNS_NullPanicFire,			/* WeaponPanicFireFunction */
626 		"hnpc_civvie",						/* Riffname */
627 		"male_bottle", 		 				/* HierarchyName */
628 		"bottle",							/* GunflashName */
629 		NULL,								/* ElevationSection */
630 		"male civvie",		 				/* HitLocationTableName */
631 		"TEMPLATE",							/* TemplateName */
632 		NULL,								/* ClipName */
633 		0,									/* MinRange (Don't fire when closer) */
634 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
635 		10000,								/* MaxRange (Don't fire if further) */
636 		-10000,								/* Accuracy */
637 		1,									/* Firing Rate */
638 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
639 		0,									/* MinimumBurstSize */
640 		AMMO_10MM_CULW,						/* Ammo profile */
641 		-1,									/* clip_size */
642 		MSSS_Standard,						/* Reload_Sequence */
643 		0,									/* TargetCallibrationShift */
644 		SID_NOSOUND,						/* StartSound */
645 		SID_NOSOUND,						/* LoopSound */
646 		SID_NOSOUND,						/* EndSound */
647 		0,									/* Enable Grenades */
648 		0,									/* UseElevation */
649 		0,									/* EnableTracker */
650 		0,									/* ARealMarine */
651 		0,									/* Android */
652 	},
653 	{
654 		MNPCW_Android,						/* ID */
655 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
656 
657 		Execute_MNS_DischargeShotgun,		/* Func. */
658 		NULL,								/* Misfire func. */
659 		Execute_MNS_PanicFireShotgun,		/* WeaponPanicFireFunction */
660 		"hnpc_civvie",						/* Riffname */
661 		"Android shotgun",	 				/* HierarchyName */
662 		"flash dummy",						/* GunflashName */
663 		"shot gun",							/* ElevationSection */
664 		"male civvie",		 				/* HitLocationTableName */
665 		"Android template",					/* TemplateName */
666 		NULL,								/* ClipName */
667 		0,									/* MinRange (Don't fire when closer) */
668 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
669 		-1,									/* MaxRange (Don't fire if further) */
670 		0,									/* Accuracy */
671 		1,									/* Firing Rate */
672 		-1,									/* Firing Time */
673 		0,									/* MinimumBurstSize */
674 		AMMO_SHOTGUN,						/* Ammo profile */
675 		8,									/* clip_size */
676 		MSSS_Reload,						/* Reload_Sequence */
677 		0,									/* TargetCallibrationShift */
678 		SID_SHOTGUN,						/* StartSound */
679 		SID_NOSOUND,						/* LoopSound */
680 		SID_NOSOUND,						/* EndSound */
681 		0,									/* Enable Grenades */
682 		1,									/* UseElevation */
683 		0,									/* EnableTracker */
684 		0,									/* ARealMarine */
685 		1,									/* Android */
686 	},
687 	{
688 		MNPCW_AndroidSpecial,				/* ID */
689 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
690 
691 		Execute_MNS_DischargeShotgun,		/* Func. */
692 		NULL,								/* Misfire func. */
693 		Execute_MNS_PanicFireShotgun,		/* WeaponPanicFireFunction */
694 		"hnpc_civvie",						/* Riffname */
695 		"Android Shotgun Special",			/* HierarchyName */
696 		"flash dummy",						/* GunflashName */
697 		"male right bicep",					/* ElevationSection */
698 		"male civvie",		 				/* HitLocationTableName */
699 		"Android template",					/* TemplateName */
700 		NULL,								/* ClipName */
701 		0,									/* MinRange (Don't fire when closer) */
702 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
703 		-1,									/* MaxRange (Don't fire if further) */
704 		0,									/* Accuracy */
705 		1,									/* Firing Rate */
706 		-1,									/* Firing Time */
707 		0,									/* MinimumBurstSize */
708 		AMMO_SHOTGUN,						/* Ammo profile */
709 		8,									/* clip_size */
710 		MSSS_Reload,						/* Reload_Sequence */
711 		0,									/* TargetCallibrationShift */
712 		SID_SHOTGUN,						/* StartSound */
713 		SID_NOSOUND,						/* LoopSound */
714 		SID_NOSOUND,						/* EndSound */
715 		0,									/* Enable Grenades */
716 		1,									/* UseElevation */
717 		0,									/* EnableTracker */
718 		0,									/* ARealMarine */
719 		1,									/* Android */
720 	},
721 	{
722 		MNPCW_Android_Pistol_Special,		/* ID */
723 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
724 
725 		Execute_MNS_DischargePistol,		/* Func. */
726 		NULL,								/* Misfire func. */
727 		Execute_MNS_PanicFirePistol,		/* WeaponPanicFireFunction */
728 		"hnpc_civvie",						/* Riffname */
729 		"Android Pistol Special",			/* HierarchyName */
730 		"flash dummy",						/* GunflashName */
731 		"male right bicep",					/* ElevationSection */
732 		"male civvie",		 				/* HitLocationTableName */
733 		"Android template",					/* TemplateName */
734 		NULL,								/* ClipName */
735 		0,									/* MinRange (Don't fire when closer) */
736 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
737 		-1,									/* MaxRange (Don't fire if further) */
738 		10000,	  							/* Accuracy */
739 		1,									/* Firing Rate */
740 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
741 		0,									/* MinimumBurstSize */
742 		AMMO_10MM_CULW_NPC,						/* Ammo profile */
743 		PISTOL_CLIP_SIZE,					/* clip_size */
744 		MSSS_Reload,						/* Reload_Sequence */
745 		0,									/* TargetCallibrationShift */
746 		SID_SHOTGUN,						/* StartSound */
747 		SID_NOSOUND,						/* LoopSound */
748 		SID_NOSOUND,						/* EndSound */
749 		0,									/* Enable Grenades */
750 		1,									/* UseElevation */
751 		0,									/* EnableTracker */
752 		0,									/* ARealMarine */
753 		1,									/* Android */
754 	},
755 	{
756 		MNPCW_TwoPistols,					/* ID */
757 		SFX_MUZZLE_FLASH_AMORPHOUS,			/* enum SFX_ID SfxID; */
758 
759 		Execute_MNS_DischargeTwoPistols,	/* Func. */
760 		NULL,								/* Misfire func. */
761 		Execute_MNS_PanicFirePistol,		/* WeaponPanicFireFunction */
762 		"hnpcmarine",						/* Riffname */
763 		"Two Pistol",		 				/* HierarchyName */
764 		"dum flash",						/* GunflashName */
765 		"Rbicep",							/* ElevationSection */
766 		"marine with pulse rifle", 			/* HitLocationTableName */
767 		"Template",							/* TemplateName */
768 		NULL,								/* ClipName */
769 		0,									/* MinRange (Don't fire when closer) */
770 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
771 		-1,									/* MaxRange (Don't fire if further) */
772 		30000,	  							/* Accuracy */
773 		12,									/* Firing Rate */
774 		(MARINE_NEAR_FIRE_TIME>>2),			/* Firing Time */
775 		0,									/* MinimumBurstSize */
776 		AMMO_MARINE_PISTOL,					/* Ammo profile */
777 		24,									/* clip_size */
778 		MSSS_Reload,						/* Reload_Sequence */
779 		250,								/* TargetCallibrationShift */
780 		SID_SHOTGUN,						/* StartSound */
781 		SID_NOSOUND,						/* LoopSound */
782 		SID_NOSOUND,						/* EndSound */
783 		0,									/* Enable Grenades */
784 		1,									/* UseElevation */
785 		0,									/* EnableTracker */
786 		1,									/* ARealMarine */
787 		0,									/* Android */
788 	},
789 	{
790 		MNPCW_Skeeter,						/* ID */
791 		SFX_MUZZLE_FLASH_SKEETER,			/* enum SFX_ID SfxID; */
792 
793 		Execute_MNS_DischargeSkeeter,		/* Func. */
794 		NULL,								/* Misfire func. */
795 		Execute_MNS_NullPanicFire,			/* WeaponPanicFireFunction */
796 		"hnpcmarine",						/* Riffname */
797 		"skeeter",							/* HierarchyName */
798 		"dum flash",						/* GunflashName */
799 		"Skeeter Tube",						/* ElevationSection */
800 		"marine with pulse rifle", 			/* HitLocationTableName */
801 		"Template",							/* TemplateName */
802 		"Skeeter",							/* ClipName */
803 		5000,								/* MinRange (Don't fire when closer) */
804 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
805 		-1,									/* MaxRange (Don't fire if further) */
806 		0,									/* Accuracy */
807 		ONE_FIXED,							/* Firing Rate */
808 		1625*65536/2000,					/* Firing Time */
809 		0,									/* MinimumBurstSize */
810 		AMMO_10MM_CULW,						/* Ammo profile */
811 		1,									/* clip_size */
812 		MSSS_Reload,						/* Reload_Sequence */
813 		300,								/* TargetCallibrationShift */
814 		SID_ED_SKEETERCHARGE,				/* StartSound */
815 		SID_NOSOUND,						/* LoopSound */
816 		SID_ED_SKEETERLAUNCH,				/* EndSound */
817 		1,									/* Enable Grenades */
818 		1,									/* UseElevation */
819 		1,									/* EnableTracker */
820 		1,									/* ARealMarine */
821 		0,									/* Android */
822 	},
823 	{
824 		MNPCW_Scientist_A,					/* ID */
825 		SFX_NONE,							/* enum SFX_ID SfxID; */
826 
827 		NULL,								/* Func. */
828 		NULL,								/* Misfire func. */
829 		Execute_MNS_NullPanicFire,			/* WeaponPanicFireFunction */
830 		"scientist",						/* Riffname */
831 		"clip",		 		 				/* HierarchyName */
832 		"clip board",						/* GunflashName */
833 		NULL,								/* ElevationSection */
834 		"bub with molotov", 				/* HitLocationTableName */
835 		"Template",							/* TemplateName */
836 		NULL,								/* ClipName */
837 		0,									/* MinRange (Don't fire when closer) */
838 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
839 		10000,								/* MaxRange (Don't fire if further) */
840 		-10000,								/* Accuracy */
841 		1,									/* Firing Rate */
842 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
843 		0,									/* MinimumBurstSize */
844 		AMMO_10MM_CULW,						/* Ammo profile */
845 		-1,									/* clip_size */
846 		MSSS_Standard,							/* Reload_Sequence */
847 		0,									/* TargetCallibrationShift */
848 		SID_NOSOUND,						/* StartSound */
849 		SID_NOSOUND,						/* LoopSound */
850 		SID_NOSOUND,						/* EndSound */
851 		0,									/* Enable Grenades */
852 		0,									/* UseElevation */
853 		0,									/* EnableTracker */
854 		0,									/* ARealMarine */
855 		0,									/* Android */
856 	},
857 	{
858 		MNPCW_Scientist_B,					/* ID */
859 		SFX_NONE,							/* enum SFX_ID SfxID; */
860 
861 		NULL,								/* Func. */
862 		NULL,								/* Misfire func. */
863 		Execute_MNS_NullPanicFire,			/* WeaponPanicFireFunction */
864 		"scientist",						/* Riffname */
865 		"testtube",	  		 				/* HierarchyName */
866 		"test tube",						/* GunflashName */
867 		NULL,								/* ElevationSection */
868 		"bub with molotov", 				/* HitLocationTableName */
869 		"Template",							/* TemplateName */
870 		NULL,								/* ClipName */
871 		0,									/* MinRange (Don't fire when closer) */
872 		MARINE_CLOSE_APPROACH_DISTANCE,		/* ForceFireRange (Fire if closer) */
873 		10000,								/* MaxRange (Don't fire if further) */
874 		-10000,								/* Accuracy */
875 		1,									/* Firing Rate */
876 		MARINE_NEAR_FIRE_TIME,				/* Firing Time */
877 		0,									/* MinimumBurstSize */
878 		AMMO_10MM_CULW,						/* Ammo profile */
879 		-1,									/* clip_size */
880 		MSSS_Standard,							/* Reload_Sequence */
881 		0,									/* TargetCallibrationShift */
882 		SID_NOSOUND,						/* StartSound */
883 		SID_NOSOUND,						/* LoopSound */
884 		SID_NOSOUND,						/* EndSound */
885 		0,									/* Enable Grenades */
886 		0,									/* UseElevation */
887 		0,									/* EnableTracker */
888 		0,									/* ARealMarine */
889 		0,									/* Android */
890 	},
891 	{
892 		MNPCW_End,
893 		SFX_NONE,
894 		NULL,
895 		NULL,
896 		NULL,
897 		NULL,
898 		NULL,
899 		NULL,
900 		NULL,
901 		NULL,
902 		NULL,
903 		NULL,
904 		0,
905 		0,
906 		0,
907 		0,
908 		0,
909 		0,
910 		0,
911 		MAX_NO_OF_AMMO_TEMPLATES,
912 		-1,
913 		MSSS_Standard,
914 		0,
915 		SID_NOSOUND,
916 		SID_NOSOUND,
917 		SID_NOSOUND,
918 		0,
919 		0,
920 		0,
921 		0,
922 		0,
923 	},
924 };
925 
926 VECTORCH ShotgunBlast[] = {
927 	{0,0,400,},
928 	{100,0,400,},
929 	{-100,0,400,},
930 	{50,0,400,},
931 	{-50,0,400,},
932 	{-1,-1,-1,},
933 };
934 
935 SQUAD_COMMAND_STATE NpcSquad;
936 int ShowSquadState=0;
937 int ShowNearSquad=0;
938 extern SCENE Global_Scene;
939 static MODULE **Global_ModuleArrayPtr;
940 extern int ModuleArraySize;
941 static char tempstring[256];
942 static int tracker_noise;
943 
ForceCaps(char * input)944 void ForceCaps(char *input) {
945 	char *p;
946 	p=input;
947 	while (*p!=0) {
948 		if ( (*p>=97) && (*p<=122) ) {
949 			/* Force Caps */
950 			*p-=32;
951 		}
952 		p++;
953 	}
954 }
955 
956 /* Squad functions, CDF 27/5/98 */
957 
InitSquad(void)958 void InitSquad(void) {
959 
960 	/* Maybe level specific later? */
961 
962 	NpcSquad.alertStatus=0;
963 	NpcSquad.responseLevel=0;
964 	NpcSquad.alertZone=NULL;
965 	NpcSquad.alertPriority=0;
966 
967 	NpcSquad.Squad_Suspicion=0;
968 	NpcSquad.squad_suspect_point.vx=0;
969 	NpcSquad.squad_suspect_point.vy=0;
970 	NpcSquad.squad_suspect_point.vz=0;
971 
972 	NpcSquad.RespondingMarines=0;
973 	NpcSquad.Alt_RespondingMarines=0;
974 
975 	NpcSquad.NearUnpanickedMarines=0;
976 	NpcSquad.Alt_NearUnpanickedMarines=0;
977 
978 	NpcSquad.NearPanickedMarines=0;
979 	NpcSquad.Alt_NearPanickedMarines=0;
980 
981 	NpcSquad.NearBurningMarines=0;
982 	NpcSquad.Alt_NearBurningMarines=0;
983 
984 	NpcSquad.Squad_Delta_Morale=0;
985 	NpcSquad.Nextframe_Squad_Delta_Morale=0;
986 }
987 
DoSquad(void)988 void DoSquad(void) {
989 
990 	/* Maintain squad level stuff. */
991 
992 	if (NpcSquad.alertZone!=NULL) {
993 		MaintainMarineTargetZone(NpcSquad.alertZone);
994 	}
995 
996 	/* Maintain squad suspicion. */
997 	if (NpcSquad.Squad_Suspicion>0) {
998 		NpcSquad.Squad_Suspicion-=NormalFrameTime;
999 		if (NpcSquad.Squad_Suspicion<0) {
1000 			NpcSquad.Squad_Suspicion=0;
1001 		}
1002 	}
1003 
1004 	/* Maintain stats. */
1005 	NpcSquad.RespondingMarines=NpcSquad.Alt_RespondingMarines;
1006 	NpcSquad.Alt_RespondingMarines=0;
1007 
1008 	NpcSquad.NearUnpanickedMarines=NpcSquad.Alt_NearUnpanickedMarines;
1009 	NpcSquad.Alt_NearUnpanickedMarines=0;
1010 
1011 	NpcSquad.NearPanickedMarines=NpcSquad.Alt_NearPanickedMarines;
1012 	NpcSquad.Alt_NearPanickedMarines=0;
1013 
1014 	NpcSquad.NearBurningMarines=NpcSquad.Alt_NearBurningMarines;
1015 	NpcSquad.Alt_NearBurningMarines=0;
1016 
1017 	NpcSquad.Squad_Delta_Morale=NpcSquad.Nextframe_Squad_Delta_Morale;
1018 	NpcSquad.Nextframe_Squad_Delta_Morale=0;
1019 
1020 	/* Update morale. */
1021 	NpcSquad.Nextframe_Squad_Delta_Morale+=MUL_FIXED(NormalFrameTime,(NpcSquad.NearUnpanickedMarines*50));
1022 	NpcSquad.Nextframe_Squad_Delta_Morale-=MUL_FIXED(NormalFrameTime,(NpcSquad.NearPanickedMarines*1000));
1023 	NpcSquad.Nextframe_Squad_Delta_Morale-=MUL_FIXED(NormalFrameTime,(NpcSquad.NearBurningMarines*3000));
1024 
1025 	if (TERROR_MODE) {
1026 		NpcSquad.Nextframe_Squad_Delta_Morale=-100000000;
1027 	}
1028 
1029 	/* Status display. */
1030 	if (ShowSquadState) {
1031 		PrintDebuggingText("Marine Alert Status = %d\n",NpcSquad.alertStatus);
1032 		PrintDebuggingText("Marine Alert Priority = %d\n",NpcSquad.alertPriority);
1033 		PrintDebuggingText("Responding Marines = %d\n",NpcSquad.RespondingMarines);
1034 		PrintDebuggingText("NearPanicked Marines = %d\n",NpcSquad.NearPanickedMarines);
1035 		PrintDebuggingText("NearUnpanicked Marines = %d\n",NpcSquad.NearUnpanickedMarines);
1036 		PrintDebuggingText("NearBurning Marines = %d\n",NpcSquad.NearBurningMarines);
1037 		PrintDebuggingText("Marine Outstanding Response Level = %d\n",NpcSquad.responseLevel);
1038 		if (NpcSquad.alertZone==NULL) {
1039 			PrintDebuggingText("Marine Alert Zone = NULL\n");
1040 		} else {
1041 			MODULE *sampleModule;
1042 
1043 			sampleModule=*(NpcSquad.alertZone->m_module_ptrs);
1044 			if (sampleModule==NULL) {
1045 				PrintDebuggingText("Marine Alert Zone = Totally Farped! %d\n",NpcSquad.alertZone->m_index);
1046 			} else {
1047 				PrintDebuggingText("Marine Alert Zone = %d, '%s'\n",sampleModule->m_index,sampleModule->name);
1048 			}
1049 		}
1050 		PrintDebuggingText("Squad Suspicion = %d\n",NpcSquad.Squad_Suspicion);
1051 		PrintDebuggingText("Squad Suspect Point = %d %d %d\n",NpcSquad.squad_suspect_point.vx,
1052 			NpcSquad.squad_suspect_point.vy,NpcSquad.squad_suspect_point.vz);
1053 	}
1054 
1055 	/* And now just for me... :-) */
1056 	PrintSpottedNumber();
1057 
1058 }
1059 
ZoneAlert(int level,AIMODULE * targetModule)1060 void ZoneAlert(int level,AIMODULE *targetModule) {
1061 
1062 	int idealResponse;
1063 	/* Bad stuff is going down. */
1064 
1065 	/* Switch to this one if it has a higher level than the current priority. */
1066 
1067 	if (level<NpcSquad.alertPriority) {
1068 		/* Don't bother me with trifles! */
1069 		return;
1070 	}
1071 
1072 	if (level>=NpcSquad.alertStatus) {
1073 		NpcSquad.alertStatus=level;
1074 	}
1075 
1076 	NpcSquad.alertPriority=level;
1077 	NpcSquad.alertZone=targetModule;
1078 	switch (NpcSquad.alertStatus) {
1079 		case 0:
1080 			/* Can this ever happen? */
1081 			idealResponse=1;
1082 			break;
1083 		case 1:
1084 			idealResponse=1;
1085 			break;
1086 		case 2:
1087 			idealResponse=3;
1088 			break;
1089 		case 3:
1090 			idealResponse=5;
1091 			break;
1092 		default:
1093 			idealResponse=1;
1094 			break;
1095 	}
1096 
1097 	if (NpcSquad.RespondingMarines<idealResponse) {
1098 		NpcSquad.responseLevel=(idealResponse-NpcSquad.RespondingMarines);
1099 	}
1100 
1101 }
1102 
PointAlert(int level,VECTORCH * point)1103 void PointAlert(int level, VECTORCH *point) {
1104 
1105 	MODULE *alertModule;
1106 
1107 	alertModule=ModuleFromPosition(point,playerPherModule);
1108 
1109 	if (NpcSquad.Squad_Suspicion!=SQUAD_PARANOIA_TIME) {
1110 		NpcSquad.Squad_Suspicion=SQUAD_PARANOIA_TIME;
1111 		NpcSquad.squad_suspect_point=*point;
1112 	}
1113 
1114 	if (alertModule==NULL) {
1115 		return;
1116 	}
1117 
1118 	ZoneAlert(level,alertModule->m_aimodule);
1119 
1120 }
1121 
DeprioritiseAlert(AIMODULE * aimodule)1122 void DeprioritiseAlert(AIMODULE *aimodule) {
1123 
1124 	/* Parameterised, to make sure we're doing it right. */
1125 
1126 	if (aimodule==NpcSquad.alertZone) {
1127 		NpcSquad.alertPriority=0;
1128 	}
1129 }
1130 
Console_ZoneAlert(int input)1131 void Console_ZoneAlert(int input) {
1132 
1133 	MODULE *target;
1134 	SCENEMODULE *smptr;
1135 
1136 	smptr = Global_ModulePtr[Global_Scene];
1137 	Global_ModuleArrayPtr = smptr->sm_marray;
1138 
1139 	if ((input==0)||(input>=ModuleArraySize)) {
1140 		target=playerPherModule;
1141 	} else {
1142 		target=Global_ModuleArrayPtr[input];
1143 	}
1144 
1145 	sprintf(tempstring,"NEW ZONE ALERT IN %d, '%s'\n",target->m_index,target->name);
1146 	ForceCaps(tempstring);
1147 	NewOnScreenMessage(tempstring);
1148 
1149 	ZoneAlert(3,target->m_aimodule);
1150 }
1151 
1152 /* Interface function - 15/12/97 */
1153 
GetThisNPCMarineWeapon(MARINE_NPC_WEAPONS this_id)1154 MARINE_WEAPON_DATA *GetThisNPCMarineWeapon(MARINE_NPC_WEAPONS this_id) {
1155 
1156 	int a;
1157 
1158 	a=0;
1159 	while (NPC_Marine_Weapons[a].id!=MNPCW_End) {
1160 		if (NPC_Marine_Weapons[a].id==this_id) {
1161 			return(&NPC_Marine_Weapons[a]);
1162 		}
1163 		a++;
1164 	}
1165 
1166 	return(NULL);
1167 
1168 }
1169 
GetThisManAWeapon(void)1170 MARINE_NPC_WEAPONS GetThisManAWeapon(void) {
1171 
1172 	int a;
1173 	MARINE_NPC_WEAPONS thisweap;
1174 
1175 	a=FastRandom()&65535;
1176 
1177 	if (a<(ONE_FIXED>>3)) {
1178 		/* 1/8: Smartgun. */
1179 		thisweap=(MNPCW_Smartgun);
1180 	} else if (a<(ONE_FIXED/3)) {
1181 		/* 5/24: Flamethrower. */
1182 		thisweap=(MNPCW_Flamethrower);
1183 	} else if (a<((2*ONE_FIXED)/3)) {
1184 		thisweap=(MNPCW_PulseRifle);
1185 		//thisweap=(MNPCW_SADAR);
1186 	} else {
1187 		thisweap=(MNPCW_MShotgun);
1188 	}
1189 
1190 	/* Check... */
1191 	{
1192 		MARINE_WEAPON_DATA *tempweap;
1193 		SECTION *root_section;
1194 
1195 		tempweap=GetThisNPCMarineWeapon(thisweap);
1196 		root_section=GetNamedHierarchyFromLibrary(tempweap->Riffname,tempweap->HierarchyName);
1197 		if (!root_section) {
1198 			thisweap=MNPCW_PulseRifle;
1199 		}
1200 	}
1201 
1202 	return(thisweap);
1203 }
1204 
ChangeToAlternateAccoutrementSet(STRATEGYBLOCK * sbPtr,int index)1205 void ChangeToAlternateAccoutrementSet(STRATEGYBLOCK *sbPtr, int index) {
1206 
1207 	HIERARCHY_VARIANT_DATA* variant_data;
1208 	HIERARCHY_SHAPE_REPLACEMENT* replacement_array;
1209 	MARINE_STATUS_BLOCK *marineStatusPointer;
1210 	int a;
1211 
1212 	LOCALASSERT(sbPtr);
1213 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
1214     LOCALASSERT(marineStatusPointer);
1215 
1216 	variant_data=GetHierarchyAlternateShapeSetCollectionFromLibrary(marineStatusPointer->My_Weapon->Riffname,index);
1217 
1218 	if (variant_data==NULL) {
1219 		return;
1220 	}
1221 
1222 	marineStatusPointer->Female=variant_data->female;
1223 	marineStatusPointer->Voice=variant_data->voice;
1224 
1225 	replacement_array=(HIERARCHY_SHAPE_REPLACEMENT*)variant_data->replacements;
1226 
1227 	if (replacement_array==NULL) {
1228 		return;
1229 	}
1230 
1231 
1232 	a=0;
1233 
1234 	while (replacement_array[a].replaced_section_name!=NULL) {
1235 		SECTION_DATA *target_section;
1236 
1237 		target_section=GetThisSectionData(marineStatusPointer->HModelController.section_data,
1238 			replacement_array[a].replaced_section_name);
1239 		if (target_section) {
1240 			target_section->Shape=replacement_array[a].replacement_shape;
1241 			#if 1
1242 			target_section->ShapeNum=replacement_array[a].replacement_shape_index;
1243 			#endif
1244 			target_section->replacement_id = replacement_array[a].replacement_id;
1245 
1246 			Setup_Texture_Animation_For_Section(target_section);
1247 
1248 		}
1249 		a++;
1250 	}
1251 
1252 }
1253 
ChangeToAlternateShapeSet(STRATEGYBLOCK * sbPtr,char * setname)1254 void ChangeToAlternateShapeSet(STRATEGYBLOCK *sbPtr, char *setname) {
1255 
1256 	HIERARCHY_SHAPE_REPLACEMENT* replacement_array;
1257 	MARINE_STATUS_BLOCK *marineStatusPointer;
1258 	int a;
1259 
1260 	LOCALASSERT(sbPtr);
1261 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
1262     LOCALASSERT(marineStatusPointer);
1263 
1264 	replacement_array=GetHierarchyAlternateShapeSetFromLibrary(marineStatusPointer->My_Weapon->Riffname,setname);
1265 
1266 	if (replacement_array==NULL) {
1267 		return;
1268 	}
1269 
1270 	a=0;
1271 
1272 	while (replacement_array[a].replaced_section_name!=NULL) {
1273 		SECTION_DATA *target_section;
1274 
1275 		target_section=GetThisSectionData(marineStatusPointer->HModelController.section_data,
1276 			replacement_array[a].replaced_section_name);
1277 		if (target_section) {
1278 			target_section->Shape=replacement_array[a].replacement_shape;
1279 			#if 1
1280 			target_section->ShapeNum=replacement_array[a].replacement_shape_index;
1281 			#endif
1282 
1283 			Setup_Texture_Animation_For_Section(target_section);
1284 		}
1285 		a++;
1286 	}
1287 }
1288 
1289 /* CDF 3/4/98 */
1290 
CastMarineBot(int weapon)1291 void CastMarineBot(int weapon) {
1292 
1293 	#define BOTRANGE 2000
1294 
1295 	VECTORCH position;
1296 
1297 	if (AvP.Network!=I_No_Network) {
1298 		NewOnScreenMessage("NO MARINEBOTS IN MULTIPLAYER MODE");
1299 		return;
1300 	}
1301 
1302 	position=Player->ObStrategyBlock->DynPtr->Position;
1303 	position.vx+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat31,BOTRANGE);
1304 	position.vy+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat32,BOTRANGE);
1305 	position.vz+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat33,BOTRANGE);
1306 
1307 	CreateMarineBot(&position, weapon);
1308 
1309 }
1310 
CreateMarineBot(VECTORCH * Position,int weapon)1311 void CreateMarineBot(VECTORCH *Position, int weapon)
1312 {
1313 	STRATEGYBLOCK* sbPtr;
1314 
1315 	/* create and initialise a strategy block */
1316 	sbPtr = CreateActiveStrategyBlock();
1317 	if(!sbPtr) {
1318 		NewOnScreenMessage("FAILED TO CREATE BOT: SB CREATION FAILURE");
1319 		return; /* failure */
1320 	}
1321 	InitialiseSBValues(sbPtr);
1322 
1323 	sbPtr->I_SBtype = I_BehaviourMarine;
1324 
1325 	AssignNewSBName(sbPtr);
1326 
1327 	/* create, initialise and attach a dynamics block */
1328 	sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_SPRITE_NPC);
1329 	if(sbPtr->DynPtr)
1330 	{
1331 		EULER zeroEuler = {0,0,0};
1332 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1333 		GLOBALASSERT(dynPtr);
1334       	dynPtr->PrevPosition = dynPtr->Position = *Position;
1335 		dynPtr->OrientEuler = zeroEuler;
1336 		CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
1337 		TransposeMatrixCH(&dynPtr->OrientMat);
1338 	}
1339 	else
1340 	{
1341 		/* dynamics block allocation failed... */
1342 		RemoveBehaviourStrategy(sbPtr);
1343 		NewOnScreenMessage("FAILED TO CREATE BOT: DYNBLOCK CREATION FAILURE");
1344 		return;
1345 	}
1346 
1347 	sbPtr->shapeIndex = 0;
1348 
1349 	sbPtr->maintainVisibility = 1;
1350 	sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (MODULE*)0);
1351 
1352 	/* create, initialise and attach a marine data block */
1353 	sbPtr->SBdataptr = (void *)AllocateMem(sizeof(MARINE_STATUS_BLOCK));
1354 	if(sbPtr->SBdataptr)
1355 	{
1356 		SECTION *root_section;
1357 		MARINE_STATUS_BLOCK *marineStatus = (MARINE_STATUS_BLOCK *)sbPtr->SBdataptr;
1358 		GLOBALASSERT(marineStatus);
1359 
1360 		NPC_InitMovementData(&(marineStatus->moveData));
1361 		NPC_InitWanderData(&(marineStatus->wanderData));
1362      	marineStatus->health = MARINE_STARTING_HEALTH;
1363    		sbPtr->integrity = marineStatus->health;
1364 		marineStatus->volleySize = 0;
1365 
1366 		marineStatus->primaryWeaponDamage = MARINE_WEAPON_DAMAGE;
1367 		marineStatus->stateTimer = MARINE_FAR_MOVE_TIME;
1368 		marineStatus->weaponTarget.vx = marineStatus->weaponTarget.vy = marineStatus->weaponTarget.vz = 0;
1369 		marineStatus->myGunFlash = (DISPLAYBLOCK *)0;
1370 		marineStatus->soundHandle = SOUND_NOACTIVEINDEX;
1371 		marineStatus->soundHandle2 = SOUND_NOACTIVEINDEX;
1372 
1373 		marineStatus->obstruction.environment=0;
1374 		marineStatus->obstruction.destructableObject=0;
1375 		marineStatus->obstruction.otherCharacter=0;
1376 		marineStatus->obstruction.anySingleObstruction=0;
1377 
1378 		Initialise_AvoidanceManager(sbPtr,&marineStatus->avoidanceManager);
1379 		InitWaypointManager(&marineStatus->waypointManager);
1380 
1381 		marineStatus->IAmCrouched = 0;
1382 		marineStatus->lastroundhit=0;
1383 		marineStatus->lasthitsection=NULL;
1384 
1385 		marineStatus->weapon_variable=0;
1386 		marineStatus->weapon_variable2=0;
1387 
1388 		marineStatus->Skill=Marine_Skill;
1389 		marineStatus->Courage=ONE_FIXED;
1390 
1391 		marineStatus->FiringAnim=0;
1392 		marineStatus->SpotFlag=0;
1393 
1394 		//a generated marine won't have a death target
1395 		{
1396 			int i;
1397 			for(i=0;i<SB_NAME_LENGTH;i++) marineStatus->death_target_ID[i] =0;
1398 			marineStatus->death_target_request=0;
1399 			marineStatus->death_target_sbptr=0;
1400 		}
1401 
1402 		//this marine wasn't produced by a generator
1403 		marineStatus->generator_sbptr=0;
1404 
1405 
1406 		marineStatus->Target=NULL; //Player->ObStrategyBlock;
1407 		if ( (weapon<=0)||(weapon>(int)MNPCW_End)) {
1408 			marineStatus->My_Weapon=GetThisNPCMarineWeapon(GetThisManAWeapon());
1409 		} else {
1410 			#if (TWO_PISTOL_GUY==0)
1411 			if (weapon>=MNPCW_TwoPistols) {
1412 				marineStatus->My_Weapon=GetThisNPCMarineWeapon(GetThisManAWeapon());
1413 			} else {
1414 				marineStatus->My_Weapon=GetThisNPCMarineWeapon(weapon-1);
1415 			}
1416 			#else
1417 			marineStatus->My_Weapon=GetThisNPCMarineWeapon(weapon-1);
1418 			#endif
1419 		}
1420 
1421 		/* Initialise marine's stats */
1422 		{
1423 			NPC_DATA *NpcData;
1424 
1425 			if (marineStatus->My_Weapon->Android) {
1426 				NpcData=GetThisNpcData(I_NPC_Android);
1427 			} else if (marineStatus->My_Weapon->ARealMarine) {
1428 				NpcData=GetThisNpcData(I_NPC_Marine);
1429 			} else {
1430 				NpcData=GetThisNpcData(I_NPC_Civilian);
1431 			}
1432 			LOCALASSERT(NpcData);
1433 			sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
1434 			sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
1435 			sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
1436 		}
1437 
1438 		{
1439 			const MOVEMENT_DATA *movementData;
1440 
1441 			marineStatus->speedConstant=(ONE_FIXED-8192)+(FastRandom()&16383);
1442 			marineStatus->accelerationConstant=(ONE_FIXED-8192)+(FastRandom()&16383);
1443 
1444 			if (marineStatus->My_Weapon->ARealMarine) {
1445 				movementData=GetThisMovementData(MDI_Marine_Combat);
1446 			} else {
1447 				movementData=GetThisMovementData(MDI_Civilian_Combat);
1448 			}
1449 			GLOBALASSERT(movementData);
1450 			marineStatus->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatus->speedConstant);
1451 			marineStatus->acceleration = MUL_FIXED(movementData->acceleration,marineStatus->accelerationConstant);
1452 		}
1453 		COPY_NAME(marineStatus->Target_SBname,Null_Name);
1454 		marineStatus->lastmodule=NULL;
1455 		marineStatus->destinationmodule=NULL;
1456 		marineStatus->missionmodule=NULL;
1457 		marineStatus->fearmodule=NULL;
1458 		marineStatus->my_facing_point=sbPtr->DynPtr->Position;
1459 		marineStatus->path=-1;
1460 		marineStatus->stepnumber=-1;
1461 		marineStatus->sawlastframe=0;
1462 		marineStatus->gotapoint=0;
1463 		marineStatus->lastframe_fallingspeed=0;
1464 		marineStatus->suspicious=0;
1465 		marineStatus->previous_suspicion=0;
1466 		marineStatus->using_squad_suspicion=0;
1467 		marineStatus->suspect_point.vx=0;
1468 		marineStatus->suspect_point.vy=0;
1469 		marineStatus->suspect_point.vz=0;
1470 		marineStatus->internalState=0;
1471 		#if MOTIONTRACKERS
1472 		if (marineStatus->My_Weapon->EnableTracker) {
1473 			if ((FastRandom()&65535)<(ONE_FIXED>>2)) {
1474 				marineStatus->mtracker_timer=FastRandom()&65535;
1475 			} else {
1476 				marineStatus->mtracker_timer=-1;
1477 			}
1478 		} else {
1479 			marineStatus->mtracker_timer=-1;
1480 		}
1481 		#else
1482 		marineStatus->mtracker_timer=-1;
1483 		#endif
1484 		marineStatus->GibbFactor=0;
1485 		marineStatus->Wounds=0;
1486 
1487 		marineStatus->incidentFlag=0;
1488 		marineStatus->incidentTimer=0;
1489 
1490 		if (marineStatus->My_Weapon->id==MNPCW_MPistol) {
1491 			/* Special case for pistols? */
1492 			marineStatus->lastroundhit=PISTOL_CLIP_SIZE;
1493 		}
1494 		marineStatus->clipammo=marineStatus->My_Weapon->clip_size;
1495 		marineStatus->roundsForThisTarget=0;
1496 
1497 		marineStatus->HModelController.section_data=NULL;
1498 		marineStatus->HModelController.Deltas=NULL;
1499 		/* In case we need to deallocate it. */
1500 		root_section=GetNamedHierarchyFromLibrary(marineStatus->My_Weapon->Riffname,marineStatus->My_Weapon->HierarchyName);
1501 		if (!root_section) {
1502 			RemoveBehaviourStrategy(sbPtr);
1503 			NewOnScreenMessage("FAILED TO CREATE BOT: NO HMODEL");
1504 			return;
1505 		}
1506 		Create_HModel(&marineStatus->HModelController,root_section);
1507 		InitHModelSequence(&marineStatus->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Standard,ONE_FIXED);
1508 
1509 		if (marineStatus->My_Weapon->UseElevation) {
1510 			DELTA_CONTROLLER *delta;
1511 			delta=Add_Delta_Sequence(&marineStatus->HModelController,"Elevation",(int)HMSQT_MarineStand,(int)MSSS_Elevation,0);
1512 			GLOBALASSERT(delta);
1513 			delta->timer=32767;
1514 		}
1515 
1516 		if (marineStatus->My_Weapon->id==MNPCW_Minigun) {
1517 			DELTA_CONTROLLER *delta;
1518 			delta=Add_Delta_Sequence(&marineStatus->HModelController,"Minigun",(int)HMSQT_MarineStand,(int)MSSS_Minigun_Delta,(ONE_FIXED>>3));
1519 			GLOBALASSERT(delta);
1520 			delta->Playing=0;
1521 			delta->Looped=1;
1522 		}
1523 
1524 		/* Create blank hit delta sequence. */
1525 		if (strcmp("hnpcmarine",marineStatus->My_Weapon->Riffname)==0)
1526 		{
1527 			if (HModelSequence_Exists(&marineStatus->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront)) {
1528 				DELTA_CONTROLLER *delta;
1529 				delta=Add_Delta_Sequence(&marineStatus->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
1530 				GLOBALASSERT(delta);
1531 				delta->Playing=0;
1532 			}
1533 		}
1534 
1535 		marineStatus->My_Gunflash_Section=GetThisSectionData(marineStatus->HModelController.section_data,marineStatus->My_Weapon->GunflashName);
1536 		marineStatus->My_Elevation_Section=GetThisSectionData(marineStatus->HModelController.section_data,marineStatus->My_Weapon->ElevationSection);
1537 
1538 		//initialise female to 0..
1539 		//may be changed by ChangeToAlternateAccoutrementSet
1540 		marineStatus->Female=0;
1541 		marineStatus->Voice=0;
1542 		marineStatus->Android=marineStatus->My_Weapon->Android;
1543 
1544 		//use accoutement set for both marine and civilian
1545 		#if 0
1546 		if (strcmp("hnpcmarine",marineStatus->My_Weapon->Riffname)==0) {
1547 			int dice=FastRandom()&65535;
1548 			if (dice<16384) {
1549 				ChangeToAlternateShapeSet(sbPtr, "Face Four");
1550 			} else if (dice<32768) {
1551 				ChangeToAlternateShapeSet(sbPtr, "Face Three");
1552 			}
1553 		} else if (strcmp("hnpc_civvie",marineStatus->My_Weapon->Riffname)==0) {
1554 			#if 0
1555 			int dice=FastRandom()&65535;
1556 			if (dice<32767) {
1557 				ChangeToAlternateShapeSet(sbPtr, "MedicalGuy");
1558 			} else if (dice<49152) {
1559 				ChangeToAlternateShapeSet(sbPtr, "CompanyGuy");
1560 			}
1561 			#else
1562 			ChangeToAlternateAccoutrementSet(sbPtr, 0);
1563 			#endif
1564 		}
1565 		#else
1566 		//pick a random texture id rather than using 0 , so that we can get
1567 		//texture ids not normally allowed by the level
1568 		ChangeToAlternateAccoutrementSet(sbPtr, FastRandom());
1569 		#endif
1570 		marineStatus->VoicePitch = (FastRandom() & 255) - 128;
1571 
1572 		Marine_SwitchExpression(sbPtr,0);
1573 		marineStatus->Target_Expression=0;
1574 		marineStatus->Blink=-1;
1575 
1576 		ProveHModel_Far(&marineStatus->HModelController,sbPtr);
1577 
1578 		if(!(sbPtr->containingModule))
1579 		{
1580 			/* no containing module can be found... abort*/
1581 			RemoveBehaviourStrategy(sbPtr);
1582 			NewOnScreenMessage("FAILED TO CREATE BOT: MODULE CONTAINMENT FAILURE");
1583 			return;
1584 		}
1585 		LOCALASSERT(sbPtr->containingModule);
1586 
1587 		if (marineStatus->My_Weapon->WeaponFireFunction==NULL) {
1588 			InitMission(sbPtr,MM_NonCom);
1589 		} else {
1590 			InitMission(sbPtr,MM_Wander);
1591 		}
1592 
1593 		MakeMarineNear(sbPtr);
1594 
1595 		NewOnScreenMessage("MARINEBOT CREATED");
1596 	}
1597 	else
1598 	{
1599 		/* no data block can be allocated */
1600 		RemoveBehaviourStrategy(sbPtr);
1601 		NewOnScreenMessage("FAILED TO CREATE BOT: MALLOC FAILURE");
1602 		return;
1603 	}
1604 }
1605 
1606 /*------------------------Patrick 24/2/97-----------------------------
1607   Marine/Seal behaviour shell functions
1608   --------------------------------------------------------------------*/
1609 
InitMarineBehaviour(void * bhdata,STRATEGYBLOCK * sbPtr)1610 void InitMarineBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr)
1611 {
1612 	TOOLS_DATA_MARINE *toolsData = (TOOLS_DATA_MARINE *)bhdata;
1613 	int i;
1614 
1615 	LOCALASSERT(sbPtr);
1616 
1617 	/* check we're not in a net game */
1618 	if(AvP.Network != I_No_Network)
1619 	{
1620 		RemoveBehaviourStrategy(sbPtr);
1621 		return;
1622 	}
1623 
1624 	/* make the assumption that the loader has initialised the strategy block sensibly...
1625 	so just set the shapeIndex from the tools data & copy the name id*/
1626 	sbPtr->shapeIndex = toolsData->shapeIndex;
1627 	for(i=0;i<SB_NAME_LENGTH;i++) sbPtr->SBname[i] = toolsData->nameID[i];
1628 
1629 	/* create, initialise and attach a dynamics block */
1630 	sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_SPRITE_NPC);
1631 	if(sbPtr->DynPtr)
1632 	{
1633 		EULER zeroEuler = {0,0,0};
1634 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1635 		GLOBALASSERT(dynPtr);
1636       	dynPtr->PrevPosition = dynPtr->Position = toolsData->position;
1637 		dynPtr->OrientEuler = zeroEuler;
1638 		CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
1639 		TransposeMatrixCH(&dynPtr->OrientMat);
1640 
1641 		/* zero linear velocity in dynamics block */
1642 		dynPtr->LinVelocity.vx = 0;
1643 		dynPtr->LinVelocity.vy = 0;
1644 		dynPtr->LinVelocity.vz = 0;
1645 
1646 		sbPtr->containingModule=ModuleFromPosition(&dynPtr->Position,NULL);
1647 
1648 		GLOBALASSERT(sbPtr->containingModule);
1649 	}
1650 	else
1651 	{
1652 		/* allocation failed */
1653 		RemoveBehaviourStrategy(sbPtr);
1654 		return;
1655 	}
1656 
1657 	/* create, initialise and attach a marine data block */
1658 	sbPtr->SBdataptr = (void *)AllocateMem(sizeof(MARINE_STATUS_BLOCK));
1659 	if(sbPtr->SBdataptr)
1660 	{
1661 		SECTION *root_section;
1662 		MARINE_STATUS_BLOCK *marineStatus = (MARINE_STATUS_BLOCK *)sbPtr->SBdataptr;
1663 		GLOBALASSERT(marineStatus);
1664 
1665 		NPC_InitMovementData(&(marineStatus->moveData));
1666 		NPC_InitWanderData(&(marineStatus->wanderData));
1667      	marineStatus->health = MARINE_STARTING_HEALTH;
1668    		sbPtr->integrity = marineStatus->health;
1669 		marineStatus->volleySize = 0;
1670 		marineStatus->primaryWeaponDamage = MARINE_WEAPON_DAMAGE;
1671 		marineStatus->stateTimer = MARINE_FAR_MOVE_TIME;
1672 		marineStatus->weaponTarget.vx = marineStatus->weaponTarget.vy = marineStatus->weaponTarget.vz = 0;
1673 		marineStatus->myGunFlash = (DISPLAYBLOCK *)0;
1674 		marineStatus->soundHandle = SOUND_NOACTIVEINDEX;
1675 		marineStatus->soundHandle2 = SOUND_NOACTIVEINDEX;
1676 
1677 		marineStatus->obstruction.environment=0;
1678 		marineStatus->obstruction.destructableObject=0;
1679 		marineStatus->obstruction.otherCharacter=0;
1680 		marineStatus->obstruction.anySingleObstruction=0;
1681 
1682 		Initialise_AvoidanceManager(sbPtr,&marineStatus->avoidanceManager);
1683 		InitWaypointManager(&marineStatus->waypointManager);
1684 
1685 		marineStatus->IAmCrouched = 0;
1686 		marineStatus->lastroundhit=0;
1687 		marineStatus->lasthitsection=NULL;
1688 
1689 		marineStatus->weapon_variable=0;
1690 		marineStatus->weapon_variable2=0;
1691 
1692 		marineStatus->Skill=Marine_Skill;
1693 		marineStatus->Courage=ONE_FIXED;
1694 
1695 		marineStatus->FiringAnim=0;
1696 		marineStatus->SpotFlag=0;
1697 
1698 		marineStatus->Target=NULL; //Player->ObStrategyBlock;
1699 
1700 		marineStatus->my_spot=sbPtr->DynPtr->Position;
1701 
1702 		#if ALL_PULSERIFLES
1703 		marineStatus->My_Weapon=GetThisNPCMarineWeapon(MNPCW_PulseRifle);
1704 		#else
1705 		marineStatus->My_Weapon=GetThisNPCMarineWeapon(toolsData->marine_type);
1706 		#endif
1707 
1708 		/* Initialise marine's stats */
1709 		{
1710 			NPC_DATA *NpcData;
1711 
1712 			if (marineStatus->My_Weapon->Android) {
1713 				NpcData=GetThisNpcData(I_NPC_Android);
1714 			} else if (marineStatus->My_Weapon->ARealMarine) {
1715 				NpcData=GetThisNpcData(I_NPC_Marine);
1716 			} else {
1717 				NpcData=GetThisNpcData(I_NPC_Civilian);
1718 			}
1719 			LOCALASSERT(NpcData);
1720 			sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
1721 			sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
1722 			sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
1723 		}
1724 
1725 		if (toolsData->Mission==MM_NonCom) {
1726 			marineStatus->My_Weapon=GetThisNPCMarineWeapon(MNPCW_MUnarmed);
1727 		}
1728 
1729 		if (marineStatus->My_Weapon->id==MNPCW_MPistol) {
1730 			/* Special case for pistols? */
1731 			marineStatus->lastroundhit=PISTOL_CLIP_SIZE;
1732 		}
1733 		marineStatus->clipammo=marineStatus->My_Weapon->clip_size;
1734 		marineStatus->roundsForThisTarget=0;
1735 
1736 		{
1737 			const MOVEMENT_DATA *movementData;
1738 
1739 			marineStatus->speedConstant=(ONE_FIXED-8192)+(FastRandom()&16383);
1740 			marineStatus->accelerationConstant=(ONE_FIXED-8192)+(FastRandom()&16383);
1741 
1742 			if (marineStatus->My_Weapon->ARealMarine) {
1743 				movementData=GetThisMovementData(MDI_Marine_Combat);
1744 			} else {
1745 				movementData=GetThisMovementData(MDI_Civilian_Combat);
1746 			}
1747 			GLOBALASSERT(movementData);
1748 			marineStatus->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatus->speedConstant);
1749 			marineStatus->acceleration = MUL_FIXED(movementData->acceleration,marineStatus->accelerationConstant);
1750 		}
1751 		COPY_NAME(marineStatus->Target_SBname,Null_Name);
1752 		marineStatus->lastmodule=NULL;
1753 		marineStatus->destinationmodule=NULL;
1754 		marineStatus->missionmodule=NULL;
1755 		marineStatus->fearmodule=NULL;
1756 		marineStatus->my_facing_point=toolsData->facing_point;
1757 		marineStatus->path=toolsData->path;
1758 		marineStatus->stepnumber=toolsData->stepnumber;
1759 		marineStatus->sawlastframe=0;
1760 		marineStatus->gotapoint=0;
1761 		marineStatus->lastframe_fallingspeed=0;
1762 		marineStatus->suspicious=0;
1763 		marineStatus->previous_suspicion=0;
1764 		marineStatus->using_squad_suspicion=0;
1765 		marineStatus->suspect_point.vx=0;
1766 		marineStatus->suspect_point.vy=0;
1767 		marineStatus->suspect_point.vz=0;
1768 		marineStatus->internalState=0;
1769 		#if MOTIONTRACKERS
1770 		if (marineStatus->My_Weapon->EnableTracker) {
1771 			if ((FastRandom()&65535)<(ONE_FIXED>>2)) {
1772 				marineStatus->mtracker_timer=FastRandom()&65535;
1773 			} else {
1774 				marineStatus->mtracker_timer=-1;
1775 			}
1776 		} else {
1777 			marineStatus->mtracker_timer=-1;
1778 		}
1779 		#else
1780 		marineStatus->mtracker_timer=-1;
1781 		#endif
1782 		marineStatus->GibbFactor=0;
1783 		marineStatus->Wounds=0;
1784 
1785 		marineStatus->incidentFlag=0;
1786 		marineStatus->incidentTimer=0;
1787 
1788 		//InitShapeAnimationController(&marineStatus->ShpAnimCtrl, GetShapeData(sbPtr->shapeIndex));
1789 
1790 		GLOBALASSERT(marineStatus->My_Weapon->HierarchyName);
1791 
1792 		root_section=GetNamedHierarchyFromLibrary(marineStatus->My_Weapon->Riffname,marineStatus->My_Weapon->HierarchyName);
1793 
1794 		Create_HModel(&marineStatus->HModelController,root_section);
1795 		InitHModelSequence(&marineStatus->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Standard,ONE_FIXED);
1796 
1797 		if (marineStatus->My_Weapon->UseElevation) {
1798 			DELTA_CONTROLLER *delta;
1799 			delta=Add_Delta_Sequence(&marineStatus->HModelController,"Elevation",(int)HMSQT_MarineStand,(int)MSSS_Elevation,0);
1800 			GLOBALASSERT(delta);
1801 			delta->timer=32767;
1802 		}
1803 
1804 		/* Create blank hit delta sequence. */
1805 		if (strcmp("hnpcmarine",marineStatus->My_Weapon->Riffname)==0)
1806 		{
1807 			if (HModelSequence_Exists(&marineStatus->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront)) {
1808 				DELTA_CONTROLLER *delta;
1809 				delta=Add_Delta_Sequence(&marineStatus->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
1810 				GLOBALASSERT(delta);
1811 				delta->Playing=0;
1812 			}
1813 		}
1814 
1815 		marineStatus->My_Gunflash_Section=GetThisSectionData(marineStatus->HModelController.section_data,marineStatus->My_Weapon->GunflashName);
1816 		marineStatus->My_Elevation_Section=GetThisSectionData(marineStatus->HModelController.section_data,marineStatus->My_Weapon->ElevationSection);
1817 
1818 		for(i=0;i<SB_NAME_LENGTH;i++) marineStatus->death_target_ID[i] = toolsData->death_target_ID[i];
1819 		marineStatus->death_target_request=toolsData->death_target_request;
1820 		marineStatus->death_target_sbptr=0;
1821 
1822 		//this marine wasn't produced by a generator
1823 		marineStatus->generator_sbptr=0;
1824 
1825 		//initialise female to 0..
1826 		//may be changed by ChangeToAlternateAccoutrementSet
1827 		marineStatus->Female=0;
1828 		marineStatus->Voice=0;
1829 		marineStatus->Android=marineStatus->My_Weapon->Android;
1830 
1831 		//use accoutement set for both marine and civilian
1832 		#if 0
1833 		if (strcmp("hnpcmarine",marineStatus->My_Weapon->Riffname)==0) {
1834 			/* Normal marine. */
1835 			if ((toolsData->textureID==0)||(toolsData->textureID>4)) {
1836 				/* Random. */
1837 				int dice=FastRandom()&65535;
1838 				if (dice<16384) {
1839 					ChangeToAlternateShapeSet(sbPtr, "Face Four");
1840 				} else if (dice<32768) {
1841 					ChangeToAlternateShapeSet(sbPtr, "Face Three");
1842 				}
1843 			} else {
1844 				switch (toolsData->textureID) {
1845 					case 1:
1846 					default:
1847 						/* No change. */
1848 						break;
1849 					case 2:
1850 						ChangeToAlternateShapeSet(sbPtr, "Face Four");
1851 						break;
1852 					case 3:
1853 						ChangeToAlternateShapeSet(sbPtr, "Face Three");
1854 						break;
1855 				}
1856 			}
1857 		} else if (strcmp("hnpc_civvie",marineStatus->My_Weapon->Riffname)==0) {
1858 			/* Civvies. */
1859 			#if 0
1860 			if ((toolsData->textureID==0)||(toolsData->textureID>3)) {
1861 				int dice=FastRandom()&65535;
1862 				if (dice<32767) {
1863 					ChangeToAlternateShapeSet(sbPtr, "MedicalGuy");
1864 				} else if (dice<49152) {
1865 					ChangeToAlternateShapeSet(sbPtr, "CompanyGuy");
1866 				}
1867 			} else {
1868 				switch (toolsData->textureID) {
1869 					case 1:
1870 					default:
1871 						/* No change. */
1872 						break;
1873 					case 2:
1874 						ChangeToAlternateShapeSet(sbPtr, "MedicalGuy");
1875 						break;
1876 					case 3:
1877 						ChangeToAlternateShapeSet(sbPtr, "CompanyGuy");
1878 						break;
1879 				}
1880 			}
1881 			#else
1882 			/* Gonna need a different handler for this? */
1883 			ChangeToAlternateAccoutrementSet(sbPtr, toolsData->textureID);
1884 			#endif
1885 		}
1886 		#else
1887 		ChangeToAlternateAccoutrementSet(sbPtr, toolsData->textureID);
1888 		#endif
1889 		marineStatus->VoicePitch = (FastRandom() & 255) - 128;
1890 
1891 		Marine_SwitchExpression(sbPtr,0);
1892 		marineStatus->Target_Expression=0;
1893 		marineStatus->Blink=-1;
1894 
1895 		ProveHModel_Far(&marineStatus->HModelController,sbPtr);
1896 
1897 		if (marineStatus->My_Weapon->WeaponFireFunction==NULL) {
1898 			InitMission(sbPtr,MM_NonCom);
1899 		} else {
1900 			InitMission(sbPtr,toolsData->Mission);
1901 		}
1902 	}
1903 	else
1904 	{
1905 		/* allocation failed */
1906 		RemoveBehaviourStrategy(sbPtr);
1907 		return;
1908 	}
1909 }
1910 
InitSealBehaviour(void * bhdata,STRATEGYBLOCK * sbPtr)1911 void InitSealBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr)
1912 {
1913 	/* Die, superfluous function!!! */
1914 	InitMarineBehaviour(bhdata,sbPtr);
1915 
1916 }
1917 
CreateMarineDynamic(STRATEGYBLOCK * Generator,MARINE_NPC_WEAPONS weapon_for_marine)1918 void CreateMarineDynamic(STRATEGYBLOCK *Generator,MARINE_NPC_WEAPONS weapon_for_marine)
1919 {
1920 	STRATEGYBLOCK* sbPtr;
1921 	GENERATOR_BLOCK *generatorBlock;
1922 
1923 	generatorBlock=Generator->SBdataptr;
1924 	GLOBALASSERT(generatorBlock);
1925 
1926 	/* check we're not in a net game */
1927 	if(AvP.Network != I_No_Network)
1928 	{
1929 		return;
1930 	}
1931 
1932 	/* create and initialise a strategy block */
1933 	sbPtr = CreateActiveStrategyBlock();
1934 	if(!sbPtr)
1935 	{
1936 		/* allocation failed */
1937 		return;
1938 	}
1939 
1940 	InitialiseSBValues(sbPtr);
1941 	sbPtr->I_SBtype = I_BehaviourMarine;
1942 
1943 	/* Old way. *
1944 	for(i = 0; i < SB_NAME_LENGTH; i++) {
1945 		sbPtr->SBname[i] = '\0';
1946 	}
1947 	* CDF - 9/9/97 */
1948 	AssignNewSBName(sbPtr);
1949 	/* New way. */
1950 
1951 	/* create, initialise and attach a dynamics block */
1952 	sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_SPRITE_NPC);
1953 	if(sbPtr->DynPtr)
1954 	{
1955 		EULER zeroEuler = {0,0,0};
1956 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1957 		GLOBALASSERT(dynPtr);
1958       	dynPtr->PrevPosition = dynPtr->Position = ((GENERATOR_BLOCK* )Generator->SBdataptr)->Position;
1959 		dynPtr->OrientEuler = zeroEuler;
1960 		CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
1961 		TransposeMatrixCH(&dynPtr->OrientMat);
1962 	}
1963 	else
1964 	{
1965 		/* allocation failed */
1966 		RemoveBehaviourStrategy(sbPtr);
1967 		return;
1968 	}
1969 
1970 	/* set the shape */
1971 	sbPtr->shapeIndex = Generator->shapeIndex;
1972 
1973 	sbPtr->maintainVisibility = 1;
1974 	sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (MODULE*)0);
1975 	LOCALASSERT(sbPtr->containingModule);
1976 	if(!(sbPtr->containingModule))
1977 	{
1978 		/* no containing module can be found... abort*/
1979 		DestroyAnyStrategyBlock(sbPtr);
1980 		return;
1981 	}
1982 
1983   	/* assert marine is starting as invisible */
1984   	LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)] == 0);
1985 
1986 	/* create, initialise and attach a marine data block */
1987 	sbPtr->SBdataptr = (void *)AllocateMem(sizeof(MARINE_STATUS_BLOCK));
1988 	if(sbPtr->SBdataptr)
1989 	{
1990 		SECTION *root_section;
1991 		MARINE_STATUS_BLOCK *marineStatus = (MARINE_STATUS_BLOCK *)sbPtr->SBdataptr;
1992 		GLOBALASSERT(marineStatus);
1993 
1994 		NPC_InitMovementData(&(marineStatus->moveData));
1995 		NPC_InitWanderData(&(marineStatus->wanderData));
1996      	marineStatus->health = MARINE_STARTING_HEALTH;
1997    		sbPtr->integrity = marineStatus->health;
1998 		marineStatus->volleySize = 0;
1999 		marineStatus->nearSpeed = MARINE_NEAR_SPEED;
2000 		marineStatus->primaryWeaponDamage = MARINE_WEAPON_DAMAGE;
2001 		marineStatus->stateTimer = MARINE_FAR_MOVE_TIME;
2002 		marineStatus->weaponTarget.vx = marineStatus->weaponTarget.vy = marineStatus->weaponTarget.vz = 0;
2003 		marineStatus->myGunFlash = (DISPLAYBLOCK *)0;
2004 		marineStatus->soundHandle = SOUND_NOACTIVEINDEX;
2005 		marineStatus->soundHandle2 = SOUND_NOACTIVEINDEX;
2006 
2007 		marineStatus->obstruction.environment=0;
2008 		marineStatus->obstruction.destructableObject=0;
2009 		marineStatus->obstruction.otherCharacter=0;
2010 		marineStatus->obstruction.anySingleObstruction=0;
2011 
2012 		Initialise_AvoidanceManager(sbPtr,&marineStatus->avoidanceManager);
2013 		InitWaypointManager(&marineStatus->waypointManager);
2014 
2015 		marineStatus->IAmCrouched = 0;
2016 		marineStatus->lastroundhit=0;
2017 		marineStatus->lasthitsection=NULL;
2018 
2019 		marineStatus->weapon_variable=0;
2020 		marineStatus->weapon_variable2=0;
2021 
2022 		marineStatus->Skill=Marine_Skill;
2023 		marineStatus->Courage=ONE_FIXED;
2024 
2025 		marineStatus->FiringAnim=0;
2026 		marineStatus->SpotFlag=0;
2027 
2028 		//a generated marine won't have a death target
2029 		{
2030 			int i;
2031 			for(i=0;i<SB_NAME_LENGTH;i++) marineStatus->death_target_ID[i] =0;
2032 			marineStatus->death_target_request=0;
2033 			marineStatus->death_target_sbptr=0;
2034 		}
2035 
2036 		//note the generator that produced this marine
2037 		marineStatus->generator_sbptr=Generator;
2038 
2039 		marineStatus->Target=NULL; //Player->ObStrategyBlock;
2040 
2041 		marineStatus->My_Weapon=GetThisNPCMarineWeapon(weapon_for_marine);
2042 
2043 		/* Initialise marine's stats */
2044 		{
2045 			NPC_DATA *NpcData;
2046 
2047 			if (marineStatus->My_Weapon->Android) {
2048 				NpcData=GetThisNpcData(I_NPC_Android);
2049 			} else if (marineStatus->My_Weapon->ARealMarine) {
2050 				NpcData=GetThisNpcData(I_NPC_Marine);
2051 			} else {
2052 				NpcData=GetThisNpcData(I_NPC_Civilian);
2053 			}
2054 			LOCALASSERT(NpcData);
2055 			sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
2056 			sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
2057 			sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
2058 		}
2059 
2060 		{
2061 			const MOVEMENT_DATA *movementData;
2062 
2063 			marineStatus->speedConstant=(ONE_FIXED-8192)+(FastRandom()&16383);
2064 			marineStatus->accelerationConstant=(ONE_FIXED-8192)+(FastRandom()&16383);
2065 
2066 			if (marineStatus->My_Weapon->ARealMarine) {
2067 				movementData=GetThisMovementData(MDI_Marine_Combat);
2068 			} else {
2069 				movementData=GetThisMovementData(MDI_Civilian_Combat);
2070 			}
2071 			GLOBALASSERT(movementData);
2072 			marineStatus->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatus->speedConstant);
2073 			marineStatus->acceleration = MUL_FIXED(movementData->acceleration,marineStatus->accelerationConstant);
2074 		}
2075 
2076 		COPY_NAME(marineStatus->Target_SBname,Null_Name);
2077 		marineStatus->lastmodule=NULL;
2078 		marineStatus->destinationmodule=NULL;
2079 		marineStatus->missionmodule=NULL;
2080 		marineStatus->fearmodule=NULL;
2081 		marineStatus->my_facing_point=sbPtr->DynPtr->Position;
2082 
2083 		marineStatus->path=generatorBlock->path;
2084 		marineStatus->stepnumber=generatorBlock->stepnumber;
2085 
2086 		marineStatus->sawlastframe=0;
2087 		marineStatus->gotapoint=0;
2088 		marineStatus->lastframe_fallingspeed=0;
2089 		marineStatus->suspicious=0;
2090 		marineStatus->previous_suspicion=0;
2091 		marineStatus->using_squad_suspicion=0;
2092 		marineStatus->suspect_point.vx=0;
2093 		marineStatus->suspect_point.vy=0;
2094 		marineStatus->suspect_point.vz=0;
2095 		marineStatus->internalState=0;
2096 		#if MOTIONTRACKERS
2097 		if (marineStatus->My_Weapon->EnableTracker) {
2098 			if ((FastRandom()&65535)<(ONE_FIXED>>2)) {
2099 				marineStatus->mtracker_timer=FastRandom()&65535;
2100 			} else {
2101 				marineStatus->mtracker_timer=-1;
2102 			}
2103 		} else {
2104 			marineStatus->mtracker_timer=-1;
2105 		}
2106 		#else
2107 		marineStatus->mtracker_timer=-1;
2108 		#endif
2109 		marineStatus->GibbFactor=0;
2110 		marineStatus->Wounds=0;
2111 
2112 		marineStatus->incidentFlag=0;
2113 		marineStatus->incidentTimer=0;
2114 
2115 		if (marineStatus->My_Weapon->id==MNPCW_MPistol) {
2116 			/* Special case for pistols? */
2117 			marineStatus->lastroundhit=PISTOL_CLIP_SIZE;
2118 		}
2119 		marineStatus->clipammo=marineStatus->My_Weapon->clip_size;
2120 		marineStatus->roundsForThisTarget=0;
2121 
2122 		//InitShapeAnimationController(&marineStatus->ShpAnimCtrl, GetShapeData(sbPtr->shapeIndex));
2123 
2124 		root_section=GetNamedHierarchyFromLibrary(marineStatus->My_Weapon->Riffname,marineStatus->My_Weapon->HierarchyName);
2125 		Create_HModel(&marineStatus->HModelController,root_section);
2126 		InitHModelSequence(&marineStatus->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Standard,ONE_FIXED);
2127 
2128 		if (marineStatus->My_Weapon->UseElevation) {
2129 			DELTA_CONTROLLER *delta;
2130 			delta=Add_Delta_Sequence(&marineStatus->HModelController,"Elevation",(int)HMSQT_MarineStand,(int)MSSS_Elevation,0);
2131 			GLOBALASSERT(delta);
2132 			delta->timer=32767;
2133 		}
2134 
2135 		/* Create blank hit delta sequence. */
2136 		if (strcmp("hnpcmarine",marineStatus->My_Weapon->Riffname)==0)
2137 		{
2138 			if (HModelSequence_Exists(&marineStatus->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront)) {
2139 				DELTA_CONTROLLER *delta;
2140 				delta=Add_Delta_Sequence(&marineStatus->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
2141 				GLOBALASSERT(delta);
2142 				delta->Playing=0;
2143 			}
2144 		}
2145 
2146 		marineStatus->My_Gunflash_Section=GetThisSectionData(marineStatus->HModelController.section_data,marineStatus->My_Weapon->GunflashName);
2147 		marineStatus->My_Elevation_Section=GetThisSectionData(marineStatus->HModelController.section_data,marineStatus->My_Weapon->ElevationSection);
2148 
2149 		//initialise female to 0..
2150 		//may be changed by ChangeToAlternateAccoutrementSet
2151 		marineStatus->Female=0;
2152 		marineStatus->Voice=0;
2153 		marineStatus->Android=marineStatus->My_Weapon->Android;
2154 
2155 		//use accoutement set for both marine and civilian
2156 		#if 0
2157 		if (strcmp("hnpcmarine",marineStatus->My_Weapon->Riffname)==0) {
2158 			int dice=FastRandom()&65535;
2159 			if (dice<16384) {
2160 				ChangeToAlternateShapeSet(sbPtr, "Face Four");
2161 			} else if (dice<32768) {
2162 				ChangeToAlternateShapeSet(sbPtr, "Face Three");
2163 			}
2164 		} else if (strcmp("hnpc_civvie",marineStatus->My_Weapon->Riffname)==0) {
2165 			#if 0
2166 			int dice=FastRandom()&65535;
2167 			if (dice<32767) {
2168 				ChangeToAlternateShapeSet(sbPtr, "MedicalGuy");
2169 			} else if (dice<49152) {
2170 				ChangeToAlternateShapeSet(sbPtr, "CompanyGuy");
2171 			}
2172 			#else
2173 			ChangeToAlternateAccoutrementSet(sbPtr, 0);
2174 			#endif
2175 		}
2176 		#else
2177 		//texture id 0 picks random one out of those allowed by the level
2178 		ChangeToAlternateAccoutrementSet(sbPtr, 0);
2179 		#endif
2180 		marineStatus->VoicePitch = (FastRandom() & 255) - 128;
2181 
2182 		Marine_SwitchExpression(sbPtr,0);
2183 		marineStatus->Target_Expression=0;
2184 		marineStatus->Blink=-1;
2185 
2186 		ProveHModel_Far(&marineStatus->HModelController,sbPtr);
2187 
2188 		if (marineStatus->My_Weapon->WeaponFireFunction==NULL) {
2189 			InitMission(sbPtr,MM_NonCom);
2190 		} else if ( (marineStatus->path!=-1)&&(marineStatus->stepnumber!=-1)) {
2191 			InitMission(sbPtr,MM_Pathfinder);
2192 		} else {
2193 			InitMission(sbPtr,MM_Wander);
2194 		}
2195 
2196 	}
2197 	else
2198 	{
2199 		/* allocation failed */
2200 		RemoveBehaviourStrategy(sbPtr);
2201 		return;
2202 	}
2203 }
2204 
SetMarineElevation(STRATEGYBLOCK * sbPtr)2205 void SetMarineElevation(STRATEGYBLOCK *sbPtr) {
2206 
2207 	MARINE_STATUS_BLOCK *marineStatusPointer;
2208 	int offsetx,offsety,offsetz,offseta,angle1;
2209 	DELTA_CONTROLLER *elevation_controller;
2210 	VECTORCH *gunpos;
2211 
2212 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
2213 
2214 	if (marineStatusPointer->My_Weapon->UseElevation==0) {
2215 		/* Non elevating weapon. */
2216 		return;
2217 	}
2218 
2219 	if (marineStatusPointer->My_Elevation_Section) {
2220 		gunpos=&marineStatusPointer->My_Elevation_Section->World_Offset;
2221 	} else {
2222 		gunpos=&sbPtr->DynPtr->Position;
2223 	}
2224 	/* Aim at weaponTarget. */
2225 
2226 	offsetx=(marineStatusPointer->weaponTarget.vx)-(gunpos->vx);
2227 	offsety=(marineStatusPointer->weaponTarget.vz)-(gunpos->vz);
2228 	offseta=-((marineStatusPointer->weaponTarget.vy)-(gunpos->vy));
2229 
2230 	while( (offsetx>(ONE_FIXED>>2))
2231 		||(offsety>(ONE_FIXED>>2))
2232 		||(offseta>(ONE_FIXED>>2))
2233 		||(offsetx<-(ONE_FIXED>>2))
2234 		||(offsety<-(ONE_FIXED>>2))
2235 		||(offseta<-(ONE_FIXED>>2))) {
2236 
2237 		offsetx>>=1;
2238 		offsety>>=1;
2239 		offseta>>=1;
2240 
2241 	}
2242 
2243 	offsetz=SqRoot32((offsetx*offsetx)+(offsety*offsety));
2244 	angle1=ArcTan(offseta,offsetz);
2245 
2246 	if (angle1>=3072) angle1-=4096;
2247 	if (angle1>=2048) angle1=angle1-3072;
2248 	if (angle1>1024) angle1=2048-angle1;
2249 
2250 	GLOBALASSERT(angle1>=-1024);
2251 	GLOBALASSERT(angle1<=1024);
2252 
2253 
2254 	elevation_controller=Get_Delta_Sequence(&marineStatusPointer->HModelController,"Elevation");
2255 	GLOBALASSERT(elevation_controller);
2256 
2257 	if (marineStatusPointer->IAmCrouched) {
2258 		elevation_controller->sequence_type=HMSQT_MarineCrouch;
2259 		elevation_controller->sub_sequence=MCrSS_Elevation;
2260 	} else {
2261 		if (marineStatusPointer->FiringAnim==1) {
2262 			elevation_controller->sequence_type=HMSQT_MarineStand;
2263 			elevation_controller->sub_sequence=MSSS_Hip_Fire_Elevation;
2264 		} else {
2265 			elevation_controller->sequence_type=HMSQT_MarineStand;
2266 			elevation_controller->sub_sequence=MSSS_Elevation;
2267 		}
2268 	}
2269 
2270 	{
2271 		int fake_timer;
2272 
2273 		fake_timer=1024-angle1;
2274 		fake_timer<<=5;
2275 		if (fake_timer==65536) fake_timer=65535;
2276 
2277 		GLOBALASSERT(fake_timer>=0);
2278 		GLOBALASSERT(fake_timer<65536);
2279 
2280 		elevation_controller->timer=fake_timer;
2281 
2282 	}
2283 
2284 	/* Unless you're a reloading pistol. */
2285 	if (marineStatusPointer->My_Weapon->id==MNPCW_MPistol) {
2286 		if (marineStatusPointer->lastroundhit==-1) {
2287 			elevation_controller->timer=32767;
2288 		}
2289 	}
2290 	/* Or a firing grenade launcher or shotgun in state 1. */
2291 	if ((marineStatusPointer->My_Weapon->id==MNPCW_GrenadeLauncher)||(marineStatusPointer->My_Weapon->id==MNPCW_MShotgun)
2292 		||(marineStatusPointer->My_Weapon->id==MNPCW_Android)
2293 		||(marineStatusPointer->My_Weapon->id==MNPCW_AndroidSpecial)) {
2294 		if ((marineStatusPointer->behaviourState==MBS_Firing)&&(marineStatusPointer->internalState)) {
2295 			elevation_controller->timer=32767;
2296 		}
2297 	}
2298 }
2299 
CentreMarineElevation(STRATEGYBLOCK * sbPtr)2300 void CentreMarineElevation(STRATEGYBLOCK *sbPtr) {
2301 
2302 	MARINE_STATUS_BLOCK *marineStatusPointer;
2303 	DELTA_CONTROLLER *elevation_controller;
2304 
2305 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
2306 
2307 	if (marineStatusPointer->My_Weapon->UseElevation==0) {
2308 		/* Non elevating weapon. */
2309 		return;
2310 	}
2311 
2312 	elevation_controller=Get_Delta_Sequence(&marineStatusPointer->HModelController,"Elevation");
2313 	GLOBALASSERT(elevation_controller);
2314 
2315 	if (marineStatusPointer->IAmCrouched) {
2316 		elevation_controller->sequence_type=HMSQT_MarineCrouch;
2317 		elevation_controller->sub_sequence=MCrSS_Elevation;
2318 	} else {
2319 		if (marineStatusPointer->FiringAnim==1) {
2320 			elevation_controller->sequence_type=HMSQT_MarineStand;
2321 			elevation_controller->sub_sequence=MSSS_Hip_Fire_Elevation;
2322 		} else {
2323 			elevation_controller->sequence_type=HMSQT_MarineStand;
2324 			elevation_controller->sub_sequence=MSSS_Elevation;
2325 		}
2326 	}
2327 
2328 	elevation_controller->timer=32767;
2329 
2330 }
2331 
MarineBehaviour(STRATEGYBLOCK * sbPtr)2332 void MarineBehaviour(STRATEGYBLOCK *sbPtr)
2333 {
2334 	MARINE_STATUS_BLOCK *marineStatusPointer;
2335 	int marineIsNear;
2336 
2337 	LOCALASSERT(sbPtr);
2338 	LOCALASSERT(sbPtr->containingModule);
2339 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
2340     LOCALASSERT(marineStatusPointer);
2341 
2342 	/* test if we've got a containing module: if we haven't, do nothing.
2343 	This is important as the object could have been marked for deletion by the visibility
2344 	management system...*/
2345 	if(!sbPtr->containingModule)
2346 	{
2347 		DestroyAnyStrategyBlock(sbPtr); /* just to make sure */
2348 		return;
2349 	} else if (marineStatusPointer->behaviourState!=MBS_Dying) {
2350 		#if SUPER_PHEROMONE_SYSTEM
2351 		AddMarinePheromones(sbPtr->containingModule->m_aimodule);
2352 		#endif
2353 	}
2354 
2355 	if(sbPtr->SBdptr) {
2356 		marineIsNear=1;
2357 		LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)]);
2358 	} else {
2359 		marineIsNear=0;
2360 	}
2361 
2362 	if (ShowSlack) {
2363 		int synthSpeed,setSpeed,slack;
2364 		VECTORCH offset;
2365 		extern int SlackTotal;
2366 		extern int SlackSize;
2367 
2368 		offset.vx=(sbPtr->DynPtr->Position.vx-sbPtr->DynPtr->PrevPosition.vx);
2369 		offset.vy=(sbPtr->DynPtr->Position.vy-sbPtr->DynPtr->PrevPosition.vy);
2370 		offset.vz=(sbPtr->DynPtr->Position.vz-sbPtr->DynPtr->PrevPosition.vz);
2371 
2372 		synthSpeed=Magnitude(&offset);
2373 		synthSpeed=DIV_FIXED(synthSpeed,NormalFrameTime);
2374 		setSpeed=Magnitude(&sbPtr->DynPtr->LinVelocity);
2375 
2376 		if (setSpeed) {
2377 			slack=(ONE_FIXED-(DIV_FIXED(synthSpeed,setSpeed)));
2378 			SlackTotal+=slack;
2379 			SlackSize++;
2380 		}
2381 		#if 0
2382 		PrintDebuggingText("MaxSpeed = %d, SynthSpeed = %d, SetSpeed = %d, Slack %d\n",alienStatusPointer->MaxSpeed,synthSpeed,setSpeed,slack);
2383 		#endif
2384 	}
2385 
2386 	GLOBALASSERT(marineStatusPointer->My_Weapon->WeaponPanicFireFunction);
2387 
2388 	InitWaypointSystem(0);
2389 
2390 	if ((Validate_Target(marineStatusPointer->Target,marineStatusPointer->Target_SBname)==0)
2391 		&&((marineStatusPointer->Target!=Player->ObStrategyBlock)||(Observer))) {
2392 		marineStatusPointer->Target=NULL;
2393 		/* Were you suspicious of something before? */
2394 		if (marineStatusPointer->previous_suspicion) {
2395 			marineStatusPointer->suspicious=marineStatusPointer->previous_suspicion;
2396 			marineStatusPointer->previous_suspicion=0;
2397 			marineStatusPointer->using_squad_suspicion=0;
2398 		}
2399 	}
2400 
2401 	/* unset suspicion? */
2402 
2403 	if (marineStatusPointer->suspicious!=0) {
2404 		if ((marineStatusPointer->behaviourState!=MBS_Approaching)
2405 			&&(marineStatusPointer->behaviourState!=MBS_Responding)) {
2406 			marineStatusPointer->suspicious-=NormalFrameTime;
2407 			/* To fix the next trap... */
2408 			if (marineStatusPointer->suspicious==0) {
2409 				marineStatusPointer->suspicious=-1;
2410 			}
2411 		}
2412 		if (marineStatusPointer->suspicious<0) {
2413 			marineStatusPointer->suspicious=0;
2414 			/* Set to zero on natural timeout, too. */
2415 			marineStatusPointer->previous_suspicion=0;
2416 			marineStatusPointer->using_squad_suspicion=0;
2417 			if ((marineStatusPointer->behaviourState==MBS_Waiting)
2418 				||(marineStatusPointer->behaviourState==MBS_Sentry)) {
2419 				/* We might concievably want to do this for all states. */
2420 				marineStatusPointer->gotapoint=0;
2421 			}
2422 		}
2423 		/* Approaching marines remain suspicious. */
2424 	} else {
2425 		/* Not suspicious. */
2426 		if (marineStatusPointer->Target) {
2427 			if (!MarineCanSeeTarget(sbPtr)) {
2428 				/* Oh well, forget it, then. */
2429 				marineStatusPointer->Target=NULL;
2430 			}
2431 		}
2432 	}
2433 	/* Squad level suspicion? */
2434 	if (((marineStatusPointer->suspicious==0)||(marineStatusPointer->using_squad_suspicion))
2435 		&&(NpcSquad.Squad_Suspicion!=0)
2436 		&&(sbPtr->SBdptr)
2437 		&&(marineStatusPointer->behaviourState!=MBS_Approaching)
2438 		&&(marineStatusPointer->behaviourState!=MBS_Firing)
2439 		&&(marineStatusPointer->behaviourState!=MBS_Dying)) {
2440 		/* Use squad suspicion. */
2441 		marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
2442 		marineStatusPointer->suspect_point=NpcSquad.squad_suspect_point;
2443 		/* Set this to zero when you get a *new* suspicion. */
2444 		marineStatusPointer->previous_suspicion=0;
2445 		marineStatusPointer->using_squad_suspicion=1;
2446 	}
2447 
2448 	if (marineStatusPointer->sawlastframe==2) {
2449 		marineStatusPointer->sawlastframe=0;
2450 	}
2451 
2452 	/* Unset incident flag. */
2453 	marineStatusPointer->incidentFlag=0;
2454 
2455 	marineStatusPointer->incidentTimer-=NormalFrameTime;
2456 
2457 	if (marineStatusPointer->incidentTimer<0) {
2458 		marineStatusPointer->incidentFlag=1;
2459 		marineStatusPointer->incidentTimer=32767+(FastRandom()&65535);
2460 	}
2461 
2462 	/* Run Motion Tracker. */
2463 
2464 	tracker_noise=0;
2465 
2466 	if (marineStatusPointer->mtracker_timer>=0) {
2467 		marineStatusPointer->mtracker_timer+=NormalFrameTime;
2468 	}
2469 	/* Negative timer means no tracker. */
2470 	if (marineStatusPointer->mtracker_timer>ONE_FIXED) {
2471 		marineStatusPointer->mtracker_timer=0;
2472 		tracker_noise=1;
2473 	}
2474 
2475 	if ((marineStatusPointer->Target==NULL)
2476 		#if ANARCHY
2477 		|| (marineStatusPointer->lastmodule!=sbPtr->containingModule->m_aimodule)
2478 		|| (marineStatusPointer->Target==Player->ObStrategyBlock)
2479 		#endif
2480 		) {
2481 
2482 		if ((marineIsNear)||(marineStatusPointer->incidentFlag)) {
2483 			/* Get new target. */
2484 			marineStatusPointer->roundsForThisTarget=0;
2485 			marineStatusPointer->sawlastframe=0;
2486 			marineStatusPointer->Target=Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr);
2487 
2488 			if (marineStatusPointer->Target) {
2489 				#if MARINE_STATE_PRINT
2490 				textprint("Marine gets new target.\n");
2491 				#endif
2492 				COPY_NAME(marineStatusPointer->Target_SBname,marineStatusPointer->Target->SBname);
2493 
2494 				/* Remember your suspicion... */
2495 				marineStatusPointer->previous_suspicion=marineStatusPointer->suspicious;
2496 				marineStatusPointer->suspicious=0;
2497 
2498 				/* Do stats. */
2499 				if (marineStatusPointer->Target==Player->ObStrategyBlock) {
2500 					if (marineStatusPointer->SpotFlag==0) {
2501 						CurrentGameStats_Spotted();
2502 						marineStatusPointer->SpotFlag=1;
2503 					}
2504 				}
2505 
2506 				/* New Enemy! */
2507 
2508 				if (NpcSquad.alertStatus==0) {
2509 					NpcSquad.alertStatus=1;
2510 				}
2511 				if (marineStatusPointer->Target->containingModule) {
2512 					ZoneAlert(2,marineStatusPointer->Target->containingModule->m_aimodule);
2513 				} else {
2514 					ZoneAlert(2,sbPtr->containingModule->m_aimodule);
2515 				}
2516 
2517 			} else {
2518 				#if 0
2519 					PrintDebuggingText("Marine found no target!\n");
2520 				#endif
2521 			}
2522 		}
2523 	} else if (marineStatusPointer->mtracker_timer==0) {
2524 		/* Fake sweep for wheeps. */
2525 		FakeTrackerWheepGenerator(&sbPtr->DynPtr->Position,sbPtr);
2526 
2527 		if (marineStatusPointer->Target->SBdptr) {
2528 			if (NpcSquad.Squad_Suspicion!=SQUAD_PARANOIA_TIME) {
2529 				if (MarineCanSeeTarget(sbPtr)) {
2530 					/* Hey, guys! */
2531 					GLOBALASSERT(marineStatusPointer->Target->DynPtr);
2532 					NpcSquad.Squad_Suspicion=SQUAD_PARANOIA_TIME;
2533 					NpcSquad.squad_suspect_point=marineStatusPointer->Target->DynPtr->Position;
2534 				}
2535 			}
2536 		}
2537 	}
2538 
2539 	/* Brushing Test. */
2540 
2541 	{
2542 		struct collisionreport *nextReport;
2543 		nextReport = sbPtr->DynPtr->CollisionReportPtr;
2544 
2545 		while(nextReport)
2546 		{
2547  			if(nextReport->ObstacleSBPtr)
2548  			{
2549 				if((nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourAlien)||
2550 				   ((nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourMarinePlayer)
2551 				   &&(AvP.PlayerType!=I_Marine))||
2552 				   (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourAlienPlayer)||
2553 				   (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourPredatorPlayer)||
2554 				   (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourNetGhost)||
2555 				   (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourXenoborg)||
2556 				   (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourPredatorAlien)||
2557 				   (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourQueenAlien)||
2558 				   (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourFaceHugger))
2559 					{
2560 					marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
2561 					marineStatusPointer->suspect_point=nextReport->ObstacleSBPtr->DynPtr->Position;
2562 					/* Set this to zero when you get a *new* suspicion. */
2563 					marineStatusPointer->previous_suspicion=0;
2564 					marineStatusPointer->using_squad_suspicion=0;
2565 					if (marineStatusPointer->Android==0) {
2566 						marineStatusPointer->Courage-=(NormalFrameTime>>1);
2567 					}
2568 				}
2569 			}
2570  			nextReport = nextReport->NextCollisionReportPtr;
2571 		}
2572 	}
2573 
2574 	/* Blinking! */
2575 	if (marineStatusPointer->behaviourState!=MBS_Dying) {
2576 		if (marineStatusPointer->Expression<3) {
2577 			if (marineStatusPointer->incidentFlag) {
2578 				if ((FastRandom()&65535)<24000) {
2579 					switch (marineStatusPointer->Expression) {
2580 						default:
2581 							GLOBALASSERT(0);
2582 							break;
2583 						case 0:
2584 							Marine_SwitchExpression(sbPtr,3);
2585 							break;
2586 						case 1:
2587 							Marine_SwitchExpression(sbPtr,4);
2588 							break;
2589 						case 2:
2590 							Marine_SwitchExpression(sbPtr,5);
2591 							break;
2592 					}
2593 					marineStatusPointer->Blink=0;
2594 				}
2595 			}
2596 		} else if (marineStatusPointer->Expression>=3) {
2597 			if (marineStatusPointer->Blink>=0) {
2598 				marineStatusPointer->Blink+=NormalFrameTime;
2599 				if (marineStatusPointer->Blink>(ONE_FIXED/7)) {
2600 					switch (marineStatusPointer->Expression) {
2601 						default:
2602 							GLOBALASSERT(0);
2603 							break;
2604 						case 3:
2605 							Marine_SwitchExpression(sbPtr,0);
2606 							break;
2607 						case 4:
2608 							Marine_SwitchExpression(sbPtr,1);
2609 							break;
2610 						case 5:
2611 							Marine_SwitchExpression(sbPtr,2);
2612 							break;
2613 					}
2614 				}
2615 			}
2616 		}
2617 	}
2618 
2619 	/* Now hearing. */
2620 
2621 	DoMarineHearing(sbPtr);
2622 
2623 	/* That was senses. Now courage. */
2624 	if (marineStatusPointer->Android==0) {
2625 
2626 		if ((marineStatusPointer->Target==NULL)&&(marineStatusPointer->suspicious==0)) {
2627 			marineStatusPointer->Courage+=MUL_FIXED(NormalFrameTime,300);
2628 		}
2629 
2630 		marineStatusPointer->Courage+=NpcSquad.Squad_Delta_Morale;
2631 
2632 		if (marineStatusPointer->Courage>=(ONE_FIXED<<1)) {
2633 			marineStatusPointer->Courage=(ONE_FIXED<<1);
2634 		} else if (marineStatusPointer->Courage<0) {
2635 			marineStatusPointer->Courage=0;
2636 		}
2637 	} else {
2638 		marineStatusPointer->Courage=ONE_FIXED;
2639 	}
2640 
2641 	/* Dead yet? */
2642 
2643 	if (marineStatusPointer->GibbFactor) {
2644 		/* If you're gibbed, you're dead. */
2645 		sbPtr->SBDamageBlock.Health = 0;
2646 	}
2647 
2648 	if (sbPtr->SBDamageBlock.IsOnFire) {
2649 
2650 		CauseDamageToObject(sbPtr,&firedamage,NormalFrameTime,NULL);
2651 
2652 		if (sbPtr->I_SBtype==I_BehaviourNetCorpse) {
2653 			/* Gettin' out of here... */
2654 			return;
2655 		}
2656 
2657 		if (marineStatusPointer->Mission!=MM_RunAroundOnFire) {
2658 			if (marineStatusPointer->Android==0) {
2659 				Convert_To_RunningOnFire(sbPtr);
2660 			} else {
2661 				/* Handle sound for an android. */
2662 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
2663 					Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
2664 				} else {
2665 					if (ActiveSounds[marineStatusPointer->soundHandle].soundIndex!=SID_FIRE) {
2666 						Sound_Stop(marineStatusPointer->soundHandle);
2667 					 	Sound_Play(SID_FIRE,"dlev",&(sbPtr->DynPtr->Position),&marineStatusPointer->soundHandle,127);
2668 					}
2669 				}
2670 			}
2671 		}
2672 
2673 	}
2674 
2675 	/* Mission Control! */
2676 
2677 	if ((ShowSquadState)||((sbPtr->SBdptr)&&(ShowNearSquad))) {
2678 		if (sbPtr->name) {
2679 			PrintDebuggingText("%s: ",sbPtr->name);
2680 		} else {
2681 			PrintDebuggingText("Unnamed: ");
2682 		}
2683 		if (marineStatusPointer->suspicious) {
2684 			PrintDebuggingText("Suspicious %d ",marineStatusPointer->suspicious);
2685 		}
2686 	}
2687 
2688 	if ((marineStatusPointer->Mission!=MM_NonCom)&&(marineStatusPointer->Mission!=MM_RunAroundOnFire)) {
2689 		if (marineStatusPointer->My_Weapon->WeaponFireFunction==NULL) {
2690 			LOGDXFMT(("Marine Weapon ID = %d\n",marineStatusPointer->My_Weapon->id));
2691 			LOGDXFMT(("Mission %d\n",marineStatusPointer->Mission));
2692 		}
2693 		GLOBALASSERT(marineStatusPointer->My_Weapon->WeaponFireFunction);
2694 	}
2695 
2696 	switch (marineStatusPointer->Mission) {
2697 		case (MM_Wait_Then_Wander):
2698 		case (MM_Wander):
2699 		{
2700 			WanderMission_Control(sbPtr);
2701 			break;
2702 		}
2703 		case (MM_Guard):
2704 		{
2705 			GuardMission_Control(sbPtr);
2706 			break;
2707 		}
2708 		case (MM_LocalGuard):
2709 		{
2710 			LocalGuardMission_Control(sbPtr);
2711 			break;
2712 		}
2713 		case (MM_NonCom):
2714 		{
2715 			LoiterMission_Control(sbPtr);
2716 			break;
2717 		}
2718 		case (MM_Pathfinder):
2719 		{
2720 			PathfinderMission_Control(sbPtr);
2721 			break;
2722 		}
2723 		case (MM_RunAroundOnFire):
2724 		{
2725 			RunAroundOnFireMission_Control(sbPtr);
2726 			break;
2727 		}
2728 		default:
2729 		{
2730 			GLOBALASSERT(0);
2731 			break;
2732 		}
2733 	}
2734 
2735 	if (TERROR_MODE) {
2736 		if ((marineStatusPointer->behaviourState!=MBS_PanicFire)
2737 			&&(marineStatusPointer->behaviourState!=MBS_PanicReloading)
2738 			&&(marineStatusPointer->behaviourState!=MBS_Retreating)
2739 			&&(marineStatusPointer->behaviourState!=MBS_Approaching)
2740 			&&(marineStatusPointer->behaviourState!=MBS_GetWeapon)
2741 			&&(marineStatusPointer->behaviourState!=MBS_Taunting)
2742 			&&(marineStatusPointer->behaviourState!=MBS_Avoidance)
2743 			&&(marineStatusPointer->behaviourState!=MBS_Dying)
2744 			) {
2745 			Marine_Enter_Retreat_State(sbPtr);
2746 		}
2747 	}
2748 
2749 	if (marineStatusPointer->My_Weapon->id==MNPCW_Minigun) {
2750 		DELTA_CONTROLLER *mgd=Get_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
2751 		if (mgd) {
2752 			NPC_Maintain_Minigun(sbPtr,mgd);
2753 		}
2754 	}
2755 
2756 	/* if we have actually died, we need to remove the strategyblock... so
2757 	do this here */
2758 	if((marineStatusPointer->behaviourState == MBS_Dying)&&(marineStatusPointer->stateTimer <= 0)) {
2759 
2760 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Stop(marineStatusPointer->soundHandle);
2761 		if(marineStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) Sound_Stop(marineStatusPointer->soundHandle2);
2762 
2763 		DestroyAnyStrategyBlock(sbPtr);
2764 	}
2765 
2766 	marineStatusPointer->lastmodule=sbPtr->containingModule->m_aimodule;
2767 
2768 	if (sbPtr->SBdptr) {
2769 		/* I reckon only near trackers wheep. */
2770 		if (tracker_noise==1) {
2771 			Sound_Play(SID_TRACKER_CLICK,"d",&sbPtr->DynPtr->Position);
2772 		} else if (tracker_noise==2) {
2773 			Sound_Play(SID_TRACKER_WHEEP,"d",&sbPtr->DynPtr->Position);
2774 		}
2775 	}
2776 
2777 	/* Update squad stats. */
2778 	if ((marineStatusPointer->behaviourState==MBS_Responding)
2779 		||((marineStatusPointer->behaviourState==MBS_Avoidance)
2780 			&&(marineStatusPointer->lastState==MBS_Responding))) {
2781 
2782 		NpcSquad.Alt_RespondingMarines++;
2783 	}
2784 
2785 	if ((marineStatusPointer->Mission==MM_RunAroundOnFire)
2786 		&&(sbPtr->SBdptr)) {
2787 
2788 		NpcSquad.Alt_NearBurningMarines++;
2789 	}
2790 
2791 	if ((sbPtr->SBdptr)&&(
2792 		(marineStatusPointer->behaviourState==MBS_Retreating)
2793 		||(marineStatusPointer->Mission==MM_RunAroundOnFire)
2794 		)) {
2795 		/* Burning marines are considered panicked, too. */
2796 
2797 		NpcSquad.Alt_NearPanickedMarines++;
2798 	}
2799 
2800 	if ((sbPtr->SBdptr)&&(marineStatusPointer->My_Weapon->ARealMarine)&&(
2801 		(marineStatusPointer->behaviourState!=MBS_Retreating)
2802 		&&(marineStatusPointer->behaviourState!=MBS_Dying)
2803 		)) {
2804 
2805 		NpcSquad.Alt_NearUnpanickedMarines++;
2806 	}
2807 
2808 	/* Make marines heal, really slowly? */
2809 	HModel_Regen(&marineStatusPointer->HModelController,(120*ONE_FIXED));
2810 	/* Two minutes.  Only heals sections, too. */
2811 
2812 	/* Change the face if we can... */
2813 	Marine_UpdateFace(sbPtr);
2814 
2815 	/* And finally, update lastframe flag. */
2816 	Marine_ConsiderFallingDamage(sbPtr);
2817 
2818 }
2819 
EndMarineMuzzleFlash(STRATEGYBLOCK * sbPtr)2820 void EndMarineMuzzleFlash(STRATEGYBLOCK *sbPtr) {
2821 
2822 	MARINE_STATUS_BLOCK *marineStatusPointer;
2823 
2824 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
2825 	LOCALASSERT(marineStatusPointer);
2826 
2827 	if(marineStatusPointer->myGunFlash)
2828 	{
2829 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
2830 		marineStatusPointer->myGunFlash = NULL;
2831 	}
2832 
2833 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
2834 		Sound_Stop(marineStatusPointer->soundHandle);
2835 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
2836 	}
2837 
2838 }
2839 
InitMission(STRATEGYBLOCK * sbPtr,MARINE_MISSION mission)2840 void InitMission(STRATEGYBLOCK *sbPtr,MARINE_MISSION mission) {
2841 
2842 	MARINE_STATUS_BLOCK *marineStatus;
2843 
2844 	marineStatus = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
2845 	LOCALASSERT(marineStatus);
2846 
2847 	switch (mission) {
2848 		case MM_RunAroundOnFire:
2849 			marineStatus->Mission=MM_RunAroundOnFire;
2850    			marineStatus->behaviourState = MBS_Wandering;
2851 			marineStatus->lastState = MBS_Waiting;
2852 			/* Shouldn't need a sequence force. */
2853 			break;
2854 		case MM_Guard:
2855 			marineStatus->Mission=MM_Guard;
2856    			marineStatus->behaviourState = MBS_Sentry;
2857 			marineStatus->lastState = MBS_Waiting;
2858 			Marine_Enter_SentryMode_State(sbPtr);
2859 			break;
2860 		case MM_LocalGuard:
2861 			marineStatus->Mission=MM_LocalGuard;
2862    			marineStatus->behaviourState = MBS_Waiting;
2863 			marineStatus->lastState = MBS_Waiting;
2864 			Marine_Enter_Wait_State(sbPtr);
2865 			break;
2866 		case MM_NonCom:
2867 			marineStatus->Mission=MM_NonCom;
2868    			marineStatus->behaviourState = MBS_Waiting;
2869 			marineStatus->lastState = MBS_Waiting;
2870 			Marine_Enter_Wait_State(sbPtr);
2871 			break;
2872 		case MM_Wait_Then_Wander:
2873 			marineStatus->Mission=MM_Wait_Then_Wander;
2874    			marineStatus->behaviourState = MBS_Waiting;
2875 			marineStatus->lastState = MBS_Waiting;
2876 			Marine_Enter_Wait_State(sbPtr);
2877 			break;
2878 		case MM_Pathfinder:
2879 			marineStatus->Mission=MM_Pathfinder;
2880    			marineStatus->behaviourState = MBS_Pathfinding;
2881 			marineStatus->lastState = MBS_Waiting;
2882 			Marine_Enter_Pathfinder_State(sbPtr);
2883 			break;
2884 		case MM_Wander:
2885 		default:
2886 			marineStatus->Mission=MM_Wander;
2887    			marineStatus->behaviourState = MBS_Approaching;
2888 			marineStatus->lastState = MBS_Waiting;
2889 			Marine_Enter_Approach_State(sbPtr);
2890 			break;
2891 	}
2892 
2893 }
2894 
WanderMission_Control(STRATEGYBLOCK * sbPtr)2895 void WanderMission_Control(STRATEGYBLOCK *sbPtr) {
2896 
2897 	MARINE_STATUS_BLOCK *marineStatusPointer;
2898 	STATE_RETURN_CONDITION state_result;
2899 	int marineIsNear;
2900 
2901 	LOCALASSERT(sbPtr);
2902 	LOCALASSERT(sbPtr->containingModule);
2903 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
2904     LOCALASSERT(marineStatusPointer);
2905 
2906 
2907 	/* Current Behaviour. */
2908 
2909 	if(sbPtr->SBdptr) {
2910 		marineIsNear=1;
2911 		LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)]);
2912 	} else {
2913 		marineIsNear=0;
2914 	}
2915 
2916 	{
2917 
2918 		if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
2919 			if (marineStatusPointer->Mission==MM_Wait_Then_Wander) {
2920 				/* A bit of a cheat. */
2921 				PrintDebuggingText("Wait Then ");
2922 			}
2923 		}
2924 
2925 		switch(marineStatusPointer->behaviourState)
2926 		{
2927 			case(MBS_Approaching):
2928 			{
2929 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
2930 					PrintDebuggingText("Wander marine approach in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
2931 				}
2932 
2933 				if(marineIsNear) {
2934 					state_result=Execute_MNS_Approach(sbPtr);
2935 					CentreMarineElevation(sbPtr);
2936 				} else {
2937 					state_result=Execute_MFS_Approach(sbPtr);
2938 				}
2939 				WanderMission_SwitchState(sbPtr,state_result);
2940 				break;
2941 			}
2942 			case(MBS_Firing):
2943 			{
2944 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
2945 					PrintDebuggingText("Wander marine firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
2946 				}
2947 
2948 				if (marineIsNear) {
2949 					state_result=(*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
2950 					SetMarineElevation(sbPtr);
2951 				} else {
2952 					state_result=Execute_MFS_Firing(sbPtr);
2953 				}
2954 				WanderMission_SwitchState(sbPtr,state_result);
2955 				break;
2956 			}
2957 			case(MBS_PumpAction):
2958 			{
2959 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
2960 					PrintDebuggingText("Wander marine pump action in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
2961 				}
2962 
2963 				if (marineIsNear) {
2964 					state_result=Execute_MNS_PumpAction(sbPtr);
2965 					CentreMarineElevation(sbPtr);
2966 				} else {
2967 					state_result=Execute_MNS_PumpAction(sbPtr);
2968 				}
2969 				WanderMission_SwitchState(sbPtr,state_result);
2970 				break;
2971 			}
2972 			case(MBS_PanicFire):
2973 			{
2974 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
2975 					PrintDebuggingText("Wander marine panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
2976 				}
2977 
2978 				if (marineIsNear) {
2979 					state_result=(*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
2980 					CentreMarineElevation(sbPtr);
2981 				} else {
2982 					state_result=Execute_MFS_Firing(sbPtr);
2983 				}
2984 				WanderMission_SwitchState(sbPtr,state_result);
2985 				break;
2986 			}
2987 			case(MBS_Avoidance):
2988 			{
2989 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
2990 					PrintDebuggingText("Wander marine ");
2991 					switch (marineStatusPointer->avoidanceManager.substate) {
2992 						default:
2993 						case AvSS_FreeMovement:
2994 							PrintDebuggingText("Avoidance Level 0");
2995 							break;
2996 						case AvSS_FirstAvoidance:
2997 							PrintDebuggingText("Avoidance Level 1");
2998 							break;
2999 						case AvSS_SecondAvoidance:
3000 							PrintDebuggingText("Avoidance Level 2");
3001 							break;
3002 						case AvSS_ThirdAvoidance:
3003 							PrintDebuggingText("Avoidance Level 3");
3004 							break;
3005 					}
3006 					PrintDebuggingText(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3007 				}
3008 				if(marineIsNear) {
3009 					state_result=Execute_MNS_Avoidance(sbPtr);
3010 					CentreMarineElevation(sbPtr);
3011 				} else {
3012 					state_result=Execute_MFS_Avoidance(sbPtr);
3013 				}
3014 				WanderMission_SwitchState(sbPtr,state_result);
3015 				break;
3016 			}
3017 			case(MBS_Wandering):
3018 			{
3019 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3020 					PrintDebuggingText("Wander marine wander in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3021 				}
3022 
3023 				if (marineIsNear) {
3024 					state_result=Execute_MNS_Wander(sbPtr);
3025 					CentreMarineElevation(sbPtr);
3026 				} else {
3027 					state_result=Execute_MFS_Wander(sbPtr);
3028 				}
3029 				WanderMission_SwitchState(sbPtr,state_result);
3030 				break;
3031 			}
3032 			case(MBS_Responding):
3033 			{
3034 				/* Closest to hunt. */
3035 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3036 					PrintDebuggingText("Wander marine responding in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3037 				}
3038 
3039 				if (marineIsNear) {
3040 					state_result=Execute_MNS_Respond(sbPtr);
3041 					CentreMarineElevation(sbPtr);
3042 				} else {
3043 					state_result=Execute_MFS_Respond(sbPtr);
3044 				}
3045 				WanderMission_SwitchState(sbPtr,state_result);
3046 				break;
3047 			}
3048 			case(MBS_Retreating):
3049 			{
3050 				/* Real men never retreat! */
3051 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3052 					PrintDebuggingText("Wander marine Retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3053 				}
3054 
3055 				if (marineIsNear) {
3056 					state_result=Execute_MNS_Retreat(sbPtr);
3057 					CentreMarineElevation(sbPtr);
3058 				} else {
3059 					state_result=Execute_MFS_Retreat(sbPtr);
3060 				}
3061 				WanderMission_SwitchState(sbPtr,state_result);
3062 				break;
3063 			}
3064 			case(MBS_Waiting):
3065 			{
3066 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3067 					PrintDebuggingText("Wander marine wait in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3068 				}
3069 
3070 				if (marineIsNear) {
3071 					state_result=Execute_MNS_Wait(sbPtr);
3072 					CentreMarineElevation(sbPtr);
3073 				} else {
3074 					state_result=Execute_MFS_Wait(sbPtr);
3075 				}
3076 				WanderMission_SwitchState(sbPtr,state_result);
3077 				break;
3078 			}
3079 			case(MBS_Sentry):
3080 			{
3081 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3082 					PrintDebuggingText("Wander marine sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3083 				}
3084 				GLOBALASSERT(0);
3085 				if(marineIsNear) {
3086 					state_result=Execute_MNS_SentryMode(sbPtr);
3087 					CentreMarineElevation(sbPtr);
3088 				} else {
3089 					state_result=Execute_MFS_Wait(sbPtr);
3090 				}
3091 				WanderMission_SwitchState(sbPtr,state_result);
3092 				break;
3093 			}
3094 			case(MBS_Dying):
3095 			{
3096 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3097 					PrintDebuggingText("Wander marine dying in %s\n",sbPtr->containingModule->name);
3098 				}
3099 				if (marineIsNear) {
3100 					Execute_Dying(sbPtr);
3101 				} else {
3102 					Execute_Dying(sbPtr);
3103 				}
3104 				break;
3105 			}
3106 			case(MBS_Taunting):
3107 			{
3108 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3109 					PrintDebuggingText("Wander marine taunt in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3110 				}
3111 
3112 				if(marineIsNear) {
3113 					state_result=Execute_MNS_Taunting(sbPtr);
3114 					CentreMarineElevation(sbPtr);
3115 				} else {
3116 					state_result=Execute_MNS_Taunting(sbPtr);
3117 				}
3118 				WanderMission_SwitchState(sbPtr,state_result);
3119 				break;
3120 			}
3121 			case(MBS_Reloading):
3122 			{
3123 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3124 					PrintDebuggingText("Wander marine reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3125 				}
3126 
3127 				if(marineIsNear) {
3128 					state_result=Execute_MNS_Reloading(sbPtr);
3129 					CentreMarineElevation(sbPtr);
3130 				} else {
3131 					state_result=Execute_MNS_Reloading(sbPtr);
3132 				}
3133 				WanderMission_SwitchState(sbPtr,state_result);
3134 				break;
3135 			}
3136 			case(MBS_PanicReloading):
3137 			{
3138 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3139 					PrintDebuggingText("Wander marine panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3140 				}
3141 
3142 				if(marineIsNear) {
3143 					state_result=Execute_MNS_PanicReloading(sbPtr);
3144 					CentreMarineElevation(sbPtr);
3145 				} else {
3146 					state_result=Execute_MNS_PanicReloading(sbPtr);
3147 				}
3148 				WanderMission_SwitchState(sbPtr,state_result);
3149 				break;
3150 			}
3151 			case(MBS_GetWeapon):
3152 			{
3153 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3154 					PrintDebuggingText("Wander marine get weapon in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3155 				}
3156 
3157 				if(marineIsNear) {
3158 					state_result=Execute_MNS_GetWeapon(sbPtr);
3159 					CentreMarineElevation(sbPtr);
3160 				} else {
3161 					state_result=Execute_MNS_GetWeapon(sbPtr);
3162 				}
3163 				WanderMission_SwitchState(sbPtr,state_result);
3164 				break;
3165 			}
3166 			case MBS_Returning:
3167 			case MBS_Pathfinding:
3168 			{
3169 				/* How the hell did you get here?!? */
3170 				Marine_Enter_Wander_State(sbPtr);
3171 				break;
3172 			}
3173 			case(MBS_AcidAvoidance):
3174 			{
3175 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3176 					PrintDebuggingText("Wander marine acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3177 				}
3178 
3179 				if (marineIsNear) {
3180 					state_result=Execute_MNS_AcidAvoidance(sbPtr);
3181 					CentreMarineElevation(sbPtr);
3182 				} else {
3183 					Marine_Enter_Wait_State(sbPtr);
3184 					break;
3185 				}
3186 				WanderMission_SwitchState(sbPtr,state_result);
3187 				break;
3188 			}
3189 			default:
3190 			{
3191 				LOGDXFMT(("Marine in unsupported state %d!\n",marineStatusPointer->behaviourState));
3192 				LOCALASSERT(1==0);
3193 			}
3194 		}
3195 	}
3196 
3197 	if (!marineIsNear) {
3198 
3199 		/* check here to see if marine is in a proximity door - if so, trigger it to open. */
3200 		{
3201 			MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
3202 
3203 			if(doorType == MDT_ProxDoor)
3204 				((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->SBdataptr)->marineTrigger = 1;
3205 		}
3206 
3207 		/* lastly, do a containment test: to make sure that we are inside a module. */
3208 		#if UseLocalAssert
3209 		{
3210 			VECTORCH localCoords;
3211 			MODULE *thisModule = sbPtr->containingModule;
3212 
3213 			LOCALASSERT(thisModule);
3214 
3215 			localCoords = sbPtr->DynPtr->Position;
3216 			localCoords.vx -= thisModule->m_world.vx;
3217 			localCoords.vy -= thisModule->m_world.vy;
3218 			localCoords.vz -= thisModule->m_world.vz;
3219 
3220 			if(PointIsInModule(thisModule, &localCoords)==0)
3221 			{
3222 				textprint("FAR MARINE MODULE CONTAINMENT FAILURE \n");
3223 				LOCALASSERT(1==0);
3224 			}
3225 		}
3226 		#endif
3227 	}
3228 
3229 }
3230 
PathfinderMission_Control(STRATEGYBLOCK * sbPtr)3231 void PathfinderMission_Control(STRATEGYBLOCK *sbPtr) {
3232 
3233 	MARINE_STATUS_BLOCK *marineStatusPointer;
3234 	STATE_RETURN_CONDITION state_result;
3235 	int marineIsNear;
3236 
3237 	LOCALASSERT(sbPtr);
3238 	LOCALASSERT(sbPtr->containingModule);
3239 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
3240     LOCALASSERT(marineStatusPointer);
3241 
3242 
3243 	/* Current Behaviour. */
3244 
3245 	if(sbPtr->SBdptr) {
3246 		marineIsNear=1;
3247 		LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)]);
3248 	} else {
3249 		marineIsNear=0;
3250 	}
3251 
3252 	{
3253 
3254 		switch(marineStatusPointer->behaviourState)
3255 		{
3256 			case(MBS_Approaching):
3257 			{
3258 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3259 					PrintDebuggingText("Pathfinder marine approach in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3260 				}
3261 
3262 				if(marineIsNear) {
3263 					state_result=Execute_MNS_Approach(sbPtr);
3264 					CentreMarineElevation(sbPtr);
3265 				} else {
3266 					state_result=Execute_MFS_Approach(sbPtr);
3267 				}
3268 				PathfinderMission_SwitchState(sbPtr,state_result);
3269 				break;
3270 			}
3271 			case(MBS_Firing):
3272 			{
3273 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3274 					PrintDebuggingText("Pathfinder marine firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3275 				}
3276 
3277 				if (marineIsNear) {
3278 					state_result=(*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
3279 					SetMarineElevation(sbPtr);
3280 				} else {
3281 					state_result=Execute_MFS_Firing(sbPtr);
3282 				}
3283 				PathfinderMission_SwitchState(sbPtr,state_result);
3284 				break;
3285 			}
3286 			case(MBS_PumpAction):
3287 			{
3288 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3289 					PrintDebuggingText("Pathfinder marine pump action in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3290 				}
3291 
3292 				if (marineIsNear) {
3293 					state_result=Execute_MNS_PumpAction(sbPtr);
3294 					CentreMarineElevation(sbPtr);
3295 				} else {
3296 					state_result=Execute_MNS_PumpAction(sbPtr);
3297 				}
3298 				PathfinderMission_SwitchState(sbPtr,state_result);
3299 				break;
3300 			}
3301 			case(MBS_PanicFire):
3302 			{
3303 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3304 					PrintDebuggingText("Pathfinder marine panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3305 				}
3306 
3307 				if (marineIsNear) {
3308 					state_result=(*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
3309 					CentreMarineElevation(sbPtr);
3310 				} else {
3311 					state_result=Execute_MFS_Firing(sbPtr);
3312 				}
3313 				PathfinderMission_SwitchState(sbPtr,state_result);
3314 				break;
3315 			}
3316 			case(MBS_Avoidance):
3317 			{
3318 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3319 					PrintDebuggingText("Pathfinder marine ");
3320 					switch (marineStatusPointer->avoidanceManager.substate) {
3321 						default:
3322 						case AvSS_FreeMovement:
3323 							PrintDebuggingText("Avoidance Level 0");
3324 							break;
3325 						case AvSS_FirstAvoidance:
3326 							PrintDebuggingText("Avoidance Level 1");
3327 							break;
3328 						case AvSS_SecondAvoidance:
3329 							PrintDebuggingText("Avoidance Level 2");
3330 							break;
3331 						case AvSS_ThirdAvoidance:
3332 							PrintDebuggingText("Avoidance Level 3");
3333 							break;
3334 					}
3335 					PrintDebuggingText(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3336 				}
3337 				if(marineIsNear) {
3338 					state_result=Execute_MNS_Avoidance(sbPtr);
3339 					CentreMarineElevation(sbPtr);
3340 				} else {
3341 					state_result=Execute_MFS_Avoidance(sbPtr);
3342 				}
3343 				PathfinderMission_SwitchState(sbPtr,state_result);
3344 				break;
3345 			}
3346 			case(MBS_Wandering):
3347 			{
3348 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3349 					PrintDebuggingText("Pathfinder marine wander in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3350 				}
3351 
3352 				if (marineIsNear) {
3353 					state_result=Execute_MNS_Wander(sbPtr);
3354 					CentreMarineElevation(sbPtr);
3355 				} else {
3356 					state_result=Execute_MFS_Wander(sbPtr);
3357 				}
3358 				PathfinderMission_SwitchState(sbPtr,state_result);
3359 				break;
3360 			}
3361 			case(MBS_Responding):
3362 			{
3363 				/* Closest to hunt. */
3364 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3365 					PrintDebuggingText("Pathfinder marine responding in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3366 				}
3367 
3368 				if (marineIsNear) {
3369 					state_result=Execute_MNS_Respond(sbPtr);
3370 					CentreMarineElevation(sbPtr);
3371 				} else {
3372 					state_result=Execute_MFS_Respond(sbPtr);
3373 				}
3374 				PathfinderMission_SwitchState(sbPtr,state_result);
3375 				break;
3376 			}
3377 			case(MBS_Retreating):
3378 			{
3379 				/* Real men never retreat! */
3380 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3381 					PrintDebuggingText("Pathfinder marine retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3382 				}
3383 
3384 				if (marineIsNear) {
3385 					state_result=Execute_MNS_Retreat(sbPtr);
3386 					CentreMarineElevation(sbPtr);
3387 				} else {
3388 					state_result=Execute_MFS_Retreat(sbPtr);
3389 				}
3390 				PathfinderMission_SwitchState(sbPtr,state_result);
3391 				break;
3392 			}
3393 			case(MBS_Waiting):
3394 			{
3395 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3396 					PrintDebuggingText("Pathfinder marine wait in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3397 				}
3398 
3399 				if (marineIsNear) {
3400 					state_result=Execute_MNS_Wait(sbPtr);
3401 					CentreMarineElevation(sbPtr);
3402 				} else {
3403 					state_result=Execute_MFS_Wait(sbPtr);
3404 				}
3405 				PathfinderMission_SwitchState(sbPtr,state_result);
3406 				break;
3407 			}
3408 			case(MBS_Sentry):
3409 			{
3410 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3411 					PrintDebuggingText("Pathfinder marine sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3412 				}
3413 				GLOBALASSERT(0);
3414 				if(marineIsNear) {
3415 					state_result=Execute_MNS_SentryMode(sbPtr);
3416 					CentreMarineElevation(sbPtr);
3417 				} else {
3418 					state_result=Execute_MFS_Wait(sbPtr);
3419 				}
3420 				PathfinderMission_SwitchState(sbPtr,state_result);
3421 				break;
3422 			}
3423 			case(MBS_Dying):
3424 			{
3425 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3426 					PrintDebuggingText("Pathfinder marine dying in %s\n",sbPtr->containingModule->name);
3427 				}
3428 				if (marineIsNear) {
3429 					Execute_Dying(sbPtr);
3430 				} else {
3431 					Execute_Dying(sbPtr);
3432 				}
3433 				break;
3434 			}
3435 			case(MBS_Pathfinding):
3436 			{
3437 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3438 					PrintDebuggingText("Pathfinder marine pathfinding in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3439 				}
3440 
3441 				if (marineIsNear) {
3442 					state_result=Execute_MNS_Pathfinder(sbPtr);
3443 					CentreMarineElevation(sbPtr);
3444 				} else {
3445 					state_result=Execute_MFS_Pathfinder(sbPtr);
3446 				}
3447 				PathfinderMission_SwitchState(sbPtr,state_result);
3448 				break;
3449 			}
3450 			case(MBS_Taunting):
3451 			{
3452 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3453 					PrintDebuggingText("Pathfinder marine taunt in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3454 				}
3455 
3456 				if(marineIsNear) {
3457 					state_result=Execute_MNS_Taunting(sbPtr);
3458 					CentreMarineElevation(sbPtr);
3459 				} else {
3460 					state_result=Execute_MNS_Taunting(sbPtr);
3461 				}
3462 				PathfinderMission_SwitchState(sbPtr,state_result);
3463 				break;
3464 			}
3465 			case(MBS_Returning):
3466 			{
3467 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3468 					PrintDebuggingText("Pathfinder marine returning in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3469 				}
3470 
3471 				if (marineIsNear) {
3472 					state_result=Execute_MNS_Return(sbPtr);
3473 					CentreMarineElevation(sbPtr);
3474 				} else {
3475 					state_result=Execute_MFS_Return(sbPtr);
3476 				}
3477 				PathfinderMission_SwitchState(sbPtr,state_result);
3478 				break;
3479 			}
3480 			case(MBS_Reloading):
3481 			{
3482 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3483 					PrintDebuggingText("Pathfinder marine reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3484 				}
3485 
3486 				if(marineIsNear) {
3487 					state_result=Execute_MNS_Reloading(sbPtr);
3488 					CentreMarineElevation(sbPtr);
3489 				} else {
3490 					state_result=Execute_MNS_Reloading(sbPtr);
3491 				}
3492 				PathfinderMission_SwitchState(sbPtr,state_result);
3493 				break;
3494 			}
3495 			case(MBS_PanicReloading):
3496 			{
3497 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3498 					PrintDebuggingText("Pathfinder marine panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3499 				}
3500 
3501 				if(marineIsNear) {
3502 					state_result=Execute_MNS_PanicReloading(sbPtr);
3503 					CentreMarineElevation(sbPtr);
3504 				} else {
3505 					state_result=Execute_MNS_PanicReloading(sbPtr);
3506 				}
3507 				PathfinderMission_SwitchState(sbPtr,state_result);
3508 				break;
3509 			}
3510 			case(MBS_GetWeapon):
3511 			{
3512 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3513 					PrintDebuggingText("Pathfinder marine get weapon in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3514 				}
3515 
3516 				if(marineIsNear) {
3517 					state_result=Execute_MNS_GetWeapon(sbPtr);
3518 					CentreMarineElevation(sbPtr);
3519 				} else {
3520 					state_result=Execute_MNS_GetWeapon(sbPtr);
3521 				}
3522 				PathfinderMission_SwitchState(sbPtr,state_result);
3523 				break;
3524 			}
3525 			case(MBS_AcidAvoidance):
3526 			{
3527 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3528 					PrintDebuggingText("Prahfinder marine acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3529 				}
3530 
3531 				if (marineIsNear) {
3532 					state_result=Execute_MNS_AcidAvoidance(sbPtr);
3533 					CentreMarineElevation(sbPtr);
3534 				} else {
3535 					Marine_Enter_Wait_State(sbPtr);
3536 					break;
3537 				}
3538 				PathfinderMission_SwitchState(sbPtr,state_result);
3539 				break;
3540 			}
3541 			default:
3542 			{
3543 				LOGDXFMT(("Marine in unsupported state %d!\n",marineStatusPointer->behaviourState));
3544 				LOCALASSERT(1==0);
3545 			}
3546 		}
3547 	}
3548 
3549 	if (!marineIsNear) {
3550 
3551 		/* check here to see if marine is in a proximity door - if so, trigger it to open. */
3552 		{
3553 			MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
3554 
3555 			if(doorType == MDT_ProxDoor)
3556 				((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->SBdataptr)->marineTrigger = 1;
3557 		}
3558 
3559 		/* lastly, do a containment test: to make sure that we are inside a module. */
3560 		#if UseLocalAssert
3561 		{
3562 			VECTORCH localCoords;
3563 			MODULE *thisModule = sbPtr->containingModule;
3564 
3565 			LOCALASSERT(thisModule);
3566 
3567 			localCoords = sbPtr->DynPtr->Position;
3568 			localCoords.vx -= thisModule->m_world.vx;
3569 			localCoords.vy -= thisModule->m_world.vy;
3570 			localCoords.vz -= thisModule->m_world.vz;
3571 
3572 			if(PointIsInModule(thisModule, &localCoords)==0)
3573 			{
3574 				textprint("FAR MARINE MODULE CONTAINMENT FAILURE \n");
3575 				LOCALASSERT(1==0);
3576 			}
3577 		}
3578 		#endif
3579 	}
3580 
3581 }
3582 
GuardMission_Control(STRATEGYBLOCK * sbPtr)3583 void GuardMission_Control(STRATEGYBLOCK *sbPtr) {
3584 
3585 	MARINE_STATUS_BLOCK *marineStatusPointer;
3586 	STATE_RETURN_CONDITION state_result;
3587 	int marineIsNear;
3588 
3589 	LOCALASSERT(sbPtr);
3590 	LOCALASSERT(sbPtr->containingModule);
3591 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
3592     LOCALASSERT(marineStatusPointer);
3593 
3594 	/* Firstly, fix missionmodule. */
3595 
3596 	if (marineStatusPointer->missionmodule==NULL) {
3597 		marineStatusPointer->missionmodule=sbPtr->containingModule->m_aimodule;
3598 		marineStatusPointer->my_spot=sbPtr->DynPtr->Position;
3599 	}
3600 
3601 	if(sbPtr->SBdptr) {
3602 		marineIsNear=1;
3603 		LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)]);
3604 	} else {
3605 		marineIsNear=0;
3606 	}
3607 
3608 	{
3609 
3610 		switch(marineStatusPointer->behaviourState)
3611 		{
3612 			case(MBS_Approaching):
3613 			{
3614 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3615 					PrintDebuggingText("Guard marine approaching in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3616 				}
3617 
3618 				GLOBALASSERT(0);
3619 				if (marineIsNear) {
3620 					state_result=Execute_MNS_Approach(sbPtr);
3621 					CentreMarineElevation(sbPtr);
3622 				} else {
3623 					state_result=Execute_MFS_Wander(sbPtr);
3624 				}
3625 				GuardMission_SwitchState(sbPtr,state_result);
3626 				break;
3627 			}
3628 			case(MBS_Firing):
3629 			{
3630 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3631 					PrintDebuggingText("Guard marine firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3632 				}
3633 
3634 				if (marineIsNear) {
3635 					state_result=(*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
3636 					SetMarineElevation(sbPtr);
3637 				} else {
3638 					state_result=Execute_MFS_Firing(sbPtr);
3639 				}
3640 				GuardMission_SwitchState(sbPtr,state_result);
3641 				break;
3642 			}
3643 			case(MBS_PumpAction):
3644 			{
3645 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3646 					PrintDebuggingText("Guard marine pump action in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3647 				}
3648 
3649 				if (marineIsNear) {
3650 					state_result=Execute_MNS_PumpAction(sbPtr);
3651 					CentreMarineElevation(sbPtr);
3652 				} else {
3653 					state_result=Execute_MNS_PumpAction(sbPtr);
3654 				}
3655 				GuardMission_SwitchState(sbPtr,state_result);
3656 				break;
3657 			}
3658 			case(MBS_PanicFire):
3659 			{
3660 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3661 					PrintDebuggingText("Guard marine panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3662 				}
3663 
3664 				if (marineIsNear) {
3665 					state_result=(*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
3666 					CentreMarineElevation(sbPtr);
3667 				} else {
3668 					state_result=Execute_MFS_Firing(sbPtr);
3669 				}
3670 				GuardMission_SwitchState(sbPtr,state_result);
3671 				break;
3672 			}
3673 			case(MBS_Avoidance):
3674 			{
3675 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3676 					PrintDebuggingText("Guard marine ");
3677 					switch (marineStatusPointer->avoidanceManager.substate) {
3678 						default:
3679 						case AvSS_FreeMovement:
3680 							PrintDebuggingText("Avoidance Level 0");
3681 							break;
3682 						case AvSS_FirstAvoidance:
3683 							PrintDebuggingText("Avoidance Level 1");
3684 							break;
3685 						case AvSS_SecondAvoidance:
3686 							PrintDebuggingText("Avoidance Level 2");
3687 							break;
3688 						case AvSS_ThirdAvoidance:
3689 							PrintDebuggingText("Avoidance Level 3");
3690 							break;
3691 					}
3692 					PrintDebuggingText(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3693 				}
3694 
3695 				if (marineIsNear) {
3696 					state_result=Execute_MNS_Avoidance(sbPtr);
3697 					CentreMarineElevation(sbPtr);
3698 				} else {
3699 					state_result=Execute_MFS_Avoidance(sbPtr);
3700 				}
3701 				GuardMission_SwitchState(sbPtr,state_result);
3702 				break;
3703 			}
3704 			case(MBS_Wandering):
3705 			{
3706 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3707 					PrintDebuggingText("Guard marine wandering in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3708 				}
3709 
3710 				if (marineIsNear) {
3711 					state_result=Execute_MNS_Wander(sbPtr);
3712 					CentreMarineElevation(sbPtr);
3713 				} else {
3714 					state_result=Execute_MFS_Wait(sbPtr);
3715 				}
3716 				GuardMission_SwitchState(sbPtr,state_result);
3717 				break;
3718 			}
3719 			case(MBS_Retreating):
3720 			{
3721 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3722 					PrintDebuggingText("Guard marine retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3723 				}
3724 
3725 				/* Real men never retreat! */
3726 				if (marineIsNear) {
3727 					state_result=Execute_MNS_Retreat(sbPtr);
3728 					CentreMarineElevation(sbPtr);
3729 				} else {
3730 					state_result=Execute_MFS_Retreat(sbPtr);
3731 				}
3732 				GuardMission_SwitchState(sbPtr,state_result);
3733 				break;
3734 			}
3735 			case(MBS_Waiting):
3736 			{
3737 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3738 					PrintDebuggingText("Guard marine waiting in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3739 				}
3740 
3741 				if (marineIsNear) {
3742 					state_result=Execute_MNS_SentryMode(sbPtr);
3743 					CentreMarineElevation(sbPtr);
3744 				} else {
3745 					state_result=Execute_MFS_SentryMode(sbPtr);
3746 				}
3747 				state_result=SRC_Request_Wait; /* Go back to sentry. */
3748 				GuardMission_SwitchState(sbPtr,state_result);
3749 				break;
3750 			}
3751 			case(MBS_Responding):
3752 			case(MBS_Sentry):
3753 			{
3754 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3755 					PrintDebuggingText("Guard marine sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3756 				}
3757 
3758 				if (marineIsNear) {
3759 					state_result=Execute_MNS_SentryMode(sbPtr);
3760 					CentreMarineElevation(sbPtr);
3761 				} else {
3762 					state_result=Execute_MFS_SentryMode(sbPtr);
3763 				}
3764 				GuardMission_SwitchState(sbPtr,state_result);
3765 				break;
3766 			}
3767 			case(MBS_Dying):
3768 			{
3769 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3770 					PrintDebuggingText("Guard marine dying in %s\n",sbPtr->containingModule->name);
3771 				}
3772 
3773 				if (marineIsNear) {
3774 					Execute_Dying(sbPtr);
3775 				} else {
3776 					Execute_Dying(sbPtr);
3777 				}
3778 				break;
3779 			}
3780 			case(MBS_Taunting):
3781 			{
3782 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3783 					PrintDebuggingText("Guard marine taunt in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3784 				}
3785 
3786 				if(marineIsNear) {
3787 					state_result=Execute_MNS_Taunting(sbPtr);
3788 					CentreMarineElevation(sbPtr);
3789 				} else {
3790 					state_result=Execute_MNS_Taunting(sbPtr);
3791 				}
3792 				GuardMission_SwitchState(sbPtr,state_result);
3793 				break;
3794 			}
3795 			case(MBS_Reloading):
3796 			{
3797 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3798 					PrintDebuggingText("Guard marine reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3799 				}
3800 
3801 				if(marineIsNear) {
3802 					state_result=Execute_MNS_Reloading(sbPtr);
3803 					CentreMarineElevation(sbPtr);
3804 				} else {
3805 					state_result=Execute_MNS_Reloading(sbPtr);
3806 				}
3807 				GuardMission_SwitchState(sbPtr,state_result);
3808 				break;
3809 			}
3810 			case(MBS_PanicReloading):
3811 			{
3812 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3813 					PrintDebuggingText("Guard marine panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3814 				}
3815 
3816 				if(marineIsNear) {
3817 					state_result=Execute_MNS_PanicReloading(sbPtr);
3818 					CentreMarineElevation(sbPtr);
3819 				} else {
3820 					state_result=Execute_MNS_PanicReloading(sbPtr);
3821 				}
3822 				GuardMission_SwitchState(sbPtr,state_result);
3823 				break;
3824 			}
3825 			case(MBS_GetWeapon):
3826 			{
3827 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3828 					PrintDebuggingText("Guard marine get weapon in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3829 				}
3830 
3831 				if(marineIsNear) {
3832 					state_result=Execute_MNS_GetWeapon(sbPtr);
3833 					CentreMarineElevation(sbPtr);
3834 				} else {
3835 					state_result=Execute_MNS_GetWeapon(sbPtr);
3836 				}
3837 				GuardMission_SwitchState(sbPtr,state_result);
3838 				break;
3839 			}
3840 			case MBS_Returning:
3841 			case MBS_Pathfinding:
3842 			{
3843 				/* How the hell did you get here?!? */
3844 				Marine_Enter_Wander_State(sbPtr);
3845 				break;
3846 			}
3847 			case(MBS_AcidAvoidance):
3848 			{
3849 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3850 					PrintDebuggingText("Guard marine acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3851 				}
3852 
3853 				if (marineIsNear) {
3854 					state_result=Execute_MNS_AcidAvoidance(sbPtr);
3855 					CentreMarineElevation(sbPtr);
3856 				} else {
3857 					Marine_Enter_Wait_State(sbPtr);
3858 					break;
3859 				}
3860 				GuardMission_SwitchState(sbPtr,state_result);
3861 				break;
3862 			}
3863 			default:
3864 			{
3865 				LOGDXFMT(("Guard marine in unsupported state %d!\n",marineStatusPointer->behaviourState));
3866 				LOCALASSERT(1==0);
3867 			}
3868 		}
3869 	}
3870 
3871 	if (!marineIsNear) {
3872 
3873 		/* check here to see if marine is in a proximity door - if so, trigger it to open. */
3874 		{
3875 			MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
3876 
3877 			if(doorType == MDT_ProxDoor)
3878 				((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->SBdataptr)->marineTrigger = 1;
3879 		}
3880 
3881 		/* lastly, do a containment test: to make sure that we are inside a module. */
3882 		#if UseLocalAssert
3883 		{
3884 			VECTORCH localCoords;
3885 			MODULE *thisModule = sbPtr->containingModule;
3886 
3887 			LOCALASSERT(thisModule);
3888 
3889 			localCoords = sbPtr->DynPtr->Position;
3890 			localCoords.vx -= thisModule->m_world.vx;
3891 			localCoords.vy -= thisModule->m_world.vy;
3892 			localCoords.vz -= thisModule->m_world.vz;
3893 
3894 			if(PointIsInModule(thisModule, &localCoords)==0)
3895 			{
3896 				textprint("FAR MARINE MODULE CONTAINMENT FAILURE \n");
3897 				LOCALASSERT(1==0);
3898 			}
3899 		}
3900 		#endif
3901 	}
3902 
3903 }
3904 
LocalGuardMission_Control(STRATEGYBLOCK * sbPtr)3905 void LocalGuardMission_Control(STRATEGYBLOCK *sbPtr) {
3906 
3907 	MARINE_STATUS_BLOCK *marineStatusPointer;
3908 	STATE_RETURN_CONDITION state_result;
3909 	int marineIsNear;
3910 
3911 	LOCALASSERT(sbPtr);
3912 	LOCALASSERT(sbPtr->containingModule);
3913 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
3914     LOCALASSERT(marineStatusPointer);
3915 
3916 	/* Firstly, fix missionmodule. */
3917 
3918 	if (marineStatusPointer->missionmodule==NULL) {
3919 		marineStatusPointer->missionmodule=sbPtr->containingModule->m_aimodule;
3920 	}
3921 
3922 	if(sbPtr->SBdptr) {
3923 		marineIsNear=1;
3924 		LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)]);
3925 	} else {
3926 		marineIsNear=0;
3927 	}
3928 
3929 	{
3930 
3931 		switch(marineStatusPointer->behaviourState)
3932 		{
3933 			case(MBS_Approaching):
3934 			{
3935 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3936 					PrintDebuggingText("Local Guard marine approaching in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3937 				}
3938 
3939 				if (marineIsNear) {
3940 					state_result=Execute_MNS_Approach(sbPtr);
3941 					CentreMarineElevation(sbPtr);
3942 				} else {
3943 					state_result=Execute_MFS_Wander(sbPtr);
3944 				}
3945 				LocalGuardMission_SwitchState(sbPtr,state_result);
3946 				break;
3947 			}
3948 			case(MBS_Firing):
3949 			{
3950 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3951 					PrintDebuggingText("Local Guard marine firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3952 				}
3953 
3954 				if (marineIsNear) {
3955 					state_result=(*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
3956 					SetMarineElevation(sbPtr);
3957 				} else {
3958 					state_result=Execute_MFS_Firing(sbPtr);
3959 				}
3960 				LocalGuardMission_SwitchState(sbPtr,state_result);
3961 				break;
3962 			}
3963 			case(MBS_PumpAction):
3964 			{
3965 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3966 					PrintDebuggingText("Local Guard marine pump action in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3967 				}
3968 
3969 				if (marineIsNear) {
3970 					state_result=Execute_MNS_PumpAction(sbPtr);
3971 					CentreMarineElevation(sbPtr);
3972 				} else {
3973 					state_result=Execute_MNS_PumpAction(sbPtr);
3974 				}
3975 				LocalGuardMission_SwitchState(sbPtr,state_result);
3976 				break;
3977 			}
3978 			case(MBS_PanicFire):
3979 			{
3980 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3981 					PrintDebuggingText("Local Guard marine panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
3982 				}
3983 
3984 				if (marineIsNear) {
3985 					state_result=(*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
3986 					CentreMarineElevation(sbPtr);
3987 				} else {
3988 					state_result=Execute_MFS_Firing(sbPtr);
3989 				}
3990 				LocalGuardMission_SwitchState(sbPtr,state_result);
3991 				break;
3992 			}
3993 			case(MBS_Avoidance):
3994 			{
3995 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
3996 					PrintDebuggingText("Local Guard marine ");
3997 					switch (marineStatusPointer->avoidanceManager.substate) {
3998 						default:
3999 						case AvSS_FreeMovement:
4000 							PrintDebuggingText("Avoidance Level 0");
4001 							break;
4002 						case AvSS_FirstAvoidance:
4003 							PrintDebuggingText("Avoidance Level 1");
4004 							break;
4005 						case AvSS_SecondAvoidance:
4006 							PrintDebuggingText("Avoidance Level 2");
4007 							break;
4008 						case AvSS_ThirdAvoidance:
4009 							PrintDebuggingText("Avoidance Level 3");
4010 							break;
4011 					}
4012 					PrintDebuggingText(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4013 				}
4014 
4015 				if (marineIsNear) {
4016 					state_result=Execute_MNS_Avoidance(sbPtr);
4017 					CentreMarineElevation(sbPtr);
4018 				} else {
4019 					state_result=Execute_MFS_Avoidance(sbPtr);
4020 				}
4021 				LocalGuardMission_SwitchState(sbPtr,state_result);
4022 				break;
4023 			}
4024 			case(MBS_Wandering):
4025 			{
4026 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4027 					PrintDebuggingText("Local Guard marine wandering in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4028 				}
4029 
4030 				if (marineIsNear) {
4031 					state_result=Execute_MNS_Wander(sbPtr);
4032 					CentreMarineElevation(sbPtr);
4033 				} else {
4034 					state_result=Execute_MFS_Wait(sbPtr);
4035 				}
4036 				LocalGuardMission_SwitchState(sbPtr,state_result);
4037 				break;
4038 			}
4039 			case(MBS_Retreating):
4040 			{
4041 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4042 					PrintDebuggingText("Local Guard marine retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4043 				}
4044 
4045 				/* Real men never retreat! */
4046 				if (marineIsNear) {
4047 					state_result=Execute_MNS_Retreat(sbPtr);
4048 					CentreMarineElevation(sbPtr);
4049 				} else {
4050 					state_result=Execute_MFS_Retreat(sbPtr);
4051 				}
4052 				LocalGuardMission_SwitchState(sbPtr,state_result);
4053 				break;
4054 			}
4055 			case(MBS_Waiting):
4056 			{
4057 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4058 					PrintDebuggingText("Local Guard marine waiting in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4059 				}
4060 
4061 				if (marineIsNear) {
4062 					state_result=Execute_MNS_Wait(sbPtr);
4063 					CentreMarineElevation(sbPtr);
4064 				} else {
4065 					state_result=Execute_MFS_Wait(sbPtr);
4066 				}
4067 				LocalGuardMission_SwitchState(sbPtr,state_result);
4068 				break;
4069 			}
4070 			case(MBS_Responding):
4071 			{
4072 				/* Well, it *might* happen... */
4073 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4074 					PrintDebuggingText("Local Guard marine responding in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4075 				}
4076 
4077 				if (marineIsNear) {
4078 					state_result=Execute_MNS_Respond(sbPtr);
4079 					CentreMarineElevation(sbPtr);
4080 				} else {
4081 					state_result=Execute_MFS_Respond(sbPtr);
4082 				}
4083 				LocalGuardMission_SwitchState(sbPtr,state_result);
4084 				break;
4085 			}
4086 			case(MBS_Returning):
4087 			{
4088 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4089 					PrintDebuggingText("Local Guard marine returning in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4090 				}
4091 
4092 				if (marineIsNear) {
4093 					state_result=Execute_MNS_Return(sbPtr);
4094 					CentreMarineElevation(sbPtr);
4095 				} else {
4096 					state_result=Execute_MFS_Return(sbPtr);
4097 				}
4098 				LocalGuardMission_SwitchState(sbPtr,state_result);
4099 				break;
4100 			}
4101 			case(MBS_Sentry):
4102 			{
4103 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4104 					PrintDebuggingText("Local Guard marine sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4105 				}
4106 
4107 				if (marineIsNear) {
4108 					state_result=Execute_MNS_SentryMode(sbPtr);
4109 					CentreMarineElevation(sbPtr);
4110 				} else {
4111 					state_result=Execute_MFS_Wait(sbPtr);
4112 				}
4113 				LocalGuardMission_SwitchState(sbPtr,state_result);
4114 				break;
4115 			}
4116 			case(MBS_Taunting):
4117 			{
4118 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4119 					PrintDebuggingText("Local Guard marine taunt in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4120 				}
4121 
4122 				if(marineIsNear) {
4123 					state_result=Execute_MNS_Taunting(sbPtr);
4124 					CentreMarineElevation(sbPtr);
4125 				} else {
4126 					state_result=Execute_MNS_Taunting(sbPtr);
4127 				}
4128 				LocalGuardMission_SwitchState(sbPtr,state_result);
4129 				break;
4130 			}
4131 			case(MBS_Reloading):
4132 			{
4133 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4134 					PrintDebuggingText("Local Guard marine reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4135 				}
4136 
4137 				if(marineIsNear) {
4138 					state_result=Execute_MNS_Reloading(sbPtr);
4139 					CentreMarineElevation(sbPtr);
4140 				} else {
4141 					state_result=Execute_MNS_Reloading(sbPtr);
4142 				}
4143 				LocalGuardMission_SwitchState(sbPtr,state_result);
4144 				break;
4145 			}
4146 			case(MBS_PanicReloading):
4147 			{
4148 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4149 					PrintDebuggingText("Local Guard marine panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4150 				}
4151 
4152 				if(marineIsNear) {
4153 					state_result=Execute_MNS_PanicReloading(sbPtr);
4154 					CentreMarineElevation(sbPtr);
4155 				} else {
4156 					state_result=Execute_MNS_PanicReloading(sbPtr);
4157 				}
4158 				LocalGuardMission_SwitchState(sbPtr,state_result);
4159 				break;
4160 			}
4161 			case(MBS_Dying):
4162 			{
4163 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4164 					PrintDebuggingText("Local Guard marine dying in %s\n",sbPtr->containingModule->name);
4165 				}
4166 
4167 				if (marineIsNear) {
4168 					Execute_Dying(sbPtr);
4169 				} else {
4170 					Execute_Dying(sbPtr);
4171 				}
4172 				break;
4173 			}
4174 			case(MBS_GetWeapon):
4175 			{
4176 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4177 					PrintDebuggingText("Local Guard marine get weapon in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4178 				}
4179 
4180 				if(marineIsNear) {
4181 					state_result=Execute_MNS_GetWeapon(sbPtr);
4182 					CentreMarineElevation(sbPtr);
4183 				} else {
4184 					state_result=Execute_MNS_GetWeapon(sbPtr);
4185 				}
4186 				LocalGuardMission_SwitchState(sbPtr,state_result);
4187 				break;
4188 			}
4189 			case MBS_Pathfinding:
4190 			{
4191 				/* How the hell did you get here?!? */
4192 				Marine_Enter_Return_State(sbPtr);
4193 				break;
4194 			}
4195 			case(MBS_AcidAvoidance):
4196 			{
4197 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4198 					PrintDebuggingText("Local Guard marine acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4199 				}
4200 
4201 				if (marineIsNear) {
4202 					state_result=Execute_MNS_AcidAvoidance(sbPtr);
4203 					CentreMarineElevation(sbPtr);
4204 				} else {
4205 					Marine_Enter_Wait_State(sbPtr);
4206 					break;
4207 				}
4208 				LocalGuardMission_SwitchState(sbPtr,state_result);
4209 				break;
4210 			}
4211 			default:
4212 			{
4213 				LOGDXFMT(("Local Guard marine in unsupported state %d!\n",marineStatusPointer->behaviourState));
4214 				LOCALASSERT(1==0);
4215 			}
4216 		}
4217 	}
4218 
4219 	if (!marineIsNear) {
4220 
4221 		/* check here to see if marine is in a proximity door - if so, trigger it to open. */
4222 		{
4223 			MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
4224 
4225 			if(doorType == MDT_ProxDoor)
4226 				((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->SBdataptr)->marineTrigger = 1;
4227 		}
4228 
4229 		/* lastly, do a containment test: to make sure that we are inside a module. */
4230 		#if UseLocalAssert
4231 		{
4232 			VECTORCH localCoords;
4233 			MODULE *thisModule = sbPtr->containingModule;
4234 
4235 			LOCALASSERT(thisModule);
4236 
4237 			localCoords = sbPtr->DynPtr->Position;
4238 			localCoords.vx -= thisModule->m_world.vx;
4239 			localCoords.vy -= thisModule->m_world.vy;
4240 			localCoords.vz -= thisModule->m_world.vz;
4241 
4242 			if(PointIsInModule(thisModule, &localCoords)==0)
4243 			{
4244 				textprint("FAR MARINE MODULE CONTAINMENT FAILURE \n");
4245 				LOCALASSERT(1==0);
4246 			}
4247 		}
4248 		#endif
4249 	}
4250 
4251 }
4252 
LoiterMission_Control(STRATEGYBLOCK * sbPtr)4253 void LoiterMission_Control(STRATEGYBLOCK *sbPtr) {
4254 
4255 	MARINE_STATUS_BLOCK *marineStatusPointer;
4256 	STATE_RETURN_CONDITION state_result;
4257 	int marineIsNear;
4258 
4259 	LOCALASSERT(sbPtr);
4260 	LOCALASSERT(sbPtr->containingModule);
4261 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
4262     LOCALASSERT(marineStatusPointer);
4263 
4264 	/* Fleeing Behaviour. */
4265 
4266 	if(sbPtr->SBdptr) {
4267 		marineIsNear=1;
4268 		LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)]);
4269 	} else {
4270 		marineIsNear=0;
4271 	}
4272 
4273 	{
4274 
4275 		switch(marineStatusPointer->behaviourState)
4276 		{
4277 			case(MBS_Approaching):
4278 			{
4279 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4280 					PrintDebuggingText("Noncombatant approaching in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4281 				}
4282 
4283 				if (marineIsNear) {
4284 					state_result=Execute_MNS_Approach(sbPtr);
4285 					CentreMarineElevation(sbPtr);
4286 				} else {
4287 					state_result=Execute_MFS_Wait(sbPtr);
4288 				}
4289 				LoiterMission_SwitchState(sbPtr,state_result);
4290 				break;
4291 			}
4292 			case(MBS_Firing):
4293 			{
4294 
4295 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4296 					PrintDebuggingText("Noncombatant firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4297 				}
4298 
4299 				if (marineIsNear) {
4300 					GLOBALASSERT(0);
4301 					state_result=(*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
4302 					SetMarineElevation(sbPtr);
4303 				} else {
4304 					state_result=Execute_MFS_Firing(sbPtr);
4305 				}
4306 				LoiterMission_SwitchState(sbPtr,state_result);
4307 				break;
4308 			}
4309 			case(MBS_PumpAction):
4310 			{
4311 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4312 					PrintDebuggingText("Noncombatant marine pump action in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4313 				}
4314 
4315 				if (marineIsNear) {
4316 					state_result=Execute_MNS_PumpAction(sbPtr);
4317 					CentreMarineElevation(sbPtr);
4318 				} else {
4319 					state_result=Execute_MNS_PumpAction(sbPtr);
4320 				}
4321 				LoiterMission_SwitchState(sbPtr,state_result);
4322 				break;
4323 			}
4324 			case(MBS_PanicFire):
4325 			{
4326 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4327 					PrintDebuggingText("Noncombatant panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4328 				}
4329 
4330 				if (marineIsNear) {
4331 					state_result=(*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
4332 					CentreMarineElevation(sbPtr);
4333 				} else {
4334 					state_result=Execute_MFS_Firing(sbPtr);
4335 				}
4336 				LoiterMission_SwitchState(sbPtr,state_result);
4337 				break;
4338 			}
4339 			case(MBS_Avoidance):
4340 			{
4341 
4342 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4343 					PrintDebuggingText("Noncombatant ");
4344 					switch (marineStatusPointer->avoidanceManager.substate) {
4345 						default:
4346 						case AvSS_FreeMovement:
4347 							PrintDebuggingText("Avoidance Level 0");
4348 							break;
4349 						case AvSS_FirstAvoidance:
4350 							PrintDebuggingText("Avoidance Level 1");
4351 							break;
4352 						case AvSS_SecondAvoidance:
4353 							PrintDebuggingText("Avoidance Level 2");
4354 							break;
4355 						case AvSS_ThirdAvoidance:
4356 							PrintDebuggingText("Avoidance Level 3");
4357 							break;
4358 					}
4359 					PrintDebuggingText(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4360 				}
4361 
4362 				if (marineIsNear) {
4363 					state_result=Execute_MNS_Avoidance(sbPtr);
4364 					CentreMarineElevation(sbPtr);
4365 				} else {
4366 					state_result=Execute_MFS_Avoidance(sbPtr);
4367 				}
4368 				LoiterMission_SwitchState(sbPtr,state_result);
4369 				break;
4370 			}
4371 			case(MBS_Responding):
4372 			case(MBS_Wandering):
4373 			{
4374 
4375 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4376 					PrintDebuggingText("Noncombatant wandering in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4377 				}
4378 
4379 				if (marineIsNear) {
4380 					state_result=Execute_MNS_Wander(sbPtr);
4381 					CentreMarineElevation(sbPtr);
4382 				} else {
4383 					state_result=Execute_MFS_Wander(sbPtr);
4384 				}
4385 				LoiterMission_SwitchState(sbPtr,state_result);
4386 				break;
4387 			}
4388 			case(MBS_Retreating):
4389 			{
4390 
4391 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4392 					PrintDebuggingText("Noncombatant retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4393 				}
4394 
4395 				/* Wusses, now: they retreat. */
4396 				if (marineIsNear) {
4397 					state_result=Execute_MNS_Retreat(sbPtr);
4398 					CentreMarineElevation(sbPtr);
4399 				} else {
4400 					state_result=Execute_MFS_Retreat(sbPtr);
4401 				}
4402 				LoiterMission_SwitchState(sbPtr,state_result);
4403 				break;
4404 			}
4405 			case(MBS_Waiting):
4406 			{
4407 
4408 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4409 					PrintDebuggingText("Noncombatant waiting in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4410 				}
4411 
4412 				if (marineIsNear) {
4413 					state_result=Execute_MNS_Wait(sbPtr);
4414 					CentreMarineElevation(sbPtr);
4415 				} else {
4416 					state_result=Execute_MFS_Wait(sbPtr);
4417 				}
4418 				LoiterMission_SwitchState(sbPtr,state_result);
4419 				break;
4420 			}
4421 			case(MBS_Sentry):
4422 			{
4423 				GLOBALASSERT(0);
4424 
4425 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4426 					PrintDebuggingText("Noncombatant sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4427 				}
4428 
4429 				if (marineIsNear) {
4430 					state_result=Execute_MNS_SentryMode(sbPtr);
4431 					CentreMarineElevation(sbPtr);
4432 				} else {
4433 					state_result=Execute_MFS_Wait(sbPtr);
4434 				}
4435 				LoiterMission_SwitchState(sbPtr,state_result);
4436 				break;
4437 			}
4438 			case(MBS_Reloading):
4439 			{
4440 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4441 					PrintDebuggingText("Noncombatant reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4442 				}
4443 
4444 				if(marineIsNear) {
4445 					state_result=Execute_MNS_Reloading(sbPtr);
4446 					CentreMarineElevation(sbPtr);
4447 				} else {
4448 					state_result=Execute_MNS_Reloading(sbPtr);
4449 				}
4450 				LoiterMission_SwitchState(sbPtr,state_result);
4451 				break;
4452 			}
4453 			case(MBS_PanicReloading):
4454 			{
4455 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4456 					PrintDebuggingText("Noncombatant panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4457 				}
4458 
4459 				if(marineIsNear) {
4460 					state_result=Execute_MNS_PanicReloading(sbPtr);
4461 					CentreMarineElevation(sbPtr);
4462 				} else {
4463 					state_result=Execute_MNS_PanicReloading(sbPtr);
4464 				}
4465 				LoiterMission_SwitchState(sbPtr,state_result);
4466 				break;
4467 			}
4468 			case(MBS_Dying):
4469 			{
4470 
4471 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4472 					PrintDebuggingText("Noncombatant dying in %s\n",sbPtr->containingModule->name);
4473 				}
4474 
4475 				if (marineIsNear) {
4476 					Execute_Dying(sbPtr);
4477 				} else {
4478 					Execute_Dying(sbPtr);
4479 				}
4480 				break;
4481 			}
4482 			case MBS_Returning:
4483 			case MBS_Pathfinding:
4484 			{
4485 				/* How the hell did you get here?!? */
4486 				Marine_Enter_Wander_State(sbPtr);
4487 				break;
4488 			}
4489 			case(MBS_AcidAvoidance):
4490 			{
4491 				if ((ShowSquadState)||((marineIsNear)&&(ShowNearSquad))) {
4492 					PrintDebuggingText("Noncombatant acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
4493 				}
4494 
4495 				if (marineIsNear) {
4496 					state_result=Execute_MNS_AcidAvoidance(sbPtr);
4497 					CentreMarineElevation(sbPtr);
4498 				} else {
4499 					Marine_Enter_Wait_State(sbPtr);
4500 					break;
4501 				}
4502 				LoiterMission_SwitchState(sbPtr,state_result);
4503 				break;
4504 			}
4505 			default:
4506 			{
4507 				/* NonComs can't taunt. */
4508 				LOGDXFMT(("Marine in unsupported state %d!\n",marineStatusPointer->behaviourState));
4509 				LOCALASSERT(1==0);
4510 			}
4511 		}
4512 	}
4513 
4514 	if (!marineIsNear) {
4515 
4516 		/* check here to see if marine is in a proximity door - if so, trigger it to open. */
4517 		{
4518 			MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
4519 
4520 			if(doorType == MDT_ProxDoor)
4521 				((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->SBdataptr)->marineTrigger = 1;
4522 		}
4523 
4524 		/* lastly, do a containment test: to make sure that we are inside a module. */
4525 		#if UseLocalAssert
4526 		{
4527 			VECTORCH localCoords;
4528 			MODULE *thisModule = sbPtr->containingModule;
4529 
4530 			LOCALASSERT(thisModule);
4531 
4532 			localCoords = sbPtr->DynPtr->Position;
4533 			localCoords.vx -= thisModule->m_world.vx;
4534 			localCoords.vy -= thisModule->m_world.vy;
4535 			localCoords.vz -= thisModule->m_world.vz;
4536 
4537 			if(PointIsInModule(thisModule, &localCoords)==0)
4538 			{
4539 				textprint("FAR MARINE MODULE CONTAINMENT FAILURE \n");
4540 				LOCALASSERT(1==0);
4541 			}
4542 		}
4543 		#endif
4544 	}
4545 
4546 }
4547 
WanderMission_SwitchState(STRATEGYBLOCK * sbPtr,STATE_RETURN_CONDITION state_result)4548 void WanderMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result) {
4549 
4550 	STATE_RETURN_CONDITION real_state_result;
4551 	/* Experiment: override result? */
4552 	switch (state_result) {
4553 		case (SRC_Request_Fire):
4554 		case (SRC_Request_Approach):
4555 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
4556 				real_state_result=SRC_Request_Retreat;
4557 				EndMarineMuzzleFlash(sbPtr);
4558 			} else {
4559 				real_state_result=state_result;
4560 			}
4561 			break;
4562 		default:
4563 			real_state_result=state_result;
4564 			break;
4565 	}
4566 
4567 	switch (real_state_result) {
4568 		case (SRC_No_Change):
4569 		{
4570 			/* No action. */
4571 			break;
4572 		}
4573 		case (SRC_Request_Taunt):
4574 		{
4575 			Marine_Enter_Taunt_State(sbPtr);
4576 			break;
4577 		}
4578 		case (SRC_Request_Wait):
4579 		{
4580 			Marine_Enter_Wait_State(sbPtr);
4581 			break;
4582 		}
4583 		case (SRC_Request_Fire):
4584 		{
4585 			Marine_Enter_Firing_State(sbPtr);
4586 			break;
4587 		}
4588 		case (SRC_Request_PanicFire):
4589 		{
4590 			Marine_Enter_PanicFire_State(sbPtr);
4591 			break;
4592 		}
4593 		case (SRC_Request_Avoidance):
4594 		{
4595 			Marine_Enter_Avoidance_State(sbPtr);
4596 			break;
4597 		}
4598 		case (SRC_Request_Approach):
4599 		{
4600 			Marine_Enter_Approach_State(sbPtr);
4601 			break;
4602 		}
4603 		case (SRC_Request_Wander):
4604 		{
4605 			Marine_Enter_Wander_State(sbPtr);
4606 			break;
4607 		}
4608 		case (SRC_Request_Retreat):
4609 		{
4610 			Marine_Enter_Retreat_State(sbPtr);
4611 			break;
4612 		}
4613 		case (SRC_Request_Respond):
4614 		{
4615 			Marine_Enter_Respond_State(sbPtr);
4616 			break;
4617 		}
4618 		case (SRC_Request_Reload):
4619 		{
4620 			Marine_Enter_Reload_State(sbPtr);
4621 			break;
4622 		}
4623 		case (SRC_Request_PanicReload):
4624 		{
4625 			Marine_Enter_PanicReload_State(sbPtr);
4626 			break;
4627 		}
4628 		case (SRC_Request_PumpAction):
4629 		{
4630 			Marine_Enter_PumpAction_State(sbPtr);
4631 			break;
4632 		}
4633 		case (SRC_Request_PullPistol):
4634 		{
4635 			Marine_Enter_PullPistol_State(sbPtr);
4636 			break;
4637 		}
4638 		default:
4639 		{
4640 			/* How did we end up here? */
4641 			GLOBALASSERT(0);
4642 			break;
4643 		}
4644 
4645 }
4646 
4647 }
4648 
PathfinderMission_SwitchState(STRATEGYBLOCK * sbPtr,STATE_RETURN_CONDITION state_result)4649 void PathfinderMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result) {
4650 
4651 	STATE_RETURN_CONDITION real_state_result;
4652 	/* Experiment: override result? */
4653 	switch (state_result) {
4654 		case (SRC_Request_Fire):
4655 		case (SRC_Request_Approach):
4656 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
4657 				real_state_result=SRC_Request_Retreat;
4658 				EndMarineMuzzleFlash(sbPtr);
4659 			} else {
4660 				real_state_result=state_result;
4661 			}
4662 			break;
4663 		default:
4664 			real_state_result=state_result;
4665 			break;
4666 	}
4667 
4668 	switch (real_state_result) {
4669 		case (SRC_No_Change):
4670 		{
4671 			/* No action. */
4672 			break;
4673 		}
4674 		case (SRC_Request_Taunt):
4675 		{
4676 			Marine_Enter_Taunt_State(sbPtr);
4677 			break;
4678 		}
4679 		case (SRC_Request_Wait):
4680 		{
4681 			Marine_Enter_Pathfinder_State(sbPtr);
4682 			break;
4683 		}
4684 		case (SRC_Request_Fire):
4685 		{
4686 			Marine_Enter_Firing_State(sbPtr);
4687 			break;
4688 		}
4689 		case (SRC_Request_PanicFire):
4690 		{
4691 			Marine_Enter_PanicFire_State(sbPtr);
4692 			break;
4693 		}
4694 		case (SRC_Request_Avoidance):
4695 		{
4696 			Marine_Enter_Avoidance_State(sbPtr);
4697 			break;
4698 		}
4699 		case (SRC_Request_Approach):
4700 		{
4701 			Marine_Enter_Approach_State(sbPtr);
4702 			break;
4703 		}
4704 		case (SRC_Request_Wander):
4705 		{
4706 			Marine_Enter_Wander_State(sbPtr);
4707 			break;
4708 		}
4709 		case (SRC_Request_Retreat):
4710 		{
4711 			Marine_Enter_Retreat_State(sbPtr);
4712 			break;
4713 		}
4714 		case (SRC_Request_Respond):
4715 		{
4716 			Marine_Enter_Respond_State(sbPtr);
4717 			break;
4718 		}
4719 		case (SRC_Request_Return):
4720 		{
4721 			Marine_Enter_Return_State(sbPtr);
4722 			break;
4723 		}
4724 		case (SRC_Request_Reload):
4725 		{
4726 			Marine_Enter_Reload_State(sbPtr);
4727 			break;
4728 		}
4729 		case (SRC_Request_PanicReload):
4730 		{
4731 			Marine_Enter_PanicReload_State(sbPtr);
4732 			break;
4733 		}
4734 		case (SRC_Request_PumpAction):
4735 		{
4736 			Marine_Enter_PumpAction_State(sbPtr);
4737 			break;
4738 		}
4739 		case (SRC_Request_PullPistol):
4740 		{
4741 			Marine_Enter_PullPistol_State(sbPtr);
4742 			break;
4743 		}
4744 		default:
4745 		{
4746 			/* How did we end up here? */
4747 			GLOBALASSERT(0);
4748 			break;
4749 		}
4750 
4751 }
4752 
4753 }
4754 
GuardMission_SwitchState(STRATEGYBLOCK * sbPtr,STATE_RETURN_CONDITION state_result)4755 void GuardMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result) {
4756 
4757 	STATE_RETURN_CONDITION real_state_result;
4758 	MARINE_STATUS_BLOCK *marineStatusPointer;
4759 
4760 	LOCALASSERT(sbPtr);
4761 	LOCALASSERT(sbPtr->containingModule);
4762 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
4763     LOCALASSERT(marineStatusPointer);
4764 
4765 	/* Experiment: override result? */
4766 	switch (state_result) {
4767 		case (SRC_Request_Fire):
4768 		case (SRC_Request_Approach):
4769 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
4770 				real_state_result=SRC_Request_PanicFire;
4771 				EndMarineMuzzleFlash(sbPtr);
4772 			} else {
4773 				real_state_result=state_result;
4774 			}
4775 			break;
4776 		default:
4777 			real_state_result=state_result;
4778 			break;
4779 	}
4780 
4781 	switch (real_state_result) {
4782 		case (SRC_No_Change):
4783 		{
4784 			/* No action. */
4785 			break;
4786 		}
4787 		case (SRC_Request_Taunt):
4788 		{
4789 			Marine_Enter_Taunt_State(sbPtr);
4790 			break;
4791 		}
4792 		case (SRC_Request_Wait):
4793 		{
4794 			Marine_Enter_SentryMode_State(sbPtr);
4795 			break;
4796 		}
4797 		case (SRC_Request_Fire):
4798 		{
4799 			Marine_Enter_Firing_State(sbPtr);
4800 			break;
4801 		}
4802 		case (SRC_Request_PanicFire):
4803 		{
4804 			Marine_Enter_PanicFire_State(sbPtr);
4805 			break;
4806 		}
4807 		case (SRC_Request_Avoidance):
4808 		{
4809 			Marine_Enter_SentryMode_State(sbPtr);
4810 			break;
4811 		}
4812 		case (SRC_Request_Approach):
4813 		{
4814 			Marine_Enter_SentryMode_State(sbPtr);
4815 			break;
4816 		}
4817 		case (SRC_Request_Wander):
4818 		{
4819 			Marine_Enter_SentryMode_State(sbPtr);
4820 			break;
4821 		}
4822 		case (SRC_Request_Retreat):
4823 		{
4824 			Marine_Enter_Retreat_State(sbPtr);
4825 			break;
4826 		}
4827 		case (SRC_Request_Reload):
4828 		{
4829 			Marine_Enter_Reload_State(sbPtr);
4830 			break;
4831 		}
4832 		case (SRC_Request_PanicReload):
4833 		{
4834 			Marine_Enter_PanicReload_State(sbPtr);
4835 			break;
4836 		}
4837 		case (SRC_Request_PumpAction):
4838 		{
4839 			Marine_Enter_PumpAction_State(sbPtr);
4840 			break;
4841 		}
4842 		case (SRC_Request_PullPistol):
4843 		{
4844 			Marine_Enter_PullPistol_State(sbPtr);
4845 			break;
4846 		}
4847 		default:
4848 		{
4849 			/* How did we end up here? */
4850 			GLOBALASSERT(0);
4851 			break;
4852 		}
4853 
4854 }
4855 
4856 }
4857 
LocalGuardMission_SwitchState(STRATEGYBLOCK * sbPtr,STATE_RETURN_CONDITION state_result)4858 void LocalGuardMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result) {
4859 
4860 	STATE_RETURN_CONDITION real_state_result;
4861 	MARINE_STATUS_BLOCK *marineStatusPointer;
4862 
4863 	LOCALASSERT(sbPtr);
4864 	LOCALASSERT(sbPtr->containingModule);
4865 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
4866     LOCALASSERT(marineStatusPointer);
4867 
4868 	/* Experiment: override result? */
4869 	switch (state_result) {
4870 		case (SRC_Request_Fire):
4871 		case (SRC_Request_Approach):
4872 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
4873 				real_state_result=SRC_Request_Retreat;
4874 				EndMarineMuzzleFlash(sbPtr);
4875 			} else {
4876 				real_state_result=state_result;
4877 			}
4878 			break;
4879 		default:
4880 			real_state_result=state_result;
4881 			break;
4882 	}
4883 
4884 	switch (real_state_result) {
4885 		case (SRC_No_Change):
4886 		{
4887 			/* No action. */
4888 			break;
4889 		}
4890 		case (SRC_Request_Taunt):
4891 		{
4892 			Marine_Enter_Taunt_State(sbPtr);
4893 			break;
4894 		}
4895 		case (SRC_Request_Wait):
4896 		{
4897 			if (marineStatusPointer->missionmodule==sbPtr->containingModule->m_aimodule) {
4898 				Marine_Enter_Wait_State(sbPtr);
4899 			} else {
4900 				Marine_Enter_Return_State(sbPtr);
4901 			}
4902 			break;
4903 		}
4904 		case (SRC_Request_Fire):
4905 		{
4906 			Marine_Enter_Firing_State(sbPtr);
4907 			break;
4908 		}
4909 		case (SRC_Request_PanicFire):
4910 		{
4911 			Marine_Enter_PanicFire_State(sbPtr);
4912 			break;
4913 		}
4914 		case (SRC_Request_Avoidance):
4915 		{
4916 			Marine_Enter_Avoidance_State(sbPtr);
4917 			break;
4918 		}
4919 		case (SRC_Request_Approach):
4920 		{
4921 			Marine_Enter_Approach_State(sbPtr);
4922 			break;
4923 		}
4924 		case (SRC_Request_Wander):
4925 		{
4926 			Marine_Enter_Wander_State(sbPtr);
4927 			break;
4928 		}
4929 		case (SRC_Request_Retreat):
4930 		{
4931 			Marine_Enter_Retreat_State(sbPtr);
4932 			break;
4933 		}
4934 		case (SRC_Request_Return):
4935 		{
4936 			Marine_Enter_Return_State(sbPtr);
4937 			break;
4938 		}
4939 		case (SRC_Request_Reload):
4940 		{
4941 			Marine_Enter_Reload_State(sbPtr);
4942 			break;
4943 		}
4944 		case (SRC_Request_PanicReload):
4945 		{
4946 			Marine_Enter_PanicReload_State(sbPtr);
4947 			break;
4948 		}
4949 		case (SRC_Request_PumpAction):
4950 		{
4951 			Marine_Enter_PumpAction_State(sbPtr);
4952 			break;
4953 		}
4954 		case (SRC_Request_PullPistol):
4955 		{
4956 			Marine_Enter_PullPistol_State(sbPtr);
4957 			break;
4958 		}
4959 		default:
4960 		{
4961 			/* How did we end up here? */
4962 			GLOBALASSERT(0);
4963 			break;
4964 		}
4965 
4966 }
4967 
4968 }
4969 
LoiterMission_SwitchState(STRATEGYBLOCK * sbPtr,STATE_RETURN_CONDITION state_result)4970 void LoiterMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result) {
4971 
4972 	STATE_RETURN_CONDITION real_state_result;
4973 
4974 	MARINE_STATUS_BLOCK *marineStatusPointer;
4975 
4976 	LOCALASSERT(sbPtr);
4977 	LOCALASSERT(sbPtr->containingModule);
4978 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
4979     LOCALASSERT(marineStatusPointer);
4980 
4981 	/* Experiment: override result? */
4982 	switch (state_result) {
4983 		case (SRC_Request_Fire):
4984 		case (SRC_Request_Approach):
4985 			if ((MarineRetreatsInTheFaceOfDanger(sbPtr))&&(marineStatusPointer->Target)) {
4986 				real_state_result=SRC_Request_Retreat;
4987 				EndMarineMuzzleFlash(sbPtr);
4988 			} else {
4989 				real_state_result=state_result;
4990 			}
4991 			break;
4992 		default:
4993 			real_state_result=state_result;
4994 			break;
4995 	}
4996 
4997 	switch (real_state_result) {
4998 		case (SRC_No_Change):
4999 		{
5000 			/* No action. */
5001 			break;
5002 		}
5003 		case (SRC_Request_Taunt):
5004 		{
5005 			Marine_Enter_Taunt_State(sbPtr);
5006 			break;
5007 		}
5008 		case (SRC_Request_Wait):
5009 		{
5010 			Marine_Enter_Wait_State(sbPtr);
5011 			break;
5012 		}
5013 		case (SRC_Request_Fire):
5014 		case (SRC_Request_Reload):
5015 		case (SRC_Request_PanicReload):
5016 		case (SRC_Request_PumpAction):
5017 		{
5018 			Marine_Enter_Retreat_State(sbPtr);
5019 			break;
5020 		}
5021 		case (SRC_Request_Avoidance):
5022 		{
5023 			Marine_Enter_Avoidance_State(sbPtr);
5024 			break;
5025 		}
5026 		case (SRC_Request_Approach):
5027 		{
5028 			if (marineStatusPointer->Target) {
5029 				/* Approach?  You must be mad! */
5030 				Marine_Enter_Retreat_State(sbPtr);
5031 			} else {
5032 				/* We must be just suspicious. */
5033 				Marine_Enter_Approach_State(sbPtr);
5034 			}
5035 			break;
5036 		}
5037 		case (SRC_Request_Retreat):
5038 		{
5039 			Marine_Enter_Retreat_State(sbPtr);
5040 			break;
5041 		}
5042 		case (SRC_Request_Wander):
5043 		{
5044 			Marine_Enter_Wander_State(sbPtr);
5045 			break;
5046 		}
5047 		case (SRC_Request_PanicFire):
5048 		{
5049 			Marine_Enter_PanicFire_State(sbPtr);
5050 			break;
5051 		}
5052 		default:
5053 		{
5054 			/* How did we end up here? */
5055 			GLOBALASSERT(0);
5056 			break;
5057 		}
5058 
5059 }
5060 
5061 }
5062 
MakeMarineNear(STRATEGYBLOCK * sbPtr)5063 void MakeMarineNear(STRATEGYBLOCK *sbPtr)
5064 {
5065 	extern MODULEMAPBLOCK AlienDefaultMap;
5066 
5067 	MODULE tempModule;
5068 	DISPLAYBLOCK *dPtr;
5069 	DYNAMICSBLOCK *dynPtr;
5070 	MARINE_STATUS_BLOCK *marineStatusPointer;
5071 
5072 	LOCALASSERT(sbPtr);
5073 	LOCALASSERT(sbPtr->SBdptr == NULL);
5074 	dynPtr = sbPtr->DynPtr;
5075 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5076     LOCALASSERT(marineStatusPointer);
5077     LOCALASSERT(dynPtr);
5078 
5079 	/* first of all, see how many marines are currently near: if there are too many,
5080 	destroy this one, and try to force a generator to make a replacement */
5081 	if(sbPtr->I_SBtype==I_BehaviourMarine)
5082 	{
5083 		if(NumGeneratorNPCsVisible() >= MAX_VISIBLEGENERATORNPCS)
5084 		{
5085 			DestroyAnyStrategyBlock(sbPtr);
5086 			ForceAGenerator();
5087 		}
5088 	}
5089 
5090 	AlienDefaultMap.MapShape = sbPtr->shapeIndex;
5091 	tempModule.m_mapptr = &AlienDefaultMap;
5092 	tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
5093 	tempModule.m_numlights = 0;
5094 	tempModule.m_lightarray = (struct lightblock *)0;
5095 	tempModule.m_extraitemdata = (struct extraitemdata *)0;
5096 	tempModule.m_dptr = NULL;
5097 	AllocateModuleObject(&tempModule);
5098 	dPtr = tempModule.m_dptr;
5099 	if(dPtr==NULL) return; /* cannot allocate displayblock, so leave far */
5100 
5101 	sbPtr->SBdptr = dPtr;
5102 	dPtr->ObStrategyBlock = sbPtr;
5103 	dPtr->ObMyModule = NULL;
5104 
5105 	/* need to initialise positional information in the new display block */
5106 	dPtr->ObWorld = dynPtr->Position;
5107 	dPtr->ObEuler = dynPtr->OrientEuler;
5108 	dPtr->ObMat = dynPtr->OrientMat;
5109 
5110 	/* marine data block init */
5111 	marineStatusPointer->weaponTarget.vx = marineStatusPointer->weaponTarget.vy = marineStatusPointer->weaponTarget.vz = 0;
5112 
5113 	/* zero linear velocity in dynamics block */
5114 	sbPtr->DynPtr->LinVelocity.vx = 0;
5115 	sbPtr->DynPtr->LinVelocity.vy = 0;
5116 	sbPtr->DynPtr->LinVelocity.vz = 0;
5117 
5118 	/* state and sequence initialisation */
5119 	//dPtr->ShapeAnimControlBlock = &marineStatusPointer->ShpAnimCtrl;
5120 
5121 	dPtr->HModelControlBlock=&marineStatusPointer->HModelController;
5122 
5123 	/* Just in case. */
5124 	CentreMarineElevation(sbPtr);
5125 	InitWaypointManager(&marineStatusPointer->waypointManager);
5126 
5127 	ProveHModel(dPtr->HModelControlBlock,dPtr);
5128 
5129 	if(MarineShouldBeCrawling(sbPtr)) marineStatusPointer->IAmCrouched = 1;
5130 	else marineStatusPointer->IAmCrouched = 0;
5131 
5132 	if (marineStatusPointer->behaviourState==MBS_Firing) {
5133 		Marine_Enter_Firing_State(sbPtr);
5134 		/* To avoid negative volleys */
5135 	}
5136 
5137 	/*Copy extents from the collision extents in extents.c*/
5138 	dPtr->ObMinX=-CollisionExtents[CE_MARINE].CollisionRadius;
5139 	dPtr->ObMaxX=CollisionExtents[CE_MARINE].CollisionRadius;
5140 	dPtr->ObMinZ=-CollisionExtents[CE_MARINE].CollisionRadius;
5141 	dPtr->ObMaxZ=CollisionExtents[CE_MARINE].CollisionRadius;
5142 	dPtr->ObMinY=CollisionExtents[CE_MARINE].CrouchingTop;
5143 	dPtr->ObMaxY=CollisionExtents[CE_MARINE].Bottom;
5144 	dPtr->ObRadius = 1000;
5145 
5146 	marineStatusPointer->gotapoint=0;
5147 
5148 	/* Once they become near, Wait_Then_Hunt marines become Wander marines. */
5149 
5150 	if (marineStatusPointer->Mission==MM_Wait_Then_Wander) {
5151 		marineStatusPointer->Mission=MM_Wander;
5152 	}
5153 
5154 	/* And force pathfinders to get a new module? */
5155 	if (marineStatusPointer->Mission==MM_Pathfinder) {
5156 		if (marineStatusPointer->behaviourState==MBS_Pathfinding) {
5157 			marineStatusPointer->wanderData.currentModule=NPC_NOWANDERMODULE;
5158 		}
5159 	}
5160 
5161 	marineStatusPointer->lastframe_fallingspeed=-1;
5162 }
5163 
MakeMarineFar(STRATEGYBLOCK * sbPtr)5164 void MakeMarineFar(STRATEGYBLOCK *sbPtr)
5165 {
5166 	MARINE_STATUS_BLOCK *marineStatusPointer;
5167 	int i;
5168 
5169 	LOCALASSERT(sbPtr);
5170 	LOCALASSERT(sbPtr->SBdptr != NULL);
5171 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5172 	LOCALASSERT(marineStatusPointer);
5173 
5174 	/* get rid of the displayblock */
5175 	i = DestroyActiveObject(sbPtr->SBdptr);
5176 	LOCALASSERT(i==0);
5177 	sbPtr->SBdptr = NULL;
5178 
5179 	marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
5180 
5181 	/* zero linear velocity in dynamics block */
5182 	sbPtr->DynPtr->LinVelocity.vx = 0;
5183 	sbPtr->DynPtr->LinVelocity.vy = 0;
5184 	sbPtr->DynPtr->LinVelocity.vz = 0;
5185 
5186 	/* if we have a gun flash, get rid of it */
5187 	if(marineStatusPointer->myGunFlash)
5188 	{
5189 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
5190 		marineStatusPointer->myGunFlash = NULL;
5191 	}
5192 	/* stop sound, if we have one */
5193 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Stop(marineStatusPointer->soundHandle);
5194 	if(marineStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) Sound_Stop(marineStatusPointer->soundHandle2);
5195 
5196 	/* set the correct state(s) or remove, if we're dying */
5197 	if(marineStatusPointer->behaviourState == MBS_Dying)
5198 	{
5199 	   /* if we're dying, we can be removed at this point */
5200 	   DestroyAnyStrategyBlock(sbPtr);
5201 	   return;
5202 	}
5203 
5204 }
5205 
KillMarine(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiple,int wounds,SECTION_DATA * Section,VECTORCH * incoming)5206 void KillMarine(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,SECTION_DATA *Section,VECTORCH *incoming) {
5207 
5208 	int deathtype,gibbFactor;
5209 	int a;
5210 	STRATEGYBLOCK *candidate;
5211 
5212 	MARINE_STATUS_BLOCK *marineStatusPointer;
5213 	SECTION_DATA *head;
5214 
5215 	LOCALASSERT(sbPtr);
5216 	LOCALASSERT(sbPtr->containingModule);
5217 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5218 	LOCALASSERT(marineStatusPointer);
5219 
5220 	/* Morale. */
5221 	if (marineStatusPointer->My_Weapon->ARealMarine) {
5222 		/* Only marine deaths get 'spotted' everywhere, by the APC guy! */
5223 		NpcSquad.Nextframe_Squad_Delta_Morale-=10000;
5224 		/* So, warn the squad? */
5225 		ZoneAlert(3,sbPtr->containingModule->m_aimodule);
5226 	}
5227 
5228 	Marine_MuteVoice(sbPtr);
5229 
5230 	/*notify death target ,if marine has one*/
5231 	if(marineStatusPointer->death_target_sbptr)
5232 	{
5233 		RequestState(marineStatusPointer->death_target_sbptr,marineStatusPointer->death_target_request, 0);
5234 	}
5235 
5236 	/* get rid of the gun flash, if we've got it */
5237 	if(marineStatusPointer->myGunFlash)
5238 	{
5239 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
5240 		marineStatusPointer->myGunFlash = NULL;
5241 	}
5242 
5243 	/* stop sound, if we have one, and it's not the fire */
5244 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
5245 		if (ActiveSounds[marineStatusPointer->soundHandle].soundIndex!=SID_FIRE) {
5246 			Sound_Stop(marineStatusPointer->soundHandle);
5247 		}
5248 	}
5249 
5250 	/* Set GibbFactor */
5251 	gibbFactor=0;
5252 	{
5253 		int tkd;
5254 
5255 		tkd=TotalKineticDamage(damage);
5256 		deathtype=0;
5257 
5258 		if (damage->ExplosivePower==1) {
5259 			if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1)))>20) {
5260 				/* Okay, you can gibb now. */
5261 				marineStatusPointer->GibbFactor=ONE_FIXED>>1;
5262 				marineStatusPointer->mtracker_timer=-1;
5263 				deathtype=2;
5264 			}
5265 		} else if ((tkd>60)&&((multiple>>16)>1)) {
5266 			int newmult;
5267 
5268 			newmult=DIV_FIXED(multiple,NormalFrameTime);
5269 			if (MUL_FIXED(tkd,newmult)>(500)) {
5270 				/* Loadsabullets! */
5271 				marineStatusPointer->GibbFactor=-(ONE_FIXED>>2);
5272 				marineStatusPointer->mtracker_timer=-1;
5273 				deathtype=2;
5274 			}
5275 		}
5276 
5277 		if ((damage->ExplosivePower==2)||(damage->ExplosivePower==6)) {
5278 			/* Basically SADARS only. */
5279 			marineStatusPointer->GibbFactor=ONE_FIXED;
5280 			marineStatusPointer->mtracker_timer=-1;
5281 			deathtype=3;
5282 		}
5283 	}
5284 	gibbFactor=marineStatusPointer->GibbFactor;
5285 
5286 	if (damage->ForceBoom) {
5287 		deathtype+=damage->ForceBoom;
5288 	}
5289 
5290 	{
5291 		SECTION_DATA *chest;
5292 
5293 		chest=GetThisSectionData(marineStatusPointer->HModelController.section_data,"chest");
5294 
5295 		if (chest==NULL) {
5296 			/* I'm impressed. */
5297 			deathtype+=2;
5298 		} else if ((chest->flags&section_data_notreal)
5299 			&&(chest->flags&section_data_terminate_here)) {
5300 			/* That's gotta hurt. */
5301 			deathtype++;
5302 		}
5303 	}
5304 
5305 	/* make a sound... if you have a head. */
5306 	head=GetThisSectionData(marineStatusPointer->HModelController.section_data,"head");
5307 
5308 	/* Is it still attached? */
5309 	if (head) {
5310 		if (head->flags&section_data_notreal) {
5311 			head=NULL;
5312 		}
5313 	}
5314 
5315 	if (marineStatusPointer->GibbFactor) {
5316 		/* Probably want to make some sort of splatting noise... */
5317 	} else if (head) {
5318 		if (marineStatusPointer->Expression!=3) {
5319 			/* Expression 3 just looks too peaceful. */
5320 			if (marineStatusPointer->Mission==MM_RunAroundOnFire) {
5321 				/* More burning screams. */
5322 				Marine_BurningDeathScream(sbPtr);
5323 			} else if ((damage->Impact==0)
5324 				&&(damage->Cutting==0)
5325 				&&(damage->Penetrative==0)
5326 				&&(damage->Fire==0)
5327 				&&(damage->Electrical>0)
5328 				&&(damage->Acid==0)
5329 				) {
5330 				Marine_ElectrocutionScream(sbPtr);
5331 			} else if ((Section)&&(damage->Id==AMMO_PRED_RIFLE)) {
5332 				/* Hit in the chest or pelvis by a speargun? */
5333 				if( (strcmp(Section->sempai->Section_Name,"pelvis")==0)
5334 					||(strcmp(Section->sempai->Section_Name,"pelvis presley")==0)
5335 					||(strcmp(Section->sempai->Section_Name,"chest")==0) ){
5336 					Marine_OoophSound(sbPtr);
5337 				} else {
5338 					Marine_DeathScream(sbPtr);
5339 				}
5340 			} else {
5341 				Marine_DeathScream(sbPtr);
5342 			}
5343 		}
5344 	}
5345 
5346 	/* Now final stage. */
5347 	{
5348 		DEATH_DATA *this_death;
5349 		HIT_FACING facing;
5350 		SECTION *root;
5351 		int burning,electrical;
5352 
5353 		root=GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,marineStatusPointer->My_Weapon->TemplateName);
5354 
5355 		facing.Front=0;
5356 		facing.Back=0;
5357 		facing.Left=0;
5358 		facing.Right=0;
5359 
5360 		if (incoming) {
5361 			if (incoming->vz>0) {
5362 				facing.Back=1;
5363 			} else {
5364 				facing.Front=1;
5365 			}
5366 			if (incoming->vx>0) {
5367 				facing.Right=1;
5368 			} else {
5369 				facing.Left=1;
5370 			}
5371 		}
5372 
5373 		if ((marineStatusPointer->Mission==MM_RunAroundOnFire)
5374 			&&(damage->Impact==0)
5375 			&&(damage->Cutting==0)
5376 			&&(damage->Penetrative==0)
5377 			&&(damage->Fire>0)
5378 			&&(damage->Electrical==0)
5379 			&&(damage->Acid==0)
5380 			) {
5381 			burning=1;
5382 		} else {
5383 			burning=0;
5384 		}
5385 
5386 		if ((damage->Impact==0)
5387 			&&(damage->Cutting==0)
5388 			&&(damage->Penetrative==0)
5389 			&&(damage->Fire==0)
5390 			&&(damage->Electrical>0)
5391 			&&(damage->Acid==0)
5392 			) {
5393 			electrical=1;
5394 		} else {
5395 			electrical=0;
5396 		}
5397 
5398 		this_death=GetMarineDeathSequence(&marineStatusPointer->HModelController,root,marineStatusPointer->Wounds,marineStatusPointer->Wounds,
5399 			deathtype,&facing,burning,marineStatusPointer->IAmCrouched,electrical);
5400 
5401 		GLOBALASSERT(this_death);
5402 
5403 		Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Elevation");
5404 		Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
5405 		Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
5406 		Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
5407 
5408 		Convert_Marine_To_Corpse(sbPtr,this_death);
5409 	}
5410 
5411 	/* See if anyone saw that? */
5412 	for (a=0; a<NumActiveStBlocks; a++) {
5413 		candidate=ActiveStBlockList[a];
5414 		GLOBALASSERT(candidate);
5415 
5416 		if (candidate->I_SBtype==I_BehaviourMarine) {
5417 			/* Are you already suspicious? */
5418 			marineStatusPointer = (MARINE_STATUS_BLOCK *)(candidate->SBdataptr);
5419 
5420 			/* Did you see that? */
5421 			if (NPCCanSeeTarget(candidate,sbPtr,MARINE_NEAR_VIEW_WIDTH)) {
5422 
5423 				if (marineStatusPointer->Android==0) {
5424 					if (gibbFactor) {
5425 						marineStatusPointer->Courage-=20000;
5426 					} else if (head==NULL) {
5427 						marineStatusPointer->Courage-=15000;
5428 					} else {
5429 						marineStatusPointer->Courage-=10000;
5430 					}
5431 				}
5432 
5433 				if ((marineStatusPointer->suspicious==0)||(marineStatusPointer->using_squad_suspicion)) {
5434 					/* Okay, react. */
5435 					marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
5436 					marineStatusPointer->suspect_point=sbPtr->DynPtr->Position;
5437 					/* Set this to zero when you get a *new* suspicion. */
5438 					marineStatusPointer->previous_suspicion=0;
5439 					marineStatusPointer->using_squad_suspicion=0;
5440 				}
5441 			}
5442 		}
5443 	}
5444 }
5445 
MarineIsDamaged(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiple,int wounds,SECTION_DATA * Section,VECTORCH * incoming)5446 void MarineIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,SECTION_DATA *Section,VECTORCH *incoming)
5447 {
5448 
5449 	MARINE_STATUS_BLOCK *marineStatusPointer;
5450 
5451 	LOCALASSERT(sbPtr);
5452 	LOCALASSERT(sbPtr->containingModule);
5453 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5454 	LOCALASSERT(marineStatusPointer);
5455 
5456 	/* if we're dying, do nothing */
5457 	if(marineStatusPointer->behaviourState==MBS_Dying)
5458 	{
5459 		/* MFS should be dying, too */
5460 		return;
5461 	}
5462 
5463 	if(!(sbPtr->SBdptr))
5464 	{
5465 		DestroyAnyStrategyBlock(sbPtr);
5466 		return;
5467 	}
5468 
5469 	marineStatusPointer->Wounds|=wounds;
5470 
5471 	if (sbPtr->SBDamageBlock.Health > 0) {
5472 
5473 		if (marineStatusPointer->Mission==MM_RunAroundOnFire) {
5474 			Marine_BurningScream(sbPtr);
5475 		} else if ((damage->Impact==0)
5476 			&&(damage->Cutting==0)
5477 			&&(damage->Penetrative==0)
5478 			&&(damage->Fire==0)
5479 			&&(damage->Electrical==0)
5480 			&&(damage->Acid>0)
5481 			) {
5482 			Marine_AcidScream(sbPtr);
5483 			if ((marineStatusPointer->behaviourState!=MBS_AcidAvoidance)
5484 				&&(marineStatusPointer->behaviourState!=MBS_Firing)
5485 				&&(marineStatusPointer->behaviourState!=MBS_Avoidance)
5486 				&&(marineStatusPointer->behaviourState!=MBS_Dying)
5487 				&&(marineStatusPointer->behaviourState!=MBS_PanicFire)
5488 				&&(marineStatusPointer->behaviourState!=MBS_Reloading)
5489 				&&(marineStatusPointer->behaviourState!=MBS_PumpAction)
5490 				&&(marineStatusPointer->behaviourState!=MBS_GetWeapon)
5491 				&&(marineStatusPointer->behaviourState!=MBS_PanicReloading))
5492 			{
5493 				Marine_Activate_AcidAvoidance_State(sbPtr,incoming);
5494 			}
5495 		} else {
5496 			Marine_WoundedScream(sbPtr);
5497 		}
5498 		/* Open the mouth? */
5499 		Marine_AssumePanicExpression(sbPtr);
5500 	}
5501 
5502 	/* Might want to get a new target? */
5503 
5504 	marineStatusPointer->Target=NULL;
5505 
5506 	if (marineStatusPointer->Android) {
5507 		/* Kill non-functional androids. */
5508 		if ((marineStatusPointer->Wounds&section_flag_left_hand)
5509 			&&(marineStatusPointer->Wounds&section_flag_right_hand)) {
5510 			sbPtr->SBDamageBlock.Health=0;
5511 		}
5512 	}
5513 
5514 	/* reduce marine health */
5515 	if(sbPtr->SBDamageBlock.Health <= 0) {
5516 		/* marine experiences death */
5517 		int dice=FastRandom()&65535;
5518 		#if 0
5519 		if ((dice<16384)||(marineStatusPointer->Android)) {
5520 		#else
5521 		if (marineStatusPointer->Android) {
5522 		#endif
5523 			Marine_SwitchExpression(sbPtr,3);
5524 		} else if (dice<32768) {
5525 			Marine_SwitchExpression(sbPtr,5);
5526 		} else {
5527 			Marine_SwitchExpression(sbPtr,4);
5528 		}
5529 		if (AvP.PlayerType!=I_Marine) {
5530 			CurrentGameStats_CreatureKilled(sbPtr,Section);
5531 		}
5532 		KillMarine(sbPtr,damage,multiple,wounds,Section,incoming);
5533 	} else {
5534 		/* If not dead, play a hit delta. */
5535 		DELTA_CONTROLLER *hitdelta;
5536 		int frontback;
5537 
5538 		hitdelta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
5539 
5540 		if (incoming) {
5541 			if (incoming->vz>=0) {
5542 				frontback=0;
5543 			} else {
5544 				frontback=1;
5545 			}
5546 		} else {
5547 			/* Default to front. */
5548 			frontback=1;
5549 		}
5550 
5551 		if (hitdelta) {
5552 			/* A hierarchy with hit deltas! */
5553 			int CrouchSubSequence;
5554 			int StandSubSequence;
5555 
5556 			if (Section==NULL) {
5557 				if (frontback==0) {
5558 					CrouchSubSequence=MCrSS_HitChestBack;
5559 					StandSubSequence=MSSS_HitChestBack;
5560 				} else {
5561 					CrouchSubSequence=MCrSS_HitChestFront;
5562 					StandSubSequence=MSSS_HitChestFront;
5563 				}
5564 			} else if (Section->sempai->flags&section_flag_head) {
5565 				if (frontback==0) {
5566 					CrouchSubSequence=MCrSS_HitHeadBack;
5567 					StandSubSequence=MSSS_HitHeadBack;
5568 				} else {
5569 					CrouchSubSequence=MCrSS_HitHeadFront;
5570 					StandSubSequence=MSSS_HitHeadFront;
5571 				}
5572 			} else if ((Section->sempai->flags&section_flag_left_arm)
5573 				||(Section->sempai->flags&section_flag_left_hand)) {
5574 				if (frontback==0) {
5575 					CrouchSubSequence=MCrSS_HitRightArm;
5576 					StandSubSequence=MSSS_HitRightArm;
5577 				} else {
5578 					CrouchSubSequence=MCrSS_HitLeftArm;
5579 					StandSubSequence=MSSS_HitLeftArm;
5580 				}
5581 			} else if ((Section->sempai->flags&section_flag_right_arm)
5582 				||(Section->sempai->flags&section_flag_right_hand)) {
5583 				if (frontback==0) {
5584 					CrouchSubSequence=MCrSS_HitLeftArm;
5585 					StandSubSequence=MSSS_HitLeftArm;
5586 				} else {
5587 					CrouchSubSequence=MCrSS_HitRightArm;
5588 					StandSubSequence=MSSS_HitRightArm;
5589 				}
5590 			} else if ((Section->sempai->flags&section_flag_left_leg)
5591 				||(Section->sempai->flags&section_flag_left_foot)) {
5592 				if (frontback==0) {
5593 					CrouchSubSequence=MCrSS_HitRightLeg;
5594 					StandSubSequence=MSSS_HitRightLeg;
5595 				} else {
5596 					CrouchSubSequence=MCrSS_HitLeftLeg;
5597 					StandSubSequence=MSSS_HitLeftLeg;
5598 				}
5599 			} else if ((Section->sempai->flags&section_flag_right_leg)
5600 				||(Section->sempai->flags&section_flag_right_foot)) {
5601 				if (frontback==0) {
5602 					CrouchSubSequence=MCrSS_HitLeftLeg;
5603 					StandSubSequence=MSSS_HitLeftLeg;
5604 				} else {
5605 					CrouchSubSequence=MCrSS_HitRightLeg;
5606 					StandSubSequence=MSSS_HitRightLeg;
5607 				}
5608 			} else {
5609 				/* Chest or misc. hit. */
5610 				if (frontback==0) {
5611 					CrouchSubSequence=MCrSS_HitChestBack;
5612 					StandSubSequence=MSSS_HitChestBack;
5613 				} else {
5614 					CrouchSubSequence=MCrSS_HitChestFront;
5615 					StandSubSequence=MSSS_HitChestFront;
5616 				}
5617 			}
5618 
5619 
5620 			if(marineStatusPointer->IAmCrouched) {
5621 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineCrouch,CrouchSubSequence)) {
5622 					Start_Delta_Sequence(hitdelta,(int)HMSQT_MarineCrouch,CrouchSubSequence,-1); /* Was (ONE_FIXED>>2) */
5623 				}
5624 			} else {
5625 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,StandSubSequence)) {
5626 					Start_Delta_Sequence(hitdelta,(int)HMSQT_MarineStand,StandSubSequence,-1); /* Was (ONE_FIXED>>2) */
5627 				}
5628 			}
5629 			hitdelta->Playing=1;
5630 			/* Not looped. */
5631 
5632 		}
5633 
5634 		/* Finally, warn the squad. */
5635 		ZoneAlert(3,sbPtr->containingModule->m_aimodule);
5636 		/* And become suspicious. */
5637 		marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
5638 		/* Set this to zero when you get a *new* suspicion. */
5639 		marineStatusPointer->previous_suspicion=0;
5640 		marineStatusPointer->using_squad_suspicion=0;
5641 		if (incoming) {
5642 			marineStatusPointer->suspect_point=*incoming;
5643 			/* Flip it round! */
5644 			marineStatusPointer->suspect_point.vx=-marineStatusPointer->suspect_point.vx;
5645 			marineStatusPointer->suspect_point.vy=-marineStatusPointer->suspect_point.vy;
5646 			marineStatusPointer->suspect_point.vz=-marineStatusPointer->suspect_point.vz;
5647 			Normalise(&marineStatusPointer->suspect_point);
5648 			marineStatusPointer->suspect_point.vx>>=5;
5649 			marineStatusPointer->suspect_point.vy>>=5;
5650 			marineStatusPointer->suspect_point.vz>>=5;
5651 		} else {
5652 			marineStatusPointer->suspect_point.vx=0;
5653 			marineStatusPointer->suspect_point.vy=0;
5654 			marineStatusPointer->suspect_point.vz=-2000;
5655 		}
5656 		RotateVector(&marineStatusPointer->suspect_point,&sbPtr->DynPtr->OrientMat);
5657 
5658 		marineStatusPointer->suspect_point.vx+=sbPtr->DynPtr->Position.vx;
5659 		marineStatusPointer->suspect_point.vy+=sbPtr->DynPtr->Position.vy;
5660 		marineStatusPointer->suspect_point.vz+=sbPtr->DynPtr->Position.vz;
5661 
5662 		/* Switch wounded androids into an appropriate state. */
5663 		if (marineStatusPointer->Android) {
5664 			if (marineStatusPointer->Wounds&section_flag_left_hand) {
5665 				if (marineStatusPointer->My_Weapon->id!=MNPCW_AndroidSpecial) {
5666 					Marine_Enter_OneArmShotgun_State(sbPtr);
5667 				}
5668 			} else if (marineStatusPointer->Wounds&section_flag_right_hand) {
5669 				if (marineStatusPointer->My_Weapon->id!=MNPCW_Android_Pistol_Special) {
5670 					Marine_Enter_OneArmPistol_State(sbPtr);
5671 				}
5672 			}
5673 
5674 		}
5675 
5676 	}
5677 
5678 }
5679 
5680 
5681 
5682 /*------------------------Patrick 24/2/97-----------------------------
5683   Marine far state behaviour functions
5684   --------------------------------------------------------------------*/
5685 
5686 static STATE_RETURN_CONDITION Execute_MFS_Firing(STRATEGYBLOCK *sbPtr)
5687 {
5688 
5689 	MARINE_STATUS_BLOCK *marineStatusPointer;
5690 
5691 	LOCALASSERT(sbPtr);
5692 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5693     LOCALASSERT(marineStatusPointer);
5694 
5695 	/* I can't deal with this right now.  Better wait instead. */
5696 
5697 	/* Remove the gunflash */
5698 	if(marineStatusPointer->myGunFlash)
5699 	{
5700 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
5701 		marineStatusPointer->myGunFlash = NULL;
5702 	}
5703 	/* .... and stop the sound */
5704 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
5705 		Sound_Stop(marineStatusPointer->soundHandle);
5706 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
5707 	}
5708 
5709 	return(SRC_Request_Wait);
5710 
5711 }
5712 
5713 static STATE_RETURN_CONDITION Execute_MFS_Avoidance(STRATEGYBLOCK *sbPtr) {
5714 
5715 	MARINE_STATUS_BLOCK *marineStatusPointer;
5716 
5717 	LOCALASSERT(sbPtr);
5718 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5719     LOCALASSERT(marineStatusPointer);
5720 
5721 	/* High on the list of Things Not To Be Doing. */
5722 
5723 	#if ALL_NEW_AVOIDANCE
5724 	Initialise_AvoidanceManager(sbPtr,&marineStatusPointer->avoidanceManager);
5725 	#endif
5726 
5727 	switch (marineStatusPointer->lastState) {
5728 		case MBS_Retreating:
5729 			return(SRC_Request_Retreat);
5730 			break;
5731 		case MBS_Returning:
5732 			return(SRC_Request_Return);
5733 			break;
5734 		case MBS_Responding:
5735 			return(SRC_Request_Respond);
5736 			break;
5737 		case MBS_Approaching:
5738 			/* Go directly to approach.  Do not pass GO.  Do not collect 200 zorkmids. */
5739 			return(SRC_Request_Approach);
5740 			break;
5741 		default:
5742 			return(SRC_Request_Wander);
5743 			break;
5744 	}
5745 	/* Still here? */
5746 	return(SRC_Request_Wander);
5747 
5748 }
5749 
5750 static STATE_RETURN_CONDITION Execute_MFS_Wait(STRATEGYBLOCK *sbPtr)
5751 {
5752 
5753 	MARINE_STATUS_BLOCK *marineStatusPointer;
5754 	AIMODULE *targetModule=0;
5755 
5756 	LOCALASSERT(sbPtr);
5757 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5758     LOCALASSERT(marineStatusPointer);
5759 
5760 	if (marineStatusPointer->suspicious) {
5761 		int correctlyOrientated;
5762 		VECTORCH orientationDirn;
5763 
5764 		orientationDirn.vx =  marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
5765 		orientationDirn.vy = 0;
5766 		orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
5767 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
5768 		marineStatusPointer->gotapoint=0;
5769 	}
5770 
5771 	/* Might want to spin on the spot. */
5772 	if (marineStatusPointer->gotapoint==1) {
5773 
5774 		VECTORCH orientationDirn;
5775 		int correctlyOrientated;
5776 
5777 		orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
5778 		orientationDirn.vy = 0;
5779 		orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
5780 
5781 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,ONE_FIXED,NULL);
5782 
5783 		if (correctlyOrientated) {
5784 			marineStatusPointer->gotapoint=2;
5785 			/* Done. */
5786 		}
5787 
5788 	} else if (marineStatusPointer->gotapoint==0) {
5789 		GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
5790 	}
5791 
5792 
5793 	/* See if you're allowed to respond. */
5794 
5795 	if (
5796 		(marineStatusPointer->Mission==MM_Wait_Then_Wander)
5797 		||(marineStatusPointer->Mission==MM_Guard)
5798 		) {
5799 		return(SRC_No_Change);
5800 	}
5801 
5802 	/* Possible response?  LocalGuarders are allowed to wander. */
5803 
5804 	if ((NpcSquad.alertZone)&&(marineStatusPointer->Mission!=MM_LocalGuard)
5805 		&&(marineStatusPointer->Mission!=MM_NonCom)) {
5806 		if (sbPtr->containingModule->m_aimodule!=NpcSquad.alertZone) {
5807 			if (NpcSquad.responseLevel>0) {
5808 				/* Picked up a target.  Can we move to respond? */
5809 				targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
5810 				if (targetModule) {
5811 					NpcSquad.responseLevel--;
5812 					return(SRC_Request_Respond);
5813 				}
5814 			}
5815 		}
5816 	}
5817 
5818 	/* Decrement the Far state timer */
5819 	marineStatusPointer->stateTimer -= NormalFrameTime;
5820 	/* check if far state timer has timed-out. If so, it is time
5821 	to do something. Otherwise just return. */
5822 	if(marineStatusPointer->stateTimer > 0) return(SRC_No_Change);
5823 
5824 	/* Might want to wander. */
5825 
5826 	if ((FastRandom()&65535)<2048)
5827 	{
5828 		/* we should be wandering... we're bored of waiting. */
5829 		return(SRC_Request_Wander);
5830 	}
5831 
5832 	/* reset timer */
5833 	marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
5834 	return(SRC_No_Change);
5835 
5836 }
5837 
5838 static STATE_RETURN_CONDITION Execute_MFS_SentryMode(STRATEGYBLOCK *sbPtr)
5839 {
5840 	MARINE_STATUS_BLOCK *marineStatusPointer;
5841 	AIMODULE *targetModule = 0;
5842 
5843 	LOCALASSERT(sbPtr);
5844 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5845     LOCALASSERT(marineStatusPointer);
5846 
5847 	/* Okay, so you're a Sentry who's been pushed off his spot. */
5848 
5849 	if ((sbPtr->containingModule->m_aimodule==marineStatusPointer->missionmodule)
5850 		||(marineStatusPointer->missionmodule==NULL)) {
5851 
5852 		if (marineStatusPointer->missionmodule!=NULL) {
5853 			int dist;
5854 			VECTORCH offset;
5855 			/* Relocate? */
5856 
5857 			offset.vx=sbPtr->DynPtr->Position.vx-marineStatusPointer->my_spot.vx;
5858 			offset.vy=sbPtr->DynPtr->Position.vy-marineStatusPointer->my_spot.vy;
5859 			offset.vz=sbPtr->DynPtr->Position.vz-marineStatusPointer->my_spot.vz;
5860 			/* Fix for midair start points, grrrr. */
5861 			offset.vy>>=2;
5862 
5863 			dist=Approximate3dMagnitude(&offset);
5864 
5865 			if (dist>SENTRY_SENSITIVITY) {
5866 				sbPtr->DynPtr->Position=marineStatusPointer->my_spot;
5867 				sbPtr->containingModule = (ModuleFromPosition(&(sbPtr->DynPtr->Position), sbPtr->containingModule));
5868 
5869 			}
5870 		}
5871 
5872 		if (marineStatusPointer->suspicious) {
5873 			int correctlyOrientated;
5874 			VECTORCH orientationDirn;
5875 
5876 			orientationDirn.vx = marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
5877 			orientationDirn.vy = 0;
5878 			orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
5879 			correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
5880 			marineStatusPointer->gotapoint=0;
5881 		}
5882 
5883 		/* Might want to spin on the spot. */
5884 		if (marineStatusPointer->gotapoint==1) {
5885 
5886 			VECTORCH orientationDirn;
5887 			int correctlyOrientated;
5888 
5889 			orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
5890 			orientationDirn.vy = 0;
5891 			orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
5892 
5893 			correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,ONE_FIXED,NULL);
5894 
5895 			if (correctlyOrientated) {
5896 				marineStatusPointer->gotapoint=2;
5897 				/* Done. */
5898 			}
5899 
5900 		} else if (marineStatusPointer->gotapoint==0) {
5901 			GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
5902 		}
5903 
5904 	} else {
5905 
5906 		/* Decrement the Far state timer */
5907 		marineStatusPointer->stateTimer -= NormalFrameTime;
5908 		/* check if far state timer has timed-out. If so, it is time
5909 		to do something. Otherwise just return. */
5910 		if(marineStatusPointer->stateTimer > 0) return(SRC_No_Change);
5911 
5912 		/* Never engage, and ignore alerts. */
5913 
5914 		if (sbPtr->containingModule->m_aimodule==marineStatusPointer->missionmodule) {
5915 			/* Same state next frame. */
5916 			return(SRC_No_Change);
5917 		}
5918 
5919 		/* get the target module... */
5920 
5921 		targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->missionmodule,7,0);
5922 
5923 		/* If there is no target module, we're way out there.  Better wander a bit more. */
5924 		if(!targetModule)
5925 		{
5926 			targetModule = FarNPC_GetTargetAIModuleForWander(sbPtr,marineStatusPointer->lastmodule,0);
5927 		}
5928 		/* Examine target, and decide what to do */
5929 		GLOBALASSERT(AIModuleIsPhysical(targetModule));
5930 		ProcessFarMarineTargetModule(sbPtr, targetModule);
5931 		/* reset timer */
5932 		marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
5933 	}
5934 	return(SRC_No_Change);
5935 }
5936 #if 0
5937 static STATE_RETURN_CONDITION Execute_MFS_Hunt(STRATEGYBLOCK *sbPtr)
5938 {
5939 	MARINE_STATUS_BLOCK *marineStatusPointer;
5940 	AIMODULE *targetModule = 0;
5941 
5942 	LOCALASSERT(sbPtr);
5943 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5944     LOCALASSERT(marineStatusPointer);
5945 
5946 	/* Decrement the Far state timer */
5947 	marineStatusPointer->stateTimer -= NormalFrameTime;
5948 	/* check if far state timer has timed-out. If so, it is time
5949 	to do something. Otherwise just return. */
5950 	if(marineStatusPointer->stateTimer > 0) return(SRC_No_Change);
5951 
5952 	/* check for state changes */
5953 
5954 	if ((!MarineIsAwareOfTarget(sbPtr))
5955 		||(marineStatusPointer->Target!=Player->ObStrategyBlock))
5956 	{
5957 		/* we should be wandering... can't hunt other NPCs */
5958 		return(SRC_Request_Wander);
5959 	}
5960 
5961 	/* get the target module... */
5962 	targetModule = FarNPC_GetTargetAIModuleForHunt(sbPtr,0);
5963 
5964 	/* if there is no target module, it means that the pred is trapped in an
5965 	unlinked module. In this case, reset the timer and return. */
5966 	if(!targetModule)
5967 	{
5968 		marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
5969 		return(SRC_Request_Wait);
5970 	}
5971 	/* Examine target, and decide what to do */
5972 	GLOBALASSERT(AIModuleIsPhysical(targetModule));
5973 	ProcessFarMarineTargetModule(sbPtr, targetModule);
5974 	/* reset timer */
5975 	marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
5976 	return(SRC_No_Change);
5977 }
5978 #endif
5979 
5980 static STATE_RETURN_CONDITION Execute_MFS_Approach(STRATEGYBLOCK *sbPtr) {
5981 
5982 	MARINE_STATUS_BLOCK *marineStatusPointer;
5983 	AIMODULE *targetModule = 0;
5984 	MODULE *tcm;
5985 
5986 	LOCALASSERT(sbPtr);
5987 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
5988     LOCALASSERT(marineStatusPointer);
5989 
5990 	if (!MarineIsAwareOfTarget(sbPtr))
5991 	{
5992 		/* we should be wandering... can't hunt other NPCs */
5993 		return(SRC_Request_Wander);
5994 	}
5995 
5996 	/* See if we can fire? */
5997 
5998 	if (marineStatusPointer->Target) {
5999 		if (marineStatusPointer->Target->containingModule) {
6000 			if (IsModuleVisibleFromModule(marineStatusPointer->Target->containingModule,sbPtr->containingModule)) {
6001 				/* Take the shot? */
6002 				return(SRC_Request_Fire);
6003 			}
6004 		}
6005 	}
6006 
6007 	/* Can't fire.  We want to get closer, then. */
6008 
6009 	if (marineStatusPointer->Target->containingModule) {
6010 		tcm=marineStatusPointer->Target->containingModule;
6011 	} else {
6012 		tcm=ModuleFromPosition(&marineStatusPointer->Target->DynPtr->Position,sbPtr->containingModule);
6013 	}
6014 
6015 	if (tcm) {
6016 		targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,tcm->m_aimodule,7,0);
6017 	}
6018 
6019 	if (targetModule) {
6020 		/* We have somewhere to go. */
6021 		GLOBALASSERT(AIModuleIsPhysical(targetModule));
6022 		ProcessFarMarineTargetModule(sbPtr, targetModule);
6023 		/* reset timer */
6024 		marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
6025 		marineStatusPointer->destinationmodule=targetModule;
6026 		return(SRC_No_Change);
6027 	}
6028 
6029 	/* Can't do nothin.  Better wait, then.  Everything else will see to itself. */
6030 	if (marineStatusPointer->Mission==MM_Pathfinder) {
6031 		return(SRC_Request_Return);
6032 	} else {
6033 		return(SRC_Request_Wait);
6034 	}
6035 }
6036 
6037 
6038 static STATE_RETURN_CONDITION Execute_MFS_Respond(STRATEGYBLOCK *sbPtr)
6039 {
6040 	MARINE_STATUS_BLOCK *marineStatusPointer;
6041 	AIMODULE *targetModule = 0;
6042 
6043 	LOCALASSERT(sbPtr);
6044 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6045     LOCALASSERT(marineStatusPointer);
6046 
6047 	/* Decrement the Far state timer */
6048 	marineStatusPointer->stateTimer -= NormalFrameTime;
6049 
6050 	if (ShowSquadState) {
6051 		if (marineStatusPointer->destinationmodule==NULL) {
6052 			PrintDebuggingText("Target module is NULL\n");
6053 		} else {
6054 			PrintDebuggingText("Target module is %s\n",(*(marineStatusPointer->destinationmodule->m_module_ptrs))->name);
6055 		}
6056 	}
6057 
6058 	/* check if far state timer has timed-out. If so, it is time
6059 	to do something. Otherwise just return. */
6060 	if(marineStatusPointer->stateTimer > 0) {
6061 		return(SRC_No_Change);
6062 	}
6063 
6064 	/* check for state changes */
6065 
6066 	if (MarineIsAwareOfTarget(sbPtr)) {
6067 		/* Picked up a target. */
6068 		return(SRC_Request_Approach);
6069 	}
6070 
6071 	/* get the target module... */
6072 	targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
6073 
6074 	if (targetModule==sbPtr->containingModule->m_aimodule) {
6075 		/* We've arrived. */
6076 		DeprioritiseAlert(sbPtr->containingModule->m_aimodule);
6077 		/* Hey, if it's real, there'll be a new one soon enough. */
6078 		return(SRC_Request_Wait);
6079 	}
6080 
6081 	/* if there is no target module, it means that the pred is trapped in an
6082 	unlinked module. In this case, reset the timer and return. */
6083 	if(!targetModule)
6084 	{
6085 		/* We can't do it. */
6086 		return(SRC_Request_Wait);
6087 	}
6088 	/* Examine target, and decide what to do */
6089 	GLOBALASSERT(AIModuleIsPhysical(targetModule));
6090 	ProcessFarMarineTargetModule(sbPtr, targetModule);
6091 	/* reset timer */
6092 	marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
6093 	marineStatusPointer->destinationmodule=targetModule;
6094 	return(SRC_No_Change);
6095 
6096 }
6097 
6098 static STATE_RETURN_CONDITION Execute_MFS_Wander(STRATEGYBLOCK *sbPtr)
6099 {
6100 	MARINE_STATUS_BLOCK *marineStatusPointer;
6101 	AIMODULE *targetModule = 0;
6102 
6103 	LOCALASSERT(sbPtr);
6104 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6105     LOCALASSERT(marineStatusPointer);
6106 
6107 	/* Decrement the Far state timer */
6108 	marineStatusPointer->stateTimer -= NormalFrameTime;
6109 	/* check if far state timer has timed-out. If so, it is time
6110 	to do something. Otherwise just return. */
6111 	if(marineStatusPointer->stateTimer > 0) {
6112 		return(SRC_No_Change);
6113 	}
6114 
6115 	/* check for state changes */
6116 	if(MarineIsAwareOfTarget(sbPtr))
6117 	/* Hack! */
6118 	{
6119 		/* we should be hunting */
6120 		return(SRC_Request_Approach);
6121 	}
6122 
6123 	/* New alert? */
6124 	if ((NpcSquad.alertZone)&&(marineStatusPointer->Mission!=MM_LocalGuard)
6125 		&&(marineStatusPointer->Mission!=MM_NonCom)) {
6126 		if (sbPtr->containingModule->m_aimodule!=NpcSquad.alertZone) {
6127 			if (NpcSquad.responseLevel>0) {
6128 				/* Picked up a target.  Can we move to respond? */
6129 				targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
6130 				if (targetModule) {
6131 					NpcSquad.responseLevel--;
6132 					return(SRC_Request_Respond);
6133 				}
6134 			}
6135 		}
6136 	}
6137 
6138 	/* Bored of wandering?  How about we wait a while? */
6139 	if ((FastRandom()&65535)<2048)
6140 	{
6141 		/* we should be wandering... we're bored of waiting. */
6142 		return(SRC_Request_Wait);
6143 	}
6144 
6145 	/* get the target module... */
6146 	targetModule = FarNPC_GetTargetAIModuleForWander(sbPtr,marineStatusPointer->lastmodule,0);
6147 
6148 	/* if there is no target module, it means that the pred is trapped in an
6149 	unlinked module. In this case, reset the timer and return. */
6150 	if(!targetModule)
6151 	{
6152 		marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
6153 		return(SRC_No_Change);
6154 	}
6155 	/* Examine target, and decide what to do */
6156 	GLOBALASSERT(AIModuleIsPhysical(targetModule));
6157 	ProcessFarMarineTargetModule(sbPtr, targetModule);
6158 	/* reset timer */
6159 	marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
6160 	return(SRC_No_Change);
6161 }
6162 
6163 static STATE_RETURN_CONDITION Execute_MFS_Return(STRATEGYBLOCK *sbPtr)
6164 {
6165 	MARINE_STATUS_BLOCK *marineStatusPointer;
6166 	AIMODULE *targetModule = 0;
6167 
6168 	LOCALASSERT(sbPtr);
6169 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6170     LOCALASSERT(marineStatusPointer);
6171 
6172 	/* Okay, so you're a LocalGuard or Pathfinder who's gotten lost. */
6173 
6174 	/* Decrement the Far state timer */
6175 	marineStatusPointer->stateTimer -= NormalFrameTime;
6176 	/* check if far state timer has timed-out. If so, it is time
6177 	to do something. Otherwise just return. */
6178 	if(marineStatusPointer->stateTimer > 0) return(SRC_No_Change);
6179 
6180 	/* check for state changes */
6181 	if(MarineIsAwareOfTarget(sbPtr))
6182 	/* Hack! */
6183 	{
6184 		/* we should be engaging */
6185 		return(SRC_Request_Approach);
6186 	}
6187 
6188 	/* Ignore alerts? */
6189 	#if 0
6190 	if ((NpcSquad.alertZone)&&(marineStatusPointer->Mission!=MM_LocalGuard)
6191 		&&(marineStatusPointer->Mission!=MM_NonCom)) {
6192 		if (sbPtr->containingModule->m_aimodule!=NpcSquad.alertZone) {
6193 			if (NpcSquad.responseLevel>0) {
6194 				/* Picked up a target.  Can we move to respond? */
6195 				targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
6196 				if (targetModule) {
6197 					NpcSquad.responseLevel--;
6198 					return(SRC_Request_Respond);
6199 				}
6200 			}
6201 		}
6202 	}
6203 	#endif
6204 
6205 	/* Never break out of return unless your life is in danger! */
6206 
6207 	/* Or unless we're back. */
6208 
6209 	if (sbPtr->containingModule->m_aimodule==marineStatusPointer->missionmodule) {
6210 		return(SRC_Request_Wait);
6211 	}
6212 
6213 	/* get the target module... */
6214 
6215 	targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->missionmodule,7,0);
6216 
6217 	/* If there is no target module, we're way out there.  Better wander a bit more. */
6218 	if(!targetModule)
6219 	{
6220 		targetModule = FarNPC_GetTargetAIModuleForWander(sbPtr,marineStatusPointer->lastmodule,0);
6221 	}
6222 	/* Examine target, and decide what to do */
6223 	if (AIModuleIsPhysical(targetModule)==0) {
6224 		#if 0
6225 		/* No longer a straight assert: not it's breakpointable. */
6226 		GLOBALASSERT(0);
6227 		#else
6228 		/* We're probably fubared.  Change to Wander. */
6229 		if (marineStatusPointer->Mission!=MM_NonCom) {
6230 			/* Dunno what a NonCom is doing here, but Code Defensively! */
6231 			marineStatusPointer->Mission=MM_Wander;
6232 		}
6233 		return(SRC_Request_Wait);
6234 		#endif
6235 	}
6236 	ProcessFarMarineTargetModule(sbPtr, targetModule);
6237 	/* reset timer */
6238 	marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
6239 	return(SRC_No_Change);
6240 }
6241 
6242 static STATE_RETURN_CONDITION Execute_MFS_Pathfinder(STRATEGYBLOCK *sbPtr)
6243 {
6244 	MARINE_STATUS_BLOCK *marineStatusPointer;
6245 	AIMODULE *targetModule = 0;
6246 	int nextModuleIndex;
6247 
6248 	LOCALASSERT(sbPtr);
6249 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6250     LOCALASSERT(marineStatusPointer);
6251 
6252 	/* Okay, so you're a LocalGuard or Pathfinder who's gotten lost. */
6253 
6254 	/* Decrement the Far state timer */
6255 	marineStatusPointer->stateTimer -= NormalFrameTime;
6256 	/* check if far state timer has timed-out. If so, it is time
6257 	to do something. Otherwise just return. */
6258 	if(marineStatusPointer->stateTimer > 0) return(SRC_No_Change);
6259 
6260 	/* check for state changes */
6261 	if(MarineIsAwareOfTarget(sbPtr))
6262 	/* Hack! */
6263 	{
6264 		/* we should be engaging */
6265 		return(SRC_Request_Approach);
6266 	}
6267 
6268 	/* Ignore alerts. */
6269 
6270 	/* Never break out of pathfinder unless your life is in danger! */
6271 
6272 	/* Okay, so where are we exactly? */
6273 
6274 	if ((marineStatusPointer->stepnumber<0)||(marineStatusPointer->path<0)) {
6275 		/* Get OUT! */
6276 		return(SRC_Request_Wander);
6277 	}
6278 
6279 	targetModule = TranslatePathIndex(marineStatusPointer->stepnumber,marineStatusPointer->path);
6280 
6281 	if (targetModule==NULL) {
6282 		/* Oh, to heck with this.  Try to wander. */
6283 		return(SRC_Request_Wander);
6284 	}
6285 
6286 	/* Right, so there is a somewhere to get to. */
6287 
6288 	if (targetModule!=sbPtr->containingModule->m_aimodule) {
6289 		/* But we're nowhere near it.  Geeze... */
6290 		marineStatusPointer->missionmodule=targetModule;
6291 		return(SRC_Request_Return);
6292 	}
6293 
6294 	/* Okay, so now we need to know where to go now. */
6295 
6296 	nextModuleIndex=GetNextModuleInPath(marineStatusPointer->stepnumber,marineStatusPointer->path);
6297 	GLOBALASSERT(nextModuleIndex>=0);
6298 	/* If that fires, it's Richard's fault. */
6299 	targetModule=TranslatePathIndex(nextModuleIndex,marineStatusPointer->path);
6300 	GLOBALASSERT(targetModule);
6301 	/* Ditto. */
6302 	marineStatusPointer->stepnumber=nextModuleIndex;
6303 
6304 	/* Examine target, and decide what to do */
6305 	GLOBALASSERT(AIModuleIsPhysical(targetModule));
6306 	ProcessFarMarineTargetModule(sbPtr, targetModule);
6307 	/* reset timer */
6308 	marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
6309 	return(SRC_No_Change);
6310 }
6311 
6312 static STATE_RETURN_CONDITION Execute_MFS_Retreat(STRATEGYBLOCK *sbPtr)
6313 {
6314 	MARINE_STATUS_BLOCK *marineStatusPointer;
6315 	AIMODULE *targetModule = 0;
6316 	AIMODULE *old_fearmod;
6317 
6318 	LOCALASSERT(sbPtr);
6319 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6320     LOCALASSERT(marineStatusPointer);
6321 
6322 	/* Decrement the Far state timer */
6323 	marineStatusPointer->stateTimer -= (NormalFrameTime<<1);
6324 	/* Double speed, remember? */
6325 
6326 	/* check if far state timer has timed-out. If so, it is time
6327 	to do something. Otherwise just return. */
6328 	if(marineStatusPointer->stateTimer > 0) {
6329 		return(SRC_No_Change);
6330 	}
6331 
6332 	old_fearmod=marineStatusPointer->fearmodule;
6333 
6334 	/* From where am I running? */
6335 	if(MarineIsAwareOfTarget(sbPtr)) {
6336 		marineStatusPointer->fearmodule=marineStatusPointer->Target->containingModule->m_aimodule;
6337 	} else if (marineStatusPointer->fearmodule==NULL) {
6338 		marineStatusPointer->fearmodule=sbPtr->containingModule->m_aimodule;
6339 	}
6340 
6341 	if (marineStatusPointer->fearmodule!=old_fearmod) {
6342 		marineStatusPointer->destinationmodule = General_GetAIModuleForRetreat(sbPtr,marineStatusPointer->fearmodule,5);
6343 	}
6344 
6345 	targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->destinationmodule,6,0);
6346 
6347 	if(!targetModule)
6348 	{
6349 		/* We can't do it. */
6350 		return(SRC_Request_Wait);
6351 	}
6352 	/* Examine target, and decide what to do */
6353 	GLOBALASSERT(AIModuleIsPhysical(targetModule));
6354 	ProcessFarMarineTargetModule(sbPtr, targetModule);
6355 	/* reset timer */
6356 	marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
6357 	marineStatusPointer->destinationmodule=targetModule;
6358 	return(SRC_No_Change);
6359 
6360 }
6361 
6362 static void ProcessFarMarineTargetModule(STRATEGYBLOCK *sbPtr, AIMODULE* targetModule)
6363 {
6364 	NPC_TARGETMODULESTATUS targetStatus;
6365 	MARINE_STATUS_BLOCK *marineStatusPointer;
6366 
6367 	LOCALASSERT(sbPtr);
6368 	LOCALASSERT(targetModule);
6369 	LOCALASSERT(sbPtr->I_SBtype == I_BehaviourMarine);
6370 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6371 	LOCALASSERT(marineStatusPointer);
6372 
6373 	targetStatus = GetTargetAIModuleStatus(sbPtr, targetModule,0);
6374 	switch(targetStatus)
6375 	{
6376 		case(NPCTM_NoEntryPoint):
6377 		{
6378 			/* do nothing */
6379 			FarNpc_FlipAround(sbPtr);
6380 			break;
6381 		}
6382 		case(NPCTM_NormalRoom):
6383 		{
6384 			/* locate to target	*/
6385 			LocateFarNPCInAIModule(sbPtr, targetModule);
6386 			break;
6387 		}
6388 		case(NPCTM_AirDuct):
6389 		{
6390 			/* loacate to target */
6391 			LocateFarNPCInAIModule(sbPtr, targetModule);
6392 			break;
6393 		}
6394 		case(NPCTM_LiftTeleport):
6395 		{
6396 			/* do nothing */
6397 			FarNpc_FlipAround(sbPtr);
6398 			break;
6399 		}
6400 		case(NPCTM_ProxDoorOpen):
6401 		{
6402 			LocateFarNPCInAIModule(sbPtr, targetModule);
6403 			break;
6404 		}
6405 		case(NPCTM_ProxDoorNotOpen):
6406 		{
6407 			MODULE *renderModule;
6408 			renderModule=*(targetModule->m_module_ptrs);
6409 			/* trigger the door, and set timer to quick so we can catch the door when it's open */
6410 			((PROXDOOR_BEHAV_BLOCK *)renderModule->m_sbptr->SBdataptr)->marineTrigger = 1;
6411 			break;
6412 		}
6413 		case(NPCTM_LiftDoorOpen):
6414 		{
6415 			///* do nothing - can't use lifts	*/
6416 			//FarNpc_FlipAround(sbPtr);
6417 			/* What the hell!!! */
6418 			LocateFarNPCInAIModule(sbPtr, targetModule);
6419 			break;
6420 		}
6421 		case(NPCTM_LiftDoorNotOpen):
6422 		{
6423 		   	/*  do nothing - can't open lift doors */
6424 			FarNpc_FlipAround(sbPtr);
6425 		   	break;
6426 		}
6427 		case(NPCTM_SecurityDoorOpen):
6428 		{
6429 			/* locate to target, and move thro' quick as we can't retrigger	*/
6430 			LocateFarNPCInAIModule(sbPtr, targetModule);
6431 			break;
6432 		}
6433 		case(NPCTM_SecurityDoorNotOpen):
6434 		{
6435 			MODULE *renderModule;
6436 			renderModule=*(targetModule->m_module_ptrs);
6437 			/* do some door opening stuff here. Door should stay open for long enough
6438 			for us to catch it open next time */
6439 			RequestState((renderModule->m_sbptr),1,0);
6440 		   	break;
6441 		}
6442 		default:
6443 		{
6444 			LOCALASSERT(1==0);
6445 		}
6446 	}
6447 }
6448 
6449 
6450 /*------------------------Patrick 24/2/97-----------------------------
6451   Marine near state behaviour functions
6452   --------------------------------------------------------------------*/
6453 
6454 void Marine_Enter_SentryMode_State(STRATEGYBLOCK *sbPtr) {
6455 
6456 	MARINE_STATUS_BLOCK *marineStatusPointer;
6457 
6458 	LOCALASSERT(sbPtr);
6459 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6460 	LOCALASSERT(marineStatusPointer);
6461 
6462 	marineStatusPointer->gotapoint=0;
6463 
6464 	marineStatusPointer->volleySize = 0;
6465 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6466 	marineStatusPointer->behaviourState = MBS_Sentry;
6467 	marineStatusPointer->stateTimer = ONE_FIXED; /* Ignored anyway... */
6468 
6469 	Marine_QueueNeutralExpression(sbPtr);
6470 
6471 	#if 0
6472 	if(marineStatusPointer->IAmCrouched) {
6473 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrouch,MCSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6474 	} else {
6475 		if (marineStatusPointer->suspicious) {
6476 			if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_Wait_Alert)) {
6477 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Wait_Alert,(ONE_FIXED<<2),(ONE_FIXED>>3));
6478 			} else {
6479 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6480 			}
6481 		} else {
6482 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6483 		}
6484 	}
6485 	#else
6486 	HandleWaitingAnimations(sbPtr);
6487 	#endif
6488 
6489 	GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
6490 
6491 }
6492 
6493 void Marine_Enter_Wait_State(STRATEGYBLOCK *sbPtr) {
6494 
6495 	MARINE_STATUS_BLOCK *marineStatusPointer;
6496 
6497 	LOCALASSERT(sbPtr);
6498 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6499 	LOCALASSERT(marineStatusPointer);
6500 
6501 	marineStatusPointer->gotapoint=0;
6502 
6503 	marineStatusPointer->internalState=0;
6504 	marineStatusPointer->volleySize = 0;
6505 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6506 	marineStatusPointer->behaviourState = MBS_Waiting;
6507 	marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
6508 
6509 	Marine_QueueNeutralExpression(sbPtr);
6510 
6511 	#if 0
6512 	if(marineStatusPointer->IAmCrouched) {
6513 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrouch,MCSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6514 	} else {
6515 		if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Stand_To_Fidget)) {
6516 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Stand_To_Fidget,((ONE_FIXED*3)/2),(ONE_FIXED>>3));
6517 			marineStatusPointer->HModelController.LoopAfterTweening=0;
6518 		} else {
6519 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6520 		}
6521 	}
6522 	#else
6523 	HandleWaitingAnimations(sbPtr);
6524 	#endif
6525 
6526 	GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
6527 
6528 }
6529 
6530 void Marine_Enter_Firing_State(STRATEGYBLOCK *sbPtr) {
6531 
6532 	MARINE_STATUS_BLOCK *marineStatusPointer;
6533 	int range;
6534 
6535 	LOCALASSERT(sbPtr);
6536 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6537 	LOCALASSERT(marineStatusPointer);
6538 
6539 	marineStatusPointer->gotapoint=0;
6540 	range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
6541 
6542 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6543 	marineStatusPointer->behaviourState = MBS_Firing;
6544 	marineStatusPointer->volleySize = 0;
6545 
6546 	if (marineStatusPointer->My_Weapon->id!=MNPCW_MPistol) {
6547 		marineStatusPointer->lastroundhit=0;
6548 	}
6549 	if ((marineStatusPointer->My_Weapon->id==MNPCW_Flamethrower)||
6550 		(marineStatusPointer->My_Weapon->id==MNPCW_MFlamer)) {
6551 		marineStatusPointer->weapon_variable=0;
6552 	}
6553 
6554 	marineStatusPointer->lasthitsection=NULL;
6555 	marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
6556 	GLOBALASSERT(marineStatusPointer->Target);
6557 	NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
6558 
6559 	{
6560 		DELTA_CONTROLLER *delta;
6561 		/* There should be NO head turn delta. */
6562 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
6563 		if (delta) {
6564 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
6565 		}
6566 	}
6567 
6568 	/* Arbitrarily decide to crouch? */
6569 	if (marineStatusPointer->Android) {
6570 		marineStatusPointer->IAmCrouched=0;
6571 	} else {
6572 		int prob;
6573 
6574 		prob=20000;
6575 
6576 		if (range<6000) {
6577 			prob+=10000;
6578 		}
6579 
6580 		if ((marineStatusPointer->Target->DynPtr->Position.vy-sbPtr->DynPtr->Position.vy)>3000) {
6581 			prob+=20000;
6582 		}
6583 
6584 		if ((FastRandom()&65535)<prob) {
6585 			marineStatusPointer->IAmCrouched=1;
6586 		}
6587 	}
6588 
6589 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_FireFromHips)) {
6590 		int target;
6591 
6592 		target=(marineStatusPointer->Courage>>1);
6593 		if (marineStatusPointer->Mission==MM_Guard) {
6594 			target+=32767;
6595 		}
6596 
6597 		if ((FastRandom()&((ONE_FIXED<<1)-1))>target) {
6598 			marineStatusPointer->FiringAnim=1;
6599 		} else {
6600 			marineStatusPointer->FiringAnim=0;
6601 		}
6602 	} else {
6603 		marineStatusPointer->FiringAnim=0;
6604 	}
6605 
6606 	if(marineStatusPointer->IAmCrouched) {
6607 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrouch,MCrSS_Attack_Primary,-1,(ONE_FIXED>>3));
6608 	} else {
6609 		if (marineStatusPointer->FiringAnim==1) {
6610 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_FireFromHips,-1,(ONE_FIXED>>3));
6611 		} else {
6612 			if (marineStatusPointer->My_Weapon->id!=MNPCW_TwoPistols) {
6613 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Attack_Primary,-1,(ONE_FIXED>>3));
6614 			} else {
6615 				/* Two Pistols uses Stand Standard. */
6616 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Standard,-1,(ONE_FIXED>>3));
6617 			}
6618 		}
6619 	}
6620 
6621 	if (marineStatusPointer->My_Weapon->id==MNPCW_PulseRifle) {
6622 		if ((marineStatusPointer->FiringAnim==0)&&(marineStatusPointer->IAmCrouched==0)) {
6623 			/* Wink 2. */
6624 			Marine_QueueWink2Expression(sbPtr);
6625 		} else {
6626 			Marine_QueueGrimaceExpression(sbPtr);
6627 		}
6628 	} else {
6629 		Marine_QueueGrimaceExpression(sbPtr);
6630 	}
6631 
6632 	/* This next for firing only! */
6633 	marineStatusPointer->HModelController.StopAfterTweening=1;
6634 
6635 	if (marineStatusPointer->My_Weapon->id==MNPCW_GrenadeLauncher) {
6636 		/* Why do we need internalState 1 here again? */
6637 		marineStatusPointer->internalState=1;
6638 		marineStatusPointer->HModelController.Looped=0;
6639 		marineStatusPointer->HModelController.LoopAfterTweening=0;
6640 
6641 		/* Put loft in now? */
6642 		{
6643 			int range;
6644 			range=VectorDistance((&marineStatusPointer->weaponTarget),(&sbPtr->DynPtr->Position));
6645 
6646 			marineStatusPointer->weaponTarget.vy-=(range/8);
6647 		}
6648 	}
6649 
6650 	if ((marineStatusPointer->My_Weapon->id==MNPCW_MShotgun)
6651 		||(marineStatusPointer->My_Weapon->id==MNPCW_Android)
6652 		||(marineStatusPointer->My_Weapon->id==MNPCW_AndroidSpecial)) {
6653 		marineStatusPointer->internalState=1;
6654 		marineStatusPointer->HModelController.Looped=0;
6655 		marineStatusPointer->HModelController.LoopAfterTweening=0;
6656 	}
6657 
6658 }
6659 
6660 void Marine_Enter_Avoidance_State(STRATEGYBLOCK *sbPtr) {
6661 
6662 	MARINE_STATUS_BLOCK *marineStatusPointer;
6663 
6664 	LOCALASSERT(sbPtr);
6665 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6666 	LOCALASSERT(marineStatusPointer);
6667 
6668 	/* Make sure obstruction is set! */
6669 
6670 	marineStatusPointer->gotapoint=0;
6671 
6672 	NPC_InitMovementData(&(marineStatusPointer->moveData));
6673 	InitWaypointManager(&marineStatusPointer->waypointManager);
6674 	NPCGetAvoidanceDirection(sbPtr, &(marineStatusPointer->moveData.avoidanceDirn),&marineStatusPointer->obstruction);
6675 	marineStatusPointer->volleySize = 0;
6676 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6677 	marineStatusPointer->behaviourState = MBS_Avoidance;
6678 	marineStatusPointer->stateTimer = NPC_AVOIDTIME;
6679 
6680 	#if 0
6681 	if(marineStatusPointer->IAmCrouched) {
6682 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6683 	} else {
6684 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6685 	}
6686 	#else
6687 	HandleMovingAnimations(sbPtr);
6688 	#endif
6689 
6690 	/* Don't interfere with expression... */
6691 
6692 }
6693 
6694 void Marine_Enter_Wander_State(STRATEGYBLOCK *sbPtr) {
6695 
6696 	MARINE_STATUS_BLOCK *marineStatusPointer;
6697 
6698 	LOCALASSERT(sbPtr);
6699 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6700 	LOCALASSERT(marineStatusPointer);
6701 
6702 	marineStatusPointer->gotapoint=0;
6703 
6704 	NPC_InitMovementData(&(marineStatusPointer->moveData));
6705 	NPC_InitWanderData(&(marineStatusPointer->wanderData));
6706 	InitWaypointManager(&marineStatusPointer->waypointManager);
6707 	marineStatusPointer->volleySize = 0;
6708 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6709 	marineStatusPointer->behaviourState = MBS_Wandering;
6710 	marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
6711 
6712 	Marine_QueueNeutralExpression(sbPtr);
6713 
6714 	#if 0
6715 	if(marineStatusPointer->IAmCrouched) {
6716 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6717 	} else {
6718 		if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineRun,MRSS_Mooch_Bored)) {
6719 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Mooch_Bored,ONE_FIXED,(ONE_FIXED>>3));
6720 		} else {
6721 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6722 		}
6723 	}
6724 	#else
6725 	HandleMovingAnimations(sbPtr);
6726 	#endif
6727 
6728 }
6729 
6730 void Marine_Enter_Approach_State(STRATEGYBLOCK *sbPtr) {
6731 
6732 	MARINE_STATUS_BLOCK *marineStatusPointer;
6733 
6734 	LOCALASSERT(sbPtr);
6735 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6736 	LOCALASSERT(marineStatusPointer);
6737 
6738 	marineStatusPointer->gotapoint=0;
6739 
6740 	marineStatusPointer->volleySize = 0;
6741 	NPC_InitMovementData(&(marineStatusPointer->moveData));
6742 	InitWaypointManager(&marineStatusPointer->waypointManager);
6743 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6744 	marineStatusPointer->behaviourState = MBS_Approaching;
6745 
6746 	marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
6747 
6748 	/* Neutral??? */
6749 	Marine_QueueNeutralExpression(sbPtr);
6750 
6751 	#if 0
6752 	if(marineStatusPointer->IAmCrouched) {
6753 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6754 	} else {
6755 		if (marineStatusPointer->Target==NULL) {
6756 			if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineRun,MRSS_Mooch_Alert)) {
6757 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Mooch_Alert,ONE_FIXED,(ONE_FIXED>>3));
6758 			} else {
6759 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6760 			}
6761 		} else {
6762 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6763 		}
6764 	}
6765 	#else
6766 	HandleMovingAnimations(sbPtr);
6767 	#endif
6768 
6769 	marineStatusPointer->destinationmodule=NULL;
6770 
6771 }
6772 
6773 void Marine_Enter_Hunt_State(STRATEGYBLOCK *sbPtr) {
6774 
6775 	MARINE_STATUS_BLOCK *marineStatusPointer;
6776 
6777 	LOCALASSERT(sbPtr);
6778 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6779 	LOCALASSERT(marineStatusPointer);
6780 
6781 	marineStatusPointer->gotapoint=0;
6782 
6783 	marineStatusPointer->volleySize = 0;
6784 	NPC_InitMovementData(&(marineStatusPointer->moveData));
6785 	InitWaypointManager(&marineStatusPointer->waypointManager);
6786 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6787 	marineStatusPointer->behaviourState = MBS_Wandering; /* CHANGE ME!!! */
6788 
6789 	marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
6790 
6791 	/* This really shouldn't be called, should it? */
6792 	Marine_QueueNeutralExpression(sbPtr);
6793 
6794 	if(marineStatusPointer->IAmCrouched) {
6795 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6796 	} else {
6797 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6798 	}
6799 
6800 }
6801 
6802 void Marine_Enter_Respond_State(STRATEGYBLOCK *sbPtr) {
6803 
6804 	MARINE_STATUS_BLOCK *marineStatusPointer;
6805 
6806 	LOCALASSERT(sbPtr);
6807 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6808 	LOCALASSERT(marineStatusPointer);
6809 
6810 	marineStatusPointer->gotapoint=0;
6811 
6812 	marineStatusPointer->volleySize = 0;
6813 	NPC_InitMovementData(&(marineStatusPointer->moveData));
6814 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6815 	marineStatusPointer->behaviourState = MBS_Responding;
6816 
6817 	if (NpcSquad.responseLevel) {
6818 		NpcSquad.responseLevel--;
6819 	}
6820 
6821 	marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
6822 
6823 	/* Determined! */
6824 	Marine_QueueNeutralExpression(sbPtr);
6825 
6826 	/* We must now be suspicious. */
6827 	marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
6828 	marineStatusPointer->suspect_point=NpcSquad.squad_suspect_point;
6829 	/* That'll do as a default. */
6830 	if (NpcSquad.alertZone) {
6831 		/* Gotta have a point. */
6832 		marineStatusPointer->suspect_point=NpcSquad.alertZone->m_world;
6833 	}
6834 	/* Set this to zero when you get a *new* suspicion. */
6835 	marineStatusPointer->previous_suspicion=0;
6836 	marineStatusPointer->using_squad_suspicion=1;
6837 
6838 	#if 0
6839 	if(marineStatusPointer->IAmCrouched) {
6840 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6841 	} else {
6842 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6843 	}
6844 	#else
6845 	HandleMovingAnimations(sbPtr);
6846 	#endif
6847 
6848 }
6849 
6850 void Marine_Enter_Return_State(STRATEGYBLOCK *sbPtr) {
6851 
6852 	MARINE_STATUS_BLOCK *marineStatusPointer;
6853 
6854 	LOCALASSERT(sbPtr);
6855 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6856 	LOCALASSERT(marineStatusPointer);
6857 
6858 	marineStatusPointer->gotapoint=0;
6859 
6860 	marineStatusPointer->volleySize = 0;
6861 	NPC_InitMovementData(&(marineStatusPointer->moveData));
6862 	InitWaypointManager(&marineStatusPointer->waypointManager);
6863 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6864 	marineStatusPointer->behaviourState = MBS_Returning;
6865 
6866 	marineStatusPointer->destinationmodule=NULL;
6867 
6868 	marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
6869 
6870 	Marine_QueueNeutralExpression(sbPtr);
6871 
6872 	#if 0
6873 	if(marineStatusPointer->IAmCrouched) {
6874 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6875 	} else {
6876 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6877 	}
6878 	#else
6879 	HandleMovingAnimations(sbPtr);
6880 	#endif
6881 
6882 }
6883 
6884 void Marine_Enter_Pathfinder_State(STRATEGYBLOCK *sbPtr) {
6885 
6886 	MARINE_STATUS_BLOCK *marineStatusPointer;
6887 
6888 	LOCALASSERT(sbPtr);
6889 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6890 	LOCALASSERT(marineStatusPointer);
6891 
6892 	marineStatusPointer->gotapoint=0;
6893 
6894 	marineStatusPointer->volleySize = 0;
6895 	NPC_InitMovementData(&(marineStatusPointer->moveData));
6896 	InitWaypointManager(&marineStatusPointer->waypointManager);
6897 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6898 	marineStatusPointer->behaviourState = MBS_Pathfinding;
6899 
6900 	marineStatusPointer->destinationmodule=NULL;
6901 
6902 	marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
6903 
6904 	Marine_QueueNeutralExpression(sbPtr);
6905 
6906 	#if 0
6907 	if(marineStatusPointer->IAmCrouched) {
6908 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6909 	} else {
6910 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6911 	}
6912 	#else
6913 	HandleMovingAnimations(sbPtr);
6914 	#endif
6915 
6916 }
6917 
6918 void Marine_Enter_Retreat_State(STRATEGYBLOCK *sbPtr) {
6919 
6920 	MARINE_STATUS_BLOCK *marineStatusPointer;
6921 
6922 	LOCALASSERT(sbPtr);
6923 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6924 	LOCALASSERT(marineStatusPointer);
6925 
6926 	marineStatusPointer->gotapoint=0;
6927 
6928 	marineStatusPointer->volleySize = 0;
6929 	NPC_InitMovementData(&(marineStatusPointer->moveData));
6930 	InitWaypointManager(&marineStatusPointer->waypointManager);
6931 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6932 	marineStatusPointer->behaviourState = MBS_Retreating;
6933 
6934 	marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
6935 
6936 	marineStatusPointer->fearmodule=NULL;
6937 	/* It'll get set on state execution. */
6938 
6939 	if ((FastRandom()&65535)<32767) {
6940 		Marine_QueuePanicExpression(sbPtr);
6941 		Marine_PanicScream(sbPtr);
6942 	} else {
6943 		Marine_QueueGrimaceExpression(sbPtr);
6944 	}
6945 
6946 	#if 0
6947 	if(marineStatusPointer->IAmCrouched) {
6948 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6949 	} else {
6950 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
6951 	}
6952 	#endif
6953 	/* Actually, sequence change is done in the function now. */
6954 
6955 }
6956 
6957 void Marine_Enter_Taunt_State(STRATEGYBLOCK *sbPtr) {
6958 
6959 	MARINE_STATUS_BLOCK *marineStatusPointer;
6960 
6961 	LOCALASSERT(sbPtr);
6962 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
6963 	LOCALASSERT(marineStatusPointer);
6964 
6965 	{
6966 		DELTA_CONTROLLER *delta;
6967 		/* There should be NO head turn delta. */
6968 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
6969 		if (delta) {
6970 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
6971 		}
6972 	}
6973 
6974 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Taunt_One)) {
6975 
6976 		marineStatusPointer->gotapoint=0;
6977 		marineStatusPointer->internalState=0;
6978 		marineStatusPointer->volleySize = 0;
6979 		marineStatusPointer->lastState=marineStatusPointer->behaviourState;
6980 		marineStatusPointer->behaviourState = MBS_Taunting;
6981 		marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
6982 
6983 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Taunt_One,-1,(ONE_FIXED>>3));
6984 		marineStatusPointer->HModelController.LoopAfterTweening=0;
6985 	} else {
6986 		/* Aw, forget it. */
6987 		Marine_Enter_Wait_State(sbPtr);
6988 		return;
6989 	}
6990 
6991 	if ((FastRandom()&65535)<32767) {
6992 		Marine_QueueWink1Expression(sbPtr);
6993 	}
6994 
6995 	Marine_TauntShout(sbPtr);
6996 
6997 }
6998 
6999 void Marine_Enter_Reload_State(STRATEGYBLOCK *sbPtr) {
7000 
7001 	MARINE_STATUS_BLOCK *marineStatusPointer;
7002 
7003 	LOCALASSERT(sbPtr);
7004 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7005 	LOCALASSERT(marineStatusPointer);
7006 
7007 	GLOBALASSERT(HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,marineStatusPointer->My_Weapon->Reload_Sequence));
7008 
7009 	marineStatusPointer->gotapoint=0;
7010 	marineStatusPointer->internalState=0;
7011 	marineStatusPointer->volleySize = 0;
7012 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
7013 	marineStatusPointer->behaviourState = MBS_Reloading;
7014 	marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
7015 
7016 	{
7017 		DELTA_CONTROLLER *delta;
7018 		/* There should be NO head turn delta. */
7019 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7020 		if (delta) {
7021 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7022 		}
7023 	}
7024 
7025 	/* Dunno if this is right. */
7026 	Marine_QueueGrimaceExpression(sbPtr);
7027 
7028 	/* Remove the gunflash */
7029 	if(marineStatusPointer->myGunFlash)
7030 	{
7031 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
7032 		marineStatusPointer->myGunFlash = NULL;
7033 	}
7034 	/* .... and stop the sound */
7035 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
7036 		Sound_Stop(marineStatusPointer->soundHandle);
7037 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
7038 	}
7039 
7040 	SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,marineStatusPointer->My_Weapon->Reload_Sequence,-1,(ONE_FIXED>>3));
7041 	marineStatusPointer->HModelController.LoopAfterTweening=0;
7042 
7043 }
7044 
7045 void Marine_Enter_PanicReload_State(STRATEGYBLOCK *sbPtr) {
7046 
7047 	MARINE_STATUS_BLOCK *marineStatusPointer;
7048 
7049 	LOCALASSERT(sbPtr);
7050 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7051 	LOCALASSERT(marineStatusPointer);
7052 
7053 	GLOBALASSERT(HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,marineStatusPointer->My_Weapon->Reload_Sequence));
7054 
7055 	marineStatusPointer->gotapoint=0;
7056 	marineStatusPointer->internalState=0;
7057 	marineStatusPointer->volleySize = 0;
7058 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
7059 	marineStatusPointer->behaviourState = MBS_PanicReloading;
7060 	marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
7061 
7062 	{
7063 		DELTA_CONTROLLER *delta;
7064 		/* There should be NO head turn delta. */
7065 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7066 		if (delta) {
7067 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7068 		}
7069 	}
7070 
7071 	if ((FastRandom()&65535)<32767) {
7072 		Marine_QueuePanicExpression(sbPtr);
7073 		if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
7074 			Marine_PanicScream(sbPtr);
7075 		} else {
7076 			Marine_AngryScream(sbPtr);
7077 		}
7078 	} else {
7079 		Marine_QueueGrimaceExpression(sbPtr);
7080 	}
7081 
7082 	/* Remove the gunflash */
7083 	if(marineStatusPointer->myGunFlash)
7084 	{
7085 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
7086 		marineStatusPointer->myGunFlash = NULL;
7087 	}
7088 	/* .... and stop the sound */
7089 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
7090 		Sound_Stop(marineStatusPointer->soundHandle);
7091 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
7092 	}
7093 
7094 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,MSSS_Panic_Reload)) {
7095 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Panic_Reload,-1,(ONE_FIXED>>3));
7096 	} else {
7097 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,marineStatusPointer->My_Weapon->Reload_Sequence,-1,(ONE_FIXED>>3));
7098 	}
7099 	marineStatusPointer->HModelController.LoopAfterTweening=0;
7100 
7101 }
7102 
7103 void Marine_Enter_PumpAction_State(STRATEGYBLOCK *sbPtr) {
7104 
7105 	MARINE_STATUS_BLOCK *marineStatusPointer;
7106 
7107 	LOCALASSERT(sbPtr);
7108 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7109 	LOCALASSERT(marineStatusPointer);
7110 
7111 	GLOBALASSERT(HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,MSSS_PumpAction));
7112 
7113 	/* Maintain many things from fire. */
7114 	marineStatusPointer->gotapoint=0;
7115 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
7116 	marineStatusPointer->behaviourState = MBS_PumpAction;
7117 
7118 	{
7119 		DELTA_CONTROLLER *delta;
7120 		/* There should be NO head turn delta. */
7121 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7122 		if (delta) {
7123 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7124 		}
7125 	}
7126 
7127 	/* Dunno if this is right. */
7128 	Marine_QueueGrimaceExpression(sbPtr);
7129 
7130 	/* Remove the gunflash */
7131 	if(marineStatusPointer->myGunFlash)
7132 	{
7133 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
7134 		marineStatusPointer->myGunFlash = NULL;
7135 	}
7136 	/* .... and stop the sound */
7137 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
7138 		Sound_Stop(marineStatusPointer->soundHandle);
7139 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
7140 	}
7141 
7142 	if (marineStatusPointer->IAmCrouched) {
7143 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrouch,MCrSS_PumpAction,-1,(ONE_FIXED>>5));
7144 		marineStatusPointer->HModelController.LoopAfterTweening=0;
7145 	} else {
7146 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_PumpAction,-1,(ONE_FIXED>>5));
7147 		marineStatusPointer->HModelController.LoopAfterTweening=0;
7148 	}
7149 
7150 }
7151 
7152 void Marine_Enter_PanicFire_State(STRATEGYBLOCK *sbPtr) {
7153 
7154 	MARINE_STATUS_BLOCK *marineStatusPointer;
7155 
7156 	LOCALASSERT(sbPtr);
7157 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7158 	LOCALASSERT(marineStatusPointer);
7159 
7160 	marineStatusPointer->gotapoint=0;
7161 
7162 	{
7163 		DELTA_CONTROLLER *delta;
7164 		/* There should be NO head turn delta. */
7165 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7166 		if (delta) {
7167 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7168 		}
7169 	}
7170 
7171 	if (marineStatusPointer->My_Weapon->id==MNPCW_SADAR) {
7172 		#if 0
7173 		if (marineStatusPointer->Target) {
7174 			Marine_Enter_Firing_State(sbPtr);
7175 			return;
7176 		} else {
7177 			Marine_Enter_Wait_State(sbPtr);
7178 			return;
7179 		}
7180 		#else
7181 		Marine_Enter_PullPistol_State(sbPtr);
7182 		return;
7183 		#endif
7184 	} else if (marineStatusPointer->My_Weapon->id==MNPCW_Skeeter) {
7185 		Marine_Enter_PullPistol_State(sbPtr);
7186 		return;
7187 	} else if (marineStatusPointer->My_Weapon->id==MNPCW_MMolotov) {
7188 		if (marineStatusPointer->Target) {
7189 			Marine_Enter_Firing_State(sbPtr);
7190 			return;
7191 		} else {
7192 			Marine_Enter_Wait_State(sbPtr);
7193 			return;
7194 		}
7195 	}
7196 
7197 	marineStatusPointer->internalState=0;
7198 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
7199 	marineStatusPointer->behaviourState = MBS_PanicFire;
7200 	marineStatusPointer->volleySize = 0;
7201 
7202 	if (marineStatusPointer->My_Weapon->id!=MNPCW_MPistol) {
7203 		marineStatusPointer->lastroundhit=0;
7204 	}
7205 	if ((marineStatusPointer->My_Weapon->id==MNPCW_Flamethrower)||
7206 		(marineStatusPointer->My_Weapon->id==MNPCW_MFlamer)) {
7207 		marineStatusPointer->weapon_variable=0;
7208 	}
7209 
7210 	marineStatusPointer->lasthitsection=NULL;
7211 	marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
7212 	if (marineStatusPointer->Target) {
7213 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
7214 	}
7215 
7216 	if ((FastRandom()&65535)<32767) {
7217 		Marine_QueuePanicExpression(sbPtr);
7218 		if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
7219 			Marine_PanicScream(sbPtr);
7220 		} else {
7221 			Marine_AngryScream(sbPtr);
7222 		}
7223 	} else {
7224 		Marine_QueueGrimaceExpression(sbPtr);
7225 	}
7226 
7227 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_WildFire_0)) {
7228 		/* *can* enter wild fire... */
7229 		#if 0
7230 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
7231 		marineStatusPointer->HModelController.LoopAfterTweening=1;
7232 		#endif
7233 		/* Sequence will be set in the function. */
7234 	} else {
7235 		/* Aw, forget it. */
7236 		Marine_Enter_Retreat_State(sbPtr);
7237 		marineStatusPointer->suspicious=MARINE_PANIC_TIME;
7238 	}
7239 
7240 }
7241 
7242 void Marine_Enter_PullPistol_State(STRATEGYBLOCK *sbPtr) {
7243 
7244 	MARINE_STATUS_BLOCK *marineStatusPointer;
7245 	SECTION *root;
7246 	MARINE_WEAPON_DATA *pistol_data;
7247 
7248 	LOCALASSERT(sbPtr);
7249 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7250 	LOCALASSERT(marineStatusPointer);
7251 
7252 	GLOBALASSERT(marineStatusPointer->My_Weapon->ARealMarine);
7253 
7254 	marineStatusPointer->gotapoint=0;
7255 	marineStatusPointer->internalState=0;
7256 	marineStatusPointer->volleySize = 0;
7257 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
7258 	marineStatusPointer->behaviourState = MBS_GetWeapon;
7259 	marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
7260 
7261 	{
7262 		DELTA_CONTROLLER *delta;
7263 		/* There should be NO head turn delta... */
7264 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7265 		if (delta) {
7266 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7267 		}
7268 		/* ...and NO Minigun delta... */
7269 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
7270 		if (delta) {
7271 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
7272 		}
7273 		/* ...and strip out HitDelta for now, too. */
7274 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
7275 		if (delta) {
7276 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
7277 		}
7278 	}
7279 
7280 	/* Now, try to be clever... */
7281 	/* Turn into a pistol guy! */
7282 	pistol_data=GetThisNPCMarineWeapon(MNPCW_PistolMarine);
7283 	GLOBALASSERT(pistol_data);
7284 
7285 	root=GetNamedHierarchyFromLibrary(pistol_data->Riffname,pistol_data->HierarchyName);
7286 	GLOBALASSERT(root);
7287 
7288 	marineStatusPointer->HModelController.Sequence_Type=HMSQT_MarineStand;
7289 	marineStatusPointer->HModelController.Sub_Sequence=MSSS_Get_Weapon;
7290 	/* That's to put the pistol in the right place... */
7291 	Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root, 1, 1,0);
7292 	marineStatusPointer->My_Weapon=pistol_data;
7293 	marineStatusPointer->My_Gunflash_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->GunflashName);
7294 	marineStatusPointer->My_Elevation_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ElevationSection);
7295 	/* Start loaded! */
7296 	marineStatusPointer->clipammo=marineStatusPointer->My_Weapon->clip_size;
7297 
7298 	/* Dunno if this is right. */
7299 	Marine_QueueGrimaceExpression(sbPtr);
7300 
7301 	/* Remove the gunflash */
7302 	if(marineStatusPointer->myGunFlash)
7303 	{
7304 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
7305 		marineStatusPointer->myGunFlash = NULL;
7306 	}
7307 	/* .... and stop the sound */
7308 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
7309 		Sound_Stop(marineStatusPointer->soundHandle);
7310 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
7311 	}
7312 
7313 	SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Get_Weapon,-1,(ONE_FIXED>>3));
7314 	marineStatusPointer->HModelController.LoopAfterTweening=0;
7315 
7316 	/* Attempt to put the hitdelta back? */
7317 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront)) {
7318 		DELTA_CONTROLLER *delta;
7319 		delta=Add_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
7320 		GLOBALASSERT(delta);
7321 		delta->Playing=0;
7322 	}
7323 
7324 	DeInitialise_HModel(&marineStatusPointer->HModelController);
7325 	ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
7326 
7327 }
7328 
7329 void Marine_Enter_OneArmShotgun_State(STRATEGYBLOCK *sbPtr) {
7330 
7331 	MARINE_STATUS_BLOCK *marineStatusPointer;
7332 	SECTION *root;
7333 	MARINE_WEAPON_DATA *pistol_data;
7334 
7335 	LOCALASSERT(sbPtr);
7336 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7337 	LOCALASSERT(marineStatusPointer);
7338 
7339 	GLOBALASSERT(marineStatusPointer->Android);
7340 
7341 	marineStatusPointer->gotapoint=0;
7342 	marineStatusPointer->internalState=0;
7343 	marineStatusPointer->volleySize = 0;
7344 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
7345 	marineStatusPointer->behaviourState = MBS_Waiting;
7346 	marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
7347 
7348 	{
7349 		DELTA_CONTROLLER *delta;
7350 		/* There should be NO head turn delta... */
7351 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7352 		if (delta) {
7353 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7354 		}
7355 		/* ...and NO Minigun delta... */
7356 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
7357 		if (delta) {
7358 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
7359 		}
7360 		/* ...and strip out HitDelta for now, too. */
7361 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
7362 		if (delta) {
7363 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
7364 		}
7365 	}
7366 
7367 	/* Now, try to be clever... */
7368 	/* Turn into an Android Special!  */
7369 	pistol_data=GetThisNPCMarineWeapon(MNPCW_AndroidSpecial);
7370 	GLOBALASSERT(pistol_data);
7371 
7372 	root=GetNamedHierarchyFromLibrary(pistol_data->Riffname,pistol_data->HierarchyName);
7373 	GLOBALASSERT(root);
7374 
7375 	marineStatusPointer->HModelController.Sequence_Type=HMSQT_MarineStand;
7376 	marineStatusPointer->HModelController.Sub_Sequence=MSSS_Standard;
7377 	/* That's to put the pistol in the right place... */
7378 	Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root, 1, 1,0);
7379 	marineStatusPointer->My_Weapon=pistol_data;
7380 	marineStatusPointer->My_Gunflash_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->GunflashName);
7381 	marineStatusPointer->My_Elevation_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ElevationSection);
7382 
7383 	/* Retain clipammo from the old shotgun. */
7384 
7385 	/* Remove the gunflash */
7386 	if(marineStatusPointer->myGunFlash)
7387 	{
7388 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
7389 		marineStatusPointer->myGunFlash = NULL;
7390 	}
7391 	/* .... and stop the sound */
7392 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
7393 		Sound_Stop(marineStatusPointer->soundHandle);
7394 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
7395 	}
7396 
7397 	SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Standard,-1,(ONE_FIXED>>3));
7398 	marineStatusPointer->HModelController.LoopAfterTweening=0;
7399 
7400 	/* Attempt to put the hitdelta back? */
7401 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront)) {
7402 		DELTA_CONTROLLER *delta;
7403 		delta=Add_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
7404 		GLOBALASSERT(delta);
7405 		delta->Playing=0;
7406 	}
7407 
7408 	DeInitialise_HModel(&marineStatusPointer->HModelController);
7409 	ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
7410 
7411 }
7412 
7413 void Marine_Enter_OneArmPistol_State(STRATEGYBLOCK *sbPtr) {
7414 
7415 	MARINE_STATUS_BLOCK *marineStatusPointer;
7416 	SECTION *root;
7417 	MARINE_WEAPON_DATA *pistol_data;
7418 
7419 	LOCALASSERT(sbPtr);
7420 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7421 	LOCALASSERT(marineStatusPointer);
7422 
7423 	GLOBALASSERT(marineStatusPointer->Android);
7424 
7425 	marineStatusPointer->gotapoint=0;
7426 	marineStatusPointer->internalState=0;
7427 	marineStatusPointer->volleySize = 0;
7428 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
7429 	marineStatusPointer->behaviourState = MBS_GetWeapon;
7430 	marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
7431 
7432 	{
7433 		DELTA_CONTROLLER *delta;
7434 		/* There should be NO head turn delta... */
7435 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7436 		if (delta) {
7437 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
7438 		}
7439 		/* ...and NO Minigun delta... */
7440 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
7441 		if (delta) {
7442 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
7443 		}
7444 		/* ...and strip out HitDelta for now, too. */
7445 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
7446 		if (delta) {
7447 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
7448 		}
7449 	}
7450 
7451 	/* Now, try to be clever... */
7452 	/* Turn into an Android Special!  */
7453 	pistol_data=GetThisNPCMarineWeapon(MNPCW_Android_Pistol_Special);
7454 	GLOBALASSERT(pistol_data);
7455 
7456 	root=GetNamedHierarchyFromLibrary(pistol_data->Riffname,pistol_data->HierarchyName);
7457 	GLOBALASSERT(root);
7458 
7459 	marineStatusPointer->HModelController.Sequence_Type=HMSQT_MarineStand;
7460 	marineStatusPointer->HModelController.Sub_Sequence=MSSS_Get_Weapon;
7461 	/* That's to put the pistol in the right place... */
7462 	Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root, 1, 1,0);
7463 	marineStatusPointer->My_Weapon=pistol_data;
7464 	marineStatusPointer->My_Gunflash_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->GunflashName);
7465 	marineStatusPointer->My_Elevation_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ElevationSection);
7466 	/* Start loaded! */
7467 	marineStatusPointer->clipammo=marineStatusPointer->My_Weapon->clip_size;
7468 
7469 	/* Remove the gunflash */
7470 	if(marineStatusPointer->myGunFlash)
7471 	{
7472 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
7473 		marineStatusPointer->myGunFlash = NULL;
7474 	}
7475 	/* .... and stop the sound */
7476 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
7477 		Sound_Stop(marineStatusPointer->soundHandle);
7478 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
7479 	}
7480 
7481 	SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Get_Weapon,-1,(ONE_FIXED>>3));
7482 	marineStatusPointer->HModelController.LoopAfterTweening=0;
7483 
7484 	/* Attempt to put the hitdelta back? */
7485 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront)) {
7486 		DELTA_CONTROLLER *delta;
7487 		delta=Add_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
7488 		GLOBALASSERT(delta);
7489 		delta->Playing=0;
7490 	}
7491 
7492 	DeInitialise_HModel(&marineStatusPointer->HModelController);
7493 	ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
7494 
7495 }
7496 
7497 static STATE_RETURN_CONDITION Execute_MNS_Approach(STRATEGYBLOCK *sbPtr)
7498 {
7499 	MARINE_STATUS_BLOCK *marineStatusPointer;
7500 	VECTORCH velocityDirection = {0,0,0};
7501 	VECTORCH targetPosition;
7502 	int targetIsAirduct = 0;
7503 	int range;
7504 
7505 	LOCALASSERT(sbPtr);
7506 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7507 	LOCALASSERT(marineStatusPointer);
7508 
7509 	HandleMovingAnimations(sbPtr);
7510 
7511 	/* now check for state changes... firstly, if we can no longer attack the target, go
7512 	to wander */
7513 	if(!(MarineIsAwareOfTarget(sbPtr)))
7514 	{
7515 		if (marineStatusPointer->suspicious==0) {
7516 			/* Return to wait.  Nothing to worry about. */
7517 			return(SRC_Request_Wait);
7518 		}
7519 
7520 	} else {
7521 
7522 		/* We have a target that we are aware of. */
7523 
7524 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
7525 
7526 		/* if we are close... go directly to firing */
7527 		if(range < marineStatusPointer->My_Weapon->ForceFireRange)
7528 		{
7529 			/* switch directly to firing, at this distance */
7530 
7531 			return(SRC_Request_Fire);
7532 		}
7533 
7534 		/* if our state timer has run out in approach state, see if we can fire*/
7535 		if(marineStatusPointer->stateTimer > 0) marineStatusPointer->stateTimer -= NormalFrameTime;
7536 		if(marineStatusPointer->stateTimer <= 0)
7537 		{
7538 			/* it is time to fire, if we can see the target  */
7539    			if((MarineCanSeeTarget(sbPtr))
7540 			   &&((marineStatusPointer->My_Weapon->MaxRange==-1)
7541 			   ||(range<marineStatusPointer->My_Weapon->MaxRange))) {
7542 
7543 				/* we are going to fire then */
7544 
7545 				return(SRC_Request_Fire);
7546 			}
7547 			else
7548 			{
7549 			   	/* renew approach state */
7550 			   	marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
7551 
7552 			}
7553 		}
7554 	}
7555 
7556 	/* Kick them out of the stupid state? */
7557 
7558 	/* See which way we want to go. */
7559 	if ((marineStatusPointer->destinationmodule==sbPtr->containingModule->m_aimodule)
7560 		||(marineStatusPointer->destinationmodule==NULL)) {
7561 
7562 		AIMODULE *targetModule;
7563 		MODULE *tcm;
7564 		FARENTRYPOINT *thisEp = (FARENTRYPOINT *)0;
7565 
7566 		if (marineStatusPointer->Target==NULL) {
7567 			/* Must be approaching a suspect point. */
7568 			GLOBALASSERT(marineStatusPointer->suspicious);
7569 			tcm=ModuleFromPosition(&marineStatusPointer->suspect_point,sbPtr->containingModule);
7570 		} else {
7571 			if (marineStatusPointer->Target->containingModule) {
7572 				tcm=marineStatusPointer->Target->containingModule;
7573 			} else {
7574 				tcm=ModuleFromPosition(&marineStatusPointer->Target->DynPtr->Position,sbPtr->containingModule);
7575 			}
7576 		}
7577 
7578 		if (tcm) {
7579 			targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,tcm->m_aimodule,7,0);
7580 		} else {
7581 			targetModule=NULL;
7582 		}
7583 
7584 		if (targetModule==sbPtr->containingModule->m_aimodule) {
7585 			/* Try going for it, we still can't see them. */
7586 			if (marineStatusPointer->Target) {
7587 				NPCGetMovementTarget(sbPtr, marineStatusPointer->Target, &targetPosition, &targetIsAirduct,0);
7588 			} else {
7589 				int range2;
7590 				VECTORCH relTargetPosition;
7591 				/* Just use the target point? */
7592 				targetPosition=marineStatusPointer->suspect_point;
7593 
7594 				#if 0
7595 				range2=VectorDistance(&targetPosition,(&sbPtr->DynPtr->Position));
7596 				#else
7597 
7598 				relTargetPosition=targetPosition;
7599 
7600 				relTargetPosition.vx-=sbPtr->DynPtr->Position.vx;
7601 				relTargetPosition.vy-=sbPtr->DynPtr->Position.vy;
7602 				relTargetPosition.vz-=sbPtr->DynPtr->Position.vz;
7603 
7604 				/* Let's try doing this. */
7605 				relTargetPosition.vy>>=2;
7606 
7607 				range2=Approximate3dMagnitude(&relTargetPosition);
7608 				#endif
7609 
7610 				if (range2<SUSPECT_SENSITIVITY) {
7611 					/* That's probably close enough. */
7612 					marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
7613 					/* Used to unset suspicion at that point. */
7614 					if (marineStatusPointer->Mission==MM_Pathfinder) {
7615 						/* Get back to business! */
7616 						return(SRC_Request_Return);
7617 					} else {
7618 						return(SRC_Request_Wait);
7619 					}
7620 				}
7621 
7622 			}
7623 			NPCGetMovementDirection(sbPtr, &velocityDirection, &targetPosition,&marineStatusPointer->waypointManager);
7624 		} else if (!targetModule) {
7625 			/* Must be inaccessible.  Time out suspicion. */
7626 			marineStatusPointer->suspicious-=NormalFrameTime;
7627 			/* To fix the next trap... */
7628 			if (marineStatusPointer->suspicious==0) {
7629 				marineStatusPointer->suspicious=-1;
7630 			}
7631 			if (marineStatusPointer->suspicious<0) {
7632 				marineStatusPointer->suspicious=0;
7633 				/* Set to zero on natural timeout, too. */
7634 				marineStatusPointer->previous_suspicion=0;
7635 				marineStatusPointer->using_squad_suspicion=0;
7636 				if ((marineStatusPointer->behaviourState==MBS_Waiting)
7637 					||(marineStatusPointer->behaviourState==MBS_Sentry)) {
7638 					/* We might concievably want to do this for all states. */
7639 					marineStatusPointer->gotapoint=0;
7640 				}
7641 			}
7642 
7643 			if (ShowSquadState) {
7644 				if (marineStatusPointer->Target) {
7645 					if (marineStatusPointer->Target->containingModule) {
7646 						PrintDebuggingText("I can see you, but I can't get there!\n");
7647 					} else {
7648 						PrintDebuggingText("Hey, you've got no Containing Module!\n");
7649 					}
7650 				} else {
7651 					PrintDebuggingText("Can't get to the suspect point!\n");
7652 					/* Yuck.  Stop it. */
7653 					#if 0
7654 					marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
7655 					/* Used to unset suspicion at that point. */
7656 					#else
7657 					marineStatusPointer->suspicious=1;
7658 					/* Just this once, let's unset it... We can't do anything about it. */
7659 					#endif
7660 					return(SRC_Request_Wait);
7661 				}
7662 			}
7663 			return(SRC_No_Change);
7664 		} else {
7665 
7666 			thisEp=GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
7667 			if (!thisEp) {
7668 				LOGDXFMT(("This assert is a busted adjacency!\nNo EP between %s and %s.",
7669 					(*(targetModule->m_module_ptrs))->name,
7670 					sbPtr->containingModule->name));
7671 				//LOGDXFMT(("This assert is a busted adjacency!"));
7672 				GLOBALASSERT(thisEp);
7673 			}
7674 			/* If that fired, there's a farped adjacency. */
7675 			GLOBALASSERT(thisEp->alien_only==0);
7676 			/* If that fired, GetNextModuleForLink went wrong. */
7677 
7678 			marineStatusPointer->wanderData.worldPosition=thisEp->position;
7679 			marineStatusPointer->wanderData.worldPosition.vx+=targetModule->m_world.vx;
7680 			marineStatusPointer->wanderData.worldPosition.vy+=targetModule->m_world.vy;
7681 			marineStatusPointer->wanderData.worldPosition.vz+=targetModule->m_world.vz;
7682 
7683 			NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
7684 
7685 		}
7686 
7687 	} else if (marineStatusPointer->destinationmodule!=NULL) {
7688 		/* Go towards next module. */
7689 		NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
7690 	} else {
7691 		/*  we are still in approach state: target the target, and move */
7692 		if (marineStatusPointer->Target) {
7693 			NPCGetMovementTarget(sbPtr, marineStatusPointer->Target, &targetPosition, &targetIsAirduct,0);
7694 		} else {
7695 			/* How did we get here, anyway? */
7696 			targetPosition=marineStatusPointer->suspect_point;
7697 		}
7698 		NPCGetMovementDirection(sbPtr, &velocityDirection, &targetPosition,&marineStatusPointer->waypointManager);
7699 	}
7700 
7701 	/* Should have a velocity set now. */
7702 
7703 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
7704 
7705 	/* test here for impeding collisions, and not being able to reach target... */
7706 	#if ALL_NEW_AVOIDANCE
7707 	{
7708 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
7709 			/* Go to all new avoidance. */
7710 			return(SRC_Request_Avoidance);
7711 		}
7712 	}
7713 	#else
7714 	{
7715 		STRATEGYBLOCK *destructableObject = NULL;
7716 
7717 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
7718 		if(marineStatusPointer->obstruction.environment)
7719 		{
7720 			/* go to avoidance */
7721 			return(SRC_Request_Avoidance);
7722 		}
7723 		if(marineStatusPointer->obstruction.destructableObject)
7724 		{
7725 			LOCALASSERT(destructableObject);
7726 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
7727 		}
7728 	}
7729 
7730 	if(NPC_CannotReachTarget(&(marineStatusPointer->moveData), &targetPosition, &velocityDirection))
7731 	{
7732 
7733 		marineStatusPointer->obstruction.environment=1;
7734 		marineStatusPointer->obstruction.destructableObject=0;
7735 		marineStatusPointer->obstruction.otherCharacter=0;
7736 		marineStatusPointer->obstruction.anySingleObstruction=0;
7737 
7738 		return(SRC_Request_Avoidance);
7739 	}
7740 	#endif
7741 
7742 	return(SRC_No_Change);
7743 }
7744 
7745 
7746 /* this function is specifically for marines, and creates a gun flash
7747 pointing in the direction of the target point */
7748 static void MaintainMarineGunFlash(STRATEGYBLOCK *sbPtr)
7749 {
7750 	VECTORCH firingDirn,firingPoint;
7751 	MARINE_STATUS_BLOCK *marineStatusPointer;
7752 	int firingOffsetUp;
7753 	int firingOffsetInfront;
7754 	int firingOffsetAcross;
7755 
7756 	LOCALASSERT(sbPtr);
7757 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7758 	LOCALASSERT(marineStatusPointer);
7759 
7760 	GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
7761 
7762 	/* get the firing point offsets:*/
7763 	if(marineStatusPointer->IAmCrouched)
7764 	{
7765 		firingOffsetUp = MARINE_FIRINGPOINT_UP;
7766 		firingOffsetInfront = MARINE_FIRINGPOINT_INFRONT;
7767 		firingOffsetAcross = MARINE_FIRINGPOINT_ACROSS;
7768 	}
7769 	else
7770 	{
7771 		firingOffsetUp = MARINE_FIRINGPOINT_UP_CROUCHED;
7772 		firingOffsetInfront = MARINE_FIRINGPOINT_INFRONT_CROUCHED;
7773 		firingOffsetAcross = MARINE_FIRINGPOINT_ACROSS_CROUCHED;
7774 	}
7775 
7776 	/* find the firing direction */
7777 	firingDirn.vx = marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
7778 	firingDirn.vy = marineStatusPointer->weaponTarget.vy - sbPtr->DynPtr->Position.vy;
7779 	firingDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
7780 	Normalise(&firingDirn);
7781 	{
7782 		VECTORCH yNormal = {0,-65536,0};
7783 		VECTORCH tempDirn;
7784 		VECTORCH acrossDirn;
7785 
7786 		/* now find firing point (conceptually, the end of the weapon muzzle)... */
7787 		firingPoint = sbPtr->DynPtr->Position;
7788 		firingPoint.vx += MUL_FIXED(firingDirn.vx,firingOffsetInfront);
7789 		firingPoint.vz += MUL_FIXED(firingDirn.vz,firingOffsetInfront);
7790 
7791 		tempDirn = firingDirn;
7792 		tempDirn.vy = 0;
7793 		Normalise(&tempDirn);
7794 		CrossProduct(&tempDirn,&yNormal,&acrossDirn);
7795 		Normalise(&acrossDirn);
7796 		firingPoint.vx += MUL_FIXED(tempDirn.vx,firingOffsetAcross);
7797 		firingPoint.vz += MUL_FIXED(tempDirn.vz,firingOffsetAcross);
7798 		firingPoint.vy += MUL_FIXED(yNormal.vy,firingOffsetUp);
7799 	}
7800 	LOCALASSERT(marineStatusPointer->myGunFlash!=NULL);
7801 
7802 	MaintainNPCGunFlashEffect(marineStatusPointer->myGunFlash,&marineStatusPointer->My_Gunflash_Section->World_Offset,
7803 		 &marineStatusPointer->My_Gunflash_Section->SecMat);
7804 }
7805 
7806 /* NB this shouldn't be called if :
7807 1. we are close to the target
7808 2. we are crouched */
7809 static void LobAGrenade(STRATEGYBLOCK *sbPtr)
7810 {
7811 	MARINE_STATUS_BLOCK *marineStatusPointer;
7812 	//VECTORCH firingPoint;
7813 	//VECTORCH firingDirn;
7814 
7815 	LOCALASSERT(sbPtr);
7816 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7817 	LOCALASSERT(marineStatusPointer);
7818 
7819 	/* first, find the firing direction */
7820 	//firingDirn.vx = marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
7821 	//firingDirn.vy = marineStatusPointer->weaponTarget.vy - sbPtr->DynPtr->Position.vz;
7822 	//firingDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
7823 	//Normalise(&firingDirn);
7824 
7825 	if((sbPtr->DynPtr->Position.vy - marineStatusPointer->weaponTarget.vy) > 2500)
7826 	{
7827 		/* too high */
7828 		return;
7829 	}
7830 
7831 	#if 0
7832 	{
7833 		VECTORCH yNormal = {0,-65536,0};
7834 		VECTORCH tempDirn;
7835 		VECTORCH acrossDirn;
7836 
7837 		/* now find firing point (conceptually, the end of the weapon muzzle + a bit)... */
7838 		firingPoint = sbPtr->DynPtr->Position;
7839 		firingPoint.vx += MUL_FIXED(firingDirn.vx,(MARINE_FIRINGPOINT_INFRONT+400));
7840 		firingPoint.vz += MUL_FIXED(firingDirn.vz,(MARINE_FIRINGPOINT_INFRONT+400));
7841 
7842 		tempDirn = firingDirn;
7843 		tempDirn.vy = 0;
7844 		Normalise(&tempDirn);
7845 		CrossProduct(&tempDirn,&yNormal,&acrossDirn);
7846 		Normalise(&acrossDirn);
7847 		firingPoint.vx += MUL_FIXED(tempDirn.vx,MARINE_FIRINGPOINT_ACROSS);
7848 		firingPoint.vz += MUL_FIXED(tempDirn.vz,MARINE_FIRINGPOINT_ACROSS);
7849 		firingPoint.vy += MUL_FIXED(yNormal.vy,MARINE_FIRINGPOINT_UP);
7850 	}
7851 	#endif
7852 
7853 	/* this bit nicked from player grenade creation	fn. in bh_weap.c :
7854 	actually, it is now a pulse rifle grenade */
7855 	{
7856 		DISPLAYBLOCK *dispPtr;
7857 		DYNAMICSBLOCK *dynPtr;
7858 
7859 		dispPtr = MakeObject(I_BehaviourPulseGrenade,&marineStatusPointer->My_Gunflash_Section->World_Offset);
7860 		if(!dispPtr) return;
7861 		LOCALASSERT(dispPtr->ObStrategyBlock);
7862 		AddLightingEffectToObject(dispPtr,LFX_ROCKETJET);
7863 		dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_ROCKET);
7864 		if(!dynPtr)
7865 		{
7866 			RemoveBehaviourStrategy(dispPtr->ObStrategyBlock);
7867 			return;
7868 		}
7869 		dispPtr->ObStrategyBlock->DynPtr = dynPtr;
7870 		dispPtr->ObStrategyBlock->SBdataptr=AllocateMem(sizeof(PREDPISTOL_BEHAV_BLOCK));
7871 		if(!dispPtr->ObStrategyBlock->SBdataptr)
7872 		{
7873 			RemoveBehaviourStrategy(dispPtr->ObStrategyBlock);
7874 			return;
7875 		}
7876 		((PREDPISTOL_BEHAV_BLOCK *)dispPtr->ObStrategyBlock->SBdataptr)->counter = 5*ONE_FIXED;
7877 		((PREDPISTOL_BEHAV_BLOCK *)dispPtr->ObStrategyBlock->SBdataptr)->player = 0;
7878 
7879 		GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
7880 
7881 	    #define PULSEGRENADE_SPEED 100000 // Was 30000
7882 		dynPtr->Position = marineStatusPointer->My_Gunflash_Section->World_Offset;
7883 		dynPtr->OrientMat = marineStatusPointer->My_Gunflash_Section->SecMat;
7884 		dynPtr->PrevOrientMat = dynPtr->OrientMat; /* stops mis-alignment if dynamics problem */
7885 
7886 	    dynPtr->LinVelocity.vx = dynPtr->OrientMat.mat31;
7887 	    dynPtr->LinVelocity.vy = dynPtr->OrientMat.mat32;
7888 	    dynPtr->LinVelocity.vz = dynPtr->OrientMat.mat33;
7889 
7890 	    dynPtr->LinVelocity.vx = MUL_FIXED(dynPtr->LinVelocity.vx, PULSEGRENADE_SPEED);
7891 	    dynPtr->LinVelocity.vy = MUL_FIXED(dynPtr->LinVelocity.vy, PULSEGRENADE_SPEED);
7892 	    dynPtr->LinVelocity.vz = MUL_FIXED(dynPtr->LinVelocity.vz, PULSEGRENADE_SPEED);
7893 
7894 	    //dynPtr->LinImpulse.vx = MUL_FIXED(firingDirn.vx,PULSEGRENADE_SPEED);
7895 	    //dynPtr->LinImpulse.vy = MUL_FIXED(firingDirn.vy,PULSEGRENADE_SPEED);
7896 	    //dynPtr->LinImpulse.vz = MUL_FIXED(firingDirn.vz,PULSEGRENADE_SPEED);
7897 	}
7898 }
7899 
7900 /*NB avoidance state behaviour function probabaly doesn't need to check
7901 for crouching, or for target becoming cloaked.  Only when we exit the state
7902 do we need to check these behaviour parameters to pick a new state and sequence*/
7903 static STATE_RETURN_CONDITION Execute_MNS_Avoidance(STRATEGYBLOCK *sbPtr)
7904 {
7905 	MARINE_STATUS_BLOCK *marineStatusPointer;
7906 	int terminateState = 0;
7907 
7908 	LOCALASSERT(sbPtr);
7909 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
7910 	LOCALASSERT(marineStatusPointer);
7911 
7912 	#if 1
7913 	HandleMovingAnimations(sbPtr);
7914 	#endif
7915 
7916 	#if ALL_NEW_AVOIDANCE
7917 	/* New avoidance kernel. */
7918 
7919 	NPCSetVelocity(sbPtr, &(marineStatusPointer->avoidanceManager.avoidanceDirection), (marineStatusPointer->nearSpeed));
7920 	/* Velocity CANNOT be zero, unless deliberately so! */
7921 	{
7922 		AVOIDANCE_RETURN_CONDITION rc;
7923 
7924 		rc=AllNewAvoidanceKernel(sbPtr,&marineStatusPointer->avoidanceManager);
7925 
7926 		if (rc!=AvRC_Avoidance) {
7927 			terminateState=1;
7928 		}
7929 		/* Should put in a test for AvRC_Failure here. */
7930 	}
7931 
7932 	#if 0
7933 	{
7934 		VECTORCH point;
7935 		/* Wacky test. */
7936 		GetTargetingPointOfObject_Far(sbPtr,&point);
7937 		MakeParticle(&point,&sbPtr->DynPtr->LinVelocity,PARTICLE_NONCOLLIDINGFLAME);
7938 
7939 		MakeParticle(&point,&(marineStatusPointer->avoidanceManager.avoidanceDirection),PARTICLE_PREDATOR_BLOOD);
7940 		MakeParticle(&point,&(marineStatusPointer->avoidanceManager.aggregateNormal),PARTICLE_ALIEN_BLOOD);
7941 
7942 	}
7943 	#endif
7944 
7945 	#else
7946 	/* set velocity */
7947 	LOCALASSERT((marineStatusPointer->moveData.avoidanceDirn.vx!=0)||
7948 				(marineStatusPointer->moveData.avoidanceDirn.vy!=0)||
7949 				(marineStatusPointer->moveData.avoidanceDirn.vz!=0));
7950 	NPCSetVelocity(sbPtr, &(marineStatusPointer->moveData.avoidanceDirn), (marineStatusPointer->nearSpeed));
7951 
7952 	/* decrement state timer */
7953 	marineStatusPointer->stateTimer -= NormalFrameTime;
7954 	if(marineStatusPointer->stateTimer <= 0) terminateState = 1;
7955 
7956 	{
7957 		STRATEGYBLOCK *destructableObject = NULL;
7958 		NPC_OBSTRUCTIONREPORT obstruction;
7959 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&obstruction,&destructableObject);
7960 		if(obstruction.anySingleObstruction)
7961 		{
7962 			terminateState = 1;
7963 		}
7964 	}
7965 	#endif
7966 
7967 	if(terminateState)
7968 	{
7969 		/* switch to approach */
7970 		if(MarineIsAwareOfTarget(sbPtr))
7971 		{
7972 			/* go to approach */
7973 
7974 			return(SRC_Request_Approach);
7975 			/* Was fire! */
7976 		}
7977 		else
7978 		{
7979 			/* go to an appropriate state */
7980 			switch (marineStatusPointer->lastState) {
7981 				case MBS_Retreating:
7982 					return(SRC_Request_Retreat);
7983 					break;
7984 				case MBS_Returning:
7985 					return(SRC_Request_Return);
7986 					break;
7987 				case MBS_Responding:
7988 					return(SRC_Request_Respond);
7989 					break;
7990 				case MBS_Approaching:
7991 					/* Go directly to approach.  Do not pass GO.  Do not collect 200 zorkmids. */
7992 					return(SRC_Request_Approach);
7993 					break;
7994 				case MBS_Sentry:
7995 					/* Go back to sentry. */
7996 					return(SRC_Request_Wait);
7997 					break;
7998 				default:
7999 					return(SRC_Request_Wander);
8000 					break;
8001 			}
8002 			/* Still here? */
8003 			return(SRC_Request_Wander);
8004 		}
8005 	}
8006 	return(SRC_No_Change);
8007 }
8008 
8009 static STATE_RETURN_CONDITION Execute_MNS_Wander(STRATEGYBLOCK *sbPtr)
8010 {
8011 	MARINE_STATUS_BLOCK *marineStatusPointer;
8012 	DYNAMICSBLOCK *dynPtr;
8013 	VECTORCH velocityDirection = {0,0,0};
8014 
8015 	LOCALASSERT(sbPtr);
8016 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
8017 	dynPtr = sbPtr->DynPtr;
8018 	LOCALASSERT(marineStatusPointer);
8019 	LOCALASSERT(dynPtr);
8020 
8021 	HandleMovingAnimations(sbPtr);
8022 
8023 	/* should we change to approach state? */
8024 	if ((MarineIsAwareOfTarget(sbPtr))||(marineStatusPointer->suspicious))
8025 	{
8026 		/* doesn't require a sequence change */
8027 		return(SRC_Request_Approach);
8028 	}
8029 
8030 	/* Is there a new alert? */
8031 	if ((NpcSquad.alertZone)&&(marineStatusPointer->Mission!=MM_LocalGuard)
8032 		&&(marineStatusPointer->Mission!=MM_NonCom)) {
8033 		/* Are we already there? */
8034 		if (sbPtr->containingModule->m_aimodule!=NpcSquad.alertZone) {
8035 			if (NpcSquad.responseLevel>0) {
8036 				/* Picked up a target.  Can we move to respond? */
8037 				AIMODULE *targetModule=0;
8038 				targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
8039 				if (targetModule) {
8040 					return(SRC_Request_Respond);
8041 				}
8042 			}
8043 		}
8044 	}
8045 
8046 	/* Are we bored of wandering yet? */
8047 
8048 	marineStatusPointer->stateTimer-=NormalFrameTime;
8049 
8050 	if (marineStatusPointer->stateTimer<=0) {
8051 		/* Time to make a decision. */
8052 		marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
8053 		if ((FastRandom()&65535)<8192)
8054 		{
8055 			/* This is too tiring... let's just wait around a while. */
8056 			return(SRC_Request_Wait);
8057 		}
8058 	}
8059 
8060 	/* Are we using bimble rules? */
8061 
8062 	if (marineStatusPointer->wanderData.currentModule==NPC_BIMBLINGINMODULE) {
8063 
8064 		int range;
8065 
8066 		/* Range to target... */
8067 
8068 		range=VectorDistance((&marineStatusPointer->wanderData.worldPosition),(&sbPtr->DynPtr->Position));
8069 
8070 		if (range<2000) {
8071 
8072 			/* Reset system, try again. */
8073 			marineStatusPointer->wanderData.currentModule=NPC_NOWANDERMODULE;
8074 			marineStatusPointer->moveData.lastModule=NULL;
8075 
8076 		}
8077 
8078 	} else {
8079 
8080 		/* wander target aquisition: if no target, or moved module */
8081 		LOCALASSERT(sbPtr->containingModule);
8082 		if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
8083 		{
8084 			NPC_InitMovementData(&(marineStatusPointer->moveData));
8085 			marineStatusPointer->moveData.lastModule=marineStatusPointer->lastmodule;
8086 			NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
8087 
8088 		}
8089 		else if(marineStatusPointer->wanderData.currentModule!=sbPtr->containingModule->m_aimodule->m_index)
8090 		{
8091 			NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
8092 
8093 		}
8094 
8095 		/* if we still haven't got one, bimble about in this one for a bit. */
8096 		if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
8097 		{
8098 			NPC_GetBimbleTarget(sbPtr,&marineStatusPointer->wanderData.worldPosition);
8099 			marineStatusPointer->wanderData.currentModule=NPC_BIMBLINGINMODULE;
8100 
8101 		}
8102 
8103 	}
8104 
8105 	/* ok: should have a current target at this stage... */
8106 	NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
8107 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
8108 
8109 	/* test here for impeding collisions, and not being able to reach target... */
8110 	#if ALL_NEW_AVOIDANCE
8111 	{
8112 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
8113 			/* Go to all new avoidance. */
8114 			return(SRC_Request_Avoidance);
8115 		}
8116 	}
8117 	#else
8118 	{
8119 		STRATEGYBLOCK *destructableObject = NULL;
8120 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
8121 		if((marineStatusPointer->obstruction.environment)||(marineStatusPointer->obstruction.otherCharacter))
8122 		{
8123 			/* go to avoidance */
8124 			return(SRC_Request_Avoidance);
8125 		}
8126 		if(marineStatusPointer->obstruction.destructableObject)
8127 		{
8128 			LOCALASSERT(destructableObject);
8129 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
8130 		}
8131 	}
8132 
8133 	if(NPC_CannotReachTarget(&(marineStatusPointer->moveData), &(marineStatusPointer->wanderData.worldPosition), &velocityDirection))
8134 	{
8135 		/* go to avoidance */
8136 		/* no sequence change required */
8137 
8138 		marineStatusPointer->obstruction.environment=1;
8139 		marineStatusPointer->obstruction.destructableObject=0;
8140 		marineStatusPointer->obstruction.otherCharacter=0;
8141 		marineStatusPointer->obstruction.anySingleObstruction=0;
8142 
8143 		return(SRC_Request_Avoidance);
8144 	}
8145 	#endif
8146 
8147 	return(SRC_No_Change);
8148 }
8149 
8150 static STATE_RETURN_CONDITION Execute_MNS_Return(STRATEGYBLOCK *sbPtr)
8151 {
8152 	MARINE_STATUS_BLOCK *marineStatusPointer;
8153 	DYNAMICSBLOCK *dynPtr;
8154 	AIMODULE *targetModule;
8155 	VECTORCH velocityDirection = {0,0,0};
8156 
8157 	LOCALASSERT(sbPtr);
8158 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
8159 	dynPtr = sbPtr->DynPtr;
8160 	LOCALASSERT(marineStatusPointer);
8161 	LOCALASSERT(dynPtr);
8162 
8163 	HandleMovingAnimations(sbPtr);
8164 
8165 	/* should we change to approach state? */
8166 	if(MarineIsAwareOfTarget(sbPtr))
8167 	{
8168 		/* doesn't require a sequence change */
8169 		return(SRC_Request_Approach);
8170 	}
8171 
8172 	#if 0
8173 	/* Ignore alerts. */
8174 	if ((NpcSquad.alertZone)&&(marineStatusPointer->Mission!=MM_LocalGuard)
8175 		&&(marineStatusPointer->Mission!=MM_NonCom)) {
8176 		/* Are we already there? */
8177 		if (sbPtr->containingModule->m_aimodule!=NpcSquad.alertZone) {
8178 			if (NpcSquad.responseLevel>0) {
8179 				/* Picked up a target.  Can we move to respond? */
8180 				AIMODULE *targetModule=0;
8181 				targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
8182 				if (targetModule) {
8183 					return(SRC_Request_Respond);
8184 				}
8185 			}
8186 		}
8187 	}
8188 	#endif
8189 
8190 	marineStatusPointer->stateTimer-=NormalFrameTime;
8191 
8192 	/* Are we there yet? */
8193 	if (sbPtr->containingModule->m_aimodule==marineStatusPointer->missionmodule) {
8194 		return(SRC_Request_Wait);
8195 	}
8196 
8197 	/* Target module aquisition. */
8198 
8199 	LOCALASSERT(sbPtr->containingModule);
8200 
8201 	if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
8202 	{
8203 		NPC_InitMovementData(&(marineStatusPointer->moveData));
8204 	}
8205 	if ((marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
8206 		||(marineStatusPointer->wanderData.currentModule!=sbPtr->containingModule->m_aimodule->m_index)) {
8207 
8208 		targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->missionmodule,7,0);
8209 
8210 		if (targetModule) {
8211 			FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
8212 			if(thisEp) {
8213 				/* aha. an ep!... */
8214 				VECTORCH thisEpWorld = thisEp->position;
8215 
8216 				thisEpWorld.vx += targetModule->m_world.vx;
8217 				thisEpWorld.vy += targetModule->m_world.vy;
8218 				thisEpWorld.vz += targetModule->m_world.vz;
8219 
8220 				marineStatusPointer->wanderData.currentModule = sbPtr->containingModule->m_aimodule->m_index;
8221 		 		marineStatusPointer->wanderData.worldPosition = thisEpWorld;
8222 
8223 				GLOBALASSERT(thisEp->alien_only==0);
8224 				/* If that fired, GetNextModuleForLink went wrong. */
8225 			} else {
8226 				/* Failure case. */
8227 				marineStatusPointer->wanderData.currentModule=NPC_NOWANDERMODULE;
8228 			}
8229 
8230 		} else {
8231 			/* Another failure case. */
8232 			marineStatusPointer->wanderData.currentModule=NPC_NOWANDERMODULE;
8233 		}
8234 	}
8235 
8236 	/* if we still haven't got one, bimble about in this one for a bit. */
8237 	if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
8238 	{
8239 		NPC_InitMovementData(&(marineStatusPointer->moveData));
8240 		marineStatusPointer->moveData.lastModule=marineStatusPointer->lastmodule;
8241 		NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
8242 	}
8243 
8244 	if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE) {
8245 		/* STILL broken!  Okay, just... wander, then. */
8246 		return(SRC_Request_Wander);
8247 	}
8248 
8249 	/* ok: should have a current target at this stage... */
8250 	NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
8251 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
8252 
8253 	/* test here for impeding collisions, and not being able to reach target... */
8254 	#if ALL_NEW_AVOIDANCE
8255 	{
8256 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
8257 			/* Go to all new avoidance. */
8258 			return(SRC_Request_Avoidance);
8259 		}
8260 	}
8261 	#else
8262 	{
8263 		STRATEGYBLOCK *destructableObject = NULL;
8264 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
8265 		if((marineStatusPointer->obstruction.environment)||(marineStatusPointer->obstruction.otherCharacter))
8266 		{
8267 			/* go to avoidance */
8268 			return(SRC_Request_Avoidance);
8269 		}
8270 		if(marineStatusPointer->obstruction.destructableObject)
8271 		{
8272 			LOCALASSERT(destructableObject);
8273 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
8274 		}
8275 	}
8276 
8277 	if(NPC_CannotReachTarget(&(marineStatusPointer->moveData), &(marineStatusPointer->wanderData.worldPosition), &velocityDirection))
8278 	{
8279 		/* go to avoidance */
8280 		/* no sequence change required */
8281 
8282 		marineStatusPointer->obstruction.environment=1;
8283 		marineStatusPointer->obstruction.destructableObject=0;
8284 		marineStatusPointer->obstruction.otherCharacter=0;
8285 		marineStatusPointer->obstruction.anySingleObstruction=0;
8286 
8287 		return(SRC_Request_Avoidance);
8288 	}
8289 	#endif
8290 
8291 	return(SRC_No_Change);
8292 }
8293 
8294 static STATE_RETURN_CONDITION Execute_MNS_Pathfinder(STRATEGYBLOCK *sbPtr)
8295 {
8296 	MARINE_STATUS_BLOCK *marineStatusPointer;
8297 	DYNAMICSBLOCK *dynPtr;
8298 	AIMODULE *targetModule;
8299 	VECTORCH velocityDirection = {0,0,0};
8300 
8301 	LOCALASSERT(sbPtr);
8302 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
8303 	dynPtr = sbPtr->DynPtr;
8304 	LOCALASSERT(marineStatusPointer);
8305 	LOCALASSERT(dynPtr);
8306 
8307 	#if 0
8308 	/* check if we should be crouched or standing up */
8309 	if(marineStatusPointer->IAmCrouched)
8310 	{
8311 		/* curently crouched */
8312 		if(!(MarineShouldBeCrawling(sbPtr)))
8313 		{
8314 			/* should be running*/
8315 			marineStatusPointer->IAmCrouched = 0;
8316 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
8317 		}
8318 	}
8319 	else
8320 	{
8321 		/* currently standing */
8322 		if(MarineShouldBeCrawling(sbPtr))
8323 		{
8324 			/* should be crawling */
8325 			marineStatusPointer->IAmCrouched = 1;
8326 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
8327 		}
8328 	}
8329 	#else
8330 	HandleMovingAnimations(sbPtr);
8331 	#endif
8332 
8333 	/* should we change to approach state? */
8334 	if(MarineIsAwareOfTarget(sbPtr))
8335 	{
8336 		/* doesn't require a sequence change */
8337 		return(SRC_Request_Approach);
8338 	}
8339 
8340 	if (marineStatusPointer->suspicious) {
8341 		MODULE *targetModule;
8342 		/* Are we allowed to check it out? */
8343 		targetModule=ModuleFromPosition(&marineStatusPointer->suspect_point,sbPtr->containingModule);
8344 		if (targetModule) {
8345 			if (IsModuleVisibleFromModule(targetModule,sbPtr->containingModule)) {
8346 				/* I suppose we'd better go, then. */
8347 				if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
8348 					return(SRC_Request_Wait);
8349 				} else {
8350 					return(SRC_Request_Approach);
8351 				}
8352 			}
8353 		}
8354 	}
8355 
8356 	/* Ignore alerts. */
8357 
8358 	marineStatusPointer->stateTimer-=NormalFrameTime;
8359 
8360 	if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
8361 	{
8362 		NPC_InitMovementData(&(marineStatusPointer->moveData));
8363 	}
8364 	if ((marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
8365 		||(marineStatusPointer->wanderData.currentModule!=sbPtr->containingModule->m_aimodule->m_index)) {
8366 
8367 		FARENTRYPOINT *thisEp;
8368 		int nextModuleIndex;
8369 		/* Okay, so where are we exactly? */
8370 
8371 		if ((marineStatusPointer->stepnumber<0)||(marineStatusPointer->path<0)) {
8372 			/* Get OUT! */
8373 			return(SRC_Request_Wander);
8374 		}
8375 
8376 		targetModule = TranslatePathIndex(marineStatusPointer->stepnumber,marineStatusPointer->path);
8377 
8378 		if (targetModule==NULL) {
8379 			/* Oh, to heck with this.  Try to wander. */
8380 			return(SRC_Request_Wander);
8381 		}
8382 
8383 		/* Right, so there is a somewhere to get to. */
8384 
8385 		if (targetModule!=sbPtr->containingModule->m_aimodule) {
8386 			/* But we're nowhere near it.  Geeze... */
8387 			marineStatusPointer->missionmodule=targetModule;
8388 			return(SRC_Request_Return);
8389 		}
8390 
8391 		/* Okay, so now we need to know where to go now. */
8392 
8393 		nextModuleIndex=GetNextModuleInPath(marineStatusPointer->stepnumber,marineStatusPointer->path);
8394 		GLOBALASSERT(nextModuleIndex>=0);
8395 		/* If that fires, it's Richard's fault. */
8396 		targetModule=TranslatePathIndex(nextModuleIndex,marineStatusPointer->path);
8397 		GLOBALASSERT(targetModule);
8398 		/* Ditto. */
8399 		marineStatusPointer->stepnumber=nextModuleIndex;
8400 
8401 		thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
8402 		if(thisEp) {
8403 			/* aha. an ep!... */
8404 			VECTORCH thisEpWorld = thisEp->position;
8405 
8406 			thisEpWorld.vx += targetModule->m_world.vx;
8407 			thisEpWorld.vy += targetModule->m_world.vy;
8408 			thisEpWorld.vz += targetModule->m_world.vz;
8409 
8410 			marineStatusPointer->wanderData.currentModule = sbPtr->containingModule->m_aimodule->m_index;
8411 			marineStatusPointer->wanderData.worldPosition = thisEpWorld;
8412 			GLOBALASSERT(thisEp->alien_only==0);
8413 			/* If that fired, the path goes through an alien-only link. */
8414 
8415 		} else {
8416 			/* Failure case. */
8417 			marineStatusPointer->wanderData.currentModule=NPC_NOWANDERMODULE;
8418 		}
8419 
8420 	}
8421 
8422 	/* if we still haven't got one, wander for a bit. */
8423 	if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
8424 	{
8425 		NPC_InitMovementData(&(marineStatusPointer->moveData));
8426 		marineStatusPointer->moveData.lastModule=marineStatusPointer->lastmodule;
8427 		NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
8428 	}
8429 
8430 	if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE) {
8431 		/* STILL broken!  Okay, just... wander forever, then. */
8432 		return(SRC_Request_Wander);
8433 	}
8434 
8435 	/* ok: should have a current target at this stage... */
8436 	NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
8437 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
8438 
8439 	/* test here for impeding collisions, and not being able to reach target... */
8440 	#if ALL_NEW_AVOIDANCE
8441 	{
8442 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
8443 			/* Go to all new avoidance. */
8444 			return(SRC_Request_Avoidance);
8445 		}
8446 	}
8447 	#else
8448 	{
8449 		STRATEGYBLOCK *destructableObject = NULL;
8450 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
8451 		if((marineStatusPointer->obstruction.environment)||(marineStatusPointer->obstruction.otherCharacter))
8452 		{
8453 			/* go to avoidance */
8454 			return(SRC_Request_Avoidance);
8455 		}
8456 		if(marineStatusPointer->obstruction.destructableObject)
8457 		{
8458 			LOCALASSERT(destructableObject);
8459 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
8460 		}
8461 	}
8462 
8463 	if(NPC_CannotReachTarget(&(marineStatusPointer->moveData), &(marineStatusPointer->wanderData.worldPosition), &velocityDirection))
8464 	{
8465 		/* go to avoidance */
8466 		/* no sequence change required */
8467 
8468 		marineStatusPointer->obstruction.environment=1;
8469 		marineStatusPointer->obstruction.destructableObject=0;
8470 		marineStatusPointer->obstruction.otherCharacter=0;
8471 		marineStatusPointer->obstruction.anySingleObstruction=0;
8472 
8473 		return(SRC_Request_Avoidance);
8474 	}
8475 	#endif
8476 
8477 	return(SRC_No_Change);
8478 }
8479 
8480 void NPC_GetBimbleTarget(STRATEGYBLOCK *sbPtr,VECTORCH *output) {
8481 
8482 	MODULE *my_module;
8483 	VECTORCH alternate;
8484 	int success;
8485 
8486 	/* Get a random position in the same module. */
8487 
8488 	my_module=sbPtr->containingModule;
8489 	success=0;
8490 
8491 	while (success==0) {
8492 
8493 		do {
8494 			output->vx=FastRandom()&65535;
8495 			output->vx+=my_module->m_minx;
8496 		} while (!( (output->vx>my_module->m_minx)&&(output->vx<my_module->m_maxx) ));
8497 
8498 		do {
8499 			output->vz=FastRandom()&65535;
8500 			output->vz+=my_module->m_minz;
8501 		} while (!( (output->vz>my_module->m_minz)&&(output->vz<my_module->m_maxz) ));
8502 
8503 		output->vy=sbPtr->DynPtr->Position.vy;
8504 		output->vy-=my_module->m_world.vy;
8505 
8506 		if (!( (output->vy>my_module->m_miny)&&(output->vy<my_module->m_maxy) )) {
8507 			do {
8508 				output->vy=FastRandom()&65535;
8509 				output->vy+=my_module->m_miny;
8510 			} while (!( (output->vy>my_module->m_miny)&&(output->vy<my_module->m_maxy) ));
8511 		}
8512 
8513 		GLOBALASSERT(PointIsInModule(my_module,output));
8514 
8515 		output->vx+=my_module->m_world.vx;
8516 		output->vy+=my_module->m_world.vy;
8517 		output->vz+=my_module->m_world.vz;
8518 
8519 		/* Check for waypoints? */
8520 
8521 		if (my_module->m_waypoints) {
8522 			if (GetPositionValidity(my_module,output,&alternate)==NULL) {
8523 				/* Failure! */
8524 				success=0;
8525 			} else {
8526 				if ( (alternate.vx!=output->vx)
8527 					|| (alternate.vy!=output->vy)
8528 					|| (alternate.vz!=output->vz) ) {
8529 					*output=alternate;
8530 					/* Success! */
8531 					success=1;
8532 				} else {
8533 					/* Success! */
8534 					success=1;
8535 				}
8536 			}
8537 		} else {
8538 			/* Success! */
8539 			success=1;
8540 		}
8541 
8542 	}
8543 
8544 }
8545 
8546 static void HandleFidgetAnimations(STRATEGYBLOCK *sbPtr) {
8547 
8548 	MARINE_STATUS_BLOCK *marineStatusPointer;
8549 
8550 	LOCALASSERT(sbPtr);
8551 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
8552 	LOCALASSERT(marineStatusPointer);
8553 
8554 	/* A sub function for simplicity. */
8555 
8556 	if(marineStatusPointer->IAmCrouched) {
8557 		/* No crouch fidget yet. */
8558 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineCrouch)
8559 			||(marineStatusPointer->HModelController.Sub_Sequence!=MCrSS_Standard)) {
8560 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrouch,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
8561 		}
8562 	} else {
8563 		/* Are we in some sort of fidget anim? */
8564 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)||(
8565 			(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Stand_To_Fidget)
8566 			&&(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Fidget_A)
8567 			&&(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Fidget_B)
8568 			&&(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Fidget_C)
8569 			)) {
8570 
8571 			if ((marineStatusPointer->HModelController.Sequence_Type==HMSQT_MarineRun)
8572 				&&(marineStatusPointer->HModelController.Sub_Sequence==MRSS_Mooch_Bored)) {
8573 				/* Mooch bored does not require Stand_To_Fidget - go directly to Fidget_A. */
8574 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_A)) {
8575 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Fidget_A,ONE_FIXED<<3,(ONE_FIXED>>3));
8576 					marineStatusPointer->internalState=0;
8577 				} else {
8578 					/* No fidgets at all! */
8579 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
8580 				}
8581 			} else if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Stand_To_Fidget)) {
8582 				/* Not in any kind of fidget anim: run Stand_To_Fidget if poss. */
8583 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Stand_To_Fidget,((ONE_FIXED*3)/2),(ONE_FIXED>>3));
8584 				marineStatusPointer->HModelController.LoopAfterTweening=0;
8585 			} else if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_A)) {
8586 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Fidget_A,ONE_FIXED<<3,(ONE_FIXED>>3));
8587 			} else {
8588 				/* No fidgets at all! */
8589 				SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
8590 			}
8591 
8592 		} else {
8593 			if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Stand_To_Fidget)) {
8594 				/* We must have gone through StandToFidget, or at least be in it. */
8595 				if (((marineStatusPointer->HModelController.Tweening==Controller_NoTweening)
8596 					&&(marineStatusPointer->HModelController.sequence_timer==(ONE_FIXED-1))
8597 					&&(marineStatusPointer->HModelController.Looped==0))
8598 				||((marineStatusPointer->HModelController.keyframe_flags)&&(marineStatusPointer->internalState))) {
8599 					/* End of old sequence. */
8600 					/* Go back to normal. */
8601 					if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_A)) {
8602 						SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Fidget_A,ONE_FIXED<<3,(ONE_FIXED>>3));
8603 						marineStatusPointer->internalState=0;
8604 					}
8605 				} else if (marineStatusPointer->HModelController.keyframe_flags) {
8606 					if ((FastRandom()&65535)<21846) {
8607 						if ((FastRandom()&65535)<32767) {
8608 							if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_B)) {
8609 								SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Fidget_B,-1,(ONE_FIXED>>3));
8610 								marineStatusPointer->HModelController.LoopAfterTweening=0;
8611 								marineStatusPointer->internalState=1;
8612 							} else if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_C)) {
8613 								SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Fidget_C,-1,(ONE_FIXED>>3));
8614 								marineStatusPointer->HModelController.LoopAfterTweening=0;
8615 								marineStatusPointer->internalState=2;
8616 							}
8617 						} else {
8618 							if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_C)) {
8619 								SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Fidget_C,-1,(ONE_FIXED>>3));
8620 								marineStatusPointer->HModelController.LoopAfterTweening=0;
8621 								marineStatusPointer->internalState=2;
8622 							} else if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_B)) {
8623 								SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Fidget_B,-1,(ONE_FIXED>>3));
8624 								marineStatusPointer->HModelController.LoopAfterTweening=0;
8625 								marineStatusPointer->internalState=1;
8626 							}
8627 						}
8628 					}
8629 					/* Else do nothing, I guess. */
8630 				}
8631 			} else {
8632 				/* No stand to fidget. */
8633 			}
8634 		}
8635 	}
8636 
8637 }
8638 
8639 static void HandleWaitingAnimations(STRATEGYBLOCK *sbPtr) {
8640 
8641 	MARINE_STATUS_BLOCK *marineStatusPointer;
8642 	int tweeningtime;
8643 
8644 	LOCALASSERT(sbPtr);
8645 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
8646 	LOCALASSERT(marineStatusPointer);
8647 
8648 	#if 0
8649 	/* If you get here, you look stationary, so BE stationary! */
8650 	sbPtr->DynPtr->LinVelocity.vx = 0;
8651 	sbPtr->DynPtr->LinVelocity.vy = 0;
8652 	sbPtr->DynPtr->LinVelocity.vz = 0;
8653 	#endif
8654 
8655 	{
8656 		DELTA_CONTROLLER *delta;
8657 		/* There should be NO head turn delta. */
8658 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
8659 		if (delta) {
8660 			Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
8661 		}
8662 	}
8663 
8664 	/* First test to see if we're in midair. */
8665 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_Jump)) {
8666 		if (!sbPtr->DynPtr->IsInContactWithFloor) {
8667 			VECTORCH offset;
8668 
8669 			offset.vx=sbPtr->DynPtr->Position.vx-sbPtr->DynPtr->PrevPosition.vx;
8670 			offset.vy=sbPtr->DynPtr->Position.vy-sbPtr->DynPtr->PrevPosition.vy;
8671 			offset.vz=sbPtr->DynPtr->Position.vz-sbPtr->DynPtr->PrevPosition.vz;
8672 
8673 			if ((offset.vx!=0)||(offset.vy!=0)||(offset.vz!=0)) {
8674 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
8675 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Jump)) {
8676 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Jump,-1,(ONE_FIXED>>4));
8677 				}
8678 			}
8679 		}
8680 	}
8681 
8682 	/* Get a random tweening time... */
8683 
8684 	tweeningtime=((FastRandom()&65535)+32767)>>3;
8685 
8686 	/* Figure out what we should be playing, and do it. */
8687 
8688 	if (MarineShouldBeCrawling(sbPtr)) {
8689 		marineStatusPointer->IAmCrouched=1;
8690 	} else {
8691 		marineStatusPointer->IAmCrouched=0;
8692 	}
8693 
8694 	if(marineStatusPointer->IAmCrouched) {
8695 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineCrouch)
8696 			||(marineStatusPointer->HModelController.Sub_Sequence!=MCSS_Standard)) {
8697 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrouch,MCSS_Standard,ONE_FIXED,tweeningtime);
8698 		}
8699 	} else {
8700 		if (marineStatusPointer->suspicious) {
8701 			/* Go directly to wait alert, if you can. */
8702 			if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_Wait_Alert)) {
8703 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
8704 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Wait_Alert)) {
8705 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Wait_Alert,(MUL_FIXED((ONE_FIXED<<2),((FastRandom()&32767)+65536))),tweeningtime);
8706 				}
8707 			} else {
8708 				HandleFidgetAnimations(sbPtr);
8709 			}
8710 		} else {
8711 			HandleFidgetAnimations(sbPtr);
8712 		}
8713 	}
8714 }
8715 
8716 static void HandleMovingAnimations(STRATEGYBLOCK *sbPtr) {
8717 
8718 	MARINE_STATUS_BLOCK *marineStatusPointer;
8719 	MARINE_MOVEMENT_STYLE style;
8720 	MARINE_BHSTATE baseState;
8721 	const MOVEMENT_DATA *movementData;
8722 	VECTORCH offset;
8723 	int can_mooch_bored;
8724 	int can_mooch_alert;
8725 	int can_sprint;
8726 	int speed,animfactor;
8727 
8728 	LOCALASSERT(sbPtr);
8729 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
8730 	LOCALASSERT(marineStatusPointer);
8731 
8732 	style=-1;
8733 
8734 	/* First test to see if we're in midair. */
8735 	if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_Jump)) {
8736 		if (!sbPtr->DynPtr->IsInContactWithFloor) {
8737 			VECTORCH offset;
8738 
8739 			offset.vx=sbPtr->DynPtr->Position.vx-sbPtr->DynPtr->PrevPosition.vx;
8740 			offset.vy=sbPtr->DynPtr->Position.vy-sbPtr->DynPtr->PrevPosition.vy;
8741 			offset.vz=sbPtr->DynPtr->Position.vz-sbPtr->DynPtr->PrevPosition.vz;
8742 
8743 			if ((offset.vx!=0)||(offset.vy!=0)||(offset.vz!=0)) {
8744 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
8745 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Jump)) {
8746 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Jump,-1,(ONE_FIXED>>4));
8747 				}
8748 			}
8749 		}
8750 	}
8751 
8752 	can_mooch_bored=HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineRun,MRSS_Mooch_Bored);
8753 	can_mooch_alert=HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineRun,MRSS_Mooch_Alert);
8754 	can_sprint=HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineRun,MRSS_Sprint);
8755 
8756 	/* Figure out what we should be playing... */
8757 
8758 	if (marineStatusPointer->behaviourState==MBS_Avoidance) {
8759 		baseState=marineStatusPointer->lastState;
8760 	} else {
8761 		baseState=marineStatusPointer->behaviourState;
8762 	}
8763 
8764 	switch (baseState) {
8765 		case MBS_Waiting:
8766 			/* Why am I here? */
8767 			style=MMS_Alert;
8768 			break;
8769 		case MBS_Wandering:
8770 			style=MMS_Bored;
8771 			break;
8772 		case MBS_Retreating:
8773 			style=MMS_Sprint;
8774 			break;
8775 		case MBS_Sentry:
8776 		case MBS_Returning:
8777 		case MBS_Pathfinding:
8778 			if (marineStatusPointer->Target==NULL) {
8779 				if (marineStatusPointer->suspicious) {
8780 					style=MMS_Alert;
8781 				} else {
8782 					style=MMS_Bored;
8783 				}
8784 			} else {
8785 				style=MMS_Combat;
8786 			}
8787 		case MBS_Approaching:
8788 		case MBS_Responding:
8789 			if (marineStatusPointer->Target==NULL) {
8790 				style=MMS_Alert;
8791 			} else {
8792 				style=MMS_Combat;
8793 			}
8794 			break;
8795 		case MBS_Firing:
8796 			/* Shouldn't really be here. */
8797 			style=MMS_Combat;
8798 			break;
8799 		case MBS_Avoidance:
8800 		case MBS_Dying:
8801 			/* Definitely shouldn't be here! */
8802 			GLOBALASSERT(0);
8803 			break;
8804 		default:
8805 			/* Shouldn't really be here. */
8806 			style=MMS_Combat;
8807 			break;
8808 	}
8809 
8810 	/* Finally... */
8811 	offset.vx=sbPtr->DynPtr->Position.vx-sbPtr->DynPtr->PrevPosition.vx;
8812 	offset.vy=sbPtr->DynPtr->Position.vy-sbPtr->DynPtr->PrevPosition.vy;
8813 	offset.vz=sbPtr->DynPtr->Position.vz-sbPtr->DynPtr->PrevPosition.vz;
8814 	{
8815 		#if 0
8816 		int dist;
8817 		/* ...compute speed factor... */
8818 		speed=Approximate3dMagnitude(&sbPtr->DynPtr->LinVelocity);
8819 		dist=Approximate3dMagnitude(&offset);
8820 		if (dist<(MUL_FIXED(NormalFrameTime,100))) {
8821 			/* Not moving much, are we? */
8822 			style=MMS_Stationary;
8823 		}
8824 		#else
8825 		/* ...compute speed factor... */
8826 		speed=Magnitude(&offset);
8827 		if (speed<(MUL_FIXED(NormalFrameTime,50))) {
8828 			/* Not moving much, are we? */
8829 			style=MMS_Stationary;
8830 		}
8831 		speed=DIV_FIXED(speed,NormalFrameTime);
8832 		#endif
8833 	}
8834 
8835 	/* Fix crouching. */
8836 	if(marineStatusPointer->IAmCrouched)
8837 	{
8838 		/* currently crouched */
8839 		if(!(MarineShouldBeCrawling(sbPtr))) {
8840 			marineStatusPointer->IAmCrouched=0;
8841 		}
8842 	} else {
8843 		/* currently standing */
8844 		if(MarineShouldBeCrawling(sbPtr)) {
8845 			marineStatusPointer->IAmCrouched=1;
8846 		}
8847 	}
8848 
8849 	/* Now, pre-emptive reject of unavailable cases. */
8850 	if (style==MMS_Bored) {
8851 		if (!can_mooch_bored) {
8852 			style=MMS_Combat;
8853 		}
8854 	}
8855 
8856 	if (style==MMS_Alert) {
8857 		if (!can_mooch_alert) {
8858 			style=MMS_Combat;
8859 		}
8860 	}
8861 
8862 	if (style==MMS_Sprint) {
8863 		#if 1
8864 		if (!can_sprint) {
8865 		#else
8866 		if (1) {
8867 		#endif
8868 			style=MMS_Combat;
8869 		}
8870 	}
8871 
8872 	if (speed==0) {
8873 		style=MMS_Stationary;
8874 		animfactor=ONE_FIXED;
8875 	} else {
8876 		animfactor=DIV_FIXED(625,speed); // Was 512!  Difference to correct for rounding down...
8877 	}
8878 	GLOBALASSERT(animfactor>0);
8879 
8880 	/* ...and do it. */
8881 	switch (style) {
8882 
8883 		case -1:
8884 			/* Whoops! */
8885 			GLOBALASSERT(0);
8886 			break;
8887 		case MMS_Stationary:
8888 			{
8889 				/* Ouch. */
8890 				HandleWaitingAnimations(sbPtr);
8891 			}
8892 			break;
8893 		case MMS_Bored:
8894 			{
8895 				if(marineStatusPointer->IAmCrouched) {
8896 					if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineCrawl)
8897 						||(marineStatusPointer->HModelController.Sub_Sequence!=MCSS_Standard)) {
8898 						SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCSS_Standard,ONE_FIXED,(ONE_FIXED>>4));
8899 					}
8900 
8901 					if (marineStatusPointer->My_Weapon->ARealMarine) {
8902 						movementData=GetThisMovementData(MDI_Marine_Combat);
8903 					} else {
8904 						movementData=GetThisMovementData(MDI_Civilian_Combat);
8905 					}
8906 					GLOBALASSERT(movementData);
8907 					marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatusPointer->speedConstant);
8908 					marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration,marineStatusPointer->accelerationConstant);
8909 
8910 				} else {
8911 					/* If we're here, we must be able to mooch bored. */
8912 					if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineRun)
8913 						||(marineStatusPointer->HModelController.Sub_Sequence!=MRSS_Mooch_Bored)) {
8914 						SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Mooch_Bored,((ONE_FIXED*7)/5),(ONE_FIXED>>4));
8915 					}
8916 
8917 					if (marineStatusPointer->My_Weapon->ARealMarine) {
8918 						movementData=GetThisMovementData(MDI_Marine_Mooch_Bored);
8919 					} else {
8920 						movementData=GetThisMovementData(MDI_Civilian_Mooch_Bored);
8921 					}
8922 					GLOBALASSERT(movementData);
8923 					marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatusPointer->speedConstant);
8924 					marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration,marineStatusPointer->accelerationConstant);
8925 
8926 					//marineStatusPointer->nearSpeed=MARINE_NEAR_SPEED>>2;
8927 				}
8928 			}
8929 			break;
8930 		case MMS_Alert:
8931 			{
8932 				if(marineStatusPointer->IAmCrouched) {
8933 					if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineCrawl)
8934 						||(marineStatusPointer->HModelController.Sub_Sequence!=MCSS_Standard)) {
8935 							SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCSS_Standard,ONE_FIXED,(ONE_FIXED>>4));
8936 					}
8937 
8938 					if (marineStatusPointer->My_Weapon->ARealMarine) {
8939 						movementData=GetThisMovementData(MDI_Marine_Combat);
8940 					} else {
8941 						movementData=GetThisMovementData(MDI_Civilian_Combat);
8942 					}
8943 					GLOBALASSERT(movementData);
8944 					marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatusPointer->speedConstant);
8945 					marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration,marineStatusPointer->accelerationConstant);
8946 				} else {
8947 					/* If we're here, we must be able to mooch alert. */
8948 					if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineRun)
8949 						||(marineStatusPointer->HModelController.Sub_Sequence!=MRSS_Mooch_Alert)) {
8950 						SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Mooch_Alert,((ONE_FIXED*23)/10),(ONE_FIXED>>4));
8951 					}
8952 					if (marineStatusPointer->My_Weapon->ARealMarine) {
8953 						movementData=GetThisMovementData(MDI_Marine_Mooch_Alert);
8954 					} else {
8955 						movementData=GetThisMovementData(MDI_Civilian_Mooch_Alert);
8956 					}
8957 					GLOBALASSERT(movementData);
8958 					marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatusPointer->speedConstant);
8959 					marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration,marineStatusPointer->accelerationConstant);
8960 				}
8961 			}
8962 			break;
8963 		case MMS_Sprint:
8964 			{
8965 				if(marineStatusPointer->IAmCrouched) {
8966 					if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineCrawl)
8967 						||(marineStatusPointer->HModelController.Sub_Sequence!=MCSS_Standard)) {
8968 							SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCSS_Standard,ONE_FIXED,(ONE_FIXED>>4));
8969 					}
8970 					if (marineStatusPointer->My_Weapon->ARealMarine) {
8971 						movementData=GetThisMovementData(MDI_Marine_Combat);
8972 					} else {
8973 						movementData=GetThisMovementData(MDI_Civilian_Combat);
8974 					}
8975 					GLOBALASSERT(movementData);
8976 					marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatusPointer->speedConstant);
8977 					marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration,marineStatusPointer->accelerationConstant);
8978 				} else {
8979 					/* If we're here, we must be able to sprint. */
8980 					if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineRun)
8981 						||(marineStatusPointer->HModelController.Sub_Sequence!=MRSS_Sprint)) {
8982 						SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Sprint,((ONE_FIXED*7)/10),(ONE_FIXED>>4));
8983 					}
8984 					if (marineStatusPointer->My_Weapon->ARealMarine) {
8985 						movementData=GetThisMovementData(MDI_Marine_Sprint);
8986 					} else {
8987 						movementData=GetThisMovementData(MDI_Civilian_Sprint);
8988 					}
8989 					GLOBALASSERT(movementData);
8990 					marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatusPointer->speedConstant);
8991 					marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration,marineStatusPointer->accelerationConstant);
8992 				}
8993 			}
8994 			break;
8995 		case MMS_Combat:
8996 		default:
8997 			{
8998 				if(marineStatusPointer->IAmCrouched) {
8999 					if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineCrawl)
9000 						||(marineStatusPointer->HModelController.Sub_Sequence!=MCSS_Standard)) {
9001 							SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCSS_Standard,ONE_FIXED,(ONE_FIXED>>4));
9002 					}
9003 					if (marineStatusPointer->My_Weapon->ARealMarine) {
9004 						movementData=GetThisMovementData(MDI_Marine_Combat);
9005 					} else {
9006 						movementData=GetThisMovementData(MDI_Civilian_Combat);
9007 					}
9008 					GLOBALASSERT(movementData);
9009 					marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatusPointer->speedConstant);
9010 					marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration,marineStatusPointer->accelerationConstant);
9011 				} else {
9012 					if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineRun)
9013 						||(marineStatusPointer->HModelController.Sub_Sequence!=MRSS_Standard)) {
9014 						SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>4));
9015 					}
9016 					if (marineStatusPointer->My_Weapon->ARealMarine) {
9017 						movementData=GetThisMovementData(MDI_Marine_Combat);
9018 					} else {
9019 						movementData=GetThisMovementData(MDI_Civilian_Combat);
9020 					}
9021 					GLOBALASSERT(movementData);
9022 					marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed,marineStatusPointer->speedConstant);
9023 					marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration,marineStatusPointer->accelerationConstant);
9024 				}
9025 			}
9026 			break;
9027 
9028 	}
9029 	if (marineStatusPointer->HModelController.Tweening==0) {
9030 		HModel_SetToolsRelativeSpeed(&marineStatusPointer->HModelController,animfactor);
9031 	}
9032 
9033 	/* Finally, civilians sprinting away look over their shoulders... */
9034 	{
9035 		int crs;
9036 		DELTA_CONTROLLER *delta;
9037 
9038 		crs=0;
9039 
9040 		if (marineStatusPointer->My_Weapon->ARealMarine==0) {
9041 			if (style==MMS_Sprint) {
9042 				if (marineStatusPointer->IAmCrouched==0) {
9043 					if (marineStatusPointer->behaviourState==MBS_Retreating) {
9044 						if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineRun,MRSS_SprintHeadDelta)) {
9045 							crs=1;
9046 						}
9047 					}
9048 				}
9049 			}
9050 		}
9051 
9052 		if (crs) {
9053 			delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
9054 			if (!delta) {
9055 				/* Add it. */
9056 				delta=Add_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta",(int)HMSQT_MarineRun,(int)MRSS_SprintHeadDelta,-1);
9057 				GLOBALASSERT(delta);
9058 				delta->Playing=0;
9059 				delta->Looped=0;
9060 			}
9061 			/* Now we must have it... */
9062 			if (delta->Playing==0) {
9063 				if (marineStatusPointer->incidentFlag) {
9064 					/* Start it. */
9065 					Start_Delta_Sequence(delta,(int)HMSQT_MarineRun,(int)MRSS_SprintHeadDelta,-1);
9066 					delta->Playing=1;
9067 				}
9068 			} else {
9069 				if (DeltaAnimation_IsFinished(delta)) {
9070 					delta->Playing=0;
9071 				}
9072 			}
9073 		} else {
9074 			/* There should be NO such delta. */
9075 			delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
9076 			if (delta) {
9077 				Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
9078 			}
9079 		}
9080 	}
9081 }
9082 
9083 static STATE_RETURN_CONDITION Execute_MNS_SentryMode(STRATEGYBLOCK *sbPtr) {
9084 
9085 	MARINE_STATUS_BLOCK *marineStatusPointer;
9086 	VECTORCH orientationDirn,offset,velocityDirection;
9087 	int correctlyOrientated,range;
9088 	int dist;
9089 
9090 	LOCALASSERT(sbPtr);
9091 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
9092 	LOCALASSERT(marineStatusPointer);
9093 
9094 	offset.vx=sbPtr->DynPtr->Position.vx-marineStatusPointer->my_spot.vx;
9095 	offset.vy=sbPtr->DynPtr->Position.vy-marineStatusPointer->my_spot.vy;
9096 	offset.vz=sbPtr->DynPtr->Position.vz-marineStatusPointer->my_spot.vz;
9097 	/* Fix for midair start points, grrrr. */
9098 	offset.vy>>=2;
9099 
9100 	/* Find distance off spot. */
9101 	dist=Approximate3dMagnitude(&offset);
9102 
9103 	if ((dist<SENTRY_SENSITIVITY)&&(sbPtr->containingModule->m_aimodule==marineStatusPointer->missionmodule)) {
9104 
9105 		/* On the spot. */
9106 
9107 		/* zero velocity */
9108 		LOCALASSERT(sbPtr->DynPtr);
9109 		sbPtr->DynPtr->LinVelocity.vx = 0;
9110 		sbPtr->DynPtr->LinVelocity.vy = 0;
9111 		sbPtr->DynPtr->LinVelocity.vz = 0;
9112 
9113 		HandleWaitingAnimations(sbPtr);
9114 
9115 		correctlyOrientated=0;
9116 
9117 		if(MarineIsAwareOfTarget(sbPtr)) {
9118 
9119 			GLOBALASSERT(marineStatusPointer->Target);
9120 			NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
9121 
9122 			/* orientate to firing point first */
9123 			orientationDirn.vx = marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
9124 			orientationDirn.vy = 0;
9125 			orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
9126 			correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
9127 
9128 		} else if (marineStatusPointer->suspicious) {
9129 			/* Orientate to suspect point? */
9130 			orientationDirn.vx = marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
9131 			orientationDirn.vy = 0;
9132 			orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
9133 			correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
9134 
9135 			if (correctlyOrientated) {
9136 				/* Please don't be staring at a wall... */
9137     			SECTION_DATA *head_sec;
9138 				VECTORCH sight_vec;
9139 
9140 				head_sec=GetThisSectionData(marineStatusPointer->HModelController.section_data,"head");
9141 				GLOBALASSERT(head_sec);
9142 
9143 				sight_vec.vx=sbPtr->DynPtr->OrientMat.mat31;
9144 				sight_vec.vy=sbPtr->DynPtr->OrientMat.mat32;
9145 				sight_vec.vz=sbPtr->DynPtr->OrientMat.mat33;
9146 
9147 				FindPolygonInLineOfSight(&sight_vec,&head_sec->World_Offset,0,sbPtr->SBdptr);
9148 				if (LOS_ObjectHitPtr) {
9149 					if (SBIsEnvironment(LOS_ObjectHitPtr->ObStrategyBlock)) {
9150 						if (LOS_Lambda<2000) {
9151 							Marine_MirrorSuspectPoint(sbPtr);
9152 						}
9153 					}
9154 				}
9155 			}
9156 			marineStatusPointer->gotapoint=0;
9157 		} else {
9158 			if (marineStatusPointer->gotapoint) {
9159 				VECTORCH orientationDirn;
9160 				int correctlyOrientated;
9161 
9162 				orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
9163 				orientationDirn.vy = 0;
9164 				orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
9165 				correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
9166 			} else {
9167 				GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
9168 			}
9169 		}
9170 
9171 		if(!correctlyOrientated) {
9172 
9173 			return(SRC_No_Change);
9174 
9175 		}
9176 
9177 		if (marineStatusPointer->Target==NULL) {
9178 			/* Must be suspicious? */
9179 			if (marineStatusPointer->suspicious) {
9180 				return(SRC_No_Change);
9181 			}
9182 			/* Else drop through? */
9183 		} else {
9184 			/* We have a target, and should be correctly orientated. */
9185 
9186 			if (MarineCanSeeTarget(sbPtr)) {
9187 				/* I can see! */
9188 				range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
9189 
9190 				if ((marineStatusPointer->My_Weapon->MaxRange==-1) ||
9191 					(range<marineStatusPointer->My_Weapon->MaxRange)) {
9192 
9193 				   return(SRC_Request_Fire);
9194 
9195 				}
9196 			} else {
9197 				/* Eh? */
9198 				if (marineStatusPointer->suspicious) {
9199 					return(SRC_No_Change);
9200 				}
9201 			}
9202 		}
9203 
9204 		/* Well, we're stuck with sentrymode. */
9205 		if (marineStatusPointer->gotapoint) {
9206 
9207 			VECTORCH orientationDirn;
9208 			int correctlyOrientated;
9209 
9210 			orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
9211 			orientationDirn.vy = 0;
9212 			orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
9213 
9214 			correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
9215 
9216 		} else {
9217 			GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
9218 		}
9219 
9220 		return(SRC_No_Change);
9221 
9222 	}
9223 
9224 	/* If you got here, you're lost. */
9225 
9226 	if (marineStatusPointer->missionmodule==NULL) {
9227 		/* Fused! */
9228 		return(SRC_No_Change);
9229 	}
9230 
9231 	HandleMovingAnimations(sbPtr);
9232 
9233 	if (sbPtr->containingModule->m_aimodule!=marineStatusPointer->missionmodule) {
9234 
9235 		AIMODULE *targetModule;
9236 		/* Not even in the same module! */
9237 
9238 		if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
9239 		{
9240 			NPC_InitMovementData(&(marineStatusPointer->moveData));
9241 		}
9242 		if ((marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
9243 			||(marineStatusPointer->wanderData.currentModule!=sbPtr->containingModule->m_aimodule->m_index)) {
9244 
9245 			targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->missionmodule,7,0);
9246 
9247 			if (targetModule) {
9248 				FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
9249 				if(thisEp) {
9250 					/* aha. an ep!... */
9251 					VECTORCH thisEpWorld = thisEp->position;
9252 
9253 					thisEpWorld.vx += targetModule->m_world.vx;
9254 					thisEpWorld.vy += targetModule->m_world.vy;
9255 					thisEpWorld.vz += targetModule->m_world.vz;
9256 
9257 					marineStatusPointer->wanderData.currentModule = sbPtr->containingModule->m_aimodule->m_index;
9258 			 		marineStatusPointer->wanderData.worldPosition = thisEpWorld;
9259 
9260 					GLOBALASSERT(thisEp->alien_only==0);
9261 					/* If that fired, GetNextModuleForLink went wrong. */
9262 
9263 				} else {
9264 					/* Failure case. */
9265 					marineStatusPointer->wanderData.currentModule=NPC_NOWANDERMODULE;
9266 				}
9267 
9268 			} else {
9269 				/* Another failure case. */
9270 				marineStatusPointer->wanderData.currentModule=NPC_NOWANDERMODULE;
9271 			}
9272 		}
9273 
9274 		/* if we still haven't got one, bimble about in this one for a bit. */
9275 		if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE)
9276 		{
9277 			NPC_InitMovementData(&(marineStatusPointer->moveData));
9278 			marineStatusPointer->moveData.lastModule=marineStatusPointer->lastmodule;
9279 			NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
9280 		}
9281 
9282 		if(marineStatusPointer->wanderData.currentModule==NPC_NOWANDERMODULE) {
9283 			/* STILL broken!  We're in a lot of trouble. */
9284 			return(SRC_No_Change);
9285 		}
9286 
9287 		/* Should have a legal target. */
9288 		NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
9289 
9290 	} else {
9291 		/* Same module, wrong place.  Just go for it.  */
9292 		NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->my_spot),&marineStatusPointer->waypointManager);
9293 
9294 	}
9295 
9296 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
9297 
9298 	/* test here for impeding collisions, and not being able to reach target... */
9299 	#if ALL_NEW_AVOIDANCE
9300 	{
9301 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
9302 			/* Go to all new avoidance. */
9303 			return(SRC_Request_Avoidance);
9304 		}
9305 	}
9306 	#else
9307 	{
9308 		STRATEGYBLOCK *destructableObject = NULL;
9309 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
9310 		if((marineStatusPointer->obstruction.environment)||(marineStatusPointer->obstruction.otherCharacter))
9311 		{
9312 			/* go to avoidance */
9313 			return(SRC_Request_Avoidance);
9314 		}
9315 		if(marineStatusPointer->obstruction.destructableObject)
9316 		{
9317 			LOCALASSERT(destructableObject);
9318 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
9319 		}
9320 	}
9321 
9322 	if(NPC_CannotReachTarget(&(marineStatusPointer->moveData), &(marineStatusPointer->wanderData.worldPosition), &velocityDirection))
9323 	{
9324 		/* go to avoidance */
9325 		/* no sequence change required */
9326 
9327 		marineStatusPointer->obstruction.environment=1;
9328 		marineStatusPointer->obstruction.destructableObject=0;
9329 		marineStatusPointer->obstruction.otherCharacter=0;
9330 		marineStatusPointer->obstruction.anySingleObstruction=0;
9331 
9332 		return(SRC_Request_Avoidance);
9333 	}
9334 	#endif
9335 
9336 	return(SRC_No_Change);
9337 
9338 
9339 }
9340 
9341 static STATE_RETURN_CONDITION Execute_MNS_Wait(STRATEGYBLOCK *sbPtr)
9342 {
9343 	/* wait until near state timer runs out, then wander:
9344 	alternatively, if we can attack the target, go straight to approach */
9345 	MARINE_STATUS_BLOCK *marineStatusPointer;
9346 	DYNAMICSBLOCK *dynPtr;
9347 
9348 	LOCALASSERT(sbPtr);
9349 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
9350 	dynPtr = sbPtr->DynPtr;
9351 	LOCALASSERT(marineStatusPointer);
9352 	LOCALASSERT(dynPtr);
9353 
9354 	/* zero velocity */
9355 	LOCALASSERT(sbPtr->DynPtr);
9356 	sbPtr->DynPtr->LinVelocity.vx = 0;
9357 	sbPtr->DynPtr->LinVelocity.vy = 0;
9358 	sbPtr->DynPtr->LinVelocity.vz = 0;
9359 
9360 	/* test for attack */
9361 	if (MarineIsAwareOfTarget(sbPtr))
9362 	{
9363 		if ((FastRandom()&65535)<32767) {
9364 			return(SRC_Request_Approach);
9365 		} else {
9366 			return(SRC_Request_Fire);
9367 		}
9368 	}
9369 
9370 	if (marineStatusPointer->suspicious) {
9371 		int range;
9372 
9373 		#if 0
9374 		range=VectorDistance(&marineStatusPointer->suspect_point,(&sbPtr->DynPtr->Position));
9375 		#else
9376 		VECTORCH targetPosition;
9377 
9378 		targetPosition=marineStatusPointer->suspect_point;
9379 
9380 		targetPosition.vx-=sbPtr->DynPtr->Position.vx;
9381 		targetPosition.vy-=sbPtr->DynPtr->Position.vy;
9382 		targetPosition.vz-=sbPtr->DynPtr->Position.vz;
9383 
9384 		/* Let's try doing this. */
9385 		targetPosition.vy>>=2;
9386 
9387 		range=Approximate3dMagnitude(&targetPosition);
9388 		#endif
9389 
9390 		if (range>SUSPECT_SENSITIVITY) {
9391 			/* Too far away! */
9392 			marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
9393 			/* Used to unset suspicion at that point. */
9394 			return(SRC_Request_Approach);
9395 		} else {
9396 			/* We could at least turn to face it. */
9397 			VECTORCH orientationDirn;
9398 			int correctlyOrientated;
9399 
9400 			orientationDirn.vx = marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
9401 			orientationDirn.vy = 0;
9402 			orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
9403 
9404 			if (sbPtr->SBDamageBlock.IsOnFire) {
9405 				/* Can't handle 'suspect points' stuck to them! */
9406 				correctlyOrientated = 1;
9407 			} else {
9408 				correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
9409 			}
9410 
9411 			/* For when suspicion times out. */
9412 			marineStatusPointer->gotapoint=0;
9413 
9414 			if (correctlyOrientated) {
9415 				/* Please don't be staring at a wall... */
9416     			SECTION_DATA *head_sec;
9417 				VECTORCH sight_vec;
9418 
9419 				head_sec=GetThisSectionData(marineStatusPointer->HModelController.section_data,"head");
9420 				GLOBALASSERT(head_sec);
9421 
9422 				sight_vec.vx=sbPtr->DynPtr->OrientMat.mat31;
9423 				sight_vec.vy=sbPtr->DynPtr->OrientMat.mat32;
9424 				sight_vec.vz=sbPtr->DynPtr->OrientMat.mat33;
9425 
9426 				FindPolygonInLineOfSight(&sight_vec,&head_sec->World_Offset,0,sbPtr->SBdptr);
9427 				if (LOS_ObjectHitPtr) {
9428 					if (SBIsEnvironment(LOS_ObjectHitPtr->ObStrategyBlock)) {
9429 						if (LOS_Lambda<2000) {
9430 							Marine_MirrorSuspectPoint(sbPtr);
9431 						}
9432 					}
9433 				}
9434 			}
9435 
9436 		}
9437 
9438 	}
9439 
9440 	/* Think Sequences. */
9441 
9442 	HandleWaitingAnimations(sbPtr);
9443 
9444 	if ((NpcSquad.alertZone)&&(marineStatusPointer->Mission!=MM_LocalGuard)
9445 		&&(marineStatusPointer->Mission!=MM_NonCom)) {
9446 		/* Are we already there? */
9447 		if (sbPtr->containingModule->m_aimodule!=NpcSquad.alertZone) {
9448 			if (NpcSquad.responseLevel>0) {
9449 				/* Picked up a target.  Can we move to respond? */
9450 				AIMODULE *targetModule=0;
9451 				targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
9452 				if (targetModule) {
9453 					return(SRC_Request_Respond);
9454 				}
9455 			}
9456 		}
9457 	}
9458 
9459 	/* still waiting: decrement timer */
9460 	marineStatusPointer->stateTimer-=NormalFrameTime;
9461 
9462 	if(marineStatusPointer->stateTimer<=0)
9463 	{
9464 
9465 		/* Might want to wander. */
9466 
9467 		if ((FastRandom()&65535)<2048)
9468 		{
9469 			/* we should be wandering... we're bored of waiting. */
9470 			return(SRC_Request_Wander);
9471 		}
9472 
9473 		/* No, I'm happy waiting. */
9474 		marineStatusPointer->stateTimer=MARINE_NEARWAITTIME;
9475 		return(SRC_No_Change);
9476 	}
9477 
9478 	/* Well, we're stuck with waiting. */
9479 
9480 	if (marineStatusPointer->suspicious) {
9481 		/* Stay facing the suspect point. */
9482 		return(SRC_No_Change);
9483 	}
9484 
9485 	if (marineStatusPointer->gotapoint) {
9486 
9487 		VECTORCH orientationDirn;
9488 		int correctlyOrientated;
9489 
9490 		orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
9491 		orientationDirn.vy = 0;
9492 		orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
9493 
9494 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
9495 
9496 	} else {
9497 		GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
9498 	}
9499 
9500 	return(SRC_No_Change);
9501 }
9502 
9503 /*----------------------- Patrick 16/6/97 ------------------------
9504   Special state for dying:
9505   NB once we have entered this state, we are locked into it until
9506   we are dead.
9507   ----------------------------------------------------------------*/
9508 static void Execute_Dying(STRATEGYBLOCK *sbPtr)
9509 {
9510 	MARINE_STATUS_BLOCK *marineStatusPointer;
9511 
9512 	LOCALASSERT(sbPtr);
9513 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
9514 	LOCALASSERT(marineStatusPointer);
9515 
9516 	#if 0
9517 	sbPtr->DynPtr->LinVelocity.vx = 0;
9518 	sbPtr->DynPtr->LinVelocity.vy = 0;
9519 	sbPtr->DynPtr->LinVelocity.vz = 0;
9520 
9521 	sbPtr->DynPtr->LinImpulse.vx = 0;
9522 	sbPtr->DynPtr->LinImpulse.vy = 0;
9523 	sbPtr->DynPtr->LinImpulse.vz = 0;
9524 	#endif
9525 
9526 	{
9527 		DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
9528 		/* do we have a displayblock? */
9529 		if (dispPtr)
9530 		{
9531 			dispPtr->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND;
9532 			dispPtr->ObFlags2 = marineStatusPointer->stateTimer/2;
9533 
9534 		}
9535 	}
9536 
9537 	marineStatusPointer->stateTimer -= NormalFrameTime;
9538 
9539 	#if 0
9540 	if ( (sbPtr->DynPtr->Position.vx=sbPtr->DynPtr->PrevPosition.vx)
9541 		|| (sbPtr->DynPtr->Position.vx=sbPtr->DynPtr->PrevPosition.vy)
9542 		|| (sbPtr->DynPtr->Position.vx=sbPtr->DynPtr->PrevPosition.vz)) {
9543 
9544 		/* Now, turn off collisions? */
9545 		if(sbPtr->DynPtr)
9546 		{
9547 			sbPtr->DynPtr->IsStatic	= 1;
9548 			sbPtr->DynPtr->DynamicsType	= DYN_TYPE_NO_COLLISIONS;
9549 			sbPtr->DynPtr->GravityOn = 0;
9550 		}
9551 
9552 	}
9553 	#endif
9554 
9555 
9556 	/* Did marine die with the trigger held down? */
9557 	if (marineStatusPointer->lastroundhit==-2) {
9558 		/* Is there a gunflash? */
9559 		if(marineStatusPointer->My_Gunflash_Section) {
9560 			/* But is it still attached? */
9561 			if (marineStatusPointer->My_Gunflash_Section->my_controller==&(marineStatusPointer->HModelController)) {
9562 				/* Keep firing! */
9563 				LOCALASSERT(marineStatusPointer->My_Weapon->WeaponMisfireFunction);
9564 				/* Shouldn't be doing this without knowing why. */
9565 				(*marineStatusPointer->My_Weapon->WeaponMisfireFunction)(marineStatusPointer->My_Gunflash_Section,&marineStatusPointer->weapon_variable);
9566 			}
9567 		}
9568 	}
9569 
9570 	/* Do we want to trim off the weapons? */
9571 
9572 	if (marineStatusPointer->HModelController.keyframe_flags) {
9573 		SECTION *root;
9574 
9575 		root=GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,marineStatusPointer->My_Weapon->TemplateName);
9576 
9577 		TrimToTemplate(sbPtr,&marineStatusPointer->HModelController,
9578 			root, 1);
9579 	}
9580 
9581 }
9582 
9583 static void MarineFireFlameThrower(STRATEGYBLOCK *sbPtr) {
9584 
9585 	VECTORCH null_vec;
9586 	MARINE_STATUS_BLOCK *marineStatusPointer;
9587 
9588 	LOCALASSERT(sbPtr);
9589 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
9590 	LOCALASSERT(marineStatusPointer);
9591 
9592 	null_vec.vx=0;
9593 	null_vec.vy=0;
9594 	null_vec.vz=0;
9595 
9596 	GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
9597 
9598 	FireFlameThrower(&marineStatusPointer->My_Gunflash_Section->World_Offset,&null_vec,
9599 		&marineStatusPointer->My_Gunflash_Section->SecMat,0,&marineStatusPointer->weapon_variable);
9600 
9601 }
9602 
9603 void MarineMisfireFlameThrower(SECTION_DATA *muzzle, int *timer) {
9604 
9605 	VECTORCH null_vec;
9606 
9607 	null_vec.vx=0;
9608 	null_vec.vy=0;
9609 	null_vec.vz=0;
9610 
9611 	FireFlameThrower(&muzzle->World_Offset,&null_vec,&muzzle->SecMat,0,timer);
9612 
9613 }
9614 
9615 /*----------------------- Patrick 18/4/97 ------------------------
9616   Support for gunflash objects. These are for use by AI marines
9617   and also network ghosted players
9618   ----------------------------------------------------------------*/
9619 
9620 /* this function is specifically for marines, and creates a gun flash
9621 pointing in the direction of the target point */
9622 static void CreateMarineGunFlash(STRATEGYBLOCK *sbPtr)
9623 {
9624 	VECTORCH firingDirn,firingPoint;
9625 	MARINE_STATUS_BLOCK *marineStatusPointer;
9626 	int	firingOffsetUp,firingOffsetInfront,firingOffsetAcross;
9627 
9628 	LOCALASSERT(sbPtr);
9629 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
9630 	LOCALASSERT(marineStatusPointer);
9631 
9632 	/* get the firing point offsets:*/
9633 	if(marineStatusPointer->IAmCrouched)
9634 	{
9635 		firingOffsetUp = MARINE_FIRINGPOINT_UP;
9636 		firingOffsetInfront = MARINE_FIRINGPOINT_INFRONT;
9637 		firingOffsetAcross = MARINE_FIRINGPOINT_ACROSS;
9638 	}
9639 	else
9640 	{
9641 		firingOffsetUp = MARINE_FIRINGPOINT_UP_CROUCHED;
9642 		firingOffsetInfront = MARINE_FIRINGPOINT_INFRONT_CROUCHED;
9643 		firingOffsetAcross = MARINE_FIRINGPOINT_ACROSS_CROUCHED;
9644 	}
9645 
9646 	/* find the firing direction */
9647 	firingDirn.vx = marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
9648 	firingDirn.vy = marineStatusPointer->weaponTarget.vy - sbPtr->DynPtr->Position.vy;
9649 	firingDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
9650 	Normalise(&firingDirn);
9651 	{
9652 		VECTORCH yNormal = {0,-65536,0};
9653 		VECTORCH tempDirn;
9654 		VECTORCH acrossDirn;
9655 
9656 		/* now find firing point (conceptually, the end of the weapon muzzle)... */
9657 		firingPoint = sbPtr->DynPtr->Position;
9658 		firingPoint.vx += MUL_FIXED(firingDirn.vx,firingOffsetInfront);
9659 		firingPoint.vz += MUL_FIXED(firingDirn.vz,firingOffsetInfront);
9660 
9661 		tempDirn = firingDirn;
9662 		tempDirn.vy = 0;
9663 		Normalise(&tempDirn);
9664 		CrossProduct(&tempDirn,&yNormal,&acrossDirn);
9665 		Normalise(&acrossDirn);
9666 		firingPoint.vx += MUL_FIXED(tempDirn.vx,firingOffsetAcross);
9667 		firingPoint.vz += MUL_FIXED(tempDirn.vz,firingOffsetAcross);
9668 		firingPoint.vy += MUL_FIXED(yNormal.vy,firingOffsetUp);
9669 	}
9670 
9671 
9672 	LOCALASSERT(marineStatusPointer->myGunFlash==NULL);
9673 	GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
9674 	marineStatusPointer->myGunFlash = AddNPCGunFlashEffect
9675  						  (
9676  						  	&marineStatusPointer->My_Gunflash_Section->World_Offset,
9677  							&marineStatusPointer->My_Gunflash_Section->SecMat,
9678  							marineStatusPointer->My_Weapon->SfxID
9679  						  );
9680 }
9681 
9682 /* Add a gun flash at the given position & orientation */
9683 DISPLAYBLOCK* AddNPCGunFlashEffect(VECTORCH *position, MATRIXCH* orientation, enum SFX_ID sfxID)
9684 {
9685 	DISPLAYBLOCK *dPtr;
9686 
9687 	dPtr = CreateSFXObject(sfxID);
9688 
9689 	if(dPtr)
9690 	{
9691 		dPtr->ObMyModule = NULL;
9692 		dPtr->ObWorld = *position;
9693 		dPtr->ObMat = *orientation;
9694 		//CreateEulerMatrix(orientation, &dPtr->ObMat);
9695 		//TransposeMatrixCH(&dPtr->ObMat);
9696 		AddLightingEffectToObject(dPtr,LFX_MUZZLEFLASH);
9697 		GLOBALASSERT(dPtr->SfxPtr);
9698 		dPtr->SfxPtr->EffectDrawnLastFrame=0;
9699 	}
9700 	return dPtr;
9701 }
9702 
9703 /* Remove the gunflash */
9704 void RemoveNPCGunFlashEffect(DISPLAYBLOCK* dPtr)
9705 {
9706 	DestroyActiveObject(dPtr);
9707 }
9708 
9709 /* Update the gunflash effect given a new position and orientation */
9710 void MaintainNPCGunFlashEffect(DISPLAYBLOCK* dPtr, VECTORCH *position, MATRIXCH* orientation)
9711 {
9712 	dPtr->ObWorld = *position;
9713 	dPtr->ObMat = *orientation;
9714 
9715 	/* oh, oh, and re-add the lighting effect  */
9716 	AddLightingEffectToObject(dPtr,LFX_MUZZLEFLASH);
9717 }
9718 
9719 
9720 
9721 /* Patrick: 2/7/97 --------------------------------------------------------
9722    Some marine support functions
9723    -------------------------------------------------------------------------*/
9724 static void SetMarineAnimationSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweening)
9725 {
9726 
9727 	MARINE_STATUS_BLOCK *marineStatusPointer;
9728 
9729 	LOCALASSERT(sbPtr);
9730 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
9731 	LOCALASSERT(marineStatusPointer);
9732 
9733 	GLOBALASSERT(length!=0);
9734 
9735 	if (tweening<=0) {
9736 		InitHModelSequence(&marineStatusPointer->HModelController,(int)type,subtype,length);
9737 	} else {
9738 		InitHModelTweening(&marineStatusPointer->HModelController, tweening, (int)type,subtype,length, 1);
9739 	}
9740 
9741 	ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
9742 }
9743 
9744 static void SetMarineAnimationSequence_Null(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweening) {
9745 	/* Ha! */
9746 	#if (NEW_ANIM_SYSTEM==0)
9747 	SetMarineAnimationSequence(sbPtr,type,subtype,length,tweening);
9748 	#endif
9749 
9750 }
9751 
9752 static int MarineCanSeeTarget(STRATEGYBLOCK *sbPtr)
9753 {
9754 	MARINE_STATUS_BLOCK *marineStatusPointer;
9755 	int targetIsCloaked,targetTaunted;
9756 	VECTORCH offset;
9757 	int dist;
9758 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
9759 
9760 	LOCALASSERT(sbPtr);
9761 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
9762 	LOCALASSERT(marineStatusPointer);
9763 
9764 	if (marineStatusPointer->Target==NULL) {
9765 		/* You can't see nothin. */
9766 		return(0);
9767 	}
9768 
9769 	targetIsCloaked=0;
9770 	targetTaunted=0;
9771 
9772 	if (marineStatusPointer->Target==Player->ObStrategyBlock) {
9773 		/* test for player being cloaked */
9774 		LOCALASSERT(playerStatusPtr);
9775 		if (AvP.PlayerType==I_Predator) {
9776 
9777 			if((playerStatusPtr->cloakOn==1)&&(playerStatusPtr->cloakPositionGivenAway==0)) {
9778 				targetIsCloaked=1;
9779 			}
9780 		}
9781 		if (playerStatusPtr->tauntTimer) {
9782 			/* Idiot. */
9783 			targetIsCloaked=0;
9784 			/* On the other hand, */
9785 			targetTaunted=1;
9786 		}
9787 
9788 	} else {
9789 		/* Test for NPC predators being cloaked, or aliens hiding? */
9790 		if (marineStatusPointer->Target->I_SBtype==I_BehaviourPredator) {
9791 			PREDATOR_STATUS_BLOCK *predStatus=(PREDATOR_STATUS_BLOCK *)marineStatusPointer->Target->SBdataptr;
9792 			GLOBALASSERT(predStatus);
9793 			if (predStatus->CloakStatus==PCLOAK_On) {
9794 				targetIsCloaked=1;
9795 			}
9796 		}
9797 	}
9798 
9799 	offset.vx=sbPtr->DynPtr->Position.vx-marineStatusPointer->Target->DynPtr->Position.vx;
9800 	offset.vy=sbPtr->DynPtr->Position.vy-marineStatusPointer->Target->DynPtr->Position.vy;
9801 	offset.vz=sbPtr->DynPtr->Position.vz-marineStatusPointer->Target->DynPtr->Position.vz;
9802 	dist=Approximate3dMagnitude(&offset);
9803 
9804 	/* If a marine is suspicious, and the target is within 2m of the suspect_point... */
9805 	if (marineStatusPointer->suspicious) {
9806 		/* Detect on the incidentFlag? */
9807 		if (marineStatusPointer->incidentFlag) {
9808 			int dice,targetnum;
9809 
9810 			dice=(FastRandom()&65535);
9811 			targetnum=(marineStatusPointer->Skill);
9812 
9813 			targetnum=MakeModifiedTargetNum(targetnum,dist);
9814 
9815 			if (marineStatusPointer->Target==Player->ObStrategyBlock) {
9816 				if (AvP.PlayerType==I_Predator) {
9817 					if (playerStatusPtr->cloakOn==1) {
9818 						dice=MUL_FIXED(dice,playerStatusPtr->CloakingEffectiveness);
9819 					}
9820 				}
9821 			} else if (marineStatusPointer->Target->I_SBtype==I_BehaviourPredator) {
9822 				PREDATOR_STATUS_BLOCK *predStatus=(PREDATOR_STATUS_BLOCK *)marineStatusPointer->Target->SBdataptr;
9823 				GLOBALASSERT(predStatus);
9824 				if (predStatus->CloakStatus==PCLOAK_On) {
9825 					dice=MUL_FIXED(dice,predStatus->CloakingEffectiveness);
9826 				}
9827 			}
9828 
9829 			if (dice<targetnum) {
9830 				targetIsCloaked=0;
9831 			}
9832 		}
9833 		if (dist<MARINE_AUTODETECT_RANGE) {
9834 			/* Too close to fool anyone. */
9835 			targetIsCloaked=0;
9836 		}
9837 	}
9838 
9839 	if (marineStatusPointer->Target==Player->ObStrategyBlock) {
9840 		/* Alien test is now here, since it uses probability differently. */
9841 		if (AvP.PlayerType==I_Alien) {
9842 			if (!AlienPCIsCurrentlyVisible(marineStatusPointer->incidentFlag,sbPtr)) {
9843 				if (playerStatusPtr->tauntTimer) {
9844 					/* Idiot. */
9845 					targetIsCloaked=0;
9846 					/* Taunted flag should already be set. */
9847 				} else {
9848 					targetIsCloaked=1;
9849 				}
9850 			}
9851 		}
9852 	}
9853 
9854 	if (marineStatusPointer->sawlastframe) {
9855 		if (marineStatusPointer->incidentFlag) {
9856 			/* Chance of losing target. */
9857 			VECTORCH offset;
9858 			int speed;
9859 
9860 			offset.vx=marineStatusPointer->Target->DynPtr->Position.vx-marineStatusPointer->Target->DynPtr->PrevPosition.vx;
9861 			offset.vy=marineStatusPointer->Target->DynPtr->Position.vy-marineStatusPointer->Target->DynPtr->PrevPosition.vy;
9862 			offset.vz=marineStatusPointer->Target->DynPtr->Position.vz-marineStatusPointer->Target->DynPtr->PrevPosition.vz;
9863 
9864 			/* ...compute speed factor... */
9865 			speed=Magnitude(&offset);
9866 			speed=DIV_FIXED(speed,NormalFrameTime);
9867 
9868 			if (speed>50) {
9869 				/* The faster you move, the more likely to be lost. */
9870 				speed<<=1;
9871 				if ((FastRandom()&65535)>speed) {
9872 					/* Retain target! */
9873 					targetIsCloaked=0;
9874 				}
9875 			} else {
9876 				/* Can't lose them if they're still. */
9877 				targetIsCloaked=0;
9878 			}
9879 		} else {
9880 			targetIsCloaked=0;
9881 		}
9882 	}
9883 
9884 	if (marineStatusPointer->Target->SBDamageBlock.IsOnFire) {
9885 		/* Oh come ON. */
9886 		targetIsCloaked=0;
9887 	}
9888 
9889 	if(!(NPCCanSeeTarget(sbPtr,marineStatusPointer->Target, MARINE_NEAR_VIEW_WIDTH))) {
9890 		if (marineStatusPointer->sawlastframe) {
9891 			marineStatusPointer->sawlastframe=2;
9892 			/* I'm suspicious now. */
9893 			marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
9894 			marineStatusPointer->suspect_point=marineStatusPointer->Target->DynPtr->Position;
9895 			/* And unset previous_suspicion. */
9896 			marineStatusPointer->previous_suspicion=0;
9897 			marineStatusPointer->using_squad_suspicion=0;
9898 		}
9899 		return(0);
9900 	}
9901 
9902 	if (targetIsCloaked) {
9903 		return(0);
9904 	}
9905 	marineStatusPointer->sawlastframe=1;
9906 
9907 	if ((targetTaunted)&&(marineStatusPointer->Target)&&(marineStatusPointer->Android==0)) {
9908 
9909 		if (dist<16834) {
9910 			dist=16384-dist;
9911 			dist<<=2;
9912 			marineStatusPointer->Courage-=MUL_FIXED((NormalFrameTime<<1),dist);
9913 		}
9914 	}
9915 	return(1);
9916 }
9917 
9918 static int MarineCanSeeObject(STRATEGYBLOCK *sbPtr,STRATEGYBLOCK *target)
9919 {
9920 	MARINE_STATUS_BLOCK *marineStatusPointer;
9921 	int targetIsCloaked, targetTaunted, targetWasCloaked;
9922 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
9923 	VECTORCH offset;
9924 	int dist;
9925 
9926 	LOCALASSERT(sbPtr);
9927 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
9928 	LOCALASSERT(marineStatusPointer);
9929 
9930 	if (target==NULL) {
9931 		/* You can't see nothin. */
9932 		return(0);
9933 	}
9934 
9935 	targetIsCloaked=0;
9936 	targetTaunted=0;
9937 	targetWasCloaked=0;
9938 
9939 	if (target==Player->ObStrategyBlock) {
9940 		/* test for player being cloaked */
9941 		LOCALASSERT(playerStatusPtr);
9942 		if (AvP.PlayerType==I_Predator) {
9943 
9944 			if((playerStatusPtr->cloakOn==1)&&(playerStatusPtr->cloakPositionGivenAway==0)) {
9945 				targetIsCloaked=1;
9946 				targetWasCloaked=1;
9947 			}
9948 		}
9949 		if (playerStatusPtr->tauntTimer) {
9950 			/* Idiot. */
9951 			targetIsCloaked=0;
9952 			/* On the other hand, */
9953 			targetTaunted=1;
9954 		}
9955 
9956 	} else {
9957 		/* Test for NPC predators being cloaked, or aliens hiding? */
9958 		if (target->I_SBtype==I_BehaviourPredator) {
9959 			PREDATOR_STATUS_BLOCK *predStatus=(PREDATOR_STATUS_BLOCK *)target->SBdataptr;
9960 			GLOBALASSERT(predStatus);
9961 			if (predStatus->CloakStatus==PCLOAK_On) {
9962 				targetIsCloaked=1;
9963 				targetWasCloaked=1;
9964 			}
9965 		}
9966 	}
9967 
9968 	offset.vx=sbPtr->DynPtr->Position.vx-target->DynPtr->Position.vx;
9969 	offset.vy=sbPtr->DynPtr->Position.vy-target->DynPtr->Position.vy;
9970 	offset.vz=sbPtr->DynPtr->Position.vz-target->DynPtr->Position.vz;
9971 	dist=Approximate3dMagnitude(&offset);
9972 
9973 	/* If a marine is suspicious, and the target is within 2m of the suspect_point... */
9974 	if (marineStatusPointer->suspicious) {
9975 		/* Detect on the incidentFlag? */
9976 		if (marineStatusPointer->incidentFlag) {
9977 			int dice,targetnum;
9978 
9979 			dice=(FastRandom()&65535);
9980 			targetnum=(marineStatusPointer->Skill);
9981 
9982 			targetnum=MakeModifiedTargetNum(targetnum,dist);
9983 
9984 			if (target==Player->ObStrategyBlock) {
9985 				if (AvP.PlayerType==I_Predator) {
9986 					if (playerStatusPtr->cloakOn==1) {
9987 						dice=MUL_FIXED(dice,playerStatusPtr->CloakingEffectiveness);
9988 					}
9989 				}
9990 			} else if (target->I_SBtype==I_BehaviourPredator) {
9991 				PREDATOR_STATUS_BLOCK *predStatus=(PREDATOR_STATUS_BLOCK *)target->SBdataptr;
9992 				GLOBALASSERT(predStatus);
9993 				if (predStatus->CloakStatus==PCLOAK_On) {
9994 					dice=MUL_FIXED(dice,predStatus->CloakingEffectiveness);
9995 				}
9996 			}
9997 
9998 			if (dice<targetnum) {
9999 				targetIsCloaked=0;
10000 			}
10001 		}
10002 		if (dist<MARINE_AUTODETECT_RANGE) {
10003 			/* Too close to fool anyone. */
10004 			targetIsCloaked=0;
10005 		}
10006 	}
10007 
10008 	if (target==Player->ObStrategyBlock) {
10009 		/* Alien test is now here, since it uses probability differently. */
10010 		if (AvP.PlayerType==I_Alien) {
10011 			if (!AlienPCIsCurrentlyVisible(marineStatusPointer->incidentFlag,sbPtr)) {
10012 				if (playerStatusPtr->tauntTimer) {
10013 					/* Idiot. */
10014 					targetIsCloaked=0;
10015 					/* Taunted flag should already be set. */
10016 				} else {
10017 					targetIsCloaked=1;
10018 					targetWasCloaked=1;
10019 				}
10020 			}
10021 		}
10022 	}
10023 
10024 	if (marineStatusPointer->sawlastframe) {
10025 		if (marineStatusPointer->incidentFlag) {
10026 			/* Chance of losing target. */
10027 			VECTORCH offset;
10028 			int speed;
10029 
10030 			offset.vx=target->DynPtr->Position.vx-target->DynPtr->PrevPosition.vx;
10031 			offset.vy=target->DynPtr->Position.vy-target->DynPtr->PrevPosition.vy;
10032 			offset.vz=target->DynPtr->Position.vz-target->DynPtr->PrevPosition.vz;
10033 
10034 			/* ...compute speed factor... */
10035 			speed=Magnitude(&offset);
10036 			speed=DIV_FIXED(speed,NormalFrameTime);
10037 
10038 			if (speed>50) {
10039 				/* The faster you move, the more likely to be lost. */
10040 				speed<<=1;
10041 				if ((FastRandom()&65535)>speed) {
10042 					/* Retain target! */
10043 					targetIsCloaked=0;
10044 				}
10045 			} else {
10046 				/* Can't lose them if they're still. */
10047 				targetIsCloaked=0;
10048 			}
10049 		} else {
10050 			targetIsCloaked=0;
10051 		}
10052 	}
10053 
10054 	if (target->SBDamageBlock.IsOnFire) {
10055 		/* Oh come ON. */
10056 		targetIsCloaked=0;
10057 	}
10058 
10059 	/* NO saw last frame usage! */
10060 
10061 	if (targetIsCloaked) {
10062 		return(0);
10063 	}
10064 
10065 	if(!(NPCCanSeeTarget(sbPtr,target, MARINE_NEAR_VIEW_WIDTH))) {
10066 		return(0);
10067 	}
10068 
10069 	if ((targetWasCloaked)&&(marineStatusPointer->Target==NULL)) {
10070 		/* Exhibit suprise? */
10071 		if ((FastRandom()&65535)<16384) {
10072 			Marine_SurpriseSound(sbPtr);
10073 		}
10074 	}
10075 
10076 	if ((targetTaunted)&&(marineStatusPointer->Target)&&(marineStatusPointer->Android==0)) {
10077 		/* It must be the player. */
10078 		if (dist<16834) {
10079 			dist=16384-dist;
10080 			dist<<=2;
10081 			marineStatusPointer->Courage-=MUL_FIXED((NormalFrameTime<<1),dist);
10082 		}
10083 	}
10084 	return(1);
10085 }
10086 
10087 void WarnMarineOfAttack(STRATEGYBLOCK *marine,STRATEGYBLOCK *attacker) {
10088 
10089 	MARINE_STATUS_BLOCK *marineStatusPointer;
10090 
10091 	GLOBALASSERT(marine);
10092 
10093 	GLOBALASSERT(marine->I_SBtype==I_BehaviourMarine);
10094 
10095 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(marine->SBdataptr);
10096 	GLOBALASSERT(marineStatusPointer);
10097 
10098 	GLOBALASSERT(attacker);
10099 
10100 	/* Test? */
10101 
10102 	if(MarineCanSeeObject(marine,attacker)) {
10103 
10104 		/* Remember your suspicion! */
10105 		marineStatusPointer->previous_suspicion=marineStatusPointer->suspicious;
10106 		marineStatusPointer->suspicious=1; /* It's right there! */
10107 		marineStatusPointer->Target=attacker;
10108 
10109 		COPY_NAME(marineStatusPointer->Target_SBname,marineStatusPointer->Target->SBname);
10110 
10111 		PointAlert(2,&attacker->DynPtr->Position);
10112 	}
10113 
10114 }
10115 
10116 static int MarineIsAwareOfTarget(STRATEGYBLOCK *sbPtr)
10117 {
10118 	MARINE_STATUS_BLOCK *marineStatusPointer;
10119 	int targetIsCloaked;
10120 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
10121 	VECTORCH offset;
10122 	int dist;
10123 
10124 	/* Like MarineCanSeeTarget, but the 'Far' version:  should it hunt? */
10125 
10126 	LOCALASSERT(sbPtr);
10127 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
10128 	LOCALASSERT(marineStatusPointer);
10129 
10130 	if (marineStatusPointer->Target!=NULL) {
10131 
10132 		/* Okay, let's try this sense malarky. */
10133 
10134 		/* Motion tracker, only when scanning. */
10135 
10136 		if (marineStatusPointer->mtracker_timer==0) {
10137 			if (marineStatusPointer->Target->DynPtr) {
10138 				DYNAMICSBLOCK *tDynPtr;
10139 				MATRIXCH WtoL;
10140 				VECTORCH offset;
10141 				/* Arc reject. */
10142 
10143 				tDynPtr=marineStatusPointer->Target->DynPtr;
10144 
10145 				offset.vx=sbPtr->DynPtr->Position.vx-marineStatusPointer->Target->DynPtr->Position.vx;
10146 				offset.vy=sbPtr->DynPtr->Position.vy-marineStatusPointer->Target->DynPtr->Position.vy;
10147 				offset.vz=sbPtr->DynPtr->Position.vz-marineStatusPointer->Target->DynPtr->Position.vz;
10148 
10149 				WtoL=sbPtr->DynPtr->OrientMat;
10150 				TransposeMatrixCH(&WtoL);
10151 				RotateVector(&offset,&WtoL);
10152 
10153 				if (offset.vz<=0) {
10154 					#if 0
10155 					if (
10156 						(tDynPtr->Position.vx!=tDynPtr->PrevPosition.vx)
10157 						||(tDynPtr->Position.vx!=tDynPtr->PrevPosition.vx)
10158 						||(tDynPtr->Position.vx!=tDynPtr->PrevPosition.vx)
10159 						) {
10160 					#else
10161 					if (ObjectShouldAppearOnMotionTracker(marineStatusPointer->Target)) {
10162 					#endif
10163 						int range;
10164 
10165 						range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
10166 
10167 						if (range<=MOTIONTRACKER_RANGE) {
10168 							marineStatusPointer->suspicious=MARINE_PARANOIA_TIME; /* It might be there. */
10169 							marineStatusPointer->suspect_point=marineStatusPointer->Target->DynPtr->Position;
10170 							/* Set this to zero when you get a *new* suspicion. */
10171 							marineStatusPointer->previous_suspicion=0;
10172 							marineStatusPointer->using_squad_suspicion=0;
10173 							tracker_noise=2; /* Wheep! */
10174 							return(1);
10175 						}
10176 					}
10177 				}
10178 			}
10179 		}
10180 
10181 		/* So, there's nothing on the scanner. */
10182 
10183 		targetIsCloaked=0;
10184 
10185 		/* Far visibility. */
10186 
10187 		if (marineStatusPointer->Target==Player->ObStrategyBlock) {
10188 			/* test for player being cloaked */
10189 			LOCALASSERT(playerStatusPtr);
10190 			if (AvP.PlayerType==I_Predator) {
10191 
10192 				if((playerStatusPtr->cloakOn==1)&&(playerStatusPtr->cloakPositionGivenAway==0)) {
10193 					targetIsCloaked=1;
10194 				}
10195 			}
10196 			if (playerStatusPtr->tauntTimer) {
10197 				/* Idiot. */
10198 				targetIsCloaked=0;
10199 			}
10200 
10201 		} else {
10202 			/* Test for NPC predators being cloaked, or aliens hiding? */
10203 			if (marineStatusPointer->Target->I_SBtype==I_BehaviourPredator) {
10204 				PREDATOR_STATUS_BLOCK *predStatus=(PREDATOR_STATUS_BLOCK *)marineStatusPointer->Target->SBdataptr;
10205 				GLOBALASSERT(predStatus);
10206 				if (predStatus->CloakStatus==PCLOAK_On) {
10207 					targetIsCloaked=1;
10208 				}
10209 			}
10210 		}
10211 
10212 		offset.vx=sbPtr->DynPtr->Position.vx-marineStatusPointer->Target->DynPtr->Position.vx;
10213 		offset.vy=sbPtr->DynPtr->Position.vy-marineStatusPointer->Target->DynPtr->Position.vy;
10214 		offset.vz=sbPtr->DynPtr->Position.vz-marineStatusPointer->Target->DynPtr->Position.vz;
10215 		dist=Approximate3dMagnitude(&offset);
10216 
10217 		/* If a marine is suspicious, and the target is within 2m of the suspect_point... */
10218 		if (marineStatusPointer->suspicious) {
10219 			/* Detect on the incidentFlag? */
10220 			if (marineStatusPointer->incidentFlag) {
10221 				int dice,targetnum;
10222 
10223 				dice=(FastRandom()&65535);
10224 				targetnum=(marineStatusPointer->Skill);
10225 
10226 				targetnum=MakeModifiedTargetNum(targetnum,dist);
10227 
10228 				if (marineStatusPointer->Target==Player->ObStrategyBlock) {
10229 					if (AvP.PlayerType==I_Predator) {
10230 						if (playerStatusPtr->cloakOn==1) {
10231 							dice=MUL_FIXED(dice,playerStatusPtr->CloakingEffectiveness);
10232 						}
10233 					}
10234 				} else if (marineStatusPointer->Target->I_SBtype==I_BehaviourPredator) {
10235 					PREDATOR_STATUS_BLOCK *predStatus=(PREDATOR_STATUS_BLOCK *)marineStatusPointer->Target->SBdataptr;
10236 					GLOBALASSERT(predStatus);
10237 					if (predStatus->CloakStatus==PCLOAK_On) {
10238 						dice=MUL_FIXED(dice,predStatus->CloakingEffectiveness);
10239 					}
10240 				}
10241 
10242 				if (dice<targetnum) {
10243 					targetIsCloaked=0;
10244 				}
10245 			}
10246 			if (dist<MARINE_AUTODETECT_RANGE) {
10247 				/* Too close to fool anyone. */
10248 				targetIsCloaked=0;
10249 			}
10250 		}
10251 
10252 		if (marineStatusPointer->Target==Player->ObStrategyBlock) {
10253 			/* Alien test is now here, since it uses probability differently. */
10254 			if (AvP.PlayerType==I_Alien) {
10255 				if (!AlienPCIsCurrentlyVisible(marineStatusPointer->incidentFlag,sbPtr)) {
10256 					if (playerStatusPtr->tauntTimer) {
10257 						/* Idiot. */
10258 						targetIsCloaked=0;
10259 					} else {
10260 						targetIsCloaked=1;
10261 					}
10262 				}
10263 			}
10264 		}
10265 
10266 		if (marineStatusPointer->sawlastframe) {
10267 			if (marineStatusPointer->incidentFlag) {
10268 				/* Chance of losing target. */
10269 				VECTORCH offset;
10270 				int speed;
10271 
10272 				offset.vx=marineStatusPointer->Target->DynPtr->Position.vx-marineStatusPointer->Target->DynPtr->PrevPosition.vx;
10273 				offset.vy=marineStatusPointer->Target->DynPtr->Position.vy-marineStatusPointer->Target->DynPtr->PrevPosition.vy;
10274 				offset.vz=marineStatusPointer->Target->DynPtr->Position.vz-marineStatusPointer->Target->DynPtr->PrevPosition.vz;
10275 
10276 				/* ...compute speed factor... */
10277 				speed=Magnitude(&offset);
10278 				speed=DIV_FIXED(speed,NormalFrameTime);
10279 
10280 				if (speed>50) {
10281 					/* The faster you move, the more likely to be lost. */
10282 					speed<<=1;
10283 					if ((FastRandom()&65535)>speed) {
10284 						/* Retain target! */
10285 						targetIsCloaked=0;
10286 					}
10287 				} else {
10288 					/* Can't lose them if they're still. */
10289 					targetIsCloaked=0;
10290 				}
10291 			} else {
10292 				targetIsCloaked=0;
10293 			}
10294 		}
10295 
10296 		if (marineStatusPointer->Target->SBDamageBlock.IsOnFire) {
10297 			/* Oh come ON. */
10298 			targetIsCloaked=0;
10299 		}
10300 
10301 		if (targetIsCloaked==0) {
10302 			if (!sbPtr->SBdptr) {
10303 				if (marineStatusPointer->Target->containingModule) {
10304 					if (IsModuleVisibleFromModule(marineStatusPointer->Target->containingModule,sbPtr->containingModule)) {
10305 						/* Remember your suspicion! */
10306 						marineStatusPointer->previous_suspicion=marineStatusPointer->suspicious;
10307 						/* Seen, unset suspicion. */
10308 						marineStatusPointer->suspicious=1;
10309 						return(1);
10310 					}
10311 				}
10312 			} else {
10313 				if (MarineCanSeeTarget(sbPtr)) {
10314 					/* Remember your suspicion! */
10315 					marineStatusPointer->previous_suspicion=marineStatusPointer->suspicious;
10316 					/* Near visibility - seen target, unset suspicion. */
10317 					marineStatusPointer->suspicious=1;
10318 					return(1);
10319 				}
10320 			}
10321 		}
10322 	}
10323 
10324 	/* Lastly, is there something we want to investigate? */
10325 
10326 	if (marineStatusPointer->suspicious) {
10327 		if (!sbPtr->SBdptr) {
10328 			MODULE *targetModule;
10329 			/* Far case. */
10330 			targetModule=ModuleFromPosition(&marineStatusPointer->suspect_point,sbPtr->containingModule);
10331 			/* Target isn't guaranteed, is it? */
10332 			if (targetModule) {
10333 				if (IsModuleVisibleFromModule(targetModule,sbPtr->containingModule)) {
10334 					/* Seen the point, unset suspicion?  Maybe not. */
10335 					#if 0
10336 					/* Remember your suspicion! */
10337 					marineStatusPointer->previous_suspicion=marineStatusPointer->suspicious;
10338 					marineStatusPointer->suspicious=1;
10339 					/* Just let it time out instead. */
10340 					#endif
10341 					/* Shouldn't have a target now. */
10342 					marineStatusPointer->Target=NULL;
10343 					return(0);
10344 					/* If there was something there, we should have picked it up by now. */
10345 				}
10346 			}
10347 			/* Still suspicious. */
10348 		} else {
10349 			/* Near case. */
10350 			VECTORCH offset;
10351 			MATRIXCH WtoL;
10352 			/* Arc reject. */
10353 
10354 			offset.vx=sbPtr->DynPtr->Position.vx-marineStatusPointer->suspect_point.vx;
10355 			offset.vy=sbPtr->DynPtr->Position.vy-marineStatusPointer->suspect_point.vy;
10356 			offset.vz=sbPtr->DynPtr->Position.vz-marineStatusPointer->suspect_point.vz;
10357 
10358 			WtoL=sbPtr->DynPtr->OrientMat;
10359 			TransposeMatrixCH(&WtoL);
10360 			RotateVector(&offset,&WtoL);
10361 			/* Do reject. */
10362 			if (MarineSight_FrustrumReject(sbPtr,&offset,NULL)) {
10363 				if (IsThisObjectVisibleFromThisPosition(sbPtr->SBdptr,&marineStatusPointer->suspect_point,NPC_MAX_VIEWRANGE)) {
10364 					/* I know what you're going to say.  That's backwards. */
10365 					#if 0
10366 					/* Remember your suspicion! */
10367 					marineStatusPointer->previous_suspicion=marineStatusPointer->suspicious;
10368 					marineStatusPointer->suspicious=1; /* Flag for unsetting nicely. */
10369 					/* Now, let's try just timing it out. */
10370 					#endif
10371 					/* By this point I would have thought there's no valid target. */
10372 					marineStatusPointer->Target=NULL;
10373 					return(0);
10374 					/* Well, show me 'IsThisPositionVisibleFromThisObject' and I'll be happy to change it. */
10375 				}
10376 			}
10377 		}
10378 	}
10379 
10380 	return(0);
10381 }
10382 
10383 static int MarineShouldBeCrawling(STRATEGYBLOCK *sbPtr)
10384 {
10385 	if(sbPtr->containingModule->m_flags & MODULEFLAG_AIRDUCT) return 1;
10386 	return 0;
10387 }
10388 
10389 static STATE_RETURN_CONDITION Execute_MNS_DischargeFlamethrower(STRATEGYBLOCK *sbPtr)
10390 {
10391 	MARINE_STATUS_BLOCK *marineStatusPointer;
10392 	VECTORCH orientationDirn;
10393 	int correctlyOrientated;
10394 
10395 	LOCALASSERT(sbPtr);
10396 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
10397 	LOCALASSERT(marineStatusPointer);
10398 
10399 	marineStatusPointer->HModelController.Playing=1;
10400 
10401 	/* zero velocity */
10402 	LOCALASSERT(sbPtr->DynPtr);
10403 	sbPtr->DynPtr->LinVelocity.vx = 0;
10404 	sbPtr->DynPtr->LinVelocity.vy = 0;
10405 	sbPtr->DynPtr->LinVelocity.vz = 0;
10406 
10407 	/* look after the gun flash */
10408 	if(marineStatusPointer->myGunFlash) {
10409 		/* No gunflash, neither. */
10410 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
10411 	}
10412 
10413 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
10414 	we should switch immediately to wait state*/
10415 	if(!MarineCanSeeTarget(sbPtr))
10416 	{
10417 
10418 		/* .... and stop the sound */
10419 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
10420 			Sound_Stop(marineStatusPointer->soundHandle);
10421 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
10422 		}
10423 		return(SRC_Request_Wait);
10424 	}
10425 
10426 	GLOBALASSERT(marineStatusPointer->Target);
10427 	NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
10428 	/* Fix weapon target! */
10429 	if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
10430 		marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
10431 			marineStatusPointer->My_Weapon->TargetCallibrationShift);
10432 		marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
10433 			marineStatusPointer->My_Weapon->TargetCallibrationShift);
10434 		marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
10435 			marineStatusPointer->My_Weapon->TargetCallibrationShift);
10436 	}
10437 
10438 	/* Here we must have a target.  Renew suspicion for new arrivals. */
10439 	if (NpcSquad.Squad_Suspicion==0) {
10440 		PointAlert(2,&marineStatusPointer->weaponTarget);
10441 	}
10442 
10443 	/* Are we out of range? */
10444 	{
10445 		int range;
10446 
10447 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
10448 
10449 		if ((marineStatusPointer->My_Weapon->MaxRange!=-1) &&
10450 			(range>=marineStatusPointer->My_Weapon->MaxRange)) {
10451 
10452 			/* .... and stop the sound */
10453 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
10454 				Sound_Stop(marineStatusPointer->soundHandle);
10455 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
10456 			}
10457 			return(SRC_Request_Approach);
10458 
10459 		}
10460 	}
10461 
10462 	/* orientate to firing point first */
10463 	orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
10464 	orientationDirn.vy = 0;
10465 	orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
10466 	correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
10467 
10468 	/* I have a cunning plan... */
10469 	{
10470 		DELTA_CONTROLLER *delta;
10471 
10472 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
10473 		if (delta) {
10474 			if (!(DeltaAnimation_IsFinished(delta))) {
10475 				correctlyOrientated=0;
10476 			}
10477 		}
10478 	}
10479 
10480 	/* we are not correctly orientated to the target: this could happen because we have
10481 	just entered this state, or the target has moved during firing*/
10482 
10483 	if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)) {
10484 
10485 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
10486 			Sound_Stop(marineStatusPointer->soundHandle);
10487 		}
10488 		return(SRC_No_Change);
10489 	}
10490 
10491 	if (marineStatusPointer->clipammo==0) {
10492 		return(SRC_Request_Reload);
10493 	}
10494 
10495 	/* at this point we are correctly orientated: if we have no gunflash yet,
10496 	and our state timer is set to marine_near_firetime then we have either
10497 	just started firing, or have become dis-orienated between bursts. This is a good
10498 	time to consider firing a grenade... */
10499 
10500 	/* No grenades with FT. */
10501 
10502 	/* look after the sound */
10503 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
10504 	else
10505 	{
10506 		/* SID_INCIN_LOOP? */
10507 		Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
10508 		Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
10509 	}
10510 
10511 	marineStatusPointer->stateTimer -= NormalFrameTime;
10512 
10513 	MarineFireFlameThrower(sbPtr);
10514 
10515 	/* Lighting? */
10516 	if (sbPtr->SBdptr) {
10517 		AddLightingEffectToObject(sbPtr->SBdptr,LFX_MUZZLEFLASH);
10518 	}
10519 
10520 	if (marineStatusPointer->clipammo>0) {
10521 		marineStatusPointer->clipammo-=NormalFrameTime;
10522 		if (marineStatusPointer->clipammo<0) {
10523 			marineStatusPointer->clipammo=0;
10524 		}
10525 	}
10526 
10527 	if(marineStatusPointer->stateTimer > 0)	return(SRC_No_Change);
10528 
10529 
10530 	{
10531 		/* we are far enough away, so return to approach */
10532 
10533 		/* ... and remove the gunflash */
10534 		if(marineStatusPointer->myGunFlash)
10535 		{
10536 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
10537 			marineStatusPointer->myGunFlash = NULL;
10538 		}
10539 
10540 		/* .... and stop the sound */
10541 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
10542 			Sound_Stop(marineStatusPointer->soundHandle);
10543 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
10544 		}
10545 		return(SRC_Request_Approach);
10546 	}
10547 }
10548 
10549 static void DischargeLOSWeapon_Core(STRATEGYBLOCK *sbPtr)
10550 {
10551 	MARINE_STATUS_BLOCK *marineStatusPointer;
10552 	VECTORCH relPos,relPos2;
10553 	int mod,hitroll,range,volleytime,volleyrounds;
10554 
10555 	LOCALASSERT(sbPtr);
10556 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
10557 	LOCALASSERT(marineStatusPointer);
10558 
10559 	/* Snipped from DischargeLOSWeapon. */
10560 
10561 	if (marineStatusPointer->Target) {
10562 		relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
10563 		relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
10564 		relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
10565 
10566 		relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
10567 		relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
10568 		relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
10569 
10570 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
10571 	} else {
10572 		/* Just a number. */
10573 		range=10000;
10574 	}
10575 
10576 	/* look after the gun flash */
10577 	if(marineStatusPointer->myGunFlash) {
10578 		MaintainMarineGunFlash(sbPtr);
10579 	} else {
10580 		CreateMarineGunFlash(sbPtr);
10581 	}
10582 
10583 	/* look after the sound */
10584 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
10585 	else
10586 	{
10587 		Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
10588 		Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
10589 	}
10590 
10591 	marineStatusPointer->stateTimer -= NormalFrameTime;
10592 
10593 	/* Volleysize is now rounds fired this state. */
10594 
10595 	volleytime=marineStatusPointer->My_Weapon->FiringTime-marineStatusPointer->stateTimer;
10596 	/* It was that or reverse the state timer for this state. */
10597 	volleyrounds=MUL_FIXED(volleytime,marineStatusPointer->My_Weapon->FiringRate);
10598 	volleyrounds>>=ONE_FIXED_SHIFT;
10599 
10600 	volleyrounds-=marineStatusPointer->volleySize;
10601 	marineStatusPointer->volleySize+=volleyrounds;
10602 
10603 	LOCALASSERT(volleyrounds>=0);
10604 
10605 	if (marineStatusPointer->clipammo!=-1) {
10606 		/* We're counting ammo. */
10607 		if (volleyrounds>marineStatusPointer->clipammo) {
10608 			volleyrounds=marineStatusPointer->clipammo;
10609 		}
10610 		marineStatusPointer->clipammo-=volleyrounds;
10611 		LOCALASSERT(marineStatusPointer->clipammo>=0);
10612 	}
10613 
10614 	marineStatusPointer->roundsForThisTarget+=volleyrounds;
10615 
10616 	/* Now hit the target with volleyrounds bullets. */
10617 
10618 	mod=SpeedRangeMods(&relPos,&relPos2);
10619 
10620 	hitroll=marineStatusPointer->Skill; /* Marine skill... */
10621 	if (marineStatusPointer->Target==Player->ObStrategyBlock) {
10622 		PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
10623 		LOCALASSERT(playerStatusPtr);
10624 		if ( (AvP.PlayerType==I_Alien)
10625 			||((AvP.PlayerType==I_Predator)&&(playerStatusPtr->cloakOn==1))) {
10626 			/* Vs the player, lighting effects on aliens and cloaked preds. */
10627 			hitroll=MUL_FIXED(hitroll,((CurrentLightAtPlayer>>1)+32767));
10628 		}
10629 	}
10630 	hitroll-=mod;
10631 	hitroll+=marineStatusPointer->My_Weapon->Accuracy;
10632 
10633 	/* Here we go... */
10634 	{
10635 		#define SUSTAINMOD (ONE_FIXED>>3)
10636 		int a,hits;
10637 
10638 		hits=0;
10639 
10640 		for (a=0; a<volleyrounds; a++) {
10641 
10642 			int realhitroll;
10643 
10644 			if (marineStatusPointer->lastroundhit) {
10645 				realhitroll=hitroll+SUSTAINMOD;
10646 			} else {
10647 				realhitroll=hitroll;
10648 			}
10649 
10650 			if (marineStatusPointer->Target) {
10651 				if (marineStatusPointer->lasthitsection) {
10652 					/* Verify this section is valid? */
10653 					HMODELCONTROLLER *tctrl=NULL;
10654 
10655 					if (marineStatusPointer->Target->SBdptr) {
10656 						tctrl=marineStatusPointer->Target->SBdptr->HModelControlBlock;
10657 					}
10658 
10659 					if ((marineStatusPointer->lasthitsection->flags&section_data_notreal)
10660 						|| (marineStatusPointer->lasthitsection->flags&section_data_terminate_here)
10661 						|| ( (tctrl!=NULL)&&(tctrl!=marineStatusPointer->lasthitsection->my_controller)) ) {
10662 						/* Invalid. */
10663 						marineStatusPointer->lasthitsection=NULL;
10664 					}
10665 				}
10666 
10667 				if ( (marineStatusPointer->lastroundhit==0)||(marineStatusPointer->lasthitsection==NULL)) {
10668 					marineStatusPointer->lasthitsection=HitLocationRoll(marineStatusPointer->Target,sbPtr);
10669 				}
10670 			}
10671 
10672 			if ((FastRandom()&65535)<realhitroll) {
10673 				hits++;
10674 				marineStatusPointer->lastroundhit=1;
10675 			} else {
10676 				marineStatusPointer->lastroundhit=0;
10677 			}
10678 
10679 			if (marineStatusPointer->Target==NULL) {
10680 				hits=0;
10681 			}
10682 		}
10683 
10684 		/* Handle Damage. */
10685 		{
10686 			VECTORCH attack_dir,rel_pos;
10687 			VECTORCH shotvector;
10688 
10689 			shotvector.vx=0;
10690 			shotvector.vy=0;
10691 			shotvector.vz=65535;
10692 			RotateVector(&shotvector,&marineStatusPointer->My_Gunflash_Section->SecMat);
10693 
10694 			/* DO DAMAGE TO TARGET HERE */
10695 			#if MARINE_STATE_PRINT
10696 			textprint("Hits = %d\n",hits);
10697 			#endif
10698 
10699 			if (hits!=0) {
10700 
10701 				int range2;
10702 
10703 				GLOBALASSERT(marineStatusPointer->Target);
10704 
10705 				rel_pos.vx=marineStatusPointer->Target->DynPtr->Position.vx-sbPtr->DynPtr->Position.vx;
10706 				rel_pos.vy=marineStatusPointer->Target->DynPtr->Position.vy-sbPtr->DynPtr->Position.vy;
10707 				rel_pos.vz=marineStatusPointer->Target->DynPtr->Position.vz-sbPtr->DynPtr->Position.vz;
10708 				range2=Approximate3dMagnitude(&rel_pos);
10709 
10710 				if (VerifyHitShot(sbPtr,marineStatusPointer->Target,&marineStatusPointer->My_Gunflash_Section->World_Offset,&shotvector, marineStatusPointer->My_Weapon->Ammo_Type, hits,range2)) {
10711 					/* If 0, hits have been dealt with. */
10712 					GetDirectionOfAttack(marineStatusPointer->Target,&rel_pos,&attack_dir);
10713 
10714 					if (marineStatusPointer->lasthitsection) {
10715 						CauseDamageToHModel(marineStatusPointer->lasthitsection->my_controller, marineStatusPointer->Target,&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage[AvP.Difficulty], ONE_FIXED*hits, marineStatusPointer->lasthitsection,&attack_dir,NULL,0);
10716 					} else {
10717 						CauseDamageToObject(marineStatusPointer->Target,&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage[AvP.Difficulty], ONE_FIXED*hits,&attack_dir);
10718 					}
10719 				}
10720 
10721 			}
10722 
10723 			if ((volleyrounds-hits)>0) {
10724 				GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
10725 
10726 				if (marineStatusPointer->Target) {
10727 					ProjectNPCShot(sbPtr, marineStatusPointer->Target, &marineStatusPointer->My_Gunflash_Section->World_Offset,&marineStatusPointer->My_Gunflash_Section->SecMat, marineStatusPointer->My_Weapon->Ammo_Type, (volleyrounds-hits));
10728 				} else {
10729 					/* Like a miss, so it's inaccurate. */
10730 					CastLOSProjectile(sbPtr,&marineStatusPointer->My_Gunflash_Section->World_Offset,&shotvector, marineStatusPointer->My_Weapon->Ammo_Type, volleyrounds,1);
10731 				}
10732 			}
10733 
10734 		}
10735 
10736 	}
10737 
10738 }
10739 
10740 static STATE_RETURN_CONDITION Execute_MNS_DischargeLOSWeapon(STRATEGYBLOCK *sbPtr)
10741 {
10742 	MARINE_STATUS_BLOCK *marineStatusPointer;
10743 	VECTORCH orientationDirn,relPos,relPos2;
10744 	int correctlyOrientated,range;
10745 
10746 	LOCALASSERT(sbPtr);
10747 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
10748 	LOCALASSERT(marineStatusPointer);
10749 
10750 	marineStatusPointer->HModelController.Playing=1;
10751 
10752 	#if MARINE_STATE_PRINT
10753 	textprint("Marine firing... ");
10754 	#endif
10755 
10756 	/* zero velocity */
10757 	LOCALASSERT(sbPtr->DynPtr);
10758 	sbPtr->DynPtr->LinVelocity.vx = 0;
10759 	sbPtr->DynPtr->LinVelocity.vy = 0;
10760 	sbPtr->DynPtr->LinVelocity.vz = 0;
10761 
10762 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
10763 	we should switch immediately to wait state*/
10764 	if (marineStatusPointer->volleySize<marineStatusPointer->My_Weapon->MinimumBurstSize) {
10765 		/* Keep firing! */
10766 	} else {
10767 		if(!MarineCanSeeTarget(sbPtr))
10768 		{
10769 			#if 1
10770 			EndMarineMuzzleFlash(sbPtr);
10771 			#else
10772 			/* ... and remove the gunflash */
10773 			if(marineStatusPointer->myGunFlash)
10774 			{
10775 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
10776 				marineStatusPointer->myGunFlash = NULL;
10777 			}
10778 
10779 			/* .... and stop the sound */
10780 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
10781 				Sound_Stop(marineStatusPointer->soundHandle);
10782 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
10783 			}
10784 			#endif
10785 
10786 			#if MARINE_STATE_PRINT
10787 			textprint("Returning no target.\n");
10788 			#endif
10789 			marineStatusPointer->lastroundhit=0;
10790 			marineStatusPointer->lasthitsection=NULL;
10791 			return(SRC_Request_Wait);
10792 		}
10793 	}
10794 
10795 	if (marineStatusPointer->clipammo==0) {
10796 		/* Reload here. */
10797 		EndMarineMuzzleFlash(sbPtr);
10798 		return(SRC_Request_Reload);
10799 	}
10800 
10801 
10802 	if (marineStatusPointer->Target) {
10803 		GLOBALASSERT(marineStatusPointer->Target);
10804 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
10805 		/* Fix weapon target! */
10806 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
10807 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
10808 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
10809 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
10810 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
10811 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
10812 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
10813 		}
10814 
10815 		/* Here we must have a target.  Renew suspicion for new arrivals. */
10816 		if (NpcSquad.Squad_Suspicion==0) {
10817 			PointAlert(2,&marineStatusPointer->weaponTarget);
10818 		}
10819 	}
10820 	/* Otherwise, stay facing the same way. */
10821 
10822 	/* orientate to firing point first */
10823 	orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
10824 	orientationDirn.vy = 0;
10825 	orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
10826 	correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
10827 
10828 	/* I have a cunning plan... */
10829 	{
10830 		DELTA_CONTROLLER *delta;
10831 
10832 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
10833 		if (delta) {
10834 			if (!(DeltaAnimation_IsFinished(delta))) {
10835 				correctlyOrientated=0;
10836 			}
10837 		}
10838 	}
10839 	/* I have another cunning plan... */
10840 	if ((marineStatusPointer->volleySize>0)&&
10841 		(marineStatusPointer->volleySize<marineStatusPointer->My_Weapon->MinimumBurstSize)) {
10842 		correctlyOrientated=1;
10843 	}
10844 
10845 
10846 	/* we are not correctly orientated to the target: this could happen because we have
10847 	just entered this state, or the target has moved during firing*/
10848 	if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)) {
10849 
10850 		/* stop visual and audio cues: technically, we're not firing at this moment */
10851 		#if 1
10852 		EndMarineMuzzleFlash(sbPtr);
10853 		#else
10854 		if(marineStatusPointer->myGunFlash)
10855 		{
10856 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
10857 			marineStatusPointer->myGunFlash = NULL;
10858 		}
10859 
10860 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
10861 			Sound_Stop(marineStatusPointer->soundHandle);
10862 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
10863 		}
10864 		#endif
10865 
10866 		#if MARINE_STATE_PRINT
10867 		textprint("Turning to face.\n");
10868 		#endif
10869 		marineStatusPointer->lastroundhit=0;
10870 		marineStatusPointer->lasthitsection=NULL;
10871 		return(SRC_No_Change);
10872 	}
10873 
10874 	if (marineStatusPointer->Target) {
10875 		relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
10876 		relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
10877 		relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
10878 
10879 		relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
10880 		relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
10881 		relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
10882 
10883 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
10884 	}
10885 
10886 	/* Test for grenading! */
10887 	if ((marineStatusPointer->myGunFlash==NULL)&&(marineStatusPointer->stateTimer == MARINE_NEAR_FIRE_TIME)
10888 		&&(marineStatusPointer->Target))
10889 	{
10890 
10891 		/* NB don't fire grenades in air ducts */
10892 		if ((FastRandom()&MARINE_CHANCEOFGRENADE) == 0) {
10893 			if (!(marineStatusPointer->IAmCrouched)) {
10894 				if (range > MARINE_TOO_CLOSE_TO_GRENADE_FOOL) {
10895 					if (marineStatusPointer->My_Weapon->EnableGrenades) {
10896 
10897 						GLOBALASSERT(marineStatusPointer->Target);
10898 						NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
10899 						LobAGrenade(sbPtr);
10900 						marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
10901 						marineStatusPointer->volleySize = 0;
10902 
10903 
10904 						#if MARINE_STATE_PRINT
10905 						textprint("fired a grenade.\n");
10906 						#endif
10907 
10908 						return(SRC_Request_Approach);
10909 					}
10910 				}
10911 			}
10912 		}
10913 	}
10914 
10915 	DischargeLOSWeapon_Core(sbPtr);
10916 
10917 	if (marineStatusPointer->Target==NULL) {
10918 		/* Getting out of here! */
10919 		return(SRC_No_Change);
10920 	}
10921 
10922 	/* Did we get him? */
10923 	if ((NPC_IsDead(marineStatusPointer->Target))
10924 		&&(marineStatusPointer->volleySize>=marineStatusPointer->My_Weapon->MinimumBurstSize)) {
10925 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
10926 			if (Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr)==NULL) {
10927 				/* Huzzah! */
10928 				#if 1
10929 				EndMarineMuzzleFlash(sbPtr);
10930 				#else
10931 				if(marineStatusPointer->myGunFlash)
10932 				{
10933 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
10934 					marineStatusPointer->myGunFlash = NULL;
10935 				}
10936 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
10937 					Sound_Stop(marineStatusPointer->soundHandle);
10938 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
10939 				}
10940 				#endif
10941 				marineStatusPointer->lastroundhit=0;
10942 				marineStatusPointer->lasthitsection=NULL;
10943 				return(SRC_Request_Taunt);
10944 			}
10945 		}
10946 	}
10947 
10948 	if(marineStatusPointer->stateTimer > 0)	{
10949 		#if MARINE_STATE_PRINT
10950 		textprint("Returning continue at range %d.\n",range);
10951 		#endif
10952 		return(SRC_No_Change);
10953 	}
10954 
10955 	if(range < MARINE_CLOSE_APPROACH_DISTANCE)
10956 	{
10957 		/* renew firing, as we are still too close to approach */
10958 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
10959 		marineStatusPointer->volleySize = 0;
10960 		GLOBALASSERT(marineStatusPointer->Target);
10961 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
10962 		#if MARINE_STATE_PRINT
10963 		textprint("Returning too close renewal at range %d.\n",range);
10964 		#endif
10965 		#if 1
10966 		/* stop visual and audio cues: technically, we're not firing at this moment */
10967 		#if 1
10968 		EndMarineMuzzleFlash(sbPtr);
10969 		#else
10970 		if(marineStatusPointer->myGunFlash)
10971 		{
10972 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
10973 			marineStatusPointer->myGunFlash = NULL;
10974 		}
10975 
10976 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
10977 			Sound_Stop(marineStatusPointer->soundHandle);
10978 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
10979 		}
10980 		#endif
10981 		#endif
10982 
10983 		if (marineStatusPointer->Android==0) {
10984 			marineStatusPointer->Courage-=(ONE_FIXED>>3);
10985 		}
10986 		return(SRC_Request_Fire);
10987 	}
10988 	else
10989 	{
10990 		/* we are far enough away, so return to approach */
10991 
10992 		#if 1
10993 		/* ... and remove the gunflash */
10994 		#if 1
10995 		EndMarineMuzzleFlash(sbPtr);
10996 		#else
10997 		if(marineStatusPointer->myGunFlash)
10998 		{
10999 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
11000 			marineStatusPointer->myGunFlash = NULL;
11001 		}
11002 		/* .... and stop the sound */
11003 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
11004 			Sound_Stop(marineStatusPointer->soundHandle);
11005 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
11006 		}
11007 		#endif
11008 		#endif
11009 
11010 		#if MARINE_STATE_PRINT
11011 		textprint("Returning too far termination at range %d.\n",range);
11012 		#endif
11013 		return(SRC_Request_Approach);
11014 	}
11015 	return(SRC_No_Change);
11016 }
11017 
11018 int SpeedRangeMods(VECTORCH *range,VECTORCH *speed) {
11019 
11020 	int dot,theta,sinthet,rmod;
11021 	int magrange,magspeed;
11022 
11023 	/* Should return between 0 and ONE_FIXED... */
11024 
11025 	magrange=Approximate3dMagnitude(range);
11026 	rmod=magrange>>2;
11027 
11028 	magspeed=Approximate3dMagnitude(speed);
11029 	dot=DotProduct(range,speed);
11030 	if (dot<0) dot=-dot;
11031 	{
11032 		int ab=MUL_FIXED(magrange,magspeed);
11033 		ab<<=1;
11034 
11035 		if (ab==0) dot=0; else dot=DIV_FIXED(dot,ab);
11036 
11037 		if (dot>ONE_FIXED) {
11038 			dot=ONE_FIXED;
11039 			/* Well, I suppose it could happen. */
11040 			/* Accuracy errors... */
11041 			LOCALASSERT(dot<=ONE_FIXED);
11042 		}
11043 
11044 		theta=ArcCos(dot);
11045 		sinthet=GetSin(theta);
11046 
11047 		dot=WideMulNarrowDiv(sinthet,magspeed,magrange);
11048 
11049 	}
11050 	dot<<=3;
11051 
11052 	return(dot+rmod);
11053 
11054 }
11055 
11056 int Validate_Target(STRATEGYBLOCK *target,char *SBname) {
11057 	/* General purpose function. */
11058 
11059 	if (target==NULL) return(0);
11060 
11061 	if (target==Player->ObStrategyBlock) {
11062 		if (Observer) {
11063 			return(0);
11064 		}
11065 	}
11066 
11067 	if (!NAME_ISEQUAL(target->SBname,SBname)) {
11068 		return(0);
11069 	} else {
11070 		if (NPC_IsDead(target)) {
11071 			return(0);
11072 		} else {
11073 			return(1);
11074 		}
11075 	}
11076 }
11077 
11078 int Validate_Strategy(STRATEGYBLOCK *target,char *SBname) {
11079 	/* General purpose function Too. */
11080 
11081 	if (target==NULL) return(0);
11082 
11083 	if (target==Player->ObStrategyBlock) {
11084 		if (Observer) {
11085 			return(0);
11086 		}
11087 	}
11088 
11089 	if (!NAME_ISEQUAL(target->SBname,SBname)) {
11090 		return(0);
11091 	} else {
11092 		return(1);
11093 	}
11094 }
11095 
11096 int Marine_TargetFilter(STRATEGYBLOCK *candidate) {
11097 
11098 	switch (candidate->I_SBtype) {
11099 		case I_BehaviourMarinePlayer:
11100 		case I_BehaviourAlienPlayer:
11101 		case I_BehaviourPredatorPlayer:
11102 			{
11103 				if (Observer) {
11104 					return(0);
11105 				}
11106 
11107 				switch(AvP.PlayerType)
11108 				{
11109 					case I_Alien:
11110 					case I_Predator:
11111 						return(1);
11112 						break;
11113 					case I_Marine:
11114 						return(0);
11115 						break;
11116 					default:
11117 						GLOBALASSERT(0);
11118 						return(0);
11119 						break;
11120 				}
11121 				break;
11122 			}
11123 		case I_BehaviourDummy:
11124 			{
11125 				DUMMY_STATUS_BLOCK *dummyStatusPointer;
11126 				dummyStatusPointer = (DUMMY_STATUS_BLOCK *)(candidate->SBdataptr);
11127 			    LOCALASSERT(dummyStatusPointer);
11128 				switch (dummyStatusPointer->PlayerType) {
11129 					case I_Alien:
11130 					case I_Predator:
11131 						return(1);
11132 						break;
11133 					case I_Marine:
11134 						return(0);
11135 						break;
11136 					default:
11137 						GLOBALASSERT(0);
11138 						return(0);
11139 						break;
11140 				}
11141 				break;
11142 			}
11143 		case I_BehaviourAlien:
11144 			{
11145 				ALIEN_STATUS_BLOCK *alienStatusPointer;
11146 				LOCALASSERT(candidate);
11147 				LOCALASSERT(candidate->DynPtr);
11148 
11149 				alienStatusPointer=(ALIEN_STATUS_BLOCK *)(candidate->SBdataptr);
11150 
11151 				if (NPC_IsDead(candidate)) {
11152 					return(0);
11153 				} else {
11154 					if ((alienStatusPointer->BehaviourState==ABS_Dormant)||
11155 						(alienStatusPointer->BehaviourState==ABS_Awakening)) {
11156 						return(0);
11157 					} else {
11158 						return(1);
11159 					}
11160 				}
11161 				break;
11162 			}
11163 		case I_BehaviourQueenAlien:
11164 		case I_BehaviourFaceHugger:
11165 		case I_BehaviourPredator:
11166 		case I_BehaviourXenoborg:
11167 		case I_BehaviourSeal:
11168 		case I_BehaviourPredatorAlien:
11169 			/* Valid. */
11170 			return(1);
11171 			break;
11172 		case I_BehaviourMarine:
11173 			#if ANARCHY
11174 			return(1);
11175 			#else
11176 			return(0);
11177 			#endif
11178 			break;
11179 		case I_BehaviourNetGhost:
11180 			{
11181 				NETGHOSTDATABLOCK *dataptr;
11182 				dataptr=candidate->SBdataptr;
11183 				switch (dataptr->type) {
11184 					case I_BehaviourMarinePlayer:
11185 					case I_BehaviourAlienPlayer:
11186 					case I_BehaviourPredatorPlayer:
11187 						//return(1);
11188 						return(0);
11189 						break;
11190 					default:
11191 						return(0);
11192 						break;
11193 				}
11194 			}
11195 			break;
11196 		default:
11197 			return(0);
11198 			break;
11199 	}
11200 
11201 }
11202 
11203 
11204 STRATEGYBLOCK *Marine_GetNewTarget(VECTORCH *marinepos, STRATEGYBLOCK *me) {
11205 
11206 	int neardist, newblip;
11207 	STRATEGYBLOCK *nearest;
11208 	#if 1
11209 	int a;
11210 	STRATEGYBLOCK *candidate;
11211 	#endif
11212 	MODULE *dmod;
11213 	MARINE_STATUS_BLOCK *marineStatusPointer;
11214 	int dist;
11215 	VECTORCH offset;
11216 
11217 	LOCALASSERT(me);
11218 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(me->SBdataptr);
11219 	LOCALASSERT(marineStatusPointer);
11220 
11221 	dmod=ModuleFromPosition(marinepos,playerPherModule);
11222 
11223 	LOCALASSERT(dmod);
11224 
11225 	nearest=NULL;
11226 	neardist=ONE_FIXED;
11227 	newblip=0;
11228 
11229 	//#if ANARCHY
11230 	#if 1
11231 	for (a=0; a<NumActiveStBlocks; a++) {
11232 		candidate=ActiveStBlockList[a];
11233 
11234 		if (candidate!=me) {
11235 			if (candidate->DynPtr) {
11236 				/* Arc reject. */
11237 				MATRIXCH WtoL;
11238 
11239 				offset.vx=marinepos->vx-candidate->DynPtr->Position.vx;
11240 				offset.vy=marinepos->vy-candidate->DynPtr->Position.vy;
11241 				offset.vz=marinepos->vz-candidate->DynPtr->Position.vz;
11242 
11243 				WtoL=me->DynPtr->OrientMat;
11244 				TransposeMatrixCH(&WtoL);
11245 				RotateVector(&offset,&WtoL);
11246 
11247 				if (offset.vz<=0) {
11248 
11249 					/* It'll wheep, anyway. */
11250 					if (marineStatusPointer->mtracker_timer==0) {
11251 						#if 0
11252 						if (
11253 							(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11254 							||(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11255 							||(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11256 							) {
11257 						#else
11258 						if (ObjectShouldAppearOnMotionTracker(candidate)) {
11259 						#endif
11260 
11261 							dist=Approximate3dMagnitude(&offset);
11262 							if (dist<MOTIONTRACKER_RANGE) {
11263 								tracker_noise=2;
11264 							}
11265 						}
11266 					}
11267 
11268 					if (Marine_TargetFilter(candidate)) {
11269 
11270 						dist=Approximate3dMagnitude(&offset);
11271 
11272 						if (dist<neardist) {
11273 							/* Check visibility? */
11274 							if ((candidate->SBdptr)&&(me->SBdptr)) {
11275 								/* Near case. */
11276 								if ((!NPC_IsDead(candidate))
11277 									||(candidate->I_SBtype==I_BehaviourMarinePlayer)
11278 									||(candidate->I_SBtype==I_BehaviourDummy)) {
11279 									if ((MarineCanSeeObject(me,candidate))) {
11280 										nearest=candidate;
11281 										neardist=dist;
11282 									}
11283 								}
11284 							} else {
11285 								if ((!NPC_IsDead(candidate))
11286 									||(candidate->I_SBtype==I_BehaviourMarinePlayer)
11287 									||(candidate->I_SBtype==I_BehaviourDummy)) {
11288 									if ((IsModuleVisibleFromModule(dmod,candidate->containingModule))) {
11289 										nearest=candidate;
11290 										neardist=dist;
11291 									}
11292 								}
11293 							}
11294 
11295 							if (marineStatusPointer->mtracker_timer==0) {
11296 								/* Hey, the tracker's on. */
11297 								if (dist<MOTIONTRACKER_RANGE) {
11298 									#if 0
11299 									if (
11300 										(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11301 										||(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11302 										||(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11303 										) {
11304 									#else
11305 									if (ObjectShouldAppearOnMotionTracker(candidate)) {
11306 									#endif
11307 										newblip=1;
11308 										marineStatusPointer->suspect_point=candidate->DynPtr->Position;
11309 										/* Set this to zero when you get a *new* suspicion. */
11310 										marineStatusPointer->previous_suspicion=0;
11311 										marineStatusPointer->using_squad_suspicion=0;
11312 									}
11313 								}
11314 							}
11315 						}
11316 					}
11317 				}
11318 			}
11319 		}
11320 	}
11321 	#endif
11322 
11323 	if (nearest==NULL) {
11324 		if (newblip) {
11325 			marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
11326 			tracker_noise=2;
11327 			PointAlert(1,&marineStatusPointer->suspect_point);
11328 		}
11329 	} else {
11330 		PointAlert(2,&nearest->DynPtr->Position);
11331 	}
11332 
11333 	if (nearest) {
11334 		/* Must have seen them. */
11335 		marineStatusPointer->roundsForThisTarget=0;
11336 		marineStatusPointer->sawlastframe=1;
11337 
11338 		if (((marineStatusPointer->suspicious==0)&&((FastRandom()&65535)<16384))
11339 			||(neardist<((FastRandom()&4095)+1000))) {
11340 			/* Exhibit suprise? */
11341 			Marine_SurpriseSound(me);
11342 		}
11343 	}
11344 
11345 	return(nearest);
11346 
11347 }
11348 
11349 void FakeTrackerWheepGenerator(VECTORCH *marinepos, STRATEGYBLOCK *me) {
11350 
11351 	int a,dist;
11352 	STRATEGYBLOCK *candidate;
11353 	MARINE_STATUS_BLOCK *marineStatusPointer;
11354 	VECTORCH offset;
11355 
11356 	LOCALASSERT(me);
11357 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(me->SBdataptr);
11358 	LOCALASSERT(marineStatusPointer);
11359 
11360 	if (marineStatusPointer->mtracker_timer==0) {
11361 		for (a=0; a<NumActiveStBlocks; a++) {
11362 			candidate=ActiveStBlockList[a];
11363 			if (candidate!=me) {
11364 				if (candidate->DynPtr) {
11365 					/* Arc reject. */
11366 					MATRIXCH WtoL;
11367 
11368 					offset.vx=marinepos->vx-candidate->DynPtr->Position.vx;
11369 					offset.vy=marinepos->vy-candidate->DynPtr->Position.vy;
11370 					offset.vz=marinepos->vz-candidate->DynPtr->Position.vz;
11371 
11372 					WtoL=me->DynPtr->OrientMat;
11373 					TransposeMatrixCH(&WtoL);
11374 					RotateVector(&offset,&WtoL);
11375 
11376 					if (offset.vz<=0) {
11377 						/* It'll wheep, anyway. */
11378 						#if 0
11379 						if (
11380 							(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11381 							||(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11382 							||(candidate->DynPtr->Position.vx!=candidate->DynPtr->PrevPosition.vx)
11383 							) {
11384 						#else
11385 						if (ObjectShouldAppearOnMotionTracker(candidate)) {
11386 						#endif
11387 							dist=Approximate3dMagnitude(&offset);
11388 							if (dist<MOTIONTRACKER_RANGE) {
11389 								tracker_noise=2;
11390 							}
11391 						}
11392 					}
11393 				}
11394 			}
11395 		}
11396 	}
11397 }
11398 
11399 #if 0
11400 static STATE_RETURN_CONDITION Execute_MNS_Hunt(STRATEGYBLOCK *sbPtr)
11401 {
11402 	MARINE_STATUS_BLOCK *marineStatusPointer;
11403 	DYNAMICSBLOCK *dynPtr;
11404 	VECTORCH velocityDirection = {0,0,0};
11405 
11406 	/* Your mission: to advance into the players module, even if near. */
11407 
11408 	LOCALASSERT(sbPtr);
11409 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
11410 	dynPtr = sbPtr->DynPtr;
11411 	LOCALASSERT(marineStatusPointer);
11412 	LOCALASSERT(dynPtr);
11413 
11414 	/* check if we should be crouched or standing up */
11415 	if(marineStatusPointer->IAmCrouched)
11416 	{
11417 		/* curently crouched */
11418 		if(!(MarineShouldBeCrawling(sbPtr)))
11419 		{
11420 			/* should be running*/
11421 			marineStatusPointer->IAmCrouched = 0;
11422 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
11423 		}
11424 	}
11425 	else
11426 	{
11427 		/* currently standing */
11428 		if(MarineShouldBeCrawling(sbPtr))
11429 		{
11430 			/* should be crawling */
11431 			marineStatusPointer->IAmCrouched = 1;
11432 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
11433 		}
11434 	}
11435 
11436 	/* should we change to approach state? */
11437 	if(MarineCanSeeTarget(sbPtr))
11438 	{
11439 		return(SRC_Request_Approach);
11440 	} else if(!(MarineIsAwareOfTarget(sbPtr))) {
11441 		return(SRC_Request_Wait);
11442 	}
11443 
11444 	{
11445 		AIMODULE *targetModule;
11446 		FARENTRYPOINT *thisEp = (FARENTRYPOINT *)0;
11447 
11448 		targetModule = FarNPC_GetTargetAIModuleForHunt(sbPtr,0);
11449 
11450 		if (targetModule) {
11451 		//	textprint("Target module is %s\n",targetModule->name);
11452 			#if MARINE_STATE_PRINT
11453 			textprint("Target module is... an AI module...\n");
11454 			#endif
11455 		} else {
11456 			#if MARINE_STATE_PRINT
11457 			textprint("Target module is NULL!\n");
11458 			#endif
11459 		}
11460 
11461 		if (targetModule==sbPtr->containingModule->m_aimodule) {
11462 			/* Hey, it'll drop through. */
11463 			return(SRC_Request_Approach);
11464 		}
11465 
11466 		if (!targetModule) {
11467 			#if 1
11468 			/* Must be sealed off. */
11469 			return(SRC_Request_Wait);
11470 			#else
11471 			extern MODULE *playerPherModule;
11472 
11473 			LOGDXFMT(("Jules's bug: marine is in %s, player is in %s",sbPtr->containingModule->name,playerPherModule->name));
11474 			GLOBALASSERT(targetModule);
11475 			#endif
11476 		}
11477 
11478 		thisEp=GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
11479 		if (!thisEp) {
11480 			//LOGDXFMT(("This assert is a busted adjacency!\nNo EP between %s and %s.",targetModule->name,sbPtr->containingModule->name));
11481 			LOGDXFMT(("This assert is a busted adjacency!"));
11482 			GLOBALASSERT(thisEp);
11483 		}
11484 		/* If that fired, there's a farped adjacency. */
11485 		GLOBALASSERT(thisEp->alien_only==0);
11486 		/* If that fired, Get...ModuleForHunt went wrong. */
11487 
11488 		marineStatusPointer->wanderData.worldPosition=thisEp->position;
11489 		marineStatusPointer->wanderData.worldPosition.vx+=targetModule->m_world.vx;
11490 		marineStatusPointer->wanderData.worldPosition.vy+=targetModule->m_world.vy;
11491 		marineStatusPointer->wanderData.worldPosition.vz+=targetModule->m_world.vz;
11492 
11493 	}
11494 
11495 	/* ok: should have a current target at this stage... */
11496 	NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
11497 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
11498 
11499 	/* test here for impeding collisions, and not being able to reach target... */
11500 	#if ALL_NEW_AVOIDANCE
11501 	{
11502 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
11503 			/* Go to all new avoidance. */
11504 			return(SRC_Request_Avoidance);
11505 		}
11506 	}
11507 	#else
11508 	{
11509 		STRATEGYBLOCK *destructableObject = NULL;
11510 
11511 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
11512 		if((marineStatusPointer->obstruction.environment)||(marineStatusPointer->obstruction.otherCharacter))
11513 		{
11514 			return(SRC_Request_Avoidance);
11515 		}
11516 		if(marineStatusPointer->obstruction.destructableObject)
11517 		{
11518 			LOCALASSERT(destructableObject);
11519 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
11520 		}
11521 	}
11522 
11523 	if(NPC_CannotReachTarget(&(marineStatusPointer->moveData), &(marineStatusPointer->wanderData.worldPosition), &velocityDirection))
11524 	{
11525 		/* go to avoidance */
11526 		/* no sequence change required */
11527 
11528 		marineStatusPointer->obstruction.environment=1;
11529 		marineStatusPointer->obstruction.destructableObject=0;
11530 		marineStatusPointer->obstruction.otherCharacter=0;
11531 		marineStatusPointer->obstruction.anySingleObstruction=0;
11532 
11533 		return(SRC_Request_Avoidance);
11534 	}
11535 	#endif
11536 
11537 	return(SRC_No_Change);
11538 }
11539 #endif
11540 
11541 static STATE_RETURN_CONDITION Execute_MNS_Respond(STRATEGYBLOCK *sbPtr)
11542 {
11543 	MARINE_STATUS_BLOCK *marineStatusPointer;
11544 	DYNAMICSBLOCK *dynPtr;
11545 	VECTORCH velocityDirection = {0,0,0};
11546 
11547 	/* Your mission: to advance into the alert zone, even if near. */
11548 
11549 	LOCALASSERT(sbPtr);
11550 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
11551 	dynPtr = sbPtr->DynPtr;
11552 	LOCALASSERT(marineStatusPointer);
11553 	LOCALASSERT(dynPtr);
11554 
11555 	#if 0
11556 	/* check if we should be crouched or standing up */
11557 	if(marineStatusPointer->IAmCrouched)
11558 	{
11559 		/* curently crouched */
11560 		if(!(MarineShouldBeCrawling(sbPtr)))
11561 		{
11562 			/* should be running*/
11563 			marineStatusPointer->IAmCrouched = 0;
11564 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineRun,MRSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
11565 		}
11566 	}
11567 	else
11568 	{
11569 		/* currently standing */
11570 		if(MarineShouldBeCrawling(sbPtr))
11571 		{
11572 			/* should be crawling */
11573 			marineStatusPointer->IAmCrouched = 1;
11574 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
11575 		}
11576 	}
11577 	#else
11578 	HandleMovingAnimations(sbPtr);
11579 	#endif
11580 
11581 	/* should we change to approach state? */
11582 	if((MarineIsAwareOfTarget(sbPtr))) {
11583 		return(SRC_Request_Approach);
11584 	}
11585 	/* If we've picked up a new target, go for it. */
11586 
11587 	if (sbPtr->containingModule->m_aimodule==NpcSquad.alertZone) {
11588 		/* We're here! */
11589 		DeprioritiseAlert(sbPtr->containingModule->m_aimodule);
11590 		/* Hey, if it's real, there'll be a new one soon enough. */
11591 		return(SRC_Request_Approach);
11592 	}
11593 
11594 	{
11595 		AIMODULE *targetModule;
11596 		FARENTRYPOINT *thisEp = (FARENTRYPOINT *)0;
11597 
11598 		targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
11599 
11600 		if (targetModule) {
11601 		//	textprint("Target module is %s\n",targetModule->name);
11602 			#if MARINE_STATE_PRINT
11603 			textprint("Target module is... an AI module...\n");
11604 			#endif
11605 		} else {
11606 			#if MARINE_STATE_PRINT
11607 			textprint("Target module is NULL!\n");
11608 			#endif
11609 		}
11610 
11611 		if (targetModule==sbPtr->containingModule->m_aimodule) {
11612 			/* Looks like we've arrived. */
11613 			/* Hey, it'll drop through. */
11614 			return(SRC_Request_Approach);
11615 		}
11616 
11617 		if (!targetModule) {
11618 			#if 1
11619 			/* Must be sealed off. */
11620 			return(SRC_Request_Wait);
11621 			#else
11622 			extern MODULE *playerPherModule;
11623 
11624 			LOGDXFMT(("Jules's bug: marine is in %s, player is in %s",sbPtr->containingModule->name,playerPherModule->name));
11625 			GLOBALASSERT(targetModule);
11626 			#endif
11627 		}
11628 
11629 		thisEp=GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
11630 		if (!thisEp) {
11631 			//LOGDXFMT(("This assert is a busted adjacency!\nNo EP between %s and %s.",targetModule->name,sbPtr->containingModule->name));
11632 			LOGDXFMT(("This assert is a busted adjacency!"));
11633 			GLOBALASSERT(thisEp);
11634 		}
11635 		/* If that fired, there's a farped adjacency. */
11636 		GLOBALASSERT(thisEp->alien_only==0);
11637 		/* If that fired, GetNextModuleForLink went wrong. */
11638 
11639 		marineStatusPointer->wanderData.worldPosition=thisEp->position;
11640 		marineStatusPointer->wanderData.worldPosition.vx+=targetModule->m_world.vx;
11641 		marineStatusPointer->wanderData.worldPosition.vy+=targetModule->m_world.vy;
11642 		marineStatusPointer->wanderData.worldPosition.vz+=targetModule->m_world.vz;
11643 
11644 	}
11645 
11646 	/* ok: should have a current target at this stage... */
11647 	NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
11648 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
11649 
11650 	/* test here for impeding collisions, and not being able to reach target... */
11651 	#if ALL_NEW_AVOIDANCE
11652 	{
11653 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
11654 			/* Go to all new avoidance. */
11655 			return(SRC_Request_Avoidance);
11656 		}
11657 	}
11658 	#else
11659 	{
11660 		STRATEGYBLOCK *destructableObject = NULL;
11661 
11662 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
11663 		if((marineStatusPointer->obstruction.environment)||(marineStatusPointer->obstruction.otherCharacter))
11664 		{
11665 			return(SRC_Request_Avoidance);
11666 		}
11667 		if(marineStatusPointer->obstruction.destructableObject)
11668 		{
11669 			LOCALASSERT(destructableObject);
11670 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
11671 		}
11672 	}
11673 
11674 	if(NPC_CannotReachTarget(&(marineStatusPointer->moveData), &(marineStatusPointer->wanderData.worldPosition), &velocityDirection))
11675 	{
11676 		/* go to avoidance */
11677 		/* no sequence change required */
11678 
11679 		marineStatusPointer->obstruction.environment=1;
11680 		marineStatusPointer->obstruction.destructableObject=0;
11681 		marineStatusPointer->obstruction.otherCharacter=0;
11682 		marineStatusPointer->obstruction.anySingleObstruction=0;
11683 
11684 		return(SRC_Request_Avoidance);
11685 	}
11686 	#endif
11687 
11688 	return(SRC_No_Change);
11689 }
11690 
11691 static int MarineRetreatsInTheFaceOfDanger(STRATEGYBLOCK *sbPtr)
11692 {
11693 	MARINE_STATUS_BLOCK *marineStatusPointer;
11694 
11695 	LOCALASSERT(sbPtr);
11696 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
11697 	LOCALASSERT(marineStatusPointer);
11698 
11699 	/* This depends on mission, armament, and whether he's cornered. */
11700 
11701 	if (marineStatusPointer->Android) {
11702 		return(0);
11703 	}
11704 
11705 	switch (marineStatusPointer->Mission) {
11706 		case MM_NonCom:
11707 			#if 0
11708 			/* Err... runferrit! */
11709 			return(1);
11710 			break;
11711 			#endif
11712 		case MM_Guard:
11713 		case MM_Wander:
11714 		case MM_Wait_Then_Wander:
11715 		case MM_LocalGuard:
11716 		case MM_Pathfinder:
11717 			{
11718 				if ((FastRandom()&65535)>marineStatusPointer->Courage) {
11719 					return(1);
11720 				} else {
11721 					return(0);
11722 				}
11723 				break;
11724 			}
11725 		default:
11726 			return(0);
11727 			break;
11728 	}
11729 
11730 	return(0);
11731 }
11732 
11733 static STATE_RETURN_CONDITION Execute_MNS_Retreat(STRATEGYBLOCK *sbPtr)
11734 {
11735 	MARINE_STATUS_BLOCK *marineStatusPointer;
11736 	DYNAMICSBLOCK *dynPtr;
11737 	VECTORCH velocityDirection = {0,0,0};
11738 	AIMODULE *old_fearmod;
11739 
11740 	/* Your mission: to advance out of trouble, even if near. */
11741 
11742 	LOCALASSERT(sbPtr);
11743 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
11744 	dynPtr = sbPtr->DynPtr;
11745 	LOCALASSERT(marineStatusPointer);
11746 	LOCALASSERT(dynPtr);
11747 
11748 	old_fearmod=marineStatusPointer->fearmodule;
11749 
11750 	/* From where am I running? */
11751 	if(MarineIsAwareOfTarget(sbPtr)) {
11752 		marineStatusPointer->fearmodule=marineStatusPointer->Target->containingModule->m_aimodule;
11753 	} else if (marineStatusPointer->fearmodule==NULL) {
11754 		marineStatusPointer->fearmodule=sbPtr->containingModule->m_aimodule;
11755 
11756 		if (TERROR_MODE) {
11757 			/* Better correct... */
11758 			marineStatusPointer->fearmodule=Player->ObStrategyBlock->containingModule->m_aimodule;
11759 		}
11760 	}
11761 
11762 	if (marineStatusPointer->fearmodule!=old_fearmod) {
11763 		marineStatusPointer->destinationmodule = General_GetAIModuleForRetreat(sbPtr,marineStatusPointer->fearmodule,5);
11764 	}
11765 
11766 	{
11767 		AIMODULE *targetModule;
11768 		FARENTRYPOINT *thisEp = (FARENTRYPOINT *)0;
11769 
11770 		targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->destinationmodule,6,0);
11771 
11772 		#if 0
11773 		if (targetModule) {
11774 			//textprint("Target module is %s\n",targetModule->name);
11775 			#if MARINE_STATE_PRINT
11776 			textprint("Target AI module found.\n");
11777 			#endif
11778 		} else {
11779 			#if MARINE_STATE_PRINT
11780 			textprint("Target module is NULL!\n");
11781 			#endif
11782 			return(SRC_Request_Wait);
11783 		}
11784 		#endif
11785 
11786 		if ((targetModule==sbPtr->containingModule->m_aimodule)
11787 			|| (targetModule==NULL)) {
11788 			/* There's no-where to run! */
11789 			if (marineStatusPointer->Target) {
11790 				return(SRC_Request_PanicFire);
11791 			} else {
11792 				return(SRC_Request_Wait);
11793 			}
11794 		}
11795 
11796 		GLOBALASSERT(targetModule);
11797 
11798 		thisEp=GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
11799 		if (!thisEp) {
11800 			//LOGDXFMT(("This assert is a busted adjacency!\nNo EP between %s and %s.",targetModule->name,sbPtr->containingModule->name));
11801 			LOGDXFMT(("This assert is a busted adjacency!"));
11802 			GLOBALASSERT(thisEp);
11803 		}
11804 		/* If that fired, there's a farped adjacency. */
11805 		GLOBALASSERT(thisEp->alien_only==0);
11806 		/* If that fired, GetNextModuleForLink went wrong. */
11807 
11808 		marineStatusPointer->wanderData.worldPosition=thisEp->position;
11809 		marineStatusPointer->wanderData.worldPosition.vx+=targetModule->m_world.vx;
11810 		marineStatusPointer->wanderData.worldPosition.vy+=targetModule->m_world.vy;
11811 		marineStatusPointer->wanderData.worldPosition.vz+=targetModule->m_world.vz;
11812 
11813 	}
11814 
11815 	/* Ok: should have a current target at this stage... */
11816 	NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
11817 	if (marineStatusPointer->Target) {
11818 		int dp;
11819 		VECTORCH vectotarget;
11820 		/* Are we running in a stupid direction? */
11821 		vectotarget.vx=marineStatusPointer->Target->DynPtr->Position.vx-sbPtr->DynPtr->Position.vx;
11822 		vectotarget.vy=marineStatusPointer->Target->DynPtr->Position.vy-sbPtr->DynPtr->Position.vy;
11823 		vectotarget.vz=marineStatusPointer->Target->DynPtr->Position.vz-sbPtr->DynPtr->Position.vz;
11824 		Normalise(&vectotarget);
11825 
11826 		dp=DotProduct(&vectotarget,&velocityDirection);
11827 
11828 		if (dp>55000) {
11829 			/* Argh!  He's in the way! */
11830 			return(SRC_Request_PanicFire);
11831 		}
11832 	}
11833 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
11834 
11835 	HandleMovingAnimations(sbPtr);
11836 	/* ...so we must be here for the duration. */
11837 
11838 	/* Scream handling. */
11839 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
11840 		if (marineStatusPointer->incidentFlag) {
11841 			if (Marine_HasHisMouthOpen(sbPtr)) {
11842 				if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
11843 					Marine_PanicScream(sbPtr);
11844 				}
11845 			}
11846 		}
11847 	}
11848 
11849 	/* test here for impeding collisions, and not being able to reach target... */
11850 	#if ALL_NEW_AVOIDANCE
11851 	{
11852 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
11853 			/* Go to all new avoidance. */
11854 			return(SRC_Request_Avoidance);
11855 		}
11856 	}
11857 	#else
11858 	{
11859 		STRATEGYBLOCK *destructableObject = NULL;
11860 
11861 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
11862 		if((marineStatusPointer->obstruction.environment)||(marineStatusPointer->obstruction.otherCharacter))
11863 		{
11864 			return(SRC_Request_Avoidance);
11865 		}
11866 		if(marineStatusPointer->obstruction.destructableObject)
11867 		{
11868 			LOCALASSERT(destructableObject);
11869 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
11870 		}
11871 	}
11872 
11873 	#if 1
11874 	if(NPC_CannotReachTarget(&(marineStatusPointer->moveData), &(marineStatusPointer->wanderData.worldPosition), &velocityDirection))
11875 	{
11876 		/* go to avoidance */
11877 		/* no sequence change required */
11878 
11879 		marineStatusPointer->obstruction.environment=1;
11880 		marineStatusPointer->obstruction.destructableObject=0;
11881 		marineStatusPointer->obstruction.otherCharacter=0;
11882 		marineStatusPointer->obstruction.anySingleObstruction=0;
11883 
11884 		return(SRC_Request_Avoidance);
11885 	}
11886 	#endif
11887 	#endif
11888 
11889 	return(SRC_No_Change);
11890 }
11891 
11892 static STATE_RETURN_CONDITION Execute_MNS_DischargeShotgun(STRATEGYBLOCK *sbPtr)
11893 {
11894 	MARINE_STATUS_BLOCK *marineStatusPointer;
11895 	VECTORCH orientationDirn,relPos,relPos2;
11896 	int correctlyOrientated,range;
11897 	int hitroll;
11898 
11899 	LOCALASSERT(sbPtr);
11900 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
11901 	LOCALASSERT(marineStatusPointer);
11902 
11903 	/* zero velocity */
11904 	LOCALASSERT(sbPtr->DynPtr);
11905 	sbPtr->DynPtr->LinVelocity.vx = 0;
11906 	sbPtr->DynPtr->LinVelocity.vy = 0;
11907 	sbPtr->DynPtr->LinVelocity.vz = 0;
11908 
11909 	#if MARINE_STATE_PRINT
11910 	textprint("Firing shotgun... ");
11911 	#endif
11912 
11913 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
11914 	we should switch immediately to wait state.*/
11915 
11916 	if(!MarineCanSeeTarget(sbPtr))
11917 	{
11918 
11919 		/* Remove the gunflash */
11920 		if(marineStatusPointer->myGunFlash)
11921 		{
11922 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
11923 			marineStatusPointer->myGunFlash = NULL;
11924 		}
11925 		/* .... and stop the sound */
11926 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
11927 			Sound_Stop(marineStatusPointer->soundHandle);
11928 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
11929 		}
11930 		return(SRC_Request_Wait);
11931 	}
11932 
11933 	if (marineStatusPointer->clipammo==0) {
11934 		return(SRC_Request_Reload);
11935 	}
11936 
11937 	/* Here we must have a target.  Renew suspicion for new arrivals. */
11938 	if (NpcSquad.Squad_Suspicion==0) {
11939 		PointAlert(2,&marineStatusPointer->weaponTarget);
11940 	}
11941 
11942 	/* Deal with tweening part. */
11943 	if (marineStatusPointer->internalState) {
11944 		if (marineStatusPointer->HModelController.Tweening==Controller_NoTweening) {
11945 			marineStatusPointer->HModelController.Playing=0;
11946 			marineStatusPointer->HModelController.sequence_timer=0;
11947 			marineStatusPointer->internalState=0;
11948 		}
11949 		return(SRC_No_Change);
11950 	}
11951 
11952 	#if 0
11953 	if ((marineStatusPointer->HModelController.keyframe_flags)
11954 		||(marineStatusPointer->HModelController.Playing==0)) {
11955 
11956 		marineStatusPointer->HModelController.Playing=0;
11957 	#else
11958 	if (marineStatusPointer->HModelController.Playing==0) {
11959 	#endif
11960 
11961 		/* Only terminate if you haven't fired yet... */
11962 		if(!MarineCanSeeTarget(sbPtr))
11963 		{
11964 
11965 			/* ... and remove the gunflash */
11966 			if(marineStatusPointer->myGunFlash)
11967 			{
11968 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
11969 				marineStatusPointer->myGunFlash = NULL;
11970 			}
11971 
11972 			/* .... and stop the sound */
11973 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
11974 				Sound_Stop(marineStatusPointer->soundHandle);
11975 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
11976 			}
11977 
11978 			#if MARINE_STATE_PRINT
11979 			textprint("Returning no target.\n");
11980 			#endif
11981 			return(SRC_Request_Wait);
11982 		}
11983 
11984 		GLOBALASSERT(marineStatusPointer->Target);
11985 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
11986 		/* Fix weapon target! */
11987 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
11988 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
11989 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
11990 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
11991 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
11992 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
11993 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
11994 		}
11995 
11996 		/* orientate to firing point first */
11997 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
11998 		orientationDirn.vy = 0;
11999 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
12000 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
12001 
12002 		/* we are not correctly orientated to the target: this could happen because we have
12003 		just entered this state, or the target has moved during firing*/
12004 		if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)) {
12005 
12006 			/* stop visual and audio cues: technically, we're not firing at this moment */
12007 			if(marineStatusPointer->myGunFlash)
12008 			{
12009 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12010 				marineStatusPointer->myGunFlash = NULL;
12011 			}
12012 
12013 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12014 				Sound_Stop(marineStatusPointer->soundHandle);
12015 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12016 			}
12017 			#if MARINE_STATE_PRINT
12018 			textprint("Turning to face.\n");
12019 			#endif
12020 			return(SRC_No_Change);
12021 		}
12022 
12023 		/* If you are correctly oriented, you can now fire! */
12024 
12025 		marineStatusPointer->HModelController.Playing=1;
12026 		marineStatusPointer->HModelController.sequence_timer=0;
12027 
12028 		relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
12029 		relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
12030 		relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
12031 
12032 		relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
12033 		relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
12034 		relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
12035 
12036 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
12037 
12038 		/* at this point we are correctly orientated: if we have no gunflash yet,
12039 		and our state timer is set to marine_near_firetime then we have either
12040 		just started firing, or have become dis-orienated between bursts. This is a good
12041 		time to consider firing a grenade... */
12042 
12043 		/* look after the gun flash */
12044 		if(marineStatusPointer->myGunFlash) {
12045 			MaintainMarineGunFlash(sbPtr);
12046 		} else {
12047 			CreateMarineGunFlash(sbPtr);
12048 		}
12049 
12050 		/* look after the sound */
12051 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
12052 		else
12053 		{
12054 			Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
12055 			Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
12056 		}
12057 
12058 		/* Now hit the target with a shotgun blast. */
12059 
12060 		hitroll=0;
12061 
12062 		while (ShotgunBlast[hitroll].vz>0) {
12063 			VECTORCH world_vec;
12064 
12065 			RotateAndCopyVector(&ShotgunBlast[hitroll],&world_vec,&marineStatusPointer->My_Gunflash_Section->SecMat);
12066 			CastLOSProjectile(sbPtr,&marineStatusPointer->My_Gunflash_Section->World_Offset,&world_vec, marineStatusPointer->My_Weapon->Ammo_Type, 1,0);
12067 
12068 			hitroll++;
12069 		}
12070 		if (marineStatusPointer->clipammo>0) {
12071 			marineStatusPointer->clipammo--;
12072 		}
12073 
12074 	} else {
12075 
12076 		/* Remove the gunflash */
12077 		if(marineStatusPointer->myGunFlash)
12078 		{
12079 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12080 			marineStatusPointer->myGunFlash = NULL;
12081 		}
12082 		/* .... and stop the sound */
12083 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12084 			Sound_Stop(marineStatusPointer->soundHandle);
12085 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12086 		}
12087 	}
12088 
12089 	marineStatusPointer->stateTimer -= NormalFrameTime;
12090 
12091 	/* You must have fired already. */
12092 	#if 1
12093 	GLOBALASSERT(marineStatusPointer->HModelController.Looped==0);
12094 	if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController)) {
12095 		return(SRC_Request_PumpAction);
12096 	}
12097 	return(SRC_No_Change);
12098 	#else
12099 	if(marineStatusPointer->stateTimer > 0)	{
12100 		#if MARINE_STATE_PRINT
12101 		textprint("Returning continue at range %d.\n",range);
12102 		#endif
12103 		return(SRC_No_Change);
12104 	}
12105 
12106 	if(range < MARINE_CLOSE_APPROACH_DISTANCE)
12107 	{
12108 		/* renew firing, as we are still too close to approach */
12109 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
12110 		marineStatusPointer->volleySize = 0;
12111 		GLOBALASSERT(marineStatusPointer->Target);
12112 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
12113 		#if MARINE_STATE_PRINT
12114 		textprint("Returning too close renewal at range %d.\n",range);
12115 		#endif
12116 		if (marineStatusPointer->Android==0) {
12117 			marineStatusPointer->Courage-=(ONE_FIXED>>3);
12118 		}
12119 		return(SRC_No_Change);
12120 	}
12121 	else
12122 	{
12123 		/* we are far enough away, so return to approach */
12124 
12125 		#if MARINE_STATE_PRINT
12126 		textprint("Returning too far termination at range %d.\n",range);
12127 		#endif
12128 		return(SRC_Request_Approach);
12129 	}
12130 	return(SRC_No_Change);
12131 	#endif
12132 }
12133 
12134 #define PISTOL_RELOAD_TIME 65536
12135 
12136 static STATE_RETURN_CONDITION Execute_MNS_DischargePistol(STRATEGYBLOCK *sbPtr)
12137 {
12138 	MARINE_STATUS_BLOCK *marineStatusPointer;
12139 	VECTORCH orientationDirn,relPos,relPos2;
12140 	int correctlyOrientated,range;
12141 	int mod,hitroll;
12142 
12143 	LOCALASSERT(sbPtr);
12144 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
12145 	LOCALASSERT(marineStatusPointer);
12146 
12147 	LOCALASSERT((marineStatusPointer->My_Weapon->id==MNPCW_MPistol)
12148 		||(marineStatusPointer->My_Weapon->id==MNPCW_PistolMarine)
12149 		||(marineStatusPointer->My_Weapon->id==MNPCW_Android_Pistol_Special));
12150 
12151 	/* zero velocity */
12152 	LOCALASSERT(sbPtr->DynPtr);
12153 	sbPtr->DynPtr->LinVelocity.vx = 0;
12154 	sbPtr->DynPtr->LinVelocity.vy = 0;
12155 	sbPtr->DynPtr->LinVelocity.vz = 0;
12156 
12157 	if(!MarineCanSeeTarget(sbPtr))
12158 	{
12159 		/* Remove the gunflash */
12160 		if(marineStatusPointer->myGunFlash)
12161 		{
12162 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12163 			marineStatusPointer->myGunFlash = NULL;
12164 		}
12165 		/* .... and stop the sound */
12166 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12167 			Sound_Stop(marineStatusPointer->soundHandle);
12168 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12169 		}
12170 		return(SRC_Request_Wait);
12171 	}
12172 
12173 	if (marineStatusPointer->clipammo==0) {
12174 		/* Remove the gunflash */
12175 		if(marineStatusPointer->myGunFlash)
12176 		{
12177 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12178 			marineStatusPointer->myGunFlash = NULL;
12179 		}
12180 		return(SRC_Request_Reload);
12181 	}
12182 
12183 	#if MARINE_STATE_PRINT
12184 	textprint("Firing pistol... ");
12185 	#endif
12186 
12187 	/* Here we must have a target.  Renew suspicion for new arrivals. */
12188 	if (NpcSquad.Squad_Suspicion==0) {
12189 		PointAlert(2,&marineStatusPointer->weaponTarget);
12190 	}
12191 
12192 	relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
12193 	relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
12194 	relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
12195 
12196 	relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
12197 	relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
12198 	relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
12199 
12200 	range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
12201 
12202 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
12203 	we should switch immediately to wait state.*/
12204 
12205 	if ((marineStatusPointer->HModelController.keyframe_flags)
12206 		||(marineStatusPointer->HModelController.Playing==0)) {
12207 
12208 		marineStatusPointer->HModelController.Playing=0;
12209 		marineStatusPointer->HModelController.sequence_timer=0;
12210 
12211 		/* Only terminate if you haven't fired yet... */
12212 		if(!MarineCanSeeTarget(sbPtr))
12213 		{
12214 			#if 1
12215 			/* ... and remove the gunflash */
12216 			if(marineStatusPointer->myGunFlash)
12217 			{
12218 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12219 				marineStatusPointer->myGunFlash = NULL;
12220 			}
12221 			#endif
12222 
12223 			/* .... and stop the sound */
12224 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12225 				Sound_Stop(marineStatusPointer->soundHandle);
12226 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12227 			}
12228 
12229 			#if MARINE_STATE_PRINT
12230 			textprint("Returning no target.\n");
12231 			#endif
12232 			return(SRC_Request_Wait);
12233 		}
12234 
12235 		GLOBALASSERT(marineStatusPointer->Target);
12236 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
12237 		/* Fix weapon target! */
12238 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
12239 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
12240 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12241 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
12242 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12243 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
12244 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12245 		}
12246 
12247 		/* orientate to firing point first */
12248 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
12249 		orientationDirn.vy = 0;
12250 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
12251 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
12252 
12253 		/* we are not correctly orientated to the target: this could happen because we have
12254 		just entered this state, or the target has moved during firing*/
12255 		if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening==Controller_Tweening)) {
12256 
12257 			#if 1
12258 			/* stop visual and audio cues: technically, we're not firing at this moment */
12259 			if(marineStatusPointer->myGunFlash)
12260 			{
12261 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12262 				marineStatusPointer->myGunFlash = NULL;
12263 			}
12264 			#endif
12265 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12266 				Sound_Stop(marineStatusPointer->soundHandle);
12267 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12268 			}
12269 			#if MARINE_STATE_PRINT
12270 			textprint("Turning to face.\n");
12271 			#endif
12272 			return(SRC_No_Change);
12273 		}
12274 
12275 		/* If you are correctly oriented, you can now fire! */
12276 
12277 		marineStatusPointer->HModelController.Playing=1;
12278 		if (marineStatusPointer->clipammo>0) {
12279 			marineStatusPointer->clipammo--;
12280 		}
12281 		marineStatusPointer->roundsForThisTarget++;
12282 
12283 		/* at this point we are correctly orientated: if we have no gunflash yet,
12284 		and our state timer is set to marine_near_firetime then we have either
12285 		just started firing, or have become dis-orienated between bursts. This is a good
12286 		time to consider firing a grenade... */
12287 
12288 		#if 1
12289 		/* look after the gun flash */
12290 		if(marineStatusPointer->myGunFlash) MaintainMarineGunFlash(sbPtr);
12291 		else CreateMarineGunFlash(sbPtr);
12292 		#else
12293 		/* KJL 15:50:48 05/01/98 - draw muzzleflash */
12294 		GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
12295 		{
12296 			VECTORCH direction;
12297 
12298 			direction.vx = marineStatusPointer->My_Gunflash_Section->SecMat.mat31;
12299 			direction.vy = marineStatusPointer->My_Gunflash_Section->SecMat.mat32;
12300 			direction.vz = marineStatusPointer->My_Gunflash_Section->SecMat.mat33;
12301 
12302 			DrawMuzzleFlash(&marineStatusPointer->My_Gunflash_Section->World_Offset,&direction,MUZZLE_FLASH_AMORPHOUS);
12303 		}
12304 		#endif
12305 
12306 		/* look after the sound */
12307 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
12308 		else
12309 		{
12310 			Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
12311 			Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
12312 		}
12313 
12314 		/* Now hit the target with one bullet. */
12315 
12316 		mod=SpeedRangeMods(&relPos,&relPos2);
12317 
12318 		hitroll=marineStatusPointer->Skill; /* Marine skill... */
12319 		if (marineStatusPointer->Target==Player->ObStrategyBlock) {
12320 			PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
12321 			LOCALASSERT(playerStatusPtr);
12322 			if ( (AvP.PlayerType==I_Alien)
12323 				||((AvP.PlayerType==I_Predator)&&(playerStatusPtr->cloakOn==1))) {
12324 				/* Vs the player, lighting effects on aliens and cloaked preds. */
12325 				hitroll=MUL_FIXED(hitroll,((CurrentLightAtPlayer>>1)+32767));
12326 			}
12327 		}
12328 		hitroll-=mod;
12329 		hitroll+=marineStatusPointer->My_Weapon->Accuracy;
12330 
12331 		{
12332 
12333 			/* Handle Damage. */
12334 			if ((FastRandom()&65535)<hitroll) {
12335 				/* DO DAMAGE TO TARGET HERE */
12336 
12337 				VECTORCH rel_pos,attack_dir;
12338 				int dist;
12339 				VECTORCH shotvector;
12340 
12341 				shotvector.vx=0;
12342 				shotvector.vy=0;
12343 				shotvector.vz=65535;
12344 				RotateVector(&shotvector,&marineStatusPointer->My_Gunflash_Section->SecMat);
12345 
12346 				rel_pos.vx=marineStatusPointer->Target->DynPtr->Position.vx-sbPtr->DynPtr->Position.vx;
12347 				rel_pos.vy=marineStatusPointer->Target->DynPtr->Position.vy-sbPtr->DynPtr->Position.vy;
12348 				rel_pos.vz=marineStatusPointer->Target->DynPtr->Position.vz-sbPtr->DynPtr->Position.vz;
12349 
12350 				dist=Approximate3dMagnitude(&rel_pos);
12351 
12352 				if (VerifyHitShot(sbPtr,marineStatusPointer->Target,&marineStatusPointer->My_Gunflash_Section->World_Offset,&shotvector, marineStatusPointer->My_Weapon->Ammo_Type, 1,dist)) {
12353 
12354 					GetDirectionOfAttack(marineStatusPointer->Target,&rel_pos,&attack_dir);
12355 					/* Get hit location? */
12356 
12357 					marineStatusPointer->lasthitsection=HitLocationRoll(marineStatusPointer->Target,sbPtr);
12358 
12359 					if (marineStatusPointer->lasthitsection) {
12360 						CauseDamageToHModel(marineStatusPointer->lasthitsection->my_controller, marineStatusPointer->Target,&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage[AvP.Difficulty], ONE_FIXED, marineStatusPointer->lasthitsection,&attack_dir,NULL,0);
12361 					} else {
12362 						CauseDamageToObject(marineStatusPointer->Target,&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage[AvP.Difficulty], ONE_FIXED,&attack_dir);
12363 					}
12364 				}
12365 			} else {
12366 				GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
12367 				ProjectNPCShot(sbPtr, marineStatusPointer->Target, &marineStatusPointer->My_Gunflash_Section->World_Offset,&marineStatusPointer->My_Gunflash_Section->SecMat, marineStatusPointer->My_Weapon->Ammo_Type, 1);
12368 			}
12369 
12370 			/* Did we get him? */
12371 			if ((NPC_IsDead(marineStatusPointer->Target))&&(marineStatusPointer->My_Weapon->ARealMarine)) {
12372 				/* Only real marines taunt. */
12373 				if ((marineStatusPointer->roundsForThisTarget==1)||(MarineRetreatsInTheFaceOfDanger(sbPtr))) {
12374 					if (Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr)==NULL) {
12375 						/* Huzzah! */
12376 						if(marineStatusPointer->myGunFlash)
12377 						{
12378 							RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12379 							marineStatusPointer->myGunFlash = NULL;
12380 						}
12381 						if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12382 							Sound_Stop(marineStatusPointer->soundHandle);
12383 							Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12384 						}
12385 						marineStatusPointer->lastroundhit=0;
12386 						marineStatusPointer->lasthitsection=NULL;
12387 						return(SRC_Request_Taunt);
12388 					}
12389 				}
12390 			}
12391 		}
12392 	} else {
12393 		/* Remove the gunflash */
12394 		if(marineStatusPointer->myGunFlash)
12395 		{
12396 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12397 			marineStatusPointer->myGunFlash = NULL;
12398 		}
12399 		/* .... and stop the sound */
12400 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12401 			Sound_Stop(marineStatusPointer->soundHandle);
12402 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12403 		}
12404 	}
12405 
12406 	marineStatusPointer->stateTimer -= NormalFrameTime;
12407 
12408 	/* You must have fired already. */
12409 
12410 	if(marineStatusPointer->stateTimer > 0)	{
12411 		#if MARINE_STATE_PRINT
12412 		textprint("Returning continue at range %d.\n",range);
12413 		#endif
12414 		return(SRC_No_Change);
12415 	}
12416 
12417 	if ((range < MARINE_CLOSE_APPROACH_DISTANCE)||(marineStatusPointer->Android))
12418 	{
12419 		/* renew firing, as we are still too close to approach */
12420 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
12421 		marineStatusPointer->volleySize = 0;
12422 		GLOBALASSERT(marineStatusPointer->Target);
12423 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
12424 		#if MARINE_STATE_PRINT
12425 		textprint("Returning too close renewal at range %d.\n",range);
12426 		#endif
12427 		if (marineStatusPointer->Android==0) {
12428 			marineStatusPointer->Courage-=(ONE_FIXED>>3);
12429 		}
12430 		return(SRC_No_Change);
12431 	}
12432 	else
12433 	{
12434 		/* we are far enough away, so return to approach */
12435 
12436 		#if MARINE_STATE_PRINT
12437 		textprint("Returning too far termination at range %d.\n",range);
12438 		#endif
12439 		/* Remove the gunflash */
12440 		if(marineStatusPointer->myGunFlash)
12441 		{
12442 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12443 			marineStatusPointer->myGunFlash = NULL;
12444 		}
12445 		return(SRC_Request_Approach);
12446 	}
12447 	return(SRC_No_Change);
12448 }
12449 
12450 static STATE_RETURN_CONDITION Execute_MNS_ThrowMolotov(STRATEGYBLOCK *sbPtr)
12451 {
12452 	MARINE_STATUS_BLOCK *marineStatusPointer;
12453 	VECTORCH orientationDirn;
12454 	int correctlyOrientated;
12455 
12456 	LOCALASSERT(sbPtr);
12457 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
12458 	LOCALASSERT(marineStatusPointer);
12459 
12460 	/* zero velocity */
12461 	LOCALASSERT(sbPtr->DynPtr);
12462 	sbPtr->DynPtr->LinVelocity.vx = 0;
12463 	sbPtr->DynPtr->LinVelocity.vy = 0;
12464 	sbPtr->DynPtr->LinVelocity.vz = 0;
12465 
12466 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
12467 	we should switch immediately to wait state.*/
12468 
12469 	if (marineStatusPointer->stateTimer==marineStatusPointer->My_Weapon->FiringTime) {
12470 		marineStatusPointer->HModelController.Playing=0;
12471 		marineStatusPointer->HModelController.sequence_timer=0;
12472 		marineStatusPointer->stateTimer--;
12473 	}
12474 
12475 	{
12476 		if (marineStatusPointer->Target) {
12477 			/* Only terminate if you haven't fired yet... */
12478 			if(!MarineCanSeeTarget(sbPtr))
12479 			{
12480 
12481 				/* .... and stop the sound */
12482 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12483 					Sound_Stop(marineStatusPointer->soundHandle);
12484 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12485 				}
12486 
12487 				#if MARINE_STATE_PRINT
12488 				textprint("Returning no target.\n");
12489 				#endif
12490 				return(SRC_Request_Wait);
12491 			}
12492 
12493 			GLOBALASSERT(marineStatusPointer->Target);
12494 			NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
12495 			/* Fix weapon target! */
12496 			if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
12497 				marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
12498 					marineStatusPointer->My_Weapon->TargetCallibrationShift);
12499 				marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
12500 					marineStatusPointer->My_Weapon->TargetCallibrationShift);
12501 				marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
12502 					marineStatusPointer->My_Weapon->TargetCallibrationShift);
12503 			}
12504 
12505 			/* Here we must have a target.  Renew suspicion for new arrivals. */
12506 			if (NpcSquad.Squad_Suspicion==0) {
12507 				PointAlert(2,&marineStatusPointer->weaponTarget);
12508 			}
12509 
12510 		}
12511 
12512 		/* orientate to firing point first */
12513 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
12514 		orientationDirn.vy = 0;
12515 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
12516 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
12517 
12518 		/* we are not correctly orientated to the target: this could happen because we have
12519 		just entered this state, or the target has moved during firing*/
12520 		if(!correctlyOrientated)
12521 		{
12522 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12523 				Sound_Stop(marineStatusPointer->soundHandle);
12524 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12525 			}
12526 			#if MARINE_STATE_PRINT
12527 			textprint("Turning to face.\n");
12528 			#endif
12529 			return(SRC_No_Change);
12530 		}
12531 
12532 		/* If you are correctly oriented, you can now fire! */
12533 
12534 		marineStatusPointer->HModelController.Playing=1;
12535 
12536 		/* at this point we are correctly orientated: if we have no gunflash yet,
12537 		and our state timer is set to marine_near_firetime then we have either
12538 		just started firing, or have become dis-orienated between bursts. This is a good
12539 		time to consider firing a grenade... */
12540 
12541 		/* No muzzle flash. */
12542 
12543 		/* look after the sound */
12544 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
12545 		else
12546 		{
12547 			Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
12548 			Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
12549 		}
12550 
12551 		if(marineStatusPointer->My_Gunflash_Section) {
12552 
12553 			if (marineStatusPointer->HModelController.keyframe_flags) {
12554 
12555 				SECTION *root;
12556 				MARINE_WEAPON_DATA *noncom;
12557 
12558 				/* Throw! */
12559 				SpawnMolotovCocktail(marineStatusPointer->My_Gunflash_Section, &sbPtr->DynPtr->OrientMat);
12560 				marineStatusPointer->My_Gunflash_Section=NULL;
12561 				marineStatusPointer->Mission=MM_NonCom;
12562 				/* Turn into a noncom! */
12563 
12564 				{
12565 					/* Remove hitdelta, if there is one. */
12566 					DELTA_CONTROLLER *delta;
12567 					delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
12568 					if (delta) {
12569 						Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
12570 					}
12571 				}
12572 
12573 				noncom=GetThisNPCMarineWeapon(MNPCW_MUnarmed);
12574 
12575 				root=GetNamedHierarchyFromLibrary(noncom->Riffname,noncom->HierarchyName);
12576 				Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root, 1, 0,0);
12577 				marineStatusPointer->My_Weapon=noncom;
12578 
12579 				/* Attempt to put the hitdelta back? */
12580 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront)) {
12581 					DELTA_CONTROLLER *delta;
12582 					delta=Add_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
12583 					GLOBALASSERT(delta);
12584 					delta->Playing=0;
12585 				}
12586 
12587 				return(SRC_Request_Retreat);
12588 			}
12589 		}
12590 	}
12591 
12592 	return(SRC_No_Change);
12593 }
12594 
12595 #if 0
12596 static STATE_RETURN_CONDITION Execute_MNS_DischargeGL(STRATEGYBLOCK *sbPtr)
12597 {
12598 	MARINE_STATUS_BLOCK *marineStatusPointer;
12599 	VECTORCH orientationDirn,relPos,relPos2;
12600 	int correctlyOrientated,range;
12601 
12602 	LOCALASSERT(sbPtr);
12603 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
12604 	LOCALASSERT(marineStatusPointer);
12605 
12606 	#if MARINE_STATE_PRINT
12607 	textprint("Firing grenade launcher... ");
12608 	#endif
12609 
12610 	/* zero velocity */
12611 	LOCALASSERT(sbPtr->DynPtr);
12612 	sbPtr->DynPtr->LinVelocity.vx = 0;
12613 	sbPtr->DynPtr->LinVelocity.vy = 0;
12614 	sbPtr->DynPtr->LinVelocity.vz = 0;
12615 
12616 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
12617 	we should switch immediately to wait state.*/
12618 
12619 	if (marineStatusPointer->HModelController.keyframe_flags&2) {
12620 		marineStatusPointer->internalState=1;
12621 	}
12622 	if (marineStatusPointer->HModelController.keyframe_flags&1) {
12623 		marineStatusPointer->internalState=0;
12624 	}
12625 
12626 	if(!MarineCanSeeTarget(sbPtr))
12627 	{
12628 		/* Remove the gunflash */
12629 		if(marineStatusPointer->myGunFlash)
12630 		{
12631 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12632 			marineStatusPointer->myGunFlash = NULL;
12633 		}
12634 		/* .... and stop the sound */
12635 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12636 			Sound_Stop(marineStatusPointer->soundHandle);
12637 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12638 		}
12639 		return(SRC_Request_Wait);
12640 	}
12641 
12642 	if (marineStatusPointer->clipammo==0) {
12643 		/* Reload here. */
12644 		return(SRC_Request_Reload);
12645 	}
12646 
12647 	/* Here we must have a target.  Renew suspicion for new arrivals. */
12648 	if (NpcSquad.Squad_Suspicion==0) {
12649 		PointAlert(2,&marineStatusPointer->weaponTarget);
12650 	}
12651 
12652 	if (marineStatusPointer->stateTimer==marineStatusPointer->My_Weapon->FiringTime) {
12653 
12654 		if (marineStatusPointer->HModelController.Tweening==Controller_NoTweening) {
12655 			marineStatusPointer->HModelController.Playing=0;
12656 		}
12657 
12658 		/* Only terminate if you haven't fired yet... */
12659 		if(!MarineCanSeeTarget(sbPtr))
12660 		{
12661 			#if 1
12662 			/* ... and remove the gunflash */
12663 			if(marineStatusPointer->myGunFlash)
12664 			{
12665 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12666 				marineStatusPointer->myGunFlash = NULL;
12667 			}
12668 			#endif
12669 
12670 			/* .... and stop the sound */
12671 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12672 				Sound_Stop(marineStatusPointer->soundHandle);
12673 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12674 			}
12675 
12676 			#if MARINE_STATE_PRINT
12677 			textprint("Returning no target.\n");
12678 			#endif
12679 			return(SRC_Request_Wait);
12680 		}
12681 
12682 		GLOBALASSERT(marineStatusPointer->Target);
12683 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
12684 		/* Fix weapon target! */
12685 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
12686 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
12687 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12688 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
12689 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12690 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
12691 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12692 		}
12693 
12694 		/* Aim up a little? */
12695 		range=VectorDistance((&marineStatusPointer->weaponTarget),(&sbPtr->DynPtr->Position));
12696 
12697 		marineStatusPointer->weaponTarget.vy-=(range/6);
12698 
12699 		/* orientate to firing point first */
12700 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
12701 		orientationDirn.vy = 0;
12702 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
12703 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
12704 
12705 		/* we are not correctly orientated to the target: this could happen because we have
12706 		just entered this state, or the target has moved during firing*/
12707 		if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)) {
12708 
12709 			#if 1
12710 			/* stop visual and audio cues: technically, we're not firing at this moment */
12711 			if(marineStatusPointer->myGunFlash)
12712 			{
12713 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12714 				marineStatusPointer->myGunFlash = NULL;
12715 			}
12716 			#endif
12717 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12718 				Sound_Stop(marineStatusPointer->soundHandle);
12719 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12720 			}
12721 			#if MARINE_STATE_PRINT
12722 			textprint("Turning to face.\n");
12723 			#endif
12724 			return(SRC_No_Change);
12725 		}
12726 
12727 		/* If you are correctly oriented, you can now fire! */
12728 
12729 		marineStatusPointer->HModelController.Playing=1;
12730 		marineStatusPointer->HModelController.sequence_timer=0;
12731 
12732 		#if 0
12733 		/* Can't afford to have the jam! */
12734 		if (marineStatusPointer->internalState!=0) {
12735 			/* Just in case. */
12736 			return(SRC_No_Change);
12737 		}
12738 		#endif
12739 
12740 		relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
12741 		relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
12742 		relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
12743 
12744 		relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
12745 		relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
12746 		relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
12747 
12748 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
12749 
12750 		/* Are they, by some chance, really close? */
12751 		if (range<marineStatusPointer->My_Weapon->MinRange) {
12752 			if (!(MarineRetreatsInTheFaceOfDanger(sbPtr))) {
12753 				/* Stay cool. */
12754 				return(SRC_Request_PullPistol);
12755 			} else {
12756 				if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
12757 					/* Fail twice, then flee... else continue. */
12758 					return(SRC_Request_Retreat);
12759 				}
12760 			}
12761 		}
12762 
12763 		#if 1
12764 		/* look after the gun flash */
12765 		if(marineStatusPointer->myGunFlash) MaintainMarineGunFlash(sbPtr);
12766 		else CreateMarineGunFlash(sbPtr);
12767 		#else
12768 		/* KJL 15:50:48 05/01/98 - draw muzzleflash */
12769 		GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
12770 		{
12771 			VECTORCH direction;
12772 
12773 			direction.vx = marineStatusPointer->My_Gunflash_Section->SecMat.mat31;
12774 			direction.vy = marineStatusPointer->My_Gunflash_Section->SecMat.mat32;
12775 			direction.vz = marineStatusPointer->My_Gunflash_Section->SecMat.mat33;
12776 
12777 			DrawMuzzleFlash(&marineStatusPointer->My_Gunflash_Section->World_Offset,&direction,MUZZLE_FLASH_AMORPHOUS);
12778 		}
12779 		#endif
12780 
12781 		/* look after the sound */
12782 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
12783 		else
12784 		{
12785 			Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
12786 			Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
12787 		}
12788 
12789 		/* Now fire a grenade. */
12790 
12791 
12792 		{
12793 			LOCALASSERT(marineStatusPointer->My_Gunflash_Section);
12794 			//LOCALASSERT(marineStatusPointer->internalState==0);
12795 
12796 			CreateGrenadeKernel(I_BehaviourGrenade, &marineStatusPointer->My_Gunflash_Section->World_Offset, &marineStatusPointer->My_Gunflash_Section->SecMat,0);
12797 
12798 			if (marineStatusPointer->clipammo>0) {
12799 				marineStatusPointer->clipammo--;
12800 			}
12801 		}
12802 	}
12803 
12804 	if (marineStatusPointer->stateTimer<marineStatusPointer->My_Weapon->FiringTime) {
12805 		/* Remove the gunflash */
12806 		if(marineStatusPointer->myGunFlash)
12807 		{
12808 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12809 			marineStatusPointer->myGunFlash = NULL;
12810 		}
12811 		/* .... and stop the sound */
12812 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12813 			Sound_Stop(marineStatusPointer->soundHandle);
12814 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12815 		}
12816 	}
12817 
12818 	marineStatusPointer->stateTimer -= NormalFrameTime;
12819 
12820 	/* You must have fired already. */
12821 
12822 	if(marineStatusPointer->stateTimer > 0)	{
12823 		#if MARINE_STATE_PRINT
12824 		textprint("Returning continue at range %d.\n",range);
12825 		#endif
12826 		return(SRC_No_Change);
12827 	}
12828 
12829 	if(range < MARINE_CLOSE_APPROACH_DISTANCE)
12830 	{
12831 		/* renew firing, as we are still too close to approach */
12832 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
12833 		marineStatusPointer->volleySize = 0;
12834 		GLOBALASSERT(marineStatusPointer->Target);
12835 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
12836 		#if MARINE_STATE_PRINT
12837 		textprint("Returning too close renewal at range %d.\n",range);
12838 		#endif
12839 		return(SRC_No_Change);
12840 	}
12841 	else
12842 	{
12843 		/* we are far enough away, so return to approach */
12844 
12845 		#if MARINE_STATE_PRINT
12846 		textprint("Returning too far termination at range %d.\n",range);
12847 		#endif
12848 		return(SRC_Request_Approach);
12849 	}
12850 	return(SRC_No_Change);
12851 }
12852 #endif
12853 
12854 static STATE_RETURN_CONDITION Execute_MNS_NewDischargeGL(STRATEGYBLOCK *sbPtr)
12855 {
12856 	MARINE_STATUS_BLOCK *marineStatusPointer;
12857 	VECTORCH orientationDirn,relPos,relPos2;
12858 	int correctlyOrientated,range;
12859 
12860 	LOCALASSERT(sbPtr);
12861 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
12862 	LOCALASSERT(marineStatusPointer);
12863 
12864 	/* zero velocity */
12865 	LOCALASSERT(sbPtr->DynPtr);
12866 	sbPtr->DynPtr->LinVelocity.vx = 0;
12867 	sbPtr->DynPtr->LinVelocity.vy = 0;
12868 	sbPtr->DynPtr->LinVelocity.vz = 0;
12869 
12870 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
12871 	we should switch immediately to wait state.*/
12872 
12873 	if(!MarineCanSeeTarget(sbPtr))
12874 	{
12875 
12876 		/* Remove the gunflash */
12877 		if(marineStatusPointer->myGunFlash)
12878 		{
12879 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12880 			marineStatusPointer->myGunFlash = NULL;
12881 		}
12882 		/* .... and stop the sound */
12883 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12884 			Sound_Stop(marineStatusPointer->soundHandle);
12885 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12886 		}
12887 		return(SRC_Request_Wait);
12888 	}
12889 
12890 	if (marineStatusPointer->clipammo==0) {
12891 		return(SRC_Request_Reload);
12892 	}
12893 
12894 	/* Here we must have a target.  Renew suspicion for new arrivals. */
12895 	if (NpcSquad.Squad_Suspicion==0) {
12896 		PointAlert(2,&marineStatusPointer->weaponTarget);
12897 	}
12898 
12899 	/* Deal with tweening part. */
12900 	if (marineStatusPointer->internalState) {
12901 		if (marineStatusPointer->HModelController.Tweening==Controller_NoTweening) {
12902 			marineStatusPointer->HModelController.Playing=0;
12903 			marineStatusPointer->HModelController.sequence_timer=0;
12904 			marineStatusPointer->internalState=0;
12905 		}
12906 		return(SRC_No_Change);
12907 	}
12908 
12909 	if (marineStatusPointer->HModelController.Playing==0) {
12910 
12911 		/* Only terminate if you haven't fired yet... */
12912 		if(!MarineCanSeeTarget(sbPtr))
12913 		{
12914 
12915 			/* ... and remove the gunflash */
12916 			if(marineStatusPointer->myGunFlash)
12917 			{
12918 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12919 				marineStatusPointer->myGunFlash = NULL;
12920 			}
12921 
12922 			/* .... and stop the sound */
12923 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12924 				Sound_Stop(marineStatusPointer->soundHandle);
12925 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12926 			}
12927 
12928 			#if MARINE_STATE_PRINT
12929 			textprint("Returning no target.\n");
12930 			#endif
12931 			return(SRC_Request_Wait);
12932 		}
12933 
12934 		GLOBALASSERT(marineStatusPointer->Target);
12935 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
12936 		/* Fix weapon target! */
12937 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
12938 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
12939 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12940 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
12941 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12942 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
12943 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
12944 		}
12945 
12946 		/* Aim up a little? */
12947 		range=VectorDistance((&marineStatusPointer->weaponTarget),(&sbPtr->DynPtr->Position));
12948 
12949 		marineStatusPointer->weaponTarget.vy-=(range/8);
12950 
12951 		/* orientate to firing point first */
12952 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
12953 		orientationDirn.vy = 0;
12954 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
12955 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
12956 
12957 		/* we are not correctly orientated to the target: this could happen because we have
12958 		just entered this state, or the target has moved during firing*/
12959 		if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)) {
12960 
12961 			/* stop visual and audio cues: technically, we're not firing at this moment */
12962 			if(marineStatusPointer->myGunFlash)
12963 			{
12964 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
12965 				marineStatusPointer->myGunFlash = NULL;
12966 			}
12967 
12968 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
12969 				Sound_Stop(marineStatusPointer->soundHandle);
12970 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
12971 			}
12972 			#if MARINE_STATE_PRINT
12973 			textprint("Turning to face.\n");
12974 			#endif
12975 			return(SRC_No_Change);
12976 		}
12977 
12978 		/* If you are correctly oriented, you can now fire! */
12979 
12980 		marineStatusPointer->HModelController.Playing=1;
12981 		marineStatusPointer->HModelController.sequence_timer=0;
12982 
12983 		relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
12984 		relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
12985 		relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
12986 
12987 		relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
12988 		relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
12989 		relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
12990 
12991 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
12992 
12993 		/* Are they, by some chance, really close? */
12994 		if (range<marineStatusPointer->My_Weapon->MinRange) {
12995 			if (!(MarineRetreatsInTheFaceOfDanger(sbPtr))) {
12996 				/* Stay cool. */
12997 				return(SRC_Request_PullPistol);
12998 			} else {
12999 				if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
13000 					/* Fail twice, then flee... else continue. */
13001 					return(SRC_Request_Retreat);
13002 				}
13003 			}
13004 		}
13005 
13006 		/* at this point we are correctly orientated: if we have no gunflash yet,
13007 		and our state timer is set to marine_near_firetime then we have either
13008 		just started firing, or have become dis-orienated between bursts. This is a good
13009 		time to consider firing a grenade... */
13010 
13011 		/* look after the gun flash */
13012 		if(marineStatusPointer->myGunFlash) {
13013 			MaintainMarineGunFlash(sbPtr);
13014 		} else {
13015 			CreateMarineGunFlash(sbPtr);
13016 		}
13017 
13018 		/* look after the sound */
13019 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
13020 		else
13021 		{
13022 			Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
13023 			Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
13024 		}
13025 
13026 		/* Now fire a grenade. */
13027 		{
13028 			LOCALASSERT(marineStatusPointer->My_Gunflash_Section);
13029 
13030 			CreateGrenadeKernel(I_BehaviourGrenade, &marineStatusPointer->My_Gunflash_Section->World_Offset, &marineStatusPointer->My_Gunflash_Section->SecMat,0);
13031 
13032 			if (marineStatusPointer->clipammo>0) {
13033 				marineStatusPointer->clipammo--;
13034 			}
13035 		}
13036 
13037 	} else {
13038 
13039 		/* Remove the gunflash */
13040 		if(marineStatusPointer->myGunFlash)
13041 		{
13042 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
13043 			marineStatusPointer->myGunFlash = NULL;
13044 		}
13045 		/* .... and stop the sound */
13046 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
13047 			Sound_Stop(marineStatusPointer->soundHandle);
13048 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
13049 		}
13050 	}
13051 
13052 	marineStatusPointer->stateTimer -= NormalFrameTime;
13053 
13054 	/* You must have fired already. */
13055 
13056 	GLOBALASSERT(marineStatusPointer->HModelController.Looped==0);
13057 	if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController)) {
13058 		return(SRC_Request_PumpAction);
13059 	}
13060 	return(SRC_No_Change);
13061 
13062 }
13063 
13064 static STATE_RETURN_CONDITION Execute_MNS_DischargeSADAR(STRATEGYBLOCK *sbPtr)
13065 {
13066 	MARINE_STATUS_BLOCK *marineStatusPointer;
13067 	VECTORCH orientationDirn,relPos,relPos2;
13068 	int correctlyOrientated,range;
13069 
13070 	LOCALASSERT(sbPtr);
13071 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
13072 	LOCALASSERT(marineStatusPointer);
13073 
13074 	#if MARINE_STATE_PRINT
13075 	textprint("Firing SADAR... ");
13076 	#endif
13077 
13078 	/* zero velocity */
13079 	LOCALASSERT(sbPtr->DynPtr);
13080 	sbPtr->DynPtr->LinVelocity.vx = 0;
13081 	sbPtr->DynPtr->LinVelocity.vy = 0;
13082 	sbPtr->DynPtr->LinVelocity.vz = 0;
13083 
13084 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
13085 	we should switch immediately to wait state.*/
13086 
13087 	if(!MarineCanSeeTarget(sbPtr))
13088 	{
13089 
13090 		/* Remove the gunflash */
13091 		if(marineStatusPointer->myGunFlash)
13092 		{
13093 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
13094 			marineStatusPointer->myGunFlash = NULL;
13095 		}
13096 		/* .... and stop the sound */
13097 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
13098 			Sound_Stop(marineStatusPointer->soundHandle);
13099 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
13100 		}
13101 		return(SRC_Request_Wait);
13102 	}
13103 
13104 	if (marineStatusPointer->clipammo==0) {
13105 		/* Reload here. */
13106 		return(SRC_Request_Reload);
13107 	}
13108 
13109 	/* Here we must have a target.  Renew suspicion for new arrivals. */
13110 	if (NpcSquad.Squad_Suspicion==0) {
13111 		PointAlert(2,&marineStatusPointer->weaponTarget);
13112 	}
13113 
13114 	if (marineStatusPointer->stateTimer==marineStatusPointer->My_Weapon->FiringTime) {
13115 
13116 		if (marineStatusPointer->HModelController.Tweening==Controller_NoTweening) {
13117 			marineStatusPointer->HModelController.Playing=0;
13118 		}
13119 
13120 		/* Only terminate if you haven't fired yet... */
13121 		if(!MarineCanSeeTarget(sbPtr))
13122 		{
13123 			#if 1
13124 			/* ... and remove the gunflash */
13125 			if(marineStatusPointer->myGunFlash)
13126 			{
13127 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
13128 				marineStatusPointer->myGunFlash = NULL;
13129 			}
13130 			#endif
13131 
13132 			/* .... and stop the sound */
13133 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
13134 				Sound_Stop(marineStatusPointer->soundHandle);
13135 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
13136 			}
13137 
13138 			#if MARINE_STATE_PRINT
13139 			textprint("Returning no target.\n");
13140 			#endif
13141 			return(SRC_Request_Wait);
13142 		}
13143 
13144 		GLOBALASSERT(marineStatusPointer->Target);
13145 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
13146 		/* Fix weapon target! */
13147 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
13148 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
13149 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
13150 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
13151 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
13152 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
13153 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
13154 		}
13155 
13156 		/* orientate to firing point first */
13157 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
13158 		orientationDirn.vy = 0;
13159 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
13160 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
13161 
13162 		/* we are not correctly orientated to the target: this could happen because we have
13163 		just entered this state, or the target has moved during firing*/
13164 		if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)) {
13165 
13166 			#if 1
13167 			/* stop visual and audio cues: technically, we're not firing at this moment */
13168 			if(marineStatusPointer->myGunFlash)
13169 			{
13170 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
13171 				marineStatusPointer->myGunFlash = NULL;
13172 			}
13173 			#endif
13174 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
13175 				Sound_Stop(marineStatusPointer->soundHandle);
13176 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
13177 			}
13178 			#if MARINE_STATE_PRINT
13179 			textprint("Turning to face.\n");
13180 			#endif
13181 			return(SRC_No_Change);
13182 		}
13183 
13184 		/* If you are correctly oriented, you can now fire! */
13185 
13186 		marineStatusPointer->HModelController.Playing=1;
13187 		marineStatusPointer->HModelController.sequence_timer=0;
13188 
13189 		relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
13190 		relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
13191 		relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
13192 
13193 		relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
13194 		relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
13195 		relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
13196 
13197 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
13198 
13199 		/* Are they, by some chance, really close? */
13200 		if (range<marineStatusPointer->My_Weapon->MinRange) {
13201 			if (!(MarineRetreatsInTheFaceOfDanger(sbPtr))) {
13202 				/* Stay cool. */
13203 				return(SRC_Request_PullPistol);
13204 			} else {
13205 				if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
13206 					/* Fail twice, then flee... else continue. */
13207 					return(SRC_Request_Retreat);
13208 				}
13209 			}
13210 		}
13211 
13212 		/* at this point we are correctly orientated: if we have no gunflash yet,
13213 		and our state timer is set to marine_near_firetime then we have either
13214 		just started firing, or have become dis-orienated between bursts. This is a good
13215 		time to consider firing a grenade... */
13216 
13217 		#if 1
13218 		/* look after the gun flash */
13219 		if(marineStatusPointer->myGunFlash) MaintainMarineGunFlash(sbPtr);
13220 		else CreateMarineGunFlash(sbPtr);
13221 		#else
13222 		/* KJL 15:50:48 05/01/98 - draw muzzleflash */
13223 		GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
13224 		{
13225 			VECTORCH direction;
13226 
13227 			direction.vx = marineStatusPointer->My_Gunflash_Section->SecMat.mat31;
13228 			direction.vy = marineStatusPointer->My_Gunflash_Section->SecMat.mat32;
13229 			direction.vz = marineStatusPointer->My_Gunflash_Section->SecMat.mat33;
13230 
13231 			DrawMuzzleFlash(&marineStatusPointer->My_Gunflash_Section->World_Offset,&direction,MUZZLE_FLASH_AMORPHOUS);
13232 		}
13233 		#endif
13234 
13235 		/* look after the sound */
13236 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
13237 		else
13238 		{
13239 			Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
13240 			Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
13241 		}
13242 
13243 		/* Now fire a rocket. */
13244 
13245 		{
13246 			SECTION_DATA *rocket_section;
13247 
13248 			rocket_section=GetThisSectionData(marineStatusPointer->HModelController.section_data,"dum flash");
13249 
13250 			LOCALASSERT(rocket_section);
13251 
13252 			CreateRocketKernel(&rocket_section->World_Offset, &rocket_section->SecMat,0);
13253 
13254 			if (marineStatusPointer->clipammo>0) {
13255 				marineStatusPointer->clipammo--;
13256 			}
13257 		}
13258 	}
13259 
13260 	if (marineStatusPointer->stateTimer<marineStatusPointer->My_Weapon->FiringTime) {
13261 		/* Remove the gunflash */
13262 		if(marineStatusPointer->myGunFlash)
13263 		{
13264 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
13265 			marineStatusPointer->myGunFlash = NULL;
13266 		}
13267 		/* .... and stop the sound */
13268 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
13269 			Sound_Stop(marineStatusPointer->soundHandle);
13270 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
13271 		}
13272 	}
13273 
13274 	marineStatusPointer->stateTimer -= NormalFrameTime;
13275 
13276 	/* You must have fired already. */
13277 
13278 	if(marineStatusPointer->stateTimer > 0)	{
13279 		#if MARINE_STATE_PRINT
13280 		textprint("Returning continue at range %d.\n",range);
13281 		#endif
13282 		return(SRC_No_Change);
13283 	}
13284 
13285 	if(range < MARINE_CLOSE_APPROACH_DISTANCE)
13286 	{
13287 		/* renew firing, as we are still too close to approach */
13288 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
13289 		marineStatusPointer->volleySize = 0;
13290 		GLOBALASSERT(marineStatusPointer->Target);
13291 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
13292 		#if MARINE_STATE_PRINT
13293 		textprint("Returning too close renewal at range %d.\n",range);
13294 		#endif
13295 		return(SRC_No_Change);
13296 	}
13297 	else
13298 	{
13299 		/* we are far enough away, so return to approach */
13300 
13301 		#if MARINE_STATE_PRINT
13302 		textprint("Returning too far termination at range %d.\n",range);
13303 		#endif
13304 		return(SRC_Request_Approach);
13305 	}
13306 	return(SRC_No_Change);
13307 }
13308 
13309 void GetNewRandomDirection(MARINE_STATUS_BLOCK *marineStatusPointer) {
13310 
13311 	int rnum;
13312 
13313 	rnum=FastRandom()&65535;
13314 
13315 	marineStatusPointer->lastroundhit&=65535;
13316 	marineStatusPointer->lastroundhit|=(rnum<<16);
13317 
13318 }
13319 
13320 void GetFirstRandomDirection(MARINE_STATUS_BLOCK *marineStatusPointer,VECTORCH *output) {
13321 
13322 	int rnum;
13323 	MATRIXCH tempmat;
13324 	EULER tempeul;
13325 	VECTORCH tempvec;
13326 
13327 	rnum=FastRandom()&65535;
13328 
13329 	rnum>>=4;
13330 
13331 	tempeul.EulerX=0;
13332 	tempeul.EulerY=rnum;
13333 	tempeul.EulerZ=0;
13334 
13335 	CreateEulerMatrix(&tempeul,&tempmat);
13336 
13337 	tempvec.vx=0;
13338 	tempvec.vy=0;
13339 	tempvec.vz=65535;
13340 
13341 	RotateAndCopyVector(&tempvec,output,&tempmat);
13342 
13343 	marineStatusPointer->lastroundhit=(rnum<<20)+(rnum<<4);
13344 
13345 }
13346 
13347 void TurnToFaceRandomDirection(MARINE_STATUS_BLOCK *marineStatusPointer,VECTORCH *output) {
13348 
13349 	int currentangle,targetangle,deltaangle,deltaangle2;
13350 	MATRIXCH tempmat;
13351 	EULER tempeul;
13352 	VECTORCH tempvec;
13353 
13354 	currentangle=(marineStatusPointer->lastroundhit)&(65535);
13355 	targetangle=(marineStatusPointer->lastroundhit>>16)&(65535);
13356 
13357 	deltaangle=targetangle-currentangle;
13358 	deltaangle2=deltaangle;
13359 	if (deltaangle<0) deltaangle+=65536;
13360 
13361 	if (deltaangle>32767) {
13362 		currentangle-=(NormalFrameTime>>1);
13363 		if (currentangle<0) currentangle+=65536;
13364 	} else {
13365 		currentangle+=(NormalFrameTime>>1);
13366 		if (currentangle>65535) currentangle-=65536;
13367 	}
13368 	/* Overshoot test. */
13369 	deltaangle=targetangle-currentangle;
13370 	if ((deltaangle*deltaangle2)<=0) {
13371 		currentangle=targetangle;
13372 	}
13373 
13374 	LOCALASSERT(currentangle<65536);
13375 	marineStatusPointer->lastroundhit&=~65535;
13376 	marineStatusPointer->lastroundhit|=currentangle;
13377 
13378 	currentangle>>=4;
13379 
13380 	tempeul.EulerX=0;
13381 	tempeul.EulerY=currentangle;
13382 	tempeul.EulerZ=0;
13383 
13384 	CreateEulerMatrix(&tempeul,&tempmat);
13385 
13386 	tempvec.vx=0;
13387 	tempvec.vy=0;
13388 	tempvec.vz=65535;
13389 
13390 	RotateAndCopyVector(&tempvec,output,&tempmat);
13391 
13392 }
13393 
13394 void Convert_To_RunningOnFire(STRATEGYBLOCK *sbPtr) {
13395 
13396 	SECTION *root;
13397 	MARINE_STATUS_BLOCK *marineStatusPointer;
13398 
13399 	LOCALASSERT(sbPtr);
13400 	LOCALASSERT(sbPtr->containingModule);
13401 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
13402     LOCALASSERT(marineStatusPointer);
13403 
13404 	/* Burn off tracker. */
13405 	marineStatusPointer->mtracker_timer=-1;
13406 
13407 	/* Grimace. */
13408 	Marine_SwitchExpression(sbPtr,5);
13409 
13410 	if (marineStatusPointer->behaviourState == MBS_Dying) {
13411 		/* Just die. */
13412 		return;
13413 	}
13414 
13415 	/* get rid of the gun flash, if we've got it */
13416 	if(marineStatusPointer->myGunFlash)
13417 	{
13418 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
13419 		marineStatusPointer->myGunFlash = NULL;
13420 	}
13421 
13422 	/* Switch to template. */
13423 	root=GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,marineStatusPointer->My_Weapon->TemplateName);
13424 
13425 	/* Remove all deltas. */
13426 	Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Elevation");
13427 	Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
13428 	Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
13429 	Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
13430 
13431 	Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,
13432 		root, 1, 0,0);
13433 
13434 	SetMarineAnimationSequence(sbPtr,HMSQT_MarineRun,MRSS_Tem_Run_On_Fire,
13435 		(ONE_FIXED*3),(ONE_FIXED>>2));
13436 
13437 	GetFirstRandomDirection(marineStatusPointer,&(marineStatusPointer->wanderData.worldPosition));
13438 	/* Hey, it's a spare vector. */
13439 	marineStatusPointer->nearSpeed=MARINE_NEAR_SPEED>>1;
13440 	NPCSetVelocity(sbPtr, &(marineStatusPointer->wanderData.worldPosition), marineStatusPointer->nearSpeed);
13441 
13442 	InitMission(sbPtr,MM_RunAroundOnFire);
13443 
13444 	marineStatusPointer->stateTimer=(ONE_FIXED);
13445 
13446 	/* Add crackling sound. */
13447 
13448 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Stop(marineStatusPointer->soundHandle);
13449 
13450  	Sound_Play(SID_FIRE,"dlev",&(sbPtr->DynPtr->Position),&marineStatusPointer->soundHandle,127);
13451 
13452 }
13453 
13454 static STATE_RETURN_CONDITION Execute_MNS_RunAroundOnFire(STRATEGYBLOCK *sbPtr)
13455 {
13456 	MARINE_STATUS_BLOCK *marineStatusPointer;
13457 	DYNAMICSBLOCK *dynPtr;
13458 
13459 	LOCALASSERT(sbPtr);
13460 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
13461 	dynPtr = sbPtr->DynPtr;
13462 	LOCALASSERT(marineStatusPointer);
13463 	LOCALASSERT(dynPtr);
13464 
13465 	if (sbPtr->SBDamageBlock.IsOnFire==0) {
13466 		/* Stay on fire! */
13467 		sbPtr->SBDamageBlock.IsOnFire=1;
13468 	}
13469 
13470 	/* check if we should be crouched or standing up */
13471 	if(marineStatusPointer->IAmCrouched)
13472 	{
13473 		/* curently crouched */
13474 		if(!(MarineShouldBeCrawling(sbPtr)))
13475 		{
13476 			/* should be running*/
13477 			marineStatusPointer->IAmCrouched = 0;
13478 			SetMarineAnimationSequence(sbPtr,HMSQT_MarineRun,MRSS_Tem_Run_On_Fire,ONE_FIXED,(ONE_FIXED>>3));
13479 		}
13480 	}
13481 	else
13482 	{
13483 		/* currently standing */
13484 		if(MarineShouldBeCrawling(sbPtr))
13485 		{
13486 			/* should be crawling, I guess... */
13487 			marineStatusPointer->IAmCrouched = 1;
13488 			SetMarineAnimationSequence(sbPtr,HMSQT_MarineCrawl,MCrSS_Standard,ONE_FIXED,(ONE_FIXED>>3));
13489 		}
13490 	}
13491 
13492 	/* Set velocity for this frame. */
13493 	marineStatusPointer->stateTimer-=NormalFrameTime;
13494 	if (marineStatusPointer->stateTimer<0) {
13495 		marineStatusPointer->stateTimer=0;
13496 		//if (FastRandom()&15==0)
13497 		{
13498 			GetNewRandomDirection(marineStatusPointer);
13499 			marineStatusPointer->stateTimer=(ONE_FIXED);
13500 		}
13501 	}
13502 	TurnToFaceRandomDirection(marineStatusPointer,&(marineStatusPointer->wanderData.worldPosition));
13503 	NPCSetVelocity(sbPtr, &(marineStatusPointer->wanderData.worldPosition), marineStatusPointer->nearSpeed);
13504 
13505 	/* Handle sound... */
13506 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
13507 
13508 	/* test here for impeding collisions, and not being able to reach target... */
13509 	#if ALL_NEW_AVOIDANCE
13510 	{
13511 		if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
13512 			/* Go to all new avoidance. */
13513 			return(SRC_Request_Avoidance);
13514 		}
13515 	}
13516 	#else
13517 	{
13518 		STRATEGYBLOCK *destructableObject = NULL;
13519 
13520 		NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
13521 		if((marineStatusPointer->obstruction.environment)||(marineStatusPointer->obstruction.otherCharacter))
13522 		{
13523 			/* go to avoidance */
13524 			GetNewRandomDirection(marineStatusPointer);
13525 			TurnToFaceRandomDirection(marineStatusPointer,&(marineStatusPointer->wanderData.worldPosition));
13526 			NPCSetVelocity(sbPtr, &(marineStatusPointer->wanderData.worldPosition), marineStatusPointer->nearSpeed);
13527 			return(SRC_Request_Avoidance);
13528 		}
13529 		if(marineStatusPointer->obstruction.destructableObject)
13530 		{
13531 			LOCALASSERT(destructableObject);
13532 			CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
13533 		}
13534 	}
13535 	#endif
13536 
13537 	return(SRC_No_Change);
13538 }
13539 
13540 void RunAroundOnFireMission_Control(STRATEGYBLOCK *sbPtr) {
13541 
13542 	MARINE_STATUS_BLOCK *marineStatusPointer;
13543 	STATE_RETURN_CONDITION state_result;
13544 	int marineIsNear;
13545 
13546 	LOCALASSERT(sbPtr);
13547 	LOCALASSERT(sbPtr->containingModule);
13548 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
13549     LOCALASSERT(marineStatusPointer);
13550 
13551 	/* Current Behaviour. */
13552 
13553 	if(sbPtr->SBdptr) {
13554 		marineIsNear=1;
13555 		LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)]);
13556 	} else {
13557 		marineIsNear=0;
13558 	}
13559 
13560 	{
13561 
13562 		switch(marineStatusPointer->behaviourState)
13563 		{
13564 			case(MBS_Dying):
13565 			{
13566 				if ((ShowSquadState)||((sbPtr->SBdptr)&&(ShowNearSquad))) {
13567 					PrintDebuggingText("RAOF marine dying in %s\n",sbPtr->containingModule->name);
13568 				}
13569 
13570 				if (marineIsNear) {
13571 					Execute_Dying(sbPtr);
13572 				} else {
13573 					Execute_Dying(sbPtr);
13574 				}
13575 				break;
13576 			}
13577 			default:
13578 			{
13579 				if ((ShowSquadState)||((sbPtr->SBdptr)&&(ShowNearSquad))) {
13580 					PrintDebuggingText("RAOF marine running in %s\n",sbPtr->containingModule->name);
13581 				}
13582 
13583 				if (marineIsNear) {
13584 					state_result=Execute_MNS_RunAroundOnFire(sbPtr);
13585 				} else {
13586 					Execute_MFS_Wait(sbPtr);
13587 				}
13588 				break;
13589 			}
13590 		}
13591 	}
13592 
13593 	if (!marineIsNear) {
13594 
13595 		/* check here to see if marine is in a proximity door - if so, trigger it to open. */
13596 		{
13597 			MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
13598 
13599 			if(doorType == MDT_ProxDoor)
13600 				((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->SBdataptr)->marineTrigger = 1;
13601 		}
13602 
13603 		/* lastly, do a containment test: to make sure that we are inside a module. */
13604 		#if UseLocalAssert
13605 		{
13606 			VECTORCH localCoords;
13607 			MODULE *thisModule = sbPtr->containingModule;
13608 
13609 			LOCALASSERT(thisModule);
13610 
13611 			localCoords = sbPtr->DynPtr->Position;
13612 			localCoords.vx -= thisModule->m_world.vx;
13613 			localCoords.vy -= thisModule->m_world.vy;
13614 			localCoords.vz -= thisModule->m_world.vz;
13615 
13616 			if(PointIsInModule(thisModule, &localCoords)==0)
13617 			{
13618 				textprint("FAR MARINE MODULE CONTAINMENT FAILURE \n");
13619 				LOCALASSERT(1==0);
13620 			}
13621 		}
13622 		#endif
13623 	}
13624 
13625 }
13626 
13627 void GetPointToFaceMarineTowards(STRATEGYBLOCK *sbPtr,VECTORCH *output) {
13628 
13629 	MARINE_STATUS_BLOCK *marineStatusPointer;
13630 	AIMODULE *targetModule;
13631 	AIMODULE **AdjModuleRefPtr;
13632 	AIMODULE* chosenModule = NULL;
13633 	VECTORCH chosenEpWorld;
13634 	int numFound = 0;
13635 
13636 	LOCALASSERT(sbPtr);
13637 	if (sbPtr->containingModule==NULL) {
13638 		return;
13639 	}
13640 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
13641     LOCALASSERT(marineStatusPointer);
13642 
13643 	/* First trap... are you suspicious? */
13644 	if (marineStatusPointer->suspicious) {
13645 		MODULE *suspect_module;
13646 
13647 		suspect_module=ModuleFromPosition(&marineStatusPointer->suspect_point,sbPtr->containingModule);
13648 
13649 		if (suspect_module==NULL) {
13650 			/* Gordon Bennet. */
13651 		 	*output = marineStatusPointer->suspect_point;
13652 			marineStatusPointer->gotapoint=1;
13653 			/* Congratulations. */
13654 			return;
13655 		}
13656 
13657 		/* In the same module? */
13658 		if (sbPtr->containingModule->m_aimodule==suspect_module->m_aimodule) {
13659 		 	*output = marineStatusPointer->suspect_point;
13660 			marineStatusPointer->gotapoint=1;
13661 			/* Congratulations. */
13662 			return;
13663 		}
13664 
13665 		/* Can you see the suspect point? */
13666 		if (sbPtr->SBdptr!=NULL) {
13667 			if (IsThisObjectVisibleFromThisPosition(sbPtr->SBdptr,&marineStatusPointer->suspect_point,NPC_MAX_VIEWRANGE)) {
13668 			 	*output = marineStatusPointer->suspect_point;
13669 				marineStatusPointer->gotapoint=1;
13670 				/* Congratulations. */
13671 				return;
13672 			}
13673 		}
13674 
13675 		{
13676 			/* Try to face towards the most appropriate EP. */
13677 			targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,suspect_module->m_aimodule,7,0);
13678 			if ((targetModule==NULL)||(targetModule==sbPtr->containingModule->m_aimodule)) {
13679 			 	*output = marineStatusPointer->suspect_point;
13680 				marineStatusPointer->gotapoint=1;
13681 				/* Congratulations. */
13682 				return;
13683 			} else {
13684 				/* Get the EP. */
13685 				FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
13686 				if(thisEp) {
13687 					VECTORCH thisEpWorld = thisEp->position;
13688 
13689 					thisEpWorld.vx += targetModule->m_world.vx;
13690 					thisEpWorld.vy += targetModule->m_world.vy;
13691 					thisEpWorld.vz += targetModule->m_world.vz;
13692 
13693 			 		*output = thisEpWorld;
13694 					marineStatusPointer->gotapoint=1;
13695 					/* Congratulations. */
13696 					return;
13697 
13698 				}
13699 				/* Still here?  Can't you get anything right? */
13700 			 	*output = marineStatusPointer->suspect_point;
13701 				marineStatusPointer->gotapoint=1;
13702 				/* Congratulations. */
13703 				return;
13704 			}
13705 		}
13706 	}
13707 
13708 	/* We know your module, don't we? */
13709 
13710 	marineStatusPointer->gotapoint=0;
13711 	targetModule=NULL;
13712 
13713 	/* Okay.  If you're a guard, do your job. */
13714 	if (marineStatusPointer->Mission==MM_Guard) {
13715 
13716  		*output = marineStatusPointer->my_facing_point;
13717 		marineStatusPointer->gotapoint=1;
13718 		/* Congratulations. */
13719 		return;
13720 	}
13721 
13722 	// SBF - 20080518 - commented out - this block of code is a NO-OP
13723 	// due to the aliased targetModule variable.  This code might have
13724 	// been disabled intentionally? In any case, disabling this code
13725 	// works around a crash in FarNPC_GetTargetAIModuleForMarineRespond
13726 	// during level reloads.
13727 #if 0 // SBF - 20080518 - commented out
13728 	if (NpcSquad.alertZone) {
13729 		/* Might want to face towards trouble. */
13730 		if (sbPtr->containingModule->m_aimodule!=NpcSquad.alertZone) {
13731 			AIMODULE *targetModule=0;
13732 			targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
13733 		}
13734 	}
13735 
13736 	/* Did that work? */
13737 
13738 	if (targetModule) {
13739 		FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
13740 		if(thisEp) {
13741 			VECTORCH thisEpWorld = thisEp->position;
13742 
13743 			thisEpWorld.vx += targetModule->m_world.vx;
13744 			thisEpWorld.vy += targetModule->m_world.vy;
13745 			thisEpWorld.vz += targetModule->m_world.vz;
13746 
13747 	 		*output = thisEpWorld;
13748 			marineStatusPointer->gotapoint=1;
13749 			/* Congratulations. */
13750 			return;
13751 
13752 		}
13753 	}
13754 #endif // SBF - 20080518 - commented out
13755 
13756 	AdjModuleRefPtr = sbPtr->containingModule->m_aimodule->m_link_ptrs;
13757 	/* check if there is a module adjacency list */
13758 	if(!AdjModuleRefPtr) {
13759 		/* Just be random, then. */
13760 		return;
13761 	}
13762 
13763 	if(!(*AdjModuleRefPtr)) {
13764 		/* Just be random, then. */
13765 		return;
13766 	}
13767 
13768 	while(*AdjModuleRefPtr != 0)
13769 	{
13770 		AIMODULE *nextAdjModule = *AdjModuleRefPtr;
13771 		if (((*(nextAdjModule->m_module_ptrs))->m_flags&MODULEFLAG_AIRDUCT)==0)
13772 		{
13773 			/* Overlook airducts :-) */
13774 			FARENTRYPOINT *thisEp = GetAIModuleEP(nextAdjModule, sbPtr->containingModule->m_aimodule);
13775 			if(thisEp)
13776 			{
13777 				if (thisEp->alien_only==0) {
13778 					/* aha. an ep!... */
13779 					VECTORCH thisEpWorld = thisEp->position;
13780 
13781 					thisEpWorld.vx += nextAdjModule->m_world.vx;
13782 					thisEpWorld.vy += nextAdjModule->m_world.vy;
13783 					thisEpWorld.vz += nextAdjModule->m_world.vz;
13784 
13785 					numFound++;
13786 					if(FastRandom()%numFound==0)
13787 					{
13788 						/* take this one */
13789 						chosenModule = nextAdjModule;
13790 						chosenEpWorld = thisEpWorld;
13791 					}
13792 				}
13793 			}
13794 		}
13795 		AdjModuleRefPtr++;
13796 	}
13797 
13798 	if(chosenModule)
13799 	{
13800 		LOCALASSERT(numFound>=1);
13801  		*output = chosenEpWorld;
13802 		marineStatusPointer->gotapoint=1;
13803 		/* Congratulations. */
13804 		return;
13805 	}
13806 
13807 	/* else... return? */
13808 
13809 	return;
13810 }
13811 
13812 int MarineSight_FrustrumReject(STRATEGYBLOCK *sbPtr,VECTORCH *localOffset,STRATEGYBLOCK *target) {
13813 
13814 	MARINE_STATUS_BLOCK *marineStatusPointer;
13815 
13816 	LOCALASSERT(sbPtr);
13817 	LOCALASSERT(sbPtr->containingModule);
13818 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
13819     LOCALASSERT(marineStatusPointer);
13820 
13821 	if (marineStatusPointer->Target==NULL) {
13822 		/* Chop off the top 45 degrees. */
13823 		if ( (localOffset->vz <0) && (
13824 			((localOffset->vy-100)>=0)||(((localOffset->vy-100)<0)&&((-(localOffset->vy-100)) < (-localOffset->vz)))
13825 			)) {
13826 			/* 180 horizontal, 180 vertical. */
13827 			return(1);
13828 		} else {
13829 			return(0);
13830 		}
13831 	} else if (marineStatusPointer->Target!=target) {
13832 
13833 		if ( (localOffset->vz <0)
13834 	//		&& (localOffset->vz <  (localOffset->vy+500))
13835 	// 		&& (localOffset->vz > -(localOffset->vy+500))
13836 			) {
13837 			/* 180 horizontal, 180 vertical. */
13838 			return(1);
13839 		} else {
13840 			return(0);
13841 		}
13842 	} else {
13843 		/* Slightly different now, for error correction. */
13844 		if (localOffset->vz <0) {
13845 			return(1);
13846 		} else {
13847 			/* 270 horizontal, 180 vertical. */
13848 			if ( ((localOffset->vx>0)&&(localOffset->vx<localOffset->vz))
13849 				||((localOffset->vx<0)&&((-localOffset->vx)<localOffset->vz)) ) {
13850 				return(0);
13851 			} else {
13852 				return(1);
13853 			}
13854 		}
13855 	}
13856 }
13857 
13858 int Marine_SoundInterest(SOUNDINDEX soundIndex) {
13859 
13860 	/* Returns 0->ONE_FIXED scale.  0 is ignored.  Otherwise, larger value means
13861 	lower priority. */
13862 
13863 	switch (soundIndex) {
13864 		case SID_ALIEN_HISS:
13865 		case SID_ALIEN_HISS1:
13866 		case SID_ALIEN_SCREAM:
13867 		case SID_SWIPE:
13868 		case SID_SWISH:
13869 		case SID_TAIL:
13870 		case SID_PRED_LAUNCHER:
13871 		case SID_PRED_FRISBEE:
13872 		case SID_PRED_PISTOL:
13873 		case SID_PRED_SNARL:
13874 		case SID_PRED_SCREAM1:
13875 		case SID_PRED_LASER:
13876 		case SID_SWIPE2:
13877 		case SID_SWIPE3:
13878 		case SID_SWIPE4:
13879 		case SID_PRED_HISS:
13880 		case SID_HIT_FLESH:
13881 		case SID_ALIEN_HIT:
13882 		case SID_ALIEN_KILL:
13883 		case SID_FHUG_ATTACKLOOP:
13884 		case SID_FHUG_MOVE:
13885 		case SID_BUGDIE1:
13886 		case SID_BUGDIE2:
13887 		case SID_BUGDIE3:
13888 		case SID_MARINE_DEATH1:
13889 		case SID_MARINE_DEATH2:
13890 		case SID_PRED_LOUDROAR:
13891 		case SID_MARINE_HIT:
13892 		case SID_ALIEN_HIT2:
13893 		case SID_PRED_SHORTROAR:
13894 		case SID_PRED_SLASH:
13895 		case SID_RIP:
13896 		case SID_PRED_NEWROAR:
13897 		case SID_PLASMABOLT_DISSIPATE:
13898 		case SID_PLASMABOLT_HIT:
13899 		case SID_ALIEN_JAW_ATTACK:
13900 		case SID_BODY_BEING_HACKED_UP_0:
13901 		case SID_BODY_BEING_HACKED_UP_1:
13902 		case SID_BODY_BEING_HACKED_UP_2:
13903 		case SID_BODY_BEING_HACKED_UP_3:
13904 		case SID_BODY_BEING_HACKED_UP_4:
13905 		case SID_PREDATOR_PICKUP_FIELDCHARGE:
13906 		case SID_PREDATOR_PICKUP_WEAPON:
13907 		case SID_PREDATOR_CLOAKING_ACTIVE:
13908 		case SID_PREDATOR_CLOAKING_DAMAGED:
13909 		case SID_PREDATOR_SPEARGUN_EMPTY:
13910 		case SID_PREDATOR_PLASMACASTER_TARGET_FOUND:
13911 		case SID_PREDATOR_PLASMACASTER_TARGET_LOCKED:
13912 		case SID_PREDATOR_PLASMACASTER_TARGET_LOST:
13913 		case SID_PREDATOR_PLASMACASTER_CHARGING:
13914 		case SID_PREDATOR_PLASMACASTER_EMPTY:
13915 		case SID_PREDATOR_DISK_TARGET_LOCKED:
13916 		case SID_PREDATOR_DISK_FLYING:
13917 		case SID_PREDATOR_DISK_HITTING_TARGET:
13918 		case SID_PREDATOR_DISK_HITTING_WALL:
13919 		case SID_PREDATOR_DISK_BEING_CAUGHT:
13920 		case SID_PREDATOR_DISK_RECOVERED:
13921 		case SID_PREDATOR_VOCAL_SNARL_1:
13922 		case SID_PREDATOR_VOCAL_SNARL_2:
13923 		case SID_ALIEN_TAILUNFURL:
13924 		case SID_ALIEN_TAUNT_1:
13925 		case SID_ALIEN_TAUNT_2:
13926 		case SID_PRED_JUMP_START_1:
13927 		case SID_PRED_JUMP_START_2:
13928 		case SID_PRED_JUMP_START_3:
13929 		case SID_PRED_CLOAKON:
13930 		case SID_PRED_CLOAKOFF:
13931 		case SID_PRED_SMALLLANDING:
13932 		case SID_ED_FACEHUGGERSLAP:
13933 		case SID_GRAPPLE_HIT_WALL:
13934 		case SID_GRAPPLE_THROW:
13935 		case SID_ED_ELEC_DEATH:
13936 			/* Enemy sounds. */
13937 			return(ONE_FIXED>>2);
13938 			break;
13939 		case SID_SWITCH1:
13940 		case SID_SWITCH2:
13941 		case SID_PULSE_START:
13942 		case SID_PULSE_LOOP:
13943 		case SID_PULSE_END:
13944 		case SID_LIFT_START:
13945 		case SID_LIFT_LOOP:
13946 		case SID_LIFT_END:
13947 		case SID_VISION_ON:
13948 		case SID_VISION_LOOP:
13949 		case SID_FIRE:
13950 		case SID_PICKUP:
13951 		case SID_SPLASH1:
13952 		case SID_SPLASH2:
13953 		case SID_SPLASH3:
13954 		case SID_SPLASH4:
13955 		case SID_POWERUP:
13956 		case SID_POWERDN:
13957 		case SID_ACID_SPRAY:
13958 		case SID_DOORSTART:
13959 		case SID_DOORMID:
13960 		case SID_DOOREND:
13961 		case SID_BORGON:
13962 		case SID_SPARKS:
13963 		case SID_STOMP:
13964 		case SID_LOADMOVE:
13965 		case SID_NOAMMO:
13966 		case SID_LONGLOAD:
13967 		case SID_NADELOAD:
13968 		case SID_NADEFIRE:
13969 		case SID_NADEEXPLODE:
13970 		case SID_SHRTLOAD:
13971 		case SID_INCIN_START:
13972 		case SID_INCIN_LOOP:
13973 		case SID_INCIN_END:
13974 		case SID_ROCKFIRE:
13975 		case SID_SHOTGUN:
13976 		case SID_SMART1:
13977 		case SID_SMART2:
13978 		case SID_SMART3:
13979 		case SID_SENTRY_GUN:
13980 		case SID_SENTRY_END:
13981 		case SID_NICE_EXPLOSION:
13982 		case SID_EXPLOSION:
13983 		case SID_MINIGUN_END:
13984 		case SID_MINIGUN_LOOP:
13985 		case SID_FRAG_RICOCHETS:
13986 		case SID_SPEARGUN_HITTING_WALL:
13987 		case SID_DISC_STICKSINWALL:
13988 		case SID_PREDATOR_PLASMACASTER_REDTRIANGLES:
13989 		case SID_WIL_PRED_PISTOL_EXPLOSION:
13990 		case SID_PROX_GRENADE_READYTOBLOW:
13991 		case SID_PROX_GRENADE_ACTIVE:
13992 		case SID_ED_GRENADE_EXPLOSION:
13993 		case SID_ED_GRENADE_PROXEXPLOSION:
13994 		case SID_ED_MOLOTOV_EXPLOSION:
13995 		case SID_SENTRYGUNDEST:
13996 			return(ONE_FIXED);
13997 			break;
13998 		case SID_ARMSTART:
13999 		case SID_ARMMID:
14000 		case SID_ARMEND:
14001 		case SID_TRACKER_CLICK:
14002 		case SID_TRACKER_WHEEP:
14003 		case SID_RICOCH1:
14004 		case SID_RICOCH2:
14005 		case SID_RICOCH3:
14006 		case SID_RICOCH4:
14007 		case SID_TELETEXT:
14008 		case SID_TRACKER_WHEEP_HIGH:
14009 		case SID_TRACKER_WHEEP_LOW:
14010 		case SID_PULSE_RIFLE_FIRING_EMPTY:
14011 		case SID_THROW_FLARE:
14012 		case SID_CONSOLE_ACTIVATES:
14013 		case SID_CONSOLE_DEACTIVATES:
14014 		case SID_CONSOLE_MARINEMESSAGE:
14015 		case SID_CONSOLE_ALIENMESSAGE:
14016 		case SID_CONSOLE_PREDATORMESSAGE:
14017 		case SID_MINIGUN_READY:
14018 		case SID_MINIGUN_EMPTY:
14019 		case SID_SMART_MODESWITCH:
14020 		case SID_GRENADE_BOUNCE:
14021 		case SID_BURNING_FLARE:
14022 		case SID_FLAMETHROWER_PILOT_LIGHT:
14023 		case SID_MARINE_JUMP_START:
14024 		case SID_MARINE_JUMP_END:
14025 		case SID_MARINE_PICKUP_WEAPON:
14026 		case SID_MARINE_PICKUP_AMMO:
14027 		case SID_MARINE_PICKUP_ARMOUR:
14028 		case SID_SENTRYGUN_LOCK:
14029 		case SID_SENTRYGUN_SHUTDOWN:
14030 		case SID_WIL_MINIGUN_READY:
14031 		case SID_SADAR_FIRE:
14032 		case SID_MARINE_JUMP_START_2:
14033 		case SID_MARINE_JUMP_START_3:
14034 		case SID_MARINE_JUMP_START_4:
14035 		case SID_ED_LARGEWEAPONDROP:
14036 		case SID_MENUS_SELECT_ITEM:
14037 		case SID_MENUS_CHANGE_ITEM:
14038 		case SID_PRED_ZOOM_IN:
14039 		case SID_PRED_ZOOM_OUT:
14040 		case SID_MARINE_SMALLLANDING:
14041 		case SID_LIGHT_FLICKER_ON:
14042 		case SID_ED_SENTRYTURN01:
14043 		case SID_PULSE_SWIPE01:
14044 		case SID_PULSE_SWIPE02:
14045 		case SID_PULSE_SWIPE03:
14046 		case SID_PULSE_SWIPE04:
14047 		case SID_ED_JETPACK_START:
14048 		case SID_ED_JETPACK_MID:
14049 		case SID_ED_JETPACK_END:
14050 		case SID_IMAGE:
14051 		case SID_IMAGE_OFF:
14052 			/* Basic marine sounds, and the sentrygun. */
14053 			return(0);
14054 			break;
14055 		case SID_STARTOF_LOADSLOTS:
14056 		case SID_UNUSED_125:
14057 		case SID_UNUSED_126:
14058 		case SID_UNUSED_127:
14059 		case SID_UNUSED_128:
14060 		case SID_UNUSED_129:
14061 		case SID_UNUSED_130:
14062 		case SID_UNUSED_131:
14063 		case SID_UNUSED_132:
14064 		case SID_UNUSED_133:
14065 		case SID_UNUSED_134:
14066 		case SID_UNUSED_135:
14067 		case SID_UNUSED_136:
14068 		case SID_UNUSED_137:
14069 		case SID_UNUSED_138:
14070 		case SID_UNUSED_139:
14071 		case SID_UNUSED_140:
14072 		case SID_UNUSED_141:
14073 		case SID_UNUSED_142:
14074 		case SID_UNUSED_143:
14075 		case SID_UNUSED_144:
14076 		case SID_UNUSED_145:
14077 		case SID_UNUSED_146:
14078 		case SID_UNUSED_147:
14079 		case SID_UNUSED_148:
14080 		case SID_UNUSED_149:
14081 		case SID_ENDOF_LOADSLOTS:
14082 			/* Environment sounds. */
14083 			return(ONE_FIXED<<1);
14084 			break;
14085 		default:
14086 			/* Eh?  Could be a scream... */
14087 			return(ONE_FIXED<<1);
14088 			break;
14089 	}
14090 
14091 }
14092 
14093 int Marine_SoundCourageBonus(SOUNDINDEX soundIndex) {
14094 
14095 	/* Returns a FRI value. + is GOOD! */
14096 
14097 	switch (soundIndex) {
14098 		case SID_ALIEN_HISS:
14099 		case SID_ALIEN_HISS1:
14100 		case SID_ALIEN_SCREAM:
14101 		case SID_SWIPE:
14102 		case SID_SWISH:
14103 		case SID_TAIL:
14104 		case SID_PRED_LAUNCHER:
14105 		case SID_PRED_FRISBEE:
14106 		case SID_PRED_PISTOL:
14107 		case SID_PRED_SNARL:
14108 		case SID_PRED_SCREAM1:
14109 		case SID_PRED_LASER:
14110 		case SID_SWIPE2:
14111 		case SID_SWIPE3:
14112 		case SID_SWIPE4:
14113 		case SID_PRED_HISS:
14114 		case SID_HIT_FLESH:
14115 		case SID_ALIEN_HIT:
14116 		case SID_ALIEN_KILL:
14117 		case SID_FHUG_ATTACKLOOP:
14118 		case SID_FHUG_MOVE:
14119 		case SID_BUGDIE1:
14120 		case SID_BUGDIE2:
14121 		case SID_BUGDIE3:
14122 		case SID_MARINE_DEATH1:
14123 		case SID_MARINE_DEATH2:
14124 		case SID_PRED_LOUDROAR:
14125 		case SID_MARINE_HIT:
14126 		case SID_ALIEN_HIT2:
14127 		case SID_PRED_SHORTROAR:
14128 		case SID_PRED_SLASH:
14129 		case SID_RIP:
14130 		case SID_PRED_NEWROAR:
14131 		case SID_PLASMABOLT_DISSIPATE:
14132 		case SID_PLASMABOLT_HIT:
14133 		case SID_ALIEN_JAW_ATTACK:
14134 		case SID_BODY_BEING_HACKED_UP_0:
14135 		case SID_BODY_BEING_HACKED_UP_1:
14136 		case SID_BODY_BEING_HACKED_UP_2:
14137 		case SID_BODY_BEING_HACKED_UP_3:
14138 		case SID_BODY_BEING_HACKED_UP_4:
14139 		case SID_PREDATOR_PICKUP_FIELDCHARGE:
14140 		case SID_PREDATOR_PICKUP_WEAPON:
14141 		case SID_PREDATOR_CLOAKING_ACTIVE:
14142 		case SID_PREDATOR_CLOAKING_DAMAGED:
14143 		case SID_PREDATOR_SPEARGUN_EMPTY:
14144 		case SID_PREDATOR_PLASMACASTER_TARGET_FOUND:
14145 		case SID_PREDATOR_PLASMACASTER_TARGET_LOCKED:
14146 		case SID_PREDATOR_PLASMACASTER_TARGET_LOST:
14147 		case SID_PREDATOR_PLASMACASTER_CHARGING:
14148 		case SID_PREDATOR_PLASMACASTER_EMPTY:
14149 		case SID_PREDATOR_DISK_TARGET_LOCKED:
14150 		case SID_PREDATOR_DISK_FLYING:
14151 		case SID_PREDATOR_DISK_HITTING_TARGET:
14152 		case SID_PREDATOR_DISK_HITTING_WALL:
14153 		case SID_PREDATOR_DISK_BEING_CAUGHT:
14154 		case SID_PREDATOR_DISK_RECOVERED:
14155 		case SID_PREDATOR_VOCAL_SNARL_1:
14156 		case SID_PREDATOR_VOCAL_SNARL_2:
14157 		case SID_ALIEN_TAILUNFURL:
14158 		case SID_ALIEN_TAUNT_1:
14159 		case SID_ALIEN_TAUNT_2:
14160 		case SID_PRED_JUMP_START_1:
14161 		case SID_PRED_JUMP_START_2:
14162 		case SID_PRED_JUMP_START_3:
14163 		case SID_PRED_CLOAKON:
14164 		case SID_PRED_CLOAKOFF:
14165 		case SID_PRED_SMALLLANDING:
14166 		case SID_ED_FACEHUGGERSLAP:
14167 		case SID_GRAPPLE_HIT_WALL:
14168 		case SID_GRAPPLE_THROW:
14169 		case SID_ED_ELEC_DEATH:
14170 			/* Enemy sounds! */
14171 			return(MUL_FIXED(NormalFrameTime,-3000));
14172 			break;
14173 		case SID_MINIGUN_END:
14174 		case SID_MINIGUN_LOOP:
14175 		case SID_INCIN_START:
14176 		case SID_INCIN_LOOP:
14177 		case SID_INCIN_END:
14178 		case SID_ROCKFIRE:
14179 		case SID_PULSE_START:
14180 		case SID_PULSE_LOOP:
14181 		case SID_PULSE_END:
14182 		case SID_SHOTGUN:
14183 		case SID_SMART1:
14184 		case SID_SMART2:
14185 		case SID_SMART3:
14186 		case SID_TRACKER_WHEEP_HIGH:
14187 		case SID_TRACKER_WHEEP_LOW:
14188 		case SID_PULSE_RIFLE_FIRING_EMPTY:
14189 		case SID_THROW_FLARE:
14190 		case SID_CONSOLE_ACTIVATES:
14191 		case SID_CONSOLE_DEACTIVATES:
14192 		case SID_CONSOLE_MARINEMESSAGE:
14193 		case SID_CONSOLE_ALIENMESSAGE:
14194 		case SID_CONSOLE_PREDATORMESSAGE:
14195 		case SID_MINIGUN_READY:
14196 		case SID_MINIGUN_EMPTY:
14197 		case SID_SMART_MODESWITCH:
14198 		case SID_GRENADE_BOUNCE:
14199 		case SID_BURNING_FLARE:
14200 		case SID_FLAMETHROWER_PILOT_LIGHT:
14201 		case SID_MARINE_JUMP_START:
14202 		case SID_MARINE_JUMP_END:
14203 		case SID_MARINE_PICKUP_WEAPON:
14204 		case SID_MARINE_PICKUP_AMMO:
14205 		case SID_MARINE_PICKUP_ARMOUR:
14206 		case SID_SENTRYGUN_LOCK:
14207 		case SID_SENTRYGUN_SHUTDOWN:
14208 		case SID_WIL_MINIGUN_READY:
14209 		case SID_SADAR_FIRE:
14210 		case SID_MARINE_JUMP_START_2:
14211 		case SID_MARINE_JUMP_START_3:
14212 		case SID_MARINE_JUMP_START_4:
14213 		case SID_ED_GRENADE_EXPLOSION:
14214 		case SID_ED_GRENADE_PROXEXPLOSION:
14215 		case SID_ED_MOLOTOV_EXPLOSION:
14216 		case SID_ED_LARGEWEAPONDROP:
14217 		case SID_MENUS_SELECT_ITEM:
14218 		case SID_MENUS_CHANGE_ITEM:
14219 		case SID_IMAGE:
14220 		case SID_IMAGE_OFF:
14221 			/* Marine type sounds. */
14222 			return(MUL_FIXED(NormalFrameTime,300));
14223 			break;
14224 		case SID_SWITCH1:
14225 		case SID_SWITCH2:
14226 		case SID_LIFT_START:
14227 		case SID_LIFT_LOOP:
14228 		case SID_LIFT_END:
14229 		case SID_VISION_ON:
14230 		case SID_VISION_LOOP:
14231 		case SID_FIRE:
14232 		case SID_PICKUP:
14233 		case SID_SPLASH1:
14234 		case SID_SPLASH2:
14235 		case SID_SPLASH3:
14236 		case SID_SPLASH4:
14237 		case SID_POWERUP:
14238 		case SID_POWERDN:
14239 		case SID_ACID_SPRAY:
14240 		case SID_DOORSTART:
14241 		case SID_DOORMID:
14242 		case SID_DOOREND:
14243 		case SID_BORGON:
14244 		case SID_SPARKS:
14245 		case SID_STOMP:
14246 		case SID_LOADMOVE:
14247 		case SID_NOAMMO:
14248 		case SID_LONGLOAD:
14249 		case SID_NADELOAD:
14250 		case SID_NADEFIRE:
14251 		case SID_NADEEXPLODE:
14252 		case SID_SHRTLOAD:
14253 		case SID_SENTRY_GUN:
14254 		case SID_SENTRY_END:
14255 		case SID_NICE_EXPLOSION:
14256 		case SID_EXPLOSION:
14257 		case SID_FRAG_RICOCHETS:
14258 		case SID_SPEARGUN_HITTING_WALL:
14259 		case SID_DISC_STICKSINWALL:
14260 		case SID_PREDATOR_PLASMACASTER_REDTRIANGLES:
14261 		case SID_WIL_PRED_PISTOL_EXPLOSION:
14262 		case SID_PROX_GRENADE_READYTOBLOW:
14263 		case SID_PROX_GRENADE_ACTIVE:
14264 		case SID_SENTRYGUNDEST:
14265 			/* Weird sounds. */
14266 			return(ONE_FIXED);
14267 			break;
14268 		case SID_ARMSTART:
14269 		case SID_ARMMID:
14270 		case SID_ARMEND:
14271 		case SID_TRACKER_CLICK:
14272 		case SID_TRACKER_WHEEP:
14273 		case SID_TELETEXT:
14274 		case SID_RICOCH1:
14275 		case SID_RICOCH2:
14276 		case SID_RICOCH3:
14277 		case SID_RICOCH4:
14278 		case SID_NOSOUND:
14279 		case SID_PRED_ZOOM_IN:
14280 		case SID_PRED_ZOOM_OUT:
14281 		case SID_MARINE_SMALLLANDING:
14282 		case SID_LIGHT_FLICKER_ON:
14283 		case SID_ED_SENTRYTURN01:
14284 		case SID_PULSE_SWIPE01:
14285 		case SID_PULSE_SWIPE02:
14286 		case SID_PULSE_SWIPE03:
14287 		case SID_PULSE_SWIPE04:
14288 		case SID_ED_JETPACK_START:
14289 		case SID_ED_JETPACK_MID:
14290 		case SID_ED_JETPACK_END:
14291 			/* Basic marine sounds, and the sentrygun. */
14292 			return(0);
14293 			break;
14294 		case SID_STARTOF_LOADSLOTS:
14295 		case SID_UNUSED_125:
14296 		case SID_UNUSED_126:
14297 		case SID_UNUSED_127:
14298 		case SID_UNUSED_128:
14299 		case SID_UNUSED_129:
14300 		case SID_UNUSED_130:
14301 		case SID_UNUSED_131:
14302 		case SID_UNUSED_132:
14303 		case SID_UNUSED_133:
14304 		case SID_UNUSED_134:
14305 		case SID_UNUSED_135:
14306 		case SID_UNUSED_136:
14307 		case SID_UNUSED_137:
14308 		case SID_UNUSED_138:
14309 		case SID_UNUSED_139:
14310 		case SID_UNUSED_140:
14311 		case SID_UNUSED_141:
14312 		case SID_UNUSED_142:
14313 		case SID_UNUSED_143:
14314 		case SID_UNUSED_144:
14315 		case SID_UNUSED_145:
14316 		case SID_UNUSED_146:
14317 		case SID_UNUSED_147:
14318 		case SID_UNUSED_148:
14319 		case SID_UNUSED_149:
14320 		case SID_ENDOF_LOADSLOTS:
14321 			/* Environment sounds. */
14322 			return(MUL_FIXED(NormalFrameTime,-300));
14323 			break;
14324 		default:
14325 			/* Eh?  Could be a scream... */
14326 			return(MUL_FIXED(NormalFrameTime,-1500));
14327 			break;
14328 	}
14329 
14330 }
14331 
14332 void DoMarineHearing(STRATEGYBLOCK *sbPtr) {
14333 
14334 	int a,nearest,neardist,dist,priority;
14335 	MARINE_STATUS_BLOCK *marineStatusPointer;
14336 	VECTORCH offset;
14337 
14338 	LOCALASSERT(sbPtr);
14339 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14340     LOCALASSERT(marineStatusPointer);
14341 
14342 	#if 0
14343 	/* Hearing is low priority. */
14344 	if (marineStatusPointer->suspicious) {
14345 		return;
14346 	}
14347 	#endif
14348 
14349 	nearest=-1;
14350 	neardist=10000000;
14351 	/* Hence, if you're still interested in something else, return. */
14352 
14353 	for(a=0;a<SOUND_MAXACTIVE;a++)
14354 	{
14355 		/* Ignore sounds with no position. */
14356 		if ((ActiveSounds[a].threedee)&&(ActiveSounds[a].loop==0)&&(ActiveSounds[a].marine_ignore==0)
14357 			&&(ActiveSounds[a].soundIndex!=SID_NOSOUND)) {
14358 			priority=Marine_SoundInterest(ActiveSounds[a].soundIndex);
14359 			if (marineStatusPointer->Android==0) {
14360 				marineStatusPointer->Courage+=Marine_SoundCourageBonus(ActiveSounds[a].soundIndex);
14361 			}
14362 			if (priority) {
14363 				int test_dist;
14364 				/* Interesting sound... */
14365 				offset.vx=sbPtr->DynPtr->Position.vx-ActiveSounds[a].threedeedata.position.vx;
14366 				offset.vy=sbPtr->DynPtr->Position.vy-ActiveSounds[a].threedeedata.position.vy;
14367 				offset.vz=sbPtr->DynPtr->Position.vz-ActiveSounds[a].threedeedata.position.vz;
14368 
14369 				dist=Approximate3dMagnitude(&offset);
14370 
14371 				if (ActiveSounds[a].threedeedata.outer_range==-1) {
14372 					test_dist=100000;
14373 					/* 100 m. */
14374 				} else {
14375 					test_dist=ActiveSounds[a].threedeedata.outer_range;
14376 				}
14377 
14378 				if (dist<=test_dist) {
14379 					/* In range.  Modify by priority. */
14380 					dist=MUL_FIXED(dist,priority);
14381 
14382 					if (dist<neardist) {
14383 						/* Got one! */
14384 						nearest=a;
14385 						neardist=dist;
14386 					}
14387 				}
14388 			}
14389 		}
14390 	}
14391 
14392 	/* Finally, test the player. */
14393 	{
14394 		extern int playerNoise;
14395 
14396 		if (playerNoise) {
14397 
14398 			offset.vx=sbPtr->DynPtr->Position.vx-Player->ObStrategyBlock->DynPtr->Position.vx;
14399 			offset.vy=sbPtr->DynPtr->Position.vy-Player->ObStrategyBlock->DynPtr->Position.vy;
14400 			offset.vz=sbPtr->DynPtr->Position.vz-Player->ObStrategyBlock->DynPtr->Position.vz;
14401 
14402 			dist=Approximate3dMagnitude(&offset);
14403 
14404 			if (dist<=100000) {
14405 				/* In range.  Assume priority is ONE_FIXED. */
14406 				if (dist<neardist) {
14407 					/* Got one! */
14408 					nearest=-2;
14409 					neardist=dist;
14410 				}
14411 			}
14412 
14413 		}
14414 	}
14415 
14416 	if (nearest!=-1) {
14417 		int level,priority;
14418 
14419 		if (nearest==-2) {
14420 			/* Heard the player! */
14421 
14422 			marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
14423 			marineStatusPointer->suspect_point=Player->ObStrategyBlock->DynPtr->Position;
14424 			/* Set this to zero when you get a *new* suspicion. */
14425 			marineStatusPointer->previous_suspicion=0;
14426 			marineStatusPointer->using_squad_suspicion=0;
14427 
14428 			level=2;
14429 
14430 		} else {
14431 
14432 			marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
14433 			marineStatusPointer->suspect_point=ActiveSounds[nearest].threedeedata.position;
14434 			/* Set this to zero when you get a *new* suspicion. */
14435 			marineStatusPointer->previous_suspicion=0;
14436 			marineStatusPointer->using_squad_suspicion=0;
14437 
14438 			priority=Marine_SoundInterest(ActiveSounds[nearest].soundIndex);
14439 			if (priority>ONE_FIXED) {
14440 				level=1;
14441 			} else if (priority<ONE_FIXED) {
14442 				level=3;
14443 			} else {
14444 				level=2;
14445 			}
14446 
14447 		}
14448 
14449 		PointAlert(level,&marineStatusPointer->suspect_point);
14450 	}
14451 
14452 }
14453 
14454 static STATE_RETURN_CONDITION Execute_MNS_Taunting(STRATEGYBLOCK *sbPtr)
14455 {
14456 
14457 	MARINE_STATUS_BLOCK *marineStatusPointer;
14458 
14459 	LOCALASSERT(sbPtr);
14460 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14461     LOCALASSERT(marineStatusPointer);
14462 
14463 	/* zero velocity */
14464 	LOCALASSERT(sbPtr->DynPtr);
14465 	sbPtr->DynPtr->LinVelocity.vx = 0;
14466 	sbPtr->DynPtr->LinVelocity.vy = 0;
14467 	sbPtr->DynPtr->LinVelocity.vz = 0;
14468 
14469 	if (!sbPtr->SBdptr) {
14470 		/* We're far... do the timer! */
14471 		ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
14472 	}
14473 
14474 	if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController)) {
14475 		return(SRC_Request_Wait);
14476 	} else {
14477 		return(SRC_No_Change);
14478 	}
14479 
14480 }
14481 
14482 static STATE_RETURN_CONDITION Execute_MNS_Reloading(STRATEGYBLOCK *sbPtr)
14483 {
14484 
14485 	MARINE_STATUS_BLOCK *marineStatusPointer;
14486 
14487 	LOCALASSERT(sbPtr);
14488 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14489     LOCALASSERT(marineStatusPointer);
14490 
14491 	/* zero velocity */
14492 	LOCALASSERT(sbPtr->DynPtr);
14493 	sbPtr->DynPtr->LinVelocity.vx = 0;
14494 	sbPtr->DynPtr->LinVelocity.vy = 0;
14495 	sbPtr->DynPtr->LinVelocity.vz = 0;
14496 
14497 	if (!sbPtr->SBdptr) {
14498 		/* We're far... do the timer! */
14499 		ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
14500 	}
14501 
14502 	/* Clip management. */
14503 	if (marineStatusPointer->My_Weapon->ClipName) {
14504 		SECTION_DATA *clip;
14505 		clip=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ClipName);
14506 		if (clip) {
14507 			/* Now, check keyframe flags. */
14508 			if (marineStatusPointer->HModelController.keyframe_flags&4) {
14509 				/* Vanish it. */
14510 				clip->flags|=(section_data_terminate_here|section_data_notreal);
14511 			}
14512 
14513 			if (marineStatusPointer->HModelController.keyframe_flags&1) {
14514 				/* Trim it off. */
14515 				MakeHierarchicalDebris(NULL,clip, &clip->World_Offset, &clip->SecMat,NULL,0);
14516 			}
14517 
14518 			if (marineStatusPointer->HModelController.keyframe_flags&2) {
14519 				/* Put it back. */
14520 				if ((marineStatusPointer->My_Weapon->id==MNPCW_SADAR)
14521 					||(marineStatusPointer->My_Weapon->id==MNPCW_Skeeter)) {
14522 					SECTION *root_section;
14523 					/* Heaven help us. */
14524 					clip->flags&=(~(section_data_terminate_here|section_data_notreal));
14525 
14526 					root_section=GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,marineStatusPointer->My_Weapon->HierarchyName);
14527 					GLOBALASSERT(root_section);
14528 
14529 					Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root_section,0,1,1);
14530 					ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
14531 					marineStatusPointer->My_Gunflash_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->GunflashName);
14532 					marineStatusPointer->My_Elevation_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ElevationSection);
14533 				} else {
14534 					clip->flags&=(~(section_data_terminate_here|section_data_notreal));
14535 				}
14536 			}
14537 		}
14538 	}
14539 
14540 	if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController)) {
14541 		marineStatusPointer->clipammo=marineStatusPointer->My_Weapon->clip_size;
14542 		return(SRC_Request_Approach);
14543 	} else {
14544 		return(SRC_No_Change);
14545 	}
14546 
14547 }
14548 
14549 static STATE_RETURN_CONDITION Execute_MNS_PanicReloading(STRATEGYBLOCK *sbPtr)
14550 {
14551 
14552 	MARINE_STATUS_BLOCK *marineStatusPointer;
14553 
14554 	LOCALASSERT(sbPtr);
14555 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14556     LOCALASSERT(marineStatusPointer);
14557 
14558 	/* zero velocity */
14559 	LOCALASSERT(sbPtr->DynPtr);
14560 	sbPtr->DynPtr->LinVelocity.vx = 0;
14561 	sbPtr->DynPtr->LinVelocity.vy = 0;
14562 	sbPtr->DynPtr->LinVelocity.vz = 0;
14563 
14564 	if (!sbPtr->SBdptr) {
14565 		/* We're far... do the timer! */
14566 		ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
14567 	}
14568 
14569 	/* Scream handling. */
14570 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
14571 		if (marineStatusPointer->incidentFlag) {
14572 			if (Marine_HasHisMouthOpen(sbPtr)) {
14573 				if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
14574 					Marine_PanicScream(sbPtr);
14575 				} else {
14576 					Marine_AngryScream(sbPtr);
14577 				}
14578 			} else {
14579 				/* Scream anyway? */
14580 				Marine_PanicScream(sbPtr);
14581 				/* Open the mouth? */
14582 				Marine_AssumePanicExpression(sbPtr);
14583 			}
14584 		}
14585 	}
14586 
14587 	/* Clip management. */
14588 	if (marineStatusPointer->My_Weapon->ClipName) {
14589 		SECTION_DATA *clip;
14590 		clip=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ClipName);
14591 		if (clip) {
14592 			/* Now, check keyframe flags. */
14593 			if (marineStatusPointer->HModelController.keyframe_flags&4) {
14594 				/* Vanish it. */
14595 				clip->flags|=(section_data_terminate_here|section_data_notreal);
14596 			}
14597 
14598 			if (marineStatusPointer->HModelController.keyframe_flags&1) {
14599 				/* Trim it off. */
14600 				MakeHierarchicalDebris(NULL,clip, &clip->World_Offset, &clip->SecMat,NULL,0);
14601 			}
14602 
14603 			if (marineStatusPointer->HModelController.keyframe_flags&2) {
14604 				/* Put it back. */
14605 				if (marineStatusPointer->My_Weapon->id==MNPCW_SADAR) {
14606 					SECTION *root_section;
14607 					/* Heaven help us. */
14608 					clip->flags&=(~(section_data_terminate_here|section_data_notreal));
14609 
14610 					root_section=GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,marineStatusPointer->My_Weapon->HierarchyName);
14611 					GLOBALASSERT(root_section);
14612 
14613 					Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root_section,0,1,1);
14614 					ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
14615 					marineStatusPointer->My_Gunflash_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->GunflashName);
14616 					marineStatusPointer->My_Elevation_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ElevationSection);
14617 				} else {
14618 					clip->flags&=(~(section_data_terminate_here|section_data_notreal));
14619 				}
14620 			}
14621 		}
14622 	}
14623 
14624 	if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController)) {
14625 		marineStatusPointer->clipammo=marineStatusPointer->My_Weapon->clip_size;
14626 		return(SRC_Request_Approach);
14627 	} else {
14628 		return(SRC_No_Change);
14629 	}
14630 
14631 }
14632 
14633 static STATE_RETURN_CONDITION Execute_MNS_GetWeapon(STRATEGYBLOCK *sbPtr)
14634 {
14635 
14636 	MARINE_STATUS_BLOCK *marineStatusPointer;
14637 
14638 	LOCALASSERT(sbPtr);
14639 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14640     LOCALASSERT(marineStatusPointer);
14641 
14642 	/* zero velocity */
14643 	LOCALASSERT(sbPtr->DynPtr);
14644 	sbPtr->DynPtr->LinVelocity.vx = 0;
14645 	sbPtr->DynPtr->LinVelocity.vy = 0;
14646 	sbPtr->DynPtr->LinVelocity.vz = 0;
14647 
14648 	if (!sbPtr->SBdptr) {
14649 		/* We're far... do the timer! */
14650 		ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
14651 	}
14652 
14653 	if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController)) {
14654 		return(SRC_Request_Wait);
14655 	} else {
14656 		return(SRC_No_Change);
14657 	}
14658 
14659 }
14660 
14661 int NPCFireMinigun_Core(STRATEGYBLOCK *sbPtr) {
14662 
14663 	MARINE_STATUS_BLOCK *marineStatusPointer;
14664 
14665 	LOCALASSERT(sbPtr);
14666 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14667     LOCALASSERT(marineStatusPointer);
14668 
14669 	marineStatusPointer->weapon_variable+=(NormalFrameTime<<7);
14670 
14671 	if (marineStatusPointer->weapon_variable>=MINIGUN_MAX_SPEED) {
14672 
14673 		marineStatusPointer->weapon_variable=MINIGUN_MAX_SPEED;
14674 
14675 		/* Fire! */
14676 		DischargeLOSWeapon_Core(sbPtr);
14677 
14678 		return(1);
14679 	}
14680 
14681 	/* Maintain_Minigun called anyway. */
14682 
14683 	return(0);
14684 
14685 }
14686 
14687 
14688 void NPC_Maintain_Minigun(STRATEGYBLOCK *sbPtr, DELTA_CONTROLLER *mgd) {
14689 
14690 	MARINE_STATUS_BLOCK *marineStatusPointer;
14691 
14692 	LOCALASSERT(sbPtr);
14693 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14694     LOCALASSERT(marineStatusPointer);
14695 
14696 	if (mgd==NULL) {
14697 		return;
14698 	}
14699 
14700    	if ((marineStatusPointer->behaviourState!=MBS_Firing)
14701    		||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)
14702    		||(marineStatusPointer->HModelController.Playing==0)) {
14703 		/* Not firing. */
14704 		marineStatusPointer->weapon_variable-=(NormalFrameTime<<3);
14705 		if (marineStatusPointer->weapon_variable<MINIGUN_IDLE_SPEED) {
14706 			marineStatusPointer->weapon_variable=MINIGUN_IDLE_SPEED;
14707 		}
14708 	}
14709 
14710 	if (marineStatusPointer->weapon_variable!=marineStatusPointer->weapon_variable2) {
14711 		int hmspinrate;
14712 
14713 		if (marineStatusPointer->weapon_variable) {
14714 
14715 			hmspinrate=DIV_FIXED(ONE_FIXED,marineStatusPointer->weapon_variable);
14716 
14717 			Delta_Sequence_ChangeSpeed(mgd,hmspinrate);
14718 			mgd->Playing=1;
14719 		} else {
14720 			mgd->Playing=0;
14721 		}
14722 	}
14723 
14724 	marineStatusPointer->weapon_variable2=marineStatusPointer->weapon_variable;
14725 
14726 }
14727 
14728 static STATE_RETURN_CONDITION Execute_MNS_DischargeMinigun(STRATEGYBLOCK *sbPtr)
14729 {
14730 	MARINE_STATUS_BLOCK *marineStatusPointer;
14731 	VECTORCH orientationDirn,relPos,relPos2;
14732 	int correctlyOrientated,range;
14733 
14734 	LOCALASSERT(sbPtr);
14735 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14736 	LOCALASSERT(marineStatusPointer);
14737 
14738 	/* zero velocity */
14739 	LOCALASSERT(sbPtr->DynPtr);
14740 	sbPtr->DynPtr->LinVelocity.vx = 0;
14741 	sbPtr->DynPtr->LinVelocity.vy = 0;
14742 	sbPtr->DynPtr->LinVelocity.vz = 0;
14743 
14744 	marineStatusPointer->HModelController.Playing=1;
14745 
14746 	#if MARINE_STATE_PRINT
14747 	textprint("Marine firing... ");
14748 	#endif
14749 
14750 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
14751 	we should switch immediately to wait state*/
14752 
14753 	if (marineStatusPointer->volleySize<marineStatusPointer->My_Weapon->MinimumBurstSize) {
14754 		/* Keep firing! */
14755 	} else {
14756 
14757 		if(!MarineCanSeeTarget(sbPtr))
14758 		{
14759 
14760 			/* ... and remove the gunflash */
14761 			if(marineStatusPointer->myGunFlash)
14762 			{
14763 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
14764 				marineStatusPointer->myGunFlash = NULL;
14765 			}
14766 
14767 			/* .... and stop the sound */
14768 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
14769 				Sound_Stop(marineStatusPointer->soundHandle);
14770 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
14771 			}
14772 
14773 			#if MARINE_STATE_PRINT
14774 			textprint("Returning no target.\n");
14775 			#endif
14776 			marineStatusPointer->lastroundhit=0;
14777 			marineStatusPointer->lasthitsection=NULL;
14778 			return(SRC_Request_Wait);
14779 		}
14780 	}
14781 
14782 	if (marineStatusPointer->Target) {
14783 		GLOBALASSERT(marineStatusPointer->Target);
14784 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
14785 		/* Fix weapon target! */
14786 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
14787 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
14788 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
14789 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
14790 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
14791 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
14792 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
14793 		}
14794 
14795 		/* Here we must have a target.  Renew suspicion for new arrivals. */
14796 		if (NpcSquad.Squad_Suspicion==0) {
14797 			PointAlert(2,&marineStatusPointer->weaponTarget);
14798 		}
14799 	}
14800 	/* Otherwise, stay facing the same way. */
14801 
14802 	/* orientate to firing point first */
14803 	orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
14804 	orientationDirn.vy = 0;
14805 	orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
14806 	correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
14807 
14808 	/* I have a cunning plan... */
14809 	{
14810 		DELTA_CONTROLLER *delta;
14811 
14812 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
14813 		if (delta) {
14814 			if (!(DeltaAnimation_IsFinished(delta))) {
14815 				correctlyOrientated=0;
14816 			}
14817 		}
14818 	}
14819 	/* I have another cunning plan... */
14820 	if ((marineStatusPointer->volleySize>0)&&
14821 		(marineStatusPointer->volleySize<marineStatusPointer->My_Weapon->MinimumBurstSize)) {
14822 		correctlyOrientated=1;
14823 	}
14824 
14825 	/* we are not correctly orientated to the target: this could happen because we have
14826 	just entered this state, or the target has moved during firing */
14827 	if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)) {
14828 
14829 		/* stop visual and audio cues: technically, we're not firing at this moment */
14830 		if(marineStatusPointer->myGunFlash)
14831 		{
14832 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
14833 			marineStatusPointer->myGunFlash = NULL;
14834 		}
14835 
14836 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
14837 			Sound_Stop(marineStatusPointer->soundHandle);
14838 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
14839 		}
14840 		#if MARINE_STATE_PRINT
14841 		textprint("Turning to face.\n");
14842 		#endif
14843 		marineStatusPointer->lastroundhit=0;
14844 		marineStatusPointer->lasthitsection=NULL;
14845 		return(SRC_No_Change);
14846 	}
14847 
14848 	NPCFireMinigun_Core(sbPtr);
14849 
14850 	if (marineStatusPointer->Target==NULL) {
14851 		/* Getting out of here! */
14852 		return(SRC_No_Change);
14853 	}
14854 
14855 	relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
14856 	relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
14857 	relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
14858 
14859 	relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
14860 	relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
14861 	relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
14862 
14863 	range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
14864 
14865 	/* Did we get him? */
14866 	if ((NPC_IsDead(marineStatusPointer->Target))
14867 		&&(marineStatusPointer->volleySize>=marineStatusPointer->My_Weapon->MinimumBurstSize)) {
14868 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
14869 			if (Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr)==NULL) {
14870 				/* Huzzah! */
14871 				if(marineStatusPointer->myGunFlash)
14872 				{
14873 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
14874 					marineStatusPointer->myGunFlash = NULL;
14875 				}
14876 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
14877 					Sound_Stop(marineStatusPointer->soundHandle);
14878 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
14879 				}
14880 				marineStatusPointer->lastroundhit=0;
14881 				marineStatusPointer->lasthitsection=NULL;
14882 				return(SRC_Request_Taunt);
14883 			}
14884 		}
14885 	}
14886 
14887 	if(marineStatusPointer->stateTimer > 0)	{
14888 		#if MARINE_STATE_PRINT
14889 		textprint("Returning continue at range %d.\n",range);
14890 		#endif
14891 		return(SRC_No_Change);
14892 	}
14893 
14894 	if(range < MARINE_CLOSE_APPROACH_DISTANCE)
14895 	{
14896 		/* renew firing, as we are still too close to approach */
14897 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
14898 		marineStatusPointer->volleySize = 0;
14899 		GLOBALASSERT(marineStatusPointer->Target);
14900 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
14901 		#if MARINE_STATE_PRINT
14902 		textprint("Returning too close renewal at range %d.\n",range);
14903 		#endif
14904 
14905 		/* stop visual and audio cues: technically, we're not firing at this moment */
14906 		if(marineStatusPointer->myGunFlash)
14907 		{
14908 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
14909 			marineStatusPointer->myGunFlash = NULL;
14910 		}
14911 
14912 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
14913 			Sound_Stop(marineStatusPointer->soundHandle);
14914 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
14915 		}
14916 		if (marineStatusPointer->Android==0) {
14917 			marineStatusPointer->Courage-=(ONE_FIXED>>3);
14918 		}
14919 		return(SRC_Request_Fire);
14920 	}
14921 	else
14922 	{
14923 		/* we are far enough away, so return to approach */
14924 
14925 		/* ... and remove the gunflash */
14926 		if(marineStatusPointer->myGunFlash)
14927 		{
14928 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
14929 			marineStatusPointer->myGunFlash = NULL;
14930 		}
14931 
14932 		/* .... and stop the sound */
14933 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
14934 			Sound_Stop(marineStatusPointer->soundHandle);
14935 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
14936 		}
14937 		#if MARINE_STATE_PRINT
14938 		textprint("Returning too far termination at range %d.\n",range);
14939 		#endif
14940 		return(SRC_Request_Approach);
14941 	}
14942 	return(SRC_No_Change);
14943 }
14944 
14945 static STATE_RETURN_CONDITION Execute_MNS_NullPanicFire(STRATEGYBLOCK *sbPtr) {
14946 
14947 	/* This MUST exist to redirect weapons with no panic fire. */
14948 
14949 	/* zero velocity */
14950 	LOCALASSERT(sbPtr->DynPtr);
14951 	sbPtr->DynPtr->LinVelocity.vx = 0;
14952 	sbPtr->DynPtr->LinVelocity.vy = 0;
14953 	sbPtr->DynPtr->LinVelocity.vz = 0;
14954 
14955 	return(SRC_Request_Wait);
14956 
14957 }
14958 
14959 static STATE_RETURN_CONDITION Execute_MNS_PanicFireLOSWeapon(STRATEGYBLOCK *sbPtr)
14960 {
14961 	MARINE_STATUS_BLOCK *marineStatusPointer;
14962 	VECTORCH orientationDirn;
14963 	int correctlyOrientated;
14964 	int volleytime,volleyrounds;
14965 
14966 	LOCALASSERT(sbPtr);
14967 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
14968 	LOCALASSERT(marineStatusPointer);
14969 
14970 	marineStatusPointer->HModelController.Playing=1;
14971 
14972 	/* zero velocity */
14973 	LOCALASSERT(sbPtr->DynPtr);
14974 	sbPtr->DynPtr->LinVelocity.vx = 0;
14975 	sbPtr->DynPtr->LinVelocity.vy = 0;
14976 	sbPtr->DynPtr->LinVelocity.vz = 0;
14977 
14978 	#if MARINE_STATE_PRINT
14979 	textprint("Marine panic firing... ");
14980 	#endif
14981 
14982 	/* Stabilise sequence. */
14983 	if (marineStatusPointer->Target==NULL) {
14984 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
14985 			||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
14986 
14987 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
14988 		}
14989 	} else {
14990 		int offsetx,offsety,offsetz,offseta,angle1;
14991 		VECTORCH *gunpos;
14992 		int sequence=0;
14993 		/* Pick a sequence based on angle. */
14994 
14995 		if (marineStatusPointer->My_Elevation_Section) {
14996 			gunpos=&marineStatusPointer->My_Elevation_Section->World_Offset;
14997 		} else {
14998 			gunpos=&sbPtr->DynPtr->Position;
14999 		}
15000 		/* Aim at Target. */
15001 
15002 		offsetx=(marineStatusPointer->Target->DynPtr->Position.vx)-(gunpos->vx);
15003 		offsety=(marineStatusPointer->Target->DynPtr->Position.vz)-(gunpos->vz);
15004 		offseta=-((marineStatusPointer->Target->DynPtr->Position.vy)-(gunpos->vy));
15005 
15006 		while( (offsetx>(ONE_FIXED>>2))
15007 			||(offsety>(ONE_FIXED>>2))
15008 			||(offseta>(ONE_FIXED>>2))
15009 			||(offsetx<-(ONE_FIXED>>2))
15010 			||(offsety<-(ONE_FIXED>>2))
15011 			||(offseta<-(ONE_FIXED>>2))) {
15012 
15013 			offsetx>>=1;
15014 			offsety>>=1;
15015 			offseta>>=1;
15016 
15017 		}
15018 
15019 		offsetz=SqRoot32((offsetx*offsetx)+(offsety*offsety));
15020 		angle1=ArcTan(offseta,offsetz);
15021 
15022 		if (angle1>=3072) angle1-=4096;
15023 		if (angle1>=2048) angle1=angle1-3072;
15024 		if (angle1>1024) angle1=2048-angle1;
15025 
15026 		GLOBALASSERT(angle1>=-1024);
15027 		GLOBALASSERT(angle1<=1024);
15028 
15029 		sequence=0;
15030 		/* Now correct for hysteresis... */
15031 		{
15032 			int threshold22,threshold45,threshold67,threshold90,ideal_sequence;
15033 
15034 			if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_90) {
15035 				threshold22=70;
15036 				threshold45=220;
15037 				threshold67=490;
15038 				threshold90=730;
15039 			} else if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_67) {
15040 				threshold22=70;
15041 				threshold45=220;
15042 				threshold67=490;
15043 				threshold90=768;
15044 			} else if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_45) {
15045 				threshold22=70;
15046 				threshold45=220;
15047 				threshold67=512;
15048 				threshold90=768;
15049 			} else if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_22) {
15050 				threshold22=70;
15051 				threshold45=256;
15052 				threshold67=512;
15053 				threshold90=768;
15054 			} else {
15055 				threshold22=90;
15056 				threshold45=256;
15057 				threshold67=512;
15058 				threshold90=768;
15059 			}
15060 
15061 			if (angle1>threshold90) {
15062 				ideal_sequence=4;
15063 			} else if (angle1>threshold67) {
15064 				ideal_sequence=3;
15065 			} else if (angle1>threshold45) {
15066 				ideal_sequence=2;
15067 			} else if (angle1>threshold22) {
15068 				ideal_sequence=1;
15069 			} else {
15070 				ideal_sequence=0;
15071 			}
15072 
15073 			sequence=-1;
15074 			while (sequence==-1) {
15075 				switch (ideal_sequence) {
15076 					case 0:
15077 					default:
15078 						sequence=0;
15079 						break;
15080 					case 1:
15081 						if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_22)) {
15082 							sequence=1;
15083 						} else {
15084 							ideal_sequence=0;
15085 						}
15086 						break;
15087 					case 2:
15088 						if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45)) {
15089 							sequence=2;
15090 						} else {
15091 							ideal_sequence=1;
15092 						}
15093 						break;
15094 					case 3:
15095 						if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_67)) {
15096 							sequence=3;
15097 						} else {
15098 							ideal_sequence=2;
15099 						}
15100 						break;
15101 					case 4:
15102 						if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90)) {
15103 							sequence=4;
15104 						} else {
15105 							ideal_sequence=3;
15106 						}
15107 						break;
15108 				}
15109 			}
15110 		}
15111 
15112 		switch (sequence) {
15113 			case 4:
15114 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15115 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_90)) {
15116 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_90,-1,(ONE_FIXED>>3));
15117 				}
15118 				break;
15119 			case 3:
15120 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15121 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_67)) {
15122 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_67,-1,(ONE_FIXED>>3));
15123 				}
15124 				break;
15125 			case 2:
15126 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15127 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_45)) {
15128 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_45,-1,(ONE_FIXED>>3));
15129 				}
15130 				break;
15131 			case 1:
15132 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15133 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_22)) {
15134 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_22,-1,(ONE_FIXED>>3));
15135 				}
15136 				break;
15137 			case 0:
15138 			default:
15139 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15140 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
15141 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
15142 				}
15143 				break;
15144 		}
15145 	}
15146 
15147 	if (marineStatusPointer->clipammo==0) {
15148 		return(SRC_Request_PanicReload);
15149 	}
15150 
15151 	/* Scream handling. */
15152 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
15153 		if (marineStatusPointer->incidentFlag) {
15154 			if (Marine_HasHisMouthOpen(sbPtr)) {
15155 				if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
15156 					Marine_AngryScream(sbPtr);
15157 				}
15158 			}
15159 		}
15160 	}
15161 
15162 	if (marineStatusPointer->Target==NULL) {
15163 		if (marineStatusPointer->incidentFlag) {
15164 			/* Courage roll to stop. */
15165 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)==0) {
15166 				/* Okay, calm down a bit. */
15167 				if(marineStatusPointer->myGunFlash)
15168 				{
15169 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15170 					marineStatusPointer->myGunFlash = NULL;
15171 				}
15172 
15173 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15174 					Sound_Stop(marineStatusPointer->soundHandle);
15175 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15176 				}
15177 				/* Try to be suspicious? */
15178 				marineStatusPointer->suspicious=MARINE_PANIC_TIME;
15179 				marineStatusPointer->suspect_point=marineStatusPointer->weaponTarget;
15180 				/* Set this to zero when you get a *new* suspicion. */
15181 				marineStatusPointer->previous_suspicion=0;
15182 				marineStatusPointer->using_squad_suspicion=0;
15183 
15184 				return(SRC_Request_Wait);
15185 			}
15186 		}
15187 	} else {
15188 		GLOBALASSERT(marineStatusPointer->Target);
15189 
15190 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
15191 
15192 		/* orientate to firing point first */
15193 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
15194 		orientationDirn.vy = 0;
15195 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
15196 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
15197 		if (correctlyOrientated) {
15198 			if (MarineCanSeeTarget(sbPtr)) {
15199 				/* Lost target... */
15200 				marineStatusPointer->Target=NULL;
15201 			}
15202 		}
15203 	}
15204 
15205 	if (NpcSquad.Squad_Suspicion==0) {
15206 		if (marineStatusPointer->Target) {
15207 			/* Here we must have a target.  Renew suspicion for new arrivals. */
15208 			PointAlert(2,&marineStatusPointer->weaponTarget);
15209 		} else {
15210 			PointAlert(1,&sbPtr->DynPtr->Position);
15211 		}
15212 	}
15213 
15214 	/* Wait for end of tweening before we proceed. */
15215 	if (marineStatusPointer->HModelController.Tweening!=Controller_NoTweening) {
15216 		#if 1
15217 		/* stop visual and audio cues: technically, we're not firing at this moment */
15218 		if(marineStatusPointer->myGunFlash)
15219 		{
15220 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15221 			marineStatusPointer->myGunFlash = NULL;
15222 		}
15223 		#endif
15224 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15225 			Sound_Stop(marineStatusPointer->soundHandle);
15226 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15227 		}
15228 		return(SRC_No_Change);
15229 	}
15230 
15231 	/* Right.  Correctly orientated or not, we blaze away. */
15232 
15233 	/* look after the gun flash */
15234 	if(marineStatusPointer->myGunFlash) {
15235 		MaintainMarineGunFlash(sbPtr);
15236 	} else {
15237 		CreateMarineGunFlash(sbPtr);
15238 	}
15239 
15240 	/* look after the sound */
15241 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
15242 	else
15243 	{
15244 		Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
15245 		Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
15246 	}
15247 
15248 	marineStatusPointer->stateTimer -= NormalFrameTime;
15249 
15250 	/* Volleysize is now rounds fired this state. */
15251 
15252 	volleytime=marineStatusPointer->My_Weapon->FiringTime-marineStatusPointer->stateTimer;
15253 	/* It was that or reverse the state timer for this state. */
15254 	volleyrounds=MUL_FIXED(volleytime,marineStatusPointer->My_Weapon->FiringRate);
15255 	volleyrounds>>=ONE_FIXED_SHIFT;
15256 
15257 	volleyrounds-=marineStatusPointer->volleySize;
15258 	marineStatusPointer->volleySize+=volleyrounds;
15259 
15260 	LOCALASSERT(volleyrounds>=0);
15261 
15262 	if (marineStatusPointer->clipammo!=-1) {
15263 		/* We're counting ammo. */
15264 		if (volleyrounds>marineStatusPointer->clipammo) {
15265 			volleyrounds=marineStatusPointer->clipammo;
15266 		}
15267 		marineStatusPointer->clipammo-=volleyrounds;
15268 		LOCALASSERT(marineStatusPointer->clipammo>=0);
15269 	}
15270 
15271 	/* Now fire volleyrounds bullets. */
15272 	if (volleyrounds>0) {
15273 		VECTORCH shotvector;
15274 
15275 		shotvector.vx=0;
15276 		shotvector.vy=0;
15277 		shotvector.vz=65535;
15278 		RotateVector(&shotvector,&marineStatusPointer->My_Gunflash_Section->SecMat);
15279 
15280 		CastLOSProjectile(sbPtr,&marineStatusPointer->My_Gunflash_Section->World_Offset,&shotvector, marineStatusPointer->My_Weapon->Ammo_Type, volleyrounds,1);
15281 
15282 	}
15283 
15284 	/* Now, consider termination. */
15285 
15286 	if (marineStatusPointer->incidentFlag) {
15287 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
15288 			/* Two consecutive tests... */
15289 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
15290 
15291 				/* stop visual and audio cues: technically, we're not firing at this moment */
15292 				if(marineStatusPointer->myGunFlash)
15293 				{
15294 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15295 					marineStatusPointer->myGunFlash = NULL;
15296 				}
15297 
15298 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15299 					Sound_Stop(marineStatusPointer->soundHandle);
15300 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15301 				}
15302 				return(SRC_Request_Retreat);
15303 			}
15304 		}
15305 	}
15306 
15307 	return(SRC_No_Change);
15308 
15309 }
15310 
15311 static STATE_RETURN_CONDITION Execute_MNS_PanicFireFlamethrower(STRATEGYBLOCK *sbPtr)
15312 {
15313 	MARINE_STATUS_BLOCK *marineStatusPointer;
15314 	VECTORCH orientationDirn;
15315 	int correctlyOrientated;
15316 
15317 	LOCALASSERT(sbPtr);
15318 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
15319 	LOCALASSERT(marineStatusPointer);
15320 
15321 	marineStatusPointer->HModelController.Playing=1;
15322 
15323 	/* zero velocity */
15324 	LOCALASSERT(sbPtr->DynPtr);
15325 	sbPtr->DynPtr->LinVelocity.vx = 0;
15326 	sbPtr->DynPtr->LinVelocity.vy = 0;
15327 	sbPtr->DynPtr->LinVelocity.vz = 0;
15328 
15329 	#if MARINE_STATE_PRINT
15330 	textprint("Marine panic firing... ");
15331 	#endif
15332 
15333 	/* Stabilise sequence. */
15334 	if (marineStatusPointer->Target==NULL) {
15335 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15336 			||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
15337 
15338 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
15339 		}
15340 	} else {
15341 		int offsetx,offsety,offsetz,offseta,angle1;
15342 		VECTORCH *gunpos;
15343 		int sequence=0;
15344 		/* Pick a sequence based on angle. */
15345 
15346 		if (marineStatusPointer->My_Elevation_Section) {
15347 			gunpos=&marineStatusPointer->My_Elevation_Section->World_Offset;
15348 		} else {
15349 			gunpos=&sbPtr->DynPtr->Position;
15350 		}
15351 		/* Aim at Target. */
15352 
15353 		offsetx=(marineStatusPointer->Target->DynPtr->Position.vx)-(gunpos->vx);
15354 		offsety=(marineStatusPointer->Target->DynPtr->Position.vz)-(gunpos->vz);
15355 		offseta=-((marineStatusPointer->Target->DynPtr->Position.vy)-(gunpos->vy));
15356 
15357 		while( (offsetx>(ONE_FIXED>>2))
15358 			||(offsety>(ONE_FIXED>>2))
15359 			||(offseta>(ONE_FIXED>>2))
15360 			||(offsetx<-(ONE_FIXED>>2))
15361 			||(offsety<-(ONE_FIXED>>2))
15362 			||(offseta<-(ONE_FIXED>>2))) {
15363 
15364 			offsetx>>=1;
15365 			offsety>>=1;
15366 			offseta>>=1;
15367 
15368 		}
15369 
15370 		offsetz=SqRoot32((offsetx*offsetx)+(offsety*offsety));
15371 		angle1=ArcTan(offseta,offsetz);
15372 
15373 		if (angle1>=3072) angle1-=4096;
15374 		if (angle1>=2048) angle1=angle1-3072;
15375 		if (angle1>1024) angle1=2048-angle1;
15376 
15377 		GLOBALASSERT(angle1>=-1024);
15378 		GLOBALASSERT(angle1<=1024);
15379 
15380 		sequence=0;
15381 		/* Now correct for hysteresis... */
15382 		{
15383 			int highthreshold,topthreshold;
15384 
15385 			if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_90) {
15386 				highthreshold=90;
15387 				topthreshold=(1024-300);
15388 			} else if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_45) {
15389 				highthreshold=90;
15390 				topthreshold=(1024-256);
15391 			} else {
15392 				highthreshold=128;
15393 				topthreshold=(1024-256);
15394 			}
15395 
15396 			if (angle1>topthreshold) {
15397 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90)) {
15398 					sequence=2;
15399 				} else {
15400 					sequence=0;
15401 				}
15402 			} else if (angle1>highthreshold) { //Was 256!
15403 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45)) {
15404 					sequence=1;
15405 				} else {
15406 					sequence=0;
15407 				}
15408 			} else {
15409 				sequence=0;
15410 			}
15411 		}
15412 
15413 		switch (sequence) {
15414 			case 2:
15415 				/* Escape for civvie flamethrower here? */
15416 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15417 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_90)) {
15418 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_90,-1,(ONE_FIXED>>3));
15419 				}
15420 				break;
15421 			case 1:
15422 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15423 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_45)) {
15424 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_45,-1,(ONE_FIXED>>3));
15425 				}
15426 				break;
15427 			case 0:
15428 			default:
15429 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15430 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
15431 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
15432 				}
15433 				break;
15434 		}
15435 	}
15436 
15437 	if (marineStatusPointer->Target==NULL) {
15438 		if (marineStatusPointer->incidentFlag) {
15439 			/* Courage roll to stop. */
15440 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)==0) {
15441 				/* Okay, calm down a bit. */
15442 				if(marineStatusPointer->myGunFlash)
15443 				{
15444 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15445 					marineStatusPointer->myGunFlash = NULL;
15446 				}
15447 
15448 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15449 					Sound_Stop(marineStatusPointer->soundHandle);
15450 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15451 				}
15452 				/* Try to be suspicious? */
15453 				marineStatusPointer->suspicious=MARINE_PANIC_TIME;
15454 				marineStatusPointer->suspect_point=marineStatusPointer->weaponTarget;
15455 				/* Set this to zero when you get a *new* suspicion. */
15456 				marineStatusPointer->previous_suspicion=0;
15457 				marineStatusPointer->using_squad_suspicion=0;
15458 
15459 				return(SRC_Request_Wait);
15460 			}
15461 		}
15462 	} else {
15463 		GLOBALASSERT(marineStatusPointer->Target);
15464 
15465 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
15466 
15467 		/* orientate to firing point first */
15468 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
15469 		orientationDirn.vy = 0;
15470 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
15471 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
15472 
15473 		if (correctlyOrientated) {
15474 			if (MarineCanSeeTarget(sbPtr)) {
15475 				/* Lost target... */
15476 				marineStatusPointer->Target=NULL;
15477 			}
15478 		}
15479 	}
15480 
15481 	if (marineStatusPointer->clipammo==0) {
15482 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
15483 			if (marineStatusPointer->My_Weapon->ARealMarine) {
15484 				return(SRC_Request_PullPistol);
15485 			} else {
15486 				return(SRC_Request_PanicReload);
15487 			}
15488 		} else {
15489 			return(SRC_Request_PanicReload);
15490 		}
15491 	}
15492 
15493 	/* Scream handling. */
15494 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
15495 		if (marineStatusPointer->incidentFlag) {
15496 			if (Marine_HasHisMouthOpen(sbPtr)) {
15497 				if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
15498 					Marine_AngryScream(sbPtr);
15499 				}
15500 			}
15501 		}
15502 	}
15503 
15504 	if (NpcSquad.Squad_Suspicion==0) {
15505 		if (marineStatusPointer->Target) {
15506 			/* Here we must have a target.  Renew suspicion for new arrivals. */
15507 			PointAlert(2,&marineStatusPointer->weaponTarget);
15508 		} else {
15509 			PointAlert(1,&sbPtr->DynPtr->Position);
15510 		}
15511 	}
15512 
15513 	/* Wait for end of tweening before we proceed. */
15514 	if (marineStatusPointer->HModelController.Tweening!=Controller_NoTweening) {
15515 		#if 1
15516 		/* stop visual and audio cues: technically, we're not firing at this moment */
15517 		if(marineStatusPointer->myGunFlash)
15518 		{
15519 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15520 			marineStatusPointer->myGunFlash = NULL;
15521 		}
15522 		#endif
15523 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15524 			Sound_Stop(marineStatusPointer->soundHandle);
15525 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15526 		}
15527 		return(SRC_No_Change);
15528 	}
15529 
15530 	/* Right.  Correctly orientated or not, we blaze away. */
15531 
15532 	/* look after the gun flash */
15533 	if(marineStatusPointer->myGunFlash) {
15534 		/* No gunflash, neither. */
15535 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15536 	}
15537 
15538 	/* look after the sound */
15539 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
15540 	else
15541 	{
15542 		Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
15543 		Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
15544 	}
15545 
15546 	marineStatusPointer->stateTimer -= NormalFrameTime;
15547 
15548 	MarineFireFlameThrower(sbPtr);
15549 
15550 	/* Lighting? */
15551 	if (sbPtr->SBdptr) {
15552 		AddLightingEffectToObject(sbPtr->SBdptr,LFX_MUZZLEFLASH);
15553 	}
15554 
15555 	if (marineStatusPointer->clipammo>0) {
15556 		marineStatusPointer->clipammo-=NormalFrameTime;
15557 		if (marineStatusPointer->clipammo<0) {
15558 			marineStatusPointer->clipammo=0;
15559 		}
15560 	}
15561 
15562 	/* Now, consider termination. */
15563 
15564 	if (marineStatusPointer->incidentFlag) {
15565 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
15566 			/* Two consecutive tests... */
15567 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
15568 
15569 				/* stop visual and audio cues: technically, we're not firing at this moment */
15570 				if(marineStatusPointer->myGunFlash)
15571 				{
15572 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15573 					marineStatusPointer->myGunFlash = NULL;
15574 				}
15575 
15576 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15577 					Sound_Stop(marineStatusPointer->soundHandle);
15578 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15579 				}
15580 				return(SRC_Request_Retreat);
15581 			}
15582 		}
15583 	}
15584 
15585 	return(SRC_No_Change);
15586 
15587 }
15588 
15589 void Marine_SwitchExpression(STRATEGYBLOCK *sbPtr,int state) {
15590 
15591 	MARINE_STATUS_BLOCK *marineStatusPointer;
15592 	SECTION_DATA *head;
15593 	TXACTRLBLK *tacb;
15594 
15595 	LOCALASSERT(sbPtr);
15596 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
15597 	LOCALASSERT(marineStatusPointer);
15598 
15599 	head=GetThisSectionData(marineStatusPointer->HModelController.section_data,"head");
15600 
15601 	marineStatusPointer->Expression=state;
15602 	marineStatusPointer->Blink=-1;
15603 
15604 	if (head) {
15605 		if ((head->flags&section_data_notreal)==0) {
15606 
15607 			tacb=head->tac_ptr;
15608 
15609 			while (tacb) {
15610 				tacb->tac_sequence = state ;
15611 				tacb->tac_txah_s = GetTxAnimHeaderFromShape(tacb, head->ShapeNum);
15612 
15613 				tacb=tacb->tac_next;
15614 			}
15615 		}
15616 	}
15617 }
15618 
15619 static STATE_RETURN_CONDITION Execute_MNS_PanicFireGL(STRATEGYBLOCK *sbPtr)
15620 {
15621 	MARINE_STATUS_BLOCK *marineStatusPointer;
15622 	VECTORCH orientationDirn;
15623 	int correctlyOrientated;
15624 	int keyframeflags,a;
15625 
15626 	LOCALASSERT(sbPtr);
15627 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
15628 	LOCALASSERT(marineStatusPointer);
15629 
15630 	/* zero velocity */
15631 	LOCALASSERT(sbPtr->DynPtr);
15632 	sbPtr->DynPtr->LinVelocity.vx = 0;
15633 	sbPtr->DynPtr->LinVelocity.vy = 0;
15634 	sbPtr->DynPtr->LinVelocity.vz = 0;
15635 
15636 	marineStatusPointer->HModelController.Playing=1;
15637 
15638 	#if MARINE_STATE_PRINT
15639 	textprint("Marine panic firing... ");
15640 	#endif
15641 
15642 	/* Stabilise sequence. */
15643 	if (marineStatusPointer->Target==NULL) {
15644 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15645 			||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
15646 
15647 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
15648 		}
15649 	} else {
15650 		int offsetx,offsety,offsetz,offseta,angle1;
15651 		VECTORCH *gunpos;
15652 		int sequence=0;
15653 		/* Pick a sequence based on angle. */
15654 
15655 		if (marineStatusPointer->My_Elevation_Section) {
15656 			gunpos=&marineStatusPointer->My_Elevation_Section->World_Offset;
15657 		} else {
15658 			gunpos=&sbPtr->DynPtr->Position;
15659 		}
15660 		/* Aim at Target. */
15661 
15662 		offsetx=(marineStatusPointer->Target->DynPtr->Position.vx)-(gunpos->vx);
15663 		offsety=(marineStatusPointer->Target->DynPtr->Position.vz)-(gunpos->vz);
15664 		offseta=-((marineStatusPointer->Target->DynPtr->Position.vy)-(gunpos->vy));
15665 
15666 		while( (offsetx>(ONE_FIXED>>2))
15667 			||(offsety>(ONE_FIXED>>2))
15668 			||(offseta>(ONE_FIXED>>2))
15669 			||(offsetx<-(ONE_FIXED>>2))
15670 			||(offsety<-(ONE_FIXED>>2))
15671 			||(offseta<-(ONE_FIXED>>2))) {
15672 
15673 			offsetx>>=1;
15674 			offsety>>=1;
15675 			offseta>>=1;
15676 
15677 		}
15678 
15679 		offsetz=SqRoot32((offsetx*offsetx)+(offsety*offsety));
15680 		angle1=ArcTan(offseta,offsetz);
15681 
15682 		if (angle1>=3072) angle1-=4096;
15683 		if (angle1>=2048) angle1=angle1-3072;
15684 		if (angle1>1024) angle1=2048-angle1;
15685 
15686 		GLOBALASSERT(angle1>=-1024);
15687 		GLOBALASSERT(angle1<=1024);
15688 
15689 		sequence=0;
15690 		/* Now correct for hysteresis... */
15691 		{
15692 			int highthreshold,topthreshold;
15693 
15694 			if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_90) {
15695 				highthreshold=90;
15696 				topthreshold=(1024-300);
15697 			} else if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_45) {
15698 				highthreshold=90;
15699 				topthreshold=(1024-256);
15700 			} else {
15701 				highthreshold=128;
15702 				topthreshold=(1024-256);
15703 			}
15704 
15705 			if (angle1>topthreshold) {
15706 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90)) {
15707 					sequence=2;
15708 				} else {
15709 					sequence=0;
15710 				}
15711 			} else if (angle1>highthreshold) { //Was 256!
15712 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45)) {
15713 					sequence=1;
15714 				} else {
15715 					sequence=0;
15716 				}
15717 			} else {
15718 				sequence=0;
15719 			}
15720 		}
15721 
15722 		switch (sequence) {
15723 			case 2:
15724 				/* Escape for civvie flamethrower here? */
15725 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15726 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_90)) {
15727 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_90,-1,(ONE_FIXED>>3));
15728 				}
15729 				break;
15730 			case 1:
15731 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15732 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_45)) {
15733 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_45,-1,(ONE_FIXED>>3));
15734 				}
15735 				break;
15736 			case 0:
15737 			default:
15738 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15739 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
15740 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
15741 				}
15742 				break;
15743 		}
15744 	}
15745 
15746 	if (marineStatusPointer->Target==NULL) {
15747 		if (marineStatusPointer->incidentFlag) {
15748 			/* Courage roll to stop. */
15749 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)==0) {
15750 				/* Okay, calm down a bit. */
15751 				if(marineStatusPointer->myGunFlash)
15752 				{
15753 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15754 					marineStatusPointer->myGunFlash = NULL;
15755 				}
15756 
15757 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15758 					Sound_Stop(marineStatusPointer->soundHandle);
15759 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15760 				}
15761 				/* Try to be suspicious? */
15762 				marineStatusPointer->suspicious=MARINE_PANIC_TIME;
15763 				marineStatusPointer->suspect_point=marineStatusPointer->weaponTarget;
15764 				/* Set this to zero when you get a *new* suspicion. */
15765 				marineStatusPointer->previous_suspicion=0;
15766 				marineStatusPointer->using_squad_suspicion=0;
15767 
15768 				return(SRC_Request_Wait);
15769 			}
15770 		}
15771 	} else {
15772 		GLOBALASSERT(marineStatusPointer->Target);
15773 
15774 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
15775 
15776 		/* orientate to firing point first */
15777 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
15778 		orientationDirn.vy = 0;
15779 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
15780 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
15781 
15782 		if (correctlyOrientated) {
15783 			if (MarineCanSeeTarget(sbPtr)) {
15784 				/* Lost target... */
15785 				marineStatusPointer->Target=NULL;
15786 			}
15787 		}
15788 	}
15789 
15790 	if (marineStatusPointer->clipammo==0) {
15791 		/* Reload here. */
15792 		return(SRC_Request_PanicReload);
15793 	}
15794 
15795 	/* Scream handling. */
15796 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
15797 		if (marineStatusPointer->incidentFlag) {
15798 			if (Marine_HasHisMouthOpen(sbPtr)) {
15799 				if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
15800 					Marine_AngryScream(sbPtr);
15801 				}
15802 			}
15803 		}
15804 	}
15805 
15806 	if (NpcSquad.Squad_Suspicion==0) {
15807 		if (marineStatusPointer->Target) {
15808 			/* Here we must have a target.  Renew suspicion for new arrivals. */
15809 			PointAlert(2,&marineStatusPointer->weaponTarget);
15810 		} else {
15811 			PointAlert(1,&sbPtr->DynPtr->Position);
15812 		}
15813 	}
15814 
15815 	/* Wait for end of tweening before we proceed. */
15816 	if (marineStatusPointer->HModelController.Tweening!=Controller_NoTweening) {
15817 		#if 1
15818 		/* stop visual and audio cues: technically, we're not firing at this moment */
15819 		if(marineStatusPointer->myGunFlash)
15820 		{
15821 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15822 			marineStatusPointer->myGunFlash = NULL;
15823 		}
15824 		#endif
15825 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15826 			Sound_Stop(marineStatusPointer->soundHandle);
15827 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15828 		}
15829 		return(SRC_No_Change);
15830 	}
15831 
15832 	/* Stop cues anyway? */
15833 	if(marineStatusPointer->myGunFlash) {
15834 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15835 		marineStatusPointer->myGunFlash = NULL;
15836 	}
15837 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15838 		Sound_Stop(marineStatusPointer->soundHandle);
15839 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15840 	}
15841 
15842 	if (marineStatusPointer->Target) {
15843 		int range;
15844 
15845 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
15846 
15847 		/* Are they, by some chance, really close? */
15848 		if (range<marineStatusPointer->My_Weapon->MinRange) {
15849 			if (!(MarineRetreatsInTheFaceOfDanger(sbPtr))) {
15850 				/* Stay cool. */
15851 				return(SRC_Request_PullPistol);
15852 			}
15853 			/* Probably can't flee... :-) */
15854 		}
15855 	}
15856 
15857 	/* Right.  Correctly orientated or not, we blaze away. */
15858 
15859 	keyframeflags=marineStatusPointer->HModelController.keyframe_flags>>1;
15860 
15861 	/* I know there are only four firing points... */
15862 	for (a=0; a<4; a++) {
15863 		if (keyframeflags&1) {
15864 			/* Fire a grenade! */
15865 
15866 			/* look after the gun flash */
15867 			if(marineStatusPointer->myGunFlash) MaintainMarineGunFlash(sbPtr);
15868 			else CreateMarineGunFlash(sbPtr);
15869 
15870 			/* look after the sound */
15871 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
15872 			else {
15873 				Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
15874 				Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
15875 			}
15876 
15877 			LOCALASSERT(marineStatusPointer->My_Gunflash_Section);
15878 			CreateGrenadeKernel(I_BehaviourGrenade, &marineStatusPointer->My_Gunflash_Section->World_Offset, &marineStatusPointer->My_Gunflash_Section->SecMat,0);
15879 			if (marineStatusPointer->clipammo>0) {
15880 				marineStatusPointer->clipammo--;
15881 			}
15882 		}
15883 		keyframeflags>>=1;
15884 	}
15885 	/* ...and they are all identical. */
15886 
15887 	/* Now, consider termination. */
15888 
15889 	if (marineStatusPointer->incidentFlag) {
15890 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
15891 			/* Two consecutive tests... */
15892 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
15893 
15894 				/* stop visual and audio cues: technically, we're not firing at this moment */
15895 				if(marineStatusPointer->myGunFlash)
15896 				{
15897 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
15898 					marineStatusPointer->myGunFlash = NULL;
15899 				}
15900 
15901 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
15902 					Sound_Stop(marineStatusPointer->soundHandle);
15903 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
15904 				}
15905 				return(SRC_Request_Retreat);
15906 			}
15907 		}
15908 	}
15909 
15910 	return(SRC_No_Change);
15911 
15912 }
15913 
15914 static STATE_RETURN_CONDITION Execute_MNS_PanicFireMinigun(STRATEGYBLOCK *sbPtr)
15915 {
15916 	MARINE_STATUS_BLOCK *marineStatusPointer;
15917 	VECTORCH orientationDirn;
15918 	int correctlyOrientated;
15919 
15920 	LOCALASSERT(sbPtr);
15921 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
15922 	LOCALASSERT(marineStatusPointer);
15923 
15924 	marineStatusPointer->HModelController.Playing=1;
15925 
15926 	#if MARINE_STATE_PRINT
15927 	textprint("Marine panic firing... ");
15928 	#endif
15929 
15930 	/* zero velocity */
15931 	LOCALASSERT(sbPtr->DynPtr);
15932 	sbPtr->DynPtr->LinVelocity.vx = 0;
15933 	sbPtr->DynPtr->LinVelocity.vy = 0;
15934 	sbPtr->DynPtr->LinVelocity.vz = 0;
15935 
15936 	/* Stabilise sequence. */
15937 	if (marineStatusPointer->Target==NULL) {
15938 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
15939 			||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
15940 
15941 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
15942 		}
15943 	} else {
15944 		int offsetx,offsety,offsetz,offseta,angle1;
15945 		VECTORCH *gunpos;
15946 		int sequence=0;
15947 		/* Pick a sequence based on angle. */
15948 
15949 		if (marineStatusPointer->My_Elevation_Section) {
15950 			gunpos=&marineStatusPointer->My_Elevation_Section->World_Offset;
15951 		} else {
15952 			gunpos=&sbPtr->DynPtr->Position;
15953 		}
15954 		/* Aim at Target. */
15955 
15956 		offsetx=(marineStatusPointer->Target->DynPtr->Position.vx)-(gunpos->vx);
15957 		offsety=(marineStatusPointer->Target->DynPtr->Position.vz)-(gunpos->vz);
15958 		offseta=-((marineStatusPointer->Target->DynPtr->Position.vy)-(gunpos->vy));
15959 
15960 		while( (offsetx>(ONE_FIXED>>2))
15961 			||(offsety>(ONE_FIXED>>2))
15962 			||(offseta>(ONE_FIXED>>2))
15963 			||(offsetx<-(ONE_FIXED>>2))
15964 			||(offsety<-(ONE_FIXED>>2))
15965 			||(offseta<-(ONE_FIXED>>2))) {
15966 
15967 			offsetx>>=1;
15968 			offsety>>=1;
15969 			offseta>>=1;
15970 
15971 		}
15972 
15973 		offsetz=SqRoot32((offsetx*offsetx)+(offsety*offsety));
15974 		angle1=ArcTan(offseta,offsetz);
15975 
15976 		if (angle1>=3072) angle1-=4096;
15977 		if (angle1>=2048) angle1=angle1-3072;
15978 		if (angle1>1024) angle1=2048-angle1;
15979 
15980 		GLOBALASSERT(angle1>=-1024);
15981 		GLOBALASSERT(angle1<=1024);
15982 
15983 		sequence=0;
15984 		/* Now correct for hysteresis... */
15985 		{
15986 			int highthreshold,topthreshold;
15987 
15988 			if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_90) {
15989 				highthreshold=90;
15990 				topthreshold=(1024-300);
15991 			} else if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_45) {
15992 				highthreshold=90;
15993 				topthreshold=(1024-256);
15994 			} else {
15995 				highthreshold=128;
15996 				topthreshold=(1024-256);
15997 			}
15998 
15999 			if (angle1>topthreshold) {
16000 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90)) {
16001 					sequence=2;
16002 				} else {
16003 					sequence=0;
16004 				}
16005 			} else if (angle1>highthreshold) { //Was 256!
16006 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45)) {
16007 					sequence=1;
16008 				} else {
16009 					sequence=0;
16010 				}
16011 			} else {
16012 				sequence=0;
16013 			}
16014 		}
16015 
16016 		switch (sequence) {
16017 			case 2:
16018 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16019 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_90)) {
16020 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_90,-1,(ONE_FIXED>>3));
16021 				}
16022 				break;
16023 			case 1:
16024 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16025 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_45)) {
16026 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_45,-1,(ONE_FIXED>>3));
16027 				}
16028 				break;
16029 			case 0:
16030 			default:
16031 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16032 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
16033 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
16034 				}
16035 				break;
16036 		}
16037 	}
16038 
16039 	if (marineStatusPointer->clipammo==0) {
16040 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16041 			return(SRC_Request_PullPistol);
16042 		} else {
16043 			return(SRC_Request_PanicReload);
16044 		}
16045 	}
16046 
16047 	/* Scream handling. */
16048 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
16049 		if (marineStatusPointer->incidentFlag) {
16050 			if (Marine_HasHisMouthOpen(sbPtr)) {
16051 				if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
16052 					Marine_AngryScream(sbPtr);
16053 				}
16054 			}
16055 		}
16056 	}
16057 
16058 	if ((marineStatusPointer->Target==NULL)&&(marineStatusPointer->volleySize>=marineStatusPointer->My_Weapon->MinimumBurstSize)) {
16059 		if (marineStatusPointer->incidentFlag) {
16060 			/* Courage roll to stop. */
16061 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)==0) {
16062 				/* Okay, calm down a bit. */
16063 				if(marineStatusPointer->myGunFlash)
16064 				{
16065 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16066 					marineStatusPointer->myGunFlash = NULL;
16067 				}
16068 
16069 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16070 					Sound_Stop(marineStatusPointer->soundHandle);
16071 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16072 				}
16073 				/* Try to be suspicious? */
16074 				marineStatusPointer->suspicious=MARINE_PANIC_TIME;
16075 				marineStatusPointer->suspect_point=marineStatusPointer->weaponTarget;
16076 				/* Set this to zero when you get a *new* suspicion. */
16077 				marineStatusPointer->previous_suspicion=0;
16078 				marineStatusPointer->using_squad_suspicion=0;
16079 
16080 				return(SRC_Request_Wait);
16081 			}
16082 		}
16083 	} else {
16084 		if (marineStatusPointer->Target) {
16085 
16086 			NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
16087 
16088 			/* orientate to firing point first */
16089 			orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
16090 			orientationDirn.vy = 0;
16091 			orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
16092 			correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
16093 
16094 			if (correctlyOrientated) {
16095 				if (MarineCanSeeTarget(sbPtr)) {
16096 					/* Lost target... */
16097 					marineStatusPointer->Target=NULL;
16098 				}
16099 			}
16100 		} else {
16101 			/* Who cares! */
16102 			correctlyOrientated=1;
16103 		}
16104 	}
16105 
16106 	if (NpcSquad.Squad_Suspicion==0) {
16107 		if (marineStatusPointer->Target) {
16108 			/* Here we must have a target.  Renew suspicion for new arrivals. */
16109 			PointAlert(2,&marineStatusPointer->weaponTarget);
16110 		} else {
16111 			PointAlert(1,&sbPtr->DynPtr->Position);
16112 		}
16113 	}
16114 
16115 	/* Wait for end of tweening before we proceed. */
16116 	if (marineStatusPointer->HModelController.Tweening!=Controller_NoTweening) {
16117 		#if 1
16118 		/* stop visual and audio cues: technically, we're not firing at this moment */
16119 		if(marineStatusPointer->myGunFlash)
16120 		{
16121 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16122 			marineStatusPointer->myGunFlash = NULL;
16123 		}
16124 		#endif
16125 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16126 			Sound_Stop(marineStatusPointer->soundHandle);
16127 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16128 		}
16129 		return(SRC_No_Change);
16130 	}
16131 
16132 	/* Right.  Correctly orientated or not, we blaze away. */
16133 
16134 	NPCFireMinigun_Core(sbPtr);
16135 
16136 	/* Now, consider termination. */
16137 
16138 	if (marineStatusPointer->volleySize<MINIGUN_MINIMUM_BURST) {
16139 		/* Can't terminate yet. */
16140 		return(SRC_No_Change);
16141 	}
16142 
16143 	if (marineStatusPointer->incidentFlag) {
16144 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16145 			/* Two consecutive tests... */
16146 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16147 
16148 				/* stop visual and audio cues: technically, we're not firing at this moment */
16149 				if(marineStatusPointer->myGunFlash)
16150 				{
16151 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16152 					marineStatusPointer->myGunFlash = NULL;
16153 				}
16154 
16155 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16156 					Sound_Stop(marineStatusPointer->soundHandle);
16157 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16158 				}
16159 				return(SRC_Request_Retreat);
16160 			}
16161 		}
16162 	}
16163 
16164 	return(SRC_No_Change);
16165 
16166 }
16167 
16168 static STATE_RETURN_CONDITION Execute_MNS_PanicFirePistol(STRATEGYBLOCK *sbPtr)
16169 {
16170 	MARINE_STATUS_BLOCK *marineStatusPointer;
16171 	VECTORCH orientationDirn;
16172 	int correctlyOrientated;
16173 	int a,keyframeflags;
16174 
16175 	LOCALASSERT(sbPtr);
16176 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
16177 	LOCALASSERT(marineStatusPointer);
16178 
16179 	marineStatusPointer->HModelController.Playing=1;
16180 
16181 	#if MARINE_STATE_PRINT
16182 	textprint("Marine panic firing... ");
16183 	#endif
16184 
16185 	/* zero velocity */
16186 	LOCALASSERT(sbPtr->DynPtr);
16187 	sbPtr->DynPtr->LinVelocity.vx = 0;
16188 	sbPtr->DynPtr->LinVelocity.vy = 0;
16189 	sbPtr->DynPtr->LinVelocity.vz = 0;
16190 
16191 	/* Stabilise sequence. */
16192 	if (marineStatusPointer->Target==NULL) {
16193 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16194 			||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
16195 
16196 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
16197 		}
16198 	} else {
16199 		int offsetx,offsety,offsetz,offseta,angle1;
16200 		VECTORCH *gunpos;
16201 		int sequence=0;
16202 		/* Pick a sequence based on angle. */
16203 
16204 		if (marineStatusPointer->My_Elevation_Section) {
16205 			gunpos=&marineStatusPointer->My_Elevation_Section->World_Offset;
16206 		} else {
16207 			gunpos=&sbPtr->DynPtr->Position;
16208 		}
16209 		/* Aim at Target. */
16210 
16211 		offsetx=(marineStatusPointer->Target->DynPtr->Position.vx)-(gunpos->vx);
16212 		offsety=(marineStatusPointer->Target->DynPtr->Position.vz)-(gunpos->vz);
16213 		offseta=-((marineStatusPointer->Target->DynPtr->Position.vy)-(gunpos->vy));
16214 
16215 		while( (offsetx>(ONE_FIXED>>2))
16216 			||(offsety>(ONE_FIXED>>2))
16217 			||(offseta>(ONE_FIXED>>2))
16218 			||(offsetx<-(ONE_FIXED>>2))
16219 			||(offsety<-(ONE_FIXED>>2))
16220 			||(offseta<-(ONE_FIXED>>2))) {
16221 
16222 			offsetx>>=1;
16223 			offsety>>=1;
16224 			offseta>>=1;
16225 
16226 		}
16227 
16228 		offsetz=SqRoot32((offsetx*offsetx)+(offsety*offsety));
16229 		angle1=ArcTan(offseta,offsetz);
16230 
16231 		if (angle1>=3072) angle1-=4096;
16232 		if (angle1>=2048) angle1=angle1-3072;
16233 		if (angle1>1024) angle1=2048-angle1;
16234 
16235 		GLOBALASSERT(angle1>=-1024);
16236 		GLOBALASSERT(angle1<=1024);
16237 
16238 		sequence=0;
16239 		/* Now correct for hysteresis... */
16240 		{
16241 			int highthreshold,topthreshold;
16242 
16243 			if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_90) {
16244 				highthreshold=90;
16245 				topthreshold=(1024-300);
16246 			} else if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_45) {
16247 				highthreshold=90;
16248 				topthreshold=(1024-256);
16249 			} else {
16250 				highthreshold=128;
16251 				topthreshold=(1024-256);
16252 			}
16253 
16254 			if (angle1>topthreshold) {
16255 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90)) {
16256 					sequence=2;
16257 				} else {
16258 					sequence=0;
16259 				}
16260 			} else if (angle1>highthreshold) { //Was 256!
16261 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45)) {
16262 					sequence=1;
16263 				} else {
16264 					sequence=0;
16265 				}
16266 			} else {
16267 				sequence=0;
16268 			}
16269 		}
16270 
16271 		switch (sequence) {
16272 			case 2:
16273 				/* Escape for civvie flamethrower here? */
16274 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16275 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_90)) {
16276 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_90,-1,(ONE_FIXED>>3));
16277 				}
16278 				break;
16279 			case 1:
16280 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16281 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_45)) {
16282 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_45,-1,(ONE_FIXED>>3));
16283 				}
16284 				break;
16285 			case 0:
16286 			default:
16287 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16288 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
16289 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
16290 				}
16291 				break;
16292 		}
16293 	}
16294 
16295 	if (marineStatusPointer->clipammo==0) {
16296 		return(SRC_Request_PanicReload);
16297 	}
16298 
16299 	/* Scream handling. */
16300 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
16301 		if (marineStatusPointer->incidentFlag) {
16302 			if (Marine_HasHisMouthOpen(sbPtr)) {
16303 				if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
16304 					Marine_AngryScream(sbPtr);
16305 				}
16306 			}
16307 		}
16308 	}
16309 
16310 	if (marineStatusPointer->Target==NULL) {
16311 		if (marineStatusPointer->incidentFlag) {
16312 			/* Courage roll to stop. */
16313 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)==0) {
16314 				/* Okay, calm down a bit. */
16315 				if(marineStatusPointer->myGunFlash)
16316 				{
16317 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16318 					marineStatusPointer->myGunFlash = NULL;
16319 				}
16320 
16321 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16322 					Sound_Stop(marineStatusPointer->soundHandle);
16323 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16324 				}
16325 				/* Try to be suspicious? */
16326 				marineStatusPointer->suspicious=MARINE_PANIC_TIME;
16327 				marineStatusPointer->suspect_point=marineStatusPointer->weaponTarget;
16328 				/* Set this to zero when you get a *new* suspicion. */
16329 				marineStatusPointer->previous_suspicion=0;
16330 				marineStatusPointer->using_squad_suspicion=0;
16331 
16332 				return(SRC_Request_Wait);
16333 			}
16334 		}
16335 	} else {
16336 		GLOBALASSERT(marineStatusPointer->Target);
16337 
16338 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
16339 		/* Fix weapon target! */
16340 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
16341 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
16342 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
16343 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
16344 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
16345 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
16346 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
16347 		}
16348 
16349 		/* orientate to firing point first */
16350 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
16351 		orientationDirn.vy = 0;
16352 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
16353 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
16354 
16355 		if (correctlyOrientated) {
16356 			if (MarineCanSeeTarget(sbPtr)) {
16357 				/* Lost target... */
16358 				marineStatusPointer->Target=NULL;
16359 			}
16360 		}
16361 	}
16362 
16363 	if (NpcSquad.Squad_Suspicion==0) {
16364 		if (marineStatusPointer->Target) {
16365 			/* Here we must have a target.  Renew suspicion for new arrivals. */
16366 			PointAlert(2,&marineStatusPointer->weaponTarget);
16367 		} else {
16368 			PointAlert(1,&sbPtr->DynPtr->Position);
16369 		}
16370 	}
16371 
16372 	/* Wait for end of tweening before we proceed. */
16373 	if (marineStatusPointer->HModelController.Tweening!=Controller_NoTweening) {
16374 		#if 1
16375 		/* stop visual and audio cues: technically, we're not firing at this moment */
16376 		if(marineStatusPointer->myGunFlash)
16377 		{
16378 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16379 			marineStatusPointer->myGunFlash = NULL;
16380 		}
16381 		#endif
16382 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16383 			Sound_Stop(marineStatusPointer->soundHandle);
16384 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16385 		}
16386 		return(SRC_No_Change);
16387 	}
16388 
16389 	/* Stop cues anyway? */
16390 	if(marineStatusPointer->myGunFlash) {
16391 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16392 		marineStatusPointer->myGunFlash = NULL;
16393 	}
16394 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16395 		Sound_Stop(marineStatusPointer->soundHandle);
16396 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16397 	}
16398 
16399 	/* Right.  Correctly orientated or not, we blaze away. */
16400 
16401 	keyframeflags=marineStatusPointer->HModelController.keyframe_flags>>1;
16402 
16403 	/* I know there are only six possible firing points... */
16404 	for (a=0; a<6; a++) {
16405 		if ((keyframeflags&1)||((a==0)&&(marineStatusPointer->HModelController.Tweening==Controller_EndTweening))) {
16406 			/* Fire a shot. */
16407 
16408 			/* look after the gun flash */
16409 			if(marineStatusPointer->myGunFlash) MaintainMarineGunFlash(sbPtr);
16410 			else CreateMarineGunFlash(sbPtr);
16411 
16412 			/* look after the sound */
16413 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
16414 			else {
16415 				Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
16416 				Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
16417 			}
16418 
16419 			{
16420 				VECTORCH shotvector;
16421 
16422 				shotvector.vx=0;
16423 				shotvector.vy=0;
16424 				shotvector.vz=65535;
16425 				RotateVector(&shotvector,&marineStatusPointer->My_Gunflash_Section->SecMat);
16426 
16427 				CastLOSProjectile(sbPtr,&marineStatusPointer->My_Gunflash_Section->World_Offset,&shotvector, marineStatusPointer->My_Weapon->Ammo_Type, 1,1);
16428 				if (marineStatusPointer->clipammo>0) {
16429 					marineStatusPointer->clipammo--;
16430 				}
16431 			}
16432 		}
16433 		keyframeflags>>=1;
16434 	}
16435 	/* ...and they are all identical. */
16436 
16437 	/* Now, consider termination. */
16438 
16439 	if (marineStatusPointer->incidentFlag) {
16440 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16441 			/* Two consecutive tests... */
16442 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16443 
16444 				/* stop visual and audio cues: technically, we're not firing at this moment */
16445 				if(marineStatusPointer->myGunFlash)
16446 				{
16447 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16448 					marineStatusPointer->myGunFlash = NULL;
16449 				}
16450 
16451 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16452 					Sound_Stop(marineStatusPointer->soundHandle);
16453 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16454 				}
16455 				return(SRC_Request_Retreat);
16456 			}
16457 		}
16458 	}
16459 
16460 	return(SRC_No_Change);
16461 
16462 }
16463 
16464 static STATE_RETURN_CONDITION Execute_MNS_PanicFireShotgun(STRATEGYBLOCK *sbPtr)
16465 {
16466 	MARINE_STATUS_BLOCK *marineStatusPointer;
16467 	VECTORCH orientationDirn;
16468 	int correctlyOrientated;
16469 	int keyframeflags,a,b;
16470 
16471 	LOCALASSERT(sbPtr);
16472 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
16473 	LOCALASSERT(marineStatusPointer);
16474 
16475 	marineStatusPointer->HModelController.Playing=1;
16476 
16477 	#if MARINE_STATE_PRINT
16478 	textprint("Marine panic firing... ");
16479 	#endif
16480 
16481 	/* zero velocity */
16482 	LOCALASSERT(sbPtr->DynPtr);
16483 	sbPtr->DynPtr->LinVelocity.vx = 0;
16484 	sbPtr->DynPtr->LinVelocity.vy = 0;
16485 	sbPtr->DynPtr->LinVelocity.vz = 0;
16486 
16487 	/* Stabilise sequence. */
16488 	if (marineStatusPointer->Target==NULL) {
16489 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16490 			||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
16491 
16492 			SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
16493 		}
16494 	} else {
16495 		int offsetx,offsety,offsetz,offseta,angle1;
16496 		VECTORCH *gunpos;
16497 		int sequence=0;
16498 		/* Pick a sequence based on angle. */
16499 
16500 		if (marineStatusPointer->My_Elevation_Section) {
16501 			gunpos=&marineStatusPointer->My_Elevation_Section->World_Offset;
16502 		} else {
16503 			gunpos=&sbPtr->DynPtr->Position;
16504 		}
16505 		/* Aim at Target. */
16506 
16507 		offsetx=(marineStatusPointer->Target->DynPtr->Position.vx)-(gunpos->vx);
16508 		offsety=(marineStatusPointer->Target->DynPtr->Position.vz)-(gunpos->vz);
16509 		offseta=-((marineStatusPointer->Target->DynPtr->Position.vy)-(gunpos->vy));
16510 
16511 		while( (offsetx>(ONE_FIXED>>2))
16512 			||(offsety>(ONE_FIXED>>2))
16513 			||(offseta>(ONE_FIXED>>2))
16514 			||(offsetx<-(ONE_FIXED>>2))
16515 			||(offsety<-(ONE_FIXED>>2))
16516 			||(offseta<-(ONE_FIXED>>2))) {
16517 
16518 			offsetx>>=1;
16519 			offsety>>=1;
16520 			offseta>>=1;
16521 
16522 		}
16523 
16524 		offsetz=SqRoot32((offsetx*offsetx)+(offsety*offsety));
16525 		angle1=ArcTan(offseta,offsetz);
16526 
16527 		if (angle1>=3072) angle1-=4096;
16528 		if (angle1>=2048) angle1=angle1-3072;
16529 		if (angle1>1024) angle1=2048-angle1;
16530 
16531 		GLOBALASSERT(angle1>=-1024);
16532 		GLOBALASSERT(angle1<=1024);
16533 
16534 		sequence=0;
16535 		/* Now correct for hysteresis... */
16536 		{
16537 			int highthreshold,topthreshold;
16538 
16539 			if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_90) {
16540 				highthreshold=90;
16541 				topthreshold=(1024-300);
16542 			} else if (marineStatusPointer->HModelController.Sub_Sequence==MSSS_WildFire_45) {
16543 				highthreshold=90;
16544 				topthreshold=(1024-256);
16545 			} else {
16546 				highthreshold=128;
16547 				topthreshold=(1024-256);
16548 			}
16549 
16550 			if (angle1>topthreshold) {
16551 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90)) {
16552 					sequence=2;
16553 				} else {
16554 					sequence=0;
16555 				}
16556 			} else if (angle1>highthreshold) { //Was 256!
16557 				if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45)) {
16558 					sequence=1;
16559 				} else {
16560 					sequence=0;
16561 				}
16562 			} else {
16563 				sequence=0;
16564 			}
16565 		}
16566 
16567 		switch (sequence) {
16568 			case 2:
16569 				/* Escape for civvie flamethrower here? */
16570 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16571 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_90)) {
16572 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_90,-1,(ONE_FIXED>>3));
16573 				}
16574 				break;
16575 			case 1:
16576 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16577 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_45)) {
16578 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_45,-1,(ONE_FIXED>>3));
16579 				}
16580 				break;
16581 			case 0:
16582 			default:
16583 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16584 					||(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)) {
16585 					SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>3));
16586 				}
16587 				break;
16588 		}
16589 	}
16590 
16591 	if (marineStatusPointer->clipammo==0) {
16592 		return(SRC_Request_PanicReload);
16593 	}
16594 
16595 	/* Scream handling. */
16596 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
16597 		if (marineStatusPointer->incidentFlag) {
16598 			if (Marine_HasHisMouthOpen(sbPtr)) {
16599 				if (marineStatusPointer->My_Weapon->id==MNPCW_MUnarmed) {
16600 					Marine_AngryScream(sbPtr);
16601 				}
16602 			}
16603 		}
16604 	}
16605 
16606 	if (marineStatusPointer->Target==NULL) {
16607 		if (marineStatusPointer->incidentFlag) {
16608 			/* Courage roll to stop. */
16609 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)==0) {
16610 				/* Okay, calm down a bit. */
16611 				if(marineStatusPointer->myGunFlash)
16612 				{
16613 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16614 					marineStatusPointer->myGunFlash = NULL;
16615 				}
16616 
16617 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16618 					Sound_Stop(marineStatusPointer->soundHandle);
16619 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16620 				}
16621 				/* Try to be suspicious? */
16622 				marineStatusPointer->suspicious=MARINE_PANIC_TIME;
16623 				marineStatusPointer->suspect_point=marineStatusPointer->weaponTarget;
16624 				/* Set this to zero when you get a *new* suspicion. */
16625 				marineStatusPointer->previous_suspicion=0;
16626 				marineStatusPointer->using_squad_suspicion=0;
16627 
16628 				return(SRC_Request_Wait);
16629 			}
16630 		}
16631 	} else {
16632 		GLOBALASSERT(marineStatusPointer->Target);
16633 
16634 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
16635 
16636 		/* orientate to firing point first */
16637 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
16638 		orientationDirn.vy = 0;
16639 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
16640 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
16641 
16642 		if (correctlyOrientated) {
16643 			if (MarineCanSeeTarget(sbPtr)) {
16644 				/* Lost target... */
16645 				marineStatusPointer->Target=NULL;
16646 			}
16647 		}
16648 	}
16649 
16650 	if (NpcSquad.Squad_Suspicion==0) {
16651 		if (marineStatusPointer->Target) {
16652 			/* Here we must have a target.  Renew suspicion for new arrivals. */
16653 			PointAlert(2,&marineStatusPointer->weaponTarget);
16654 		} else {
16655 			PointAlert(1,&sbPtr->DynPtr->Position);
16656 		}
16657 	}
16658 
16659 	/* Wait for end of tweening before we proceed. */
16660 	if (marineStatusPointer->HModelController.Tweening!=Controller_NoTweening) {
16661 		#if 1
16662 		/* stop visual and audio cues: technically, we're not firing at this moment */
16663 		if(marineStatusPointer->myGunFlash)
16664 		{
16665 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16666 			marineStatusPointer->myGunFlash = NULL;
16667 		}
16668 		#endif
16669 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16670 			Sound_Stop(marineStatusPointer->soundHandle);
16671 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16672 		}
16673 		return(SRC_No_Change);
16674 	}
16675 
16676 	/* Stop cues anyway? */
16677 	if(marineStatusPointer->myGunFlash) {
16678 		RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16679 		marineStatusPointer->myGunFlash = NULL;
16680 	}
16681 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16682 		Sound_Stop(marineStatusPointer->soundHandle);
16683 		Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16684 	}
16685 
16686 	/* Right.  Correctly orientated or not, we blaze away. */
16687 
16688 	keyframeflags=marineStatusPointer->HModelController.keyframe_flags>>1;
16689 
16690 	/* I know there are only three firing points... */
16691 	for (a=0; a<3; a++) {
16692 		if (keyframeflags&1) {
16693 
16694 			/* look after the gun flash */
16695 			if(marineStatusPointer->myGunFlash) MaintainMarineGunFlash(sbPtr);
16696 			else CreateMarineGunFlash(sbPtr);
16697 
16698 			/* look after the sound */
16699 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
16700 			else {
16701 				Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
16702 				Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
16703 			}
16704 
16705 			/* Now hit the target with a shotgun blast. */
16706 
16707 			b=0;
16708 
16709 			while (ShotgunBlast[b].vz>0) {
16710 				VECTORCH world_vec;
16711 
16712 				RotateAndCopyVector(&ShotgunBlast[b],&world_vec,&marineStatusPointer->My_Gunflash_Section->SecMat);
16713 				CastLOSProjectile(sbPtr,&marineStatusPointer->My_Gunflash_Section->World_Offset,&world_vec, marineStatusPointer->My_Weapon->Ammo_Type, 1,0);
16714 
16715 				b++;
16716 			}
16717 			if (marineStatusPointer->clipammo>0) {
16718 				marineStatusPointer->clipammo--;
16719 			}
16720 		}
16721 		keyframeflags>>=1;
16722 	}
16723 	/* ...and they are all identical. */
16724 
16725 	/* Now, consider termination. */
16726 
16727 	if (marineStatusPointer->incidentFlag) {
16728 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16729 			/* Two consecutive tests... */
16730 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16731 
16732 				/* stop visual and audio cues: technically, we're not firing at this moment */
16733 				if(marineStatusPointer->myGunFlash)
16734 				{
16735 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16736 					marineStatusPointer->myGunFlash = NULL;
16737 				}
16738 
16739 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16740 					Sound_Stop(marineStatusPointer->soundHandle);
16741 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16742 				}
16743 				return(SRC_Request_Retreat);
16744 			}
16745 		}
16746 	}
16747 
16748 	return(SRC_No_Change);
16749 
16750 }
16751 
16752 static void Marine_EnterExtremePanicAnimation(STRATEGYBLOCK *sbPtr) {
16753 
16754 	if ((FastRandom()&65535)<21845) {
16755 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_90,-1,(ONE_FIXED>>1));
16756 	} else if ((FastRandom()&65535)<21845) {
16757 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_45,-1,(ONE_FIXED>>1));
16758 	} else {
16759 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_WildFire_0,-1,(ONE_FIXED>>1));
16760 	}
16761 
16762 }
16763 
16764 static void Marine_EnterLesserPanicAnimation(STRATEGYBLOCK *sbPtr) {
16765 
16766 	if ((FastRandom()&65535)<32767) {
16767 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Panic_One,-1,(ONE_FIXED>>1));
16768 	} else {
16769 		SetMarineAnimationSequence_Null(sbPtr,HMSQT_MarineStand,MSSS_Panic_Two,-1,(ONE_FIXED>>1));
16770 	}
16771 
16772 }
16773 
16774 static STATE_RETURN_CONDITION Execute_MNS_PanicFireUnarmed(STRATEGYBLOCK *sbPtr)
16775 {
16776 	MARINE_STATUS_BLOCK *marineStatusPointer;
16777 	VECTORCH orientationDirn;
16778 
16779 	/* Also known as... gibber in terror. */
16780 
16781 	LOCALASSERT(sbPtr);
16782 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
16783 	LOCALASSERT(marineStatusPointer);
16784 
16785 	marineStatusPointer->HModelController.Playing=1;
16786 
16787 	#if MARINE_STATE_PRINT
16788 	textprint("Marine panic firing... ");
16789 	#endif
16790 
16791 	/* zero velocity */
16792 	LOCALASSERT(sbPtr->DynPtr);
16793 	sbPtr->DynPtr->LinVelocity.vx = 0;
16794 	sbPtr->DynPtr->LinVelocity.vy = 0;
16795 	sbPtr->DynPtr->LinVelocity.vz = 0;
16796 
16797 	/* Firstly, are we trying to retreat? */
16798 	if (marineStatusPointer->internalState==1) {
16799 		/* Wait for tweening to finish... */
16800 		if (marineStatusPointer->HModelController.Tweening==Controller_NoTweening) {
16801 			/* Then the first incidentFlag we get, we're outta here. */
16802 			if (marineStatusPointer->incidentFlag) {
16803 				return(SRC_Request_Retreat);
16804 			}
16805 		}
16806 		return(SRC_No_Change);
16807 	}
16808 
16809 	/* Stabilise sequence. */
16810 	if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16811 		||((marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_0)
16812 			&&(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_45)
16813 			&&(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_WildFire_90))) {
16814 
16815 		/* If we're not in one of the 'extreme panic' animations, are we in one of the others? */
16816 		if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16817 			||((marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Panic_One)
16818 				&&(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Panic_Two))) {
16819 			/* No, we're not.  See which level of panic to go into... */
16820 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16821 				/* It's PaNiC tImE! */
16822 				Marine_EnterExtremePanicAnimation(sbPtr);
16823 			} else {
16824 				/* Just look worried. */
16825 				Marine_EnterLesserPanicAnimation(sbPtr);
16826 			}
16827 		} else {
16828 			/* Yes, we are.  Is it getting worse? */
16829 			int range;
16830 			STRATEGYBLOCK *threat;
16831 
16832 			if (marineStatusPointer->incidentFlag) {
16833 
16834 				threat=Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr);
16835 				if (threat) {
16836 					range=VectorDistance(&sbPtr->DynPtr->Position,&threat->DynPtr->Position);
16837 				} else {
16838 					range=100000;
16839 				}
16840 
16841 				if ((MarineRetreatsInTheFaceOfDanger(sbPtr))||(range<3000)) {
16842 					if (range<3000) {
16843 						if (marineStatusPointer->Android==0) {
16844 							marineStatusPointer->Courage-=5000;
16845 						}
16846 					}
16847 					Marine_EnterExtremePanicAnimation(sbPtr);
16848 				} else {
16849 					/* Feeling really brave? */
16850 					if (MarineRetreatsInTheFaceOfDanger(sbPtr)==0) {
16851 						Marine_QueueGrimaceExpression(sbPtr);
16852 					}
16853 				}
16854 			}
16855 			/* Else remain as you were. */
16856 		}
16857 	} else {
16858 		/* We are in extreme panic.  Is it getting better? */
16859 		if (marineStatusPointer->incidentFlag) {
16860 			if ((FastRandom()&65535)<13107) {
16861 				if (!(MarineRetreatsInTheFaceOfDanger(sbPtr))) {
16862 					if (!(MarineRetreatsInTheFaceOfDanger(sbPtr))) {
16863 						/* Two consecutive tests. */
16864 						Marine_EnterLesserPanicAnimation(sbPtr);
16865 					}
16866 				}
16867 			}
16868 		}
16869 		/* Enforce panic expression, too. */
16870 		Marine_QueuePanicExpression(sbPtr);
16871 	}
16872 
16873 	if (marineStatusPointer->Target==NULL) {
16874 		/* Civvies with courage 0 get a bonus to shut up... */
16875 		if (marineStatusPointer->Courage==0) {
16876 			/* No reason to block this for Androids. */
16877 			marineStatusPointer->Courage=5000;
16878 		}
16879 
16880 		if (marineStatusPointer->incidentFlag) {
16881 			/* Courage roll to stop. */
16882 			if (MarineRetreatsInTheFaceOfDanger(sbPtr)==0) {
16883 				/* Okay, calm down a bit. */
16884 				if(marineStatusPointer->myGunFlash)
16885 				{
16886 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16887 					marineStatusPointer->myGunFlash = NULL;
16888 				}
16889 
16890 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16891 					Sound_Stop(marineStatusPointer->soundHandle);
16892 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16893 				}
16894 				/* Try to be suspicious? */
16895 				marineStatusPointer->suspicious=MARINE_PANIC_TIME;
16896 				marineStatusPointer->suspect_point=marineStatusPointer->weaponTarget;
16897 				/* Set this to zero when you get a *new* suspicion. */
16898 				marineStatusPointer->previous_suspicion=0;
16899 				marineStatusPointer->using_squad_suspicion=0;
16900 
16901 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16902 					||((marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Panic_One)
16903 						&&(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Panic_Two))) {
16904 					Marine_EnterLesserPanicAnimation(sbPtr);
16905 					return(SRC_No_Change);
16906 				} else {
16907 					return(SRC_Request_Wait);
16908 				}
16909 			}
16910 		}
16911 	} else {
16912 		GLOBALASSERT(marineStatusPointer->Target);
16913 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
16914 
16915 		/* May as well keep an eye out. */
16916 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
16917 		orientationDirn.vy = 0;
16918 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
16919 		#if 0
16920 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
16921 		#endif
16922 	}
16923 
16924 	/* Scream handling. */
16925 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
16926 		if (marineStatusPointer->incidentFlag) {
16927 			if (Marine_HasHisMouthOpen(sbPtr)) {
16928 				Marine_Sobbing(sbPtr);
16929 			} else {
16930 				/* Start yelling again? */
16931 				if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
16932 					Marine_QueuePanicExpression(sbPtr);
16933 				}
16934 			}
16935 		}
16936 	}
16937 
16938 	if (NpcSquad.Squad_Suspicion==0) {
16939 		if (marineStatusPointer->Target) {
16940 			/* Here we must have a target.  Renew suspicion for new arrivals. */
16941 			PointAlert(2,&marineStatusPointer->weaponTarget);
16942 		} else {
16943 			PointAlert(1,&sbPtr->DynPtr->Position);
16944 		}
16945 	}
16946 
16947 	/* Wait for end of tweening before we proceed. */
16948 	if (marineStatusPointer->HModelController.Tweening!=Controller_NoTweening) {
16949 		#if 1
16950 		/* stop visual and audio cues: technically, we're not firing at this moment */
16951 		if(marineStatusPointer->myGunFlash)
16952 		{
16953 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16954 			marineStatusPointer->myGunFlash = NULL;
16955 		}
16956 		#endif
16957 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16958 			Sound_Stop(marineStatusPointer->soundHandle);
16959 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16960 		}
16961 		return(SRC_No_Change);
16962 	}
16963 
16964 	/* No functionality in here... */
16965 
16966 	marineStatusPointer->stateTimer -= NormalFrameTime;
16967 
16968 	/* Now, consider termination. */
16969 
16970 	if (marineStatusPointer->incidentFlag) {
16971 		if ((FastRandom()&65535)<13107) {
16972 			if ((!(MarineRetreatsInTheFaceOfDanger(sbPtr)))
16973 				||(!(MarineRetreatsInTheFaceOfDanger(sbPtr)))) {
16974 				/* Two chances... */
16975 
16976 				/* stop visual and audio cues: technically, we're not firing at this moment */
16977 				if(marineStatusPointer->myGunFlash)
16978 				{
16979 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
16980 					marineStatusPointer->myGunFlash = NULL;
16981 				}
16982 
16983 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
16984 					Sound_Stop(marineStatusPointer->soundHandle);
16985 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
16986 				}
16987 				if ((marineStatusPointer->HModelController.Sequence_Type!=HMSQT_MarineStand)
16988 					||((marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Panic_One)
16989 						&&(marineStatusPointer->HModelController.Sub_Sequence!=MSSS_Panic_Two))) {
16990 					Marine_EnterLesserPanicAnimation(sbPtr);
16991 					marineStatusPointer->internalState=1;
16992 					/* This is a bit pre-emptive, but never mind. */
16993 					if (marineStatusPointer->Android==0) {
16994 						marineStatusPointer->Courage-=5000;
16995 					}
16996 					return(SRC_No_Change);
16997 				} else {
16998 					return(SRC_Request_Retreat);
16999 				}
17000 			}
17001 		}
17002 	}
17003 
17004 	return(SRC_No_Change);
17005 
17006 }
17007 
17008 void Marine_AssumeNeutralExpression(STRATEGYBLOCK *sbPtr) {
17009 
17010 	MARINE_STATUS_BLOCK *marineStatusPointer;
17011 
17012 	LOCALASSERT(sbPtr);
17013 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17014 	LOCALASSERT(marineStatusPointer);
17015 
17016 	if ((marineStatusPointer->Expression>2)&&(marineStatusPointer->Expression<6)) {
17017 		/* In a blink. */
17018 		Marine_SwitchExpression(sbPtr,3);
17019 		if (marineStatusPointer->Blink<0) {
17020 			/* Dunno why, but you never know. */
17021 			marineStatusPointer->Blink=0;
17022 		}
17023 	} else {
17024 		/* Not in a blink. */
17025 		Marine_SwitchExpression(sbPtr,0);
17026 	}
17027 
17028 }
17029 
17030 void Marine_AssumeGrimaceExpression(STRATEGYBLOCK *sbPtr) {
17031 
17032 	MARINE_STATUS_BLOCK *marineStatusPointer;
17033 
17034 	LOCALASSERT(sbPtr);
17035 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17036 	LOCALASSERT(marineStatusPointer);
17037 
17038 	if ((marineStatusPointer->Expression>2)&&(marineStatusPointer->Expression<6)) {
17039 		/* In a blink. */
17040 		Marine_SwitchExpression(sbPtr,4);
17041 		if (marineStatusPointer->Blink<0) {
17042 			/* Dunno why, but you never know. */
17043 			marineStatusPointer->Blink=0;
17044 		}
17045 	} else {
17046 		/* Not in a blink. */
17047 		Marine_SwitchExpression(sbPtr,1);
17048 	}
17049 
17050 }
17051 
17052 void Marine_AssumePanicExpression(STRATEGYBLOCK *sbPtr) {
17053 
17054 	MARINE_STATUS_BLOCK *marineStatusPointer;
17055 
17056 	LOCALASSERT(sbPtr);
17057 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17058 	LOCALASSERT(marineStatusPointer);
17059 
17060 	if ((marineStatusPointer->Expression>2)&&(marineStatusPointer->Expression<6)) {
17061 		/* In a blink. */
17062 		Marine_SwitchExpression(sbPtr,5);
17063 		if (marineStatusPointer->Blink<0) {
17064 			/* Dunno why, but you never know. */
17065 			marineStatusPointer->Blink=0;
17066 		}
17067 	} else {
17068 		/* Not in a blink. */
17069 		Marine_SwitchExpression(sbPtr,2);
17070 	}
17071 
17072 }
17073 
17074 void Marine_AssumeWink1Expression(STRATEGYBLOCK *sbPtr) {
17075 
17076 	MARINE_STATUS_BLOCK *marineStatusPointer;
17077 
17078 	LOCALASSERT(sbPtr);
17079 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17080 	LOCALASSERT(marineStatusPointer);
17081 
17082 	/* Who cares about blinking? */
17083 	Marine_SwitchExpression(sbPtr,6);
17084 	marineStatusPointer->Blink=-1;
17085 
17086 }
17087 
17088 void Marine_AssumeWink2Expression(STRATEGYBLOCK *sbPtr) {
17089 
17090 	MARINE_STATUS_BLOCK *marineStatusPointer;
17091 
17092 	LOCALASSERT(sbPtr);
17093 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17094 	LOCALASSERT(marineStatusPointer);
17095 
17096 	/* Who cares about blinking? */
17097 	Marine_SwitchExpression(sbPtr,7);
17098 	marineStatusPointer->Blink=-1;
17099 
17100 }
17101 
17102 static STATE_RETURN_CONDITION Execute_MNS_PumpAction(STRATEGYBLOCK *sbPtr)
17103 {
17104 
17105 	MARINE_STATUS_BLOCK *marineStatusPointer;
17106 	int range;
17107 
17108 	LOCALASSERT(sbPtr);
17109 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17110     LOCALASSERT(marineStatusPointer);
17111 
17112 	/* zero velocity */
17113 	LOCALASSERT(sbPtr->DynPtr);
17114 	sbPtr->DynPtr->LinVelocity.vx = 0;
17115 	sbPtr->DynPtr->LinVelocity.vy = 0;
17116 	sbPtr->DynPtr->LinVelocity.vz = 0;
17117 
17118 	if (!sbPtr->SBdptr) {
17119 		/* We're far... do the timer! */
17120 		ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
17121 	}
17122 
17123 	if (!(HModelAnimation_IsFinished(&marineStatusPointer->HModelController))) {
17124 		return(SRC_No_Change);
17125 	}
17126 
17127 	/* Exit procedure... same as firing was. */
17128 
17129 	if (marineStatusPointer->Target==NULL) {
17130 		return(SRC_Request_Wait);
17131 	}
17132 
17133 	range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
17134 
17135 	/* State timer should be continuous from fire state. */
17136 	if(marineStatusPointer->stateTimer > 0)	{
17137 		#if MARINE_STATE_PRINT
17138 		textprint("Returning firing at range %d.\n",range);
17139 		#endif
17140 		return(SRC_Request_Fire);
17141 	}
17142 
17143 	if(range < MARINE_CLOSE_APPROACH_DISTANCE)
17144 	{
17145 		/* renew firing, as we are still too close to approach */
17146 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
17147 		marineStatusPointer->volleySize = 0;
17148 		GLOBALASSERT(marineStatusPointer->Target);
17149 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
17150 		#if MARINE_STATE_PRINT
17151 		textprint("Returning too close firing at range %d.\n",range);
17152 		#endif
17153 		return(SRC_Request_Fire);
17154 	}
17155 	else
17156 	{
17157 		/* we are far enough away, so return to approach */
17158 
17159 		if (marineStatusPointer->Android) {
17160 			return(SRC_Request_Fire);
17161 		} else {
17162 			#if MARINE_STATE_PRINT
17163 			textprint("Returning too far termination at range %d.\n",range);
17164 			#endif
17165 			return(SRC_Request_Approach);
17166 		}
17167 	}
17168 	return(SRC_Request_Fire);
17169 
17170 }
17171 
17172 void Marine_CorpseSightingTest(STRATEGYBLOCK *corpse) {
17173 
17174 	int a;
17175 	STRATEGYBLOCK *candidate;
17176 	MARINE_STATUS_BLOCK *marineStatusPointer;
17177 
17178 	/* This is called from CORPSE behaviour. */
17179 	for (a=0; a<NumActiveStBlocks; a++) {
17180 		candidate=ActiveStBlockList[a];
17181 		GLOBALASSERT(candidate);
17182 
17183 		if (candidate->I_SBtype==I_BehaviourMarine) {
17184 			/* Are you already suspicious? */
17185 			marineStatusPointer = (MARINE_STATUS_BLOCK *)(candidate->SBdataptr);
17186 
17187 			if (((marineStatusPointer->suspicious==0)||(marineStatusPointer->using_squad_suspicion))
17188 				/* As if we'd care... */
17189 				&&(marineStatusPointer->Target==NULL)
17190 				/* To make the tests a bit rarer. */
17191 				&&(marineStatusPointer->incidentFlag)) {
17192 				/* Did you see that? */
17193 				if (NPCCanSeeTarget(candidate,corpse,MARINE_NEAR_VIEW_WIDTH)) {
17194 					/* Okay, react. */
17195 					marineStatusPointer->suspicious=MARINE_PARANOIA_TIME;
17196 					marineStatusPointer->suspect_point=corpse->DynPtr->Position;
17197 					/* Set this to zero when you get a *new* suspicion. */
17198 					marineStatusPointer->previous_suspicion=0;
17199 					marineStatusPointer->using_squad_suspicion=0;
17200 				}
17201 			}
17202 		}
17203 	}
17204 }
17205 
17206 void Marine_MuteVoice(STRATEGYBLOCK *sbPtr) {
17207 
17208 	MARINE_STATUS_BLOCK *marineStatusPointer;
17209 
17210 	LOCALASSERT(sbPtr);
17211 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17212 	LOCALASSERT(marineStatusPointer);
17213 
17214 	if(marineStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
17215 		/* Cut them off! */
17216 		Sound_Stop(marineStatusPointer->soundHandle2);
17217 	}
17218 
17219 }
17220 
17221 void Marine_OoophSound(STRATEGYBLOCK *sbPtr) {
17222 
17223 	MARINE_STATUS_BLOCK *marineStatusPointer;
17224 
17225 	LOCALASSERT(sbPtr);
17226 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17227 	LOCALASSERT(marineStatusPointer);
17228 
17229 	if (marineStatusPointer->Android) {
17230 		return;
17231 	}
17232 
17233 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17234 		PlayMarineScream(marineStatusPointer->Voice,SC_Oooph,marineStatusPointer->VoicePitch,
17235 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17236 	}
17237 }
17238 
17239 void Marine_SurpriseSound(STRATEGYBLOCK *sbPtr) {
17240 
17241 	MARINE_STATUS_BLOCK *marineStatusPointer;
17242 
17243 	LOCALASSERT(sbPtr);
17244 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17245 	LOCALASSERT(marineStatusPointer);
17246 
17247 	if (marineStatusPointer->Android) {
17248 		return;
17249 	}
17250 
17251 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17252 		PlayMarineScream(marineStatusPointer->Voice,SC_Surprise,marineStatusPointer->VoicePitch,
17253 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17254 		if (marineStatusPointer->Android==0) {
17255 			marineStatusPointer->Courage-=5000;
17256 		}
17257 	}
17258 
17259 	/* Open the mouth? */
17260 	Marine_AssumePanicExpression(sbPtr);
17261 
17262 }
17263 
17264 void Marine_WoundedScream(STRATEGYBLOCK *sbPtr) {
17265 
17266 	MARINE_STATUS_BLOCK *marineStatusPointer;
17267 
17268 	LOCALASSERT(sbPtr);
17269 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17270 	LOCALASSERT(marineStatusPointer);
17271 
17272 	if (marineStatusPointer->Android) {
17273 		return;
17274 	}
17275 
17276 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17277 		PlayMarineScream(marineStatusPointer->Voice,SC_Pain,marineStatusPointer->VoicePitch,
17278 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17279 	}
17280 }
17281 
17282 void Marine_AcidScream(STRATEGYBLOCK *sbPtr) {
17283 
17284 	MARINE_STATUS_BLOCK *marineStatusPointer;
17285 
17286 	LOCALASSERT(sbPtr);
17287 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17288 	LOCALASSERT(marineStatusPointer);
17289 
17290 	if (marineStatusPointer->Android) {
17291 		return;
17292 	}
17293 
17294 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17295 		PlayMarineScream(marineStatusPointer->Voice,SC_Acid,marineStatusPointer->VoicePitch,
17296 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17297 	}
17298 }
17299 
17300 void Marine_BurningScream(STRATEGYBLOCK *sbPtr) {
17301 
17302 	MARINE_STATUS_BLOCK *marineStatusPointer;
17303 
17304 	LOCALASSERT(sbPtr);
17305 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17306 	LOCALASSERT(marineStatusPointer);
17307 
17308 	if (marineStatusPointer->Android) {
17309 		return;
17310 	}
17311 
17312 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17313 		PlayMarineScream(marineStatusPointer->Voice,SC_OnFire,marineStatusPointer->VoicePitch,
17314 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17315 	}
17316 	/* Urgh, that was really grim. */
17317 
17318 }
17319 
17320 void Marine_DeathScream(STRATEGYBLOCK *sbPtr) {
17321 
17322 	MARINE_STATUS_BLOCK *marineStatusPointer;
17323 
17324 	LOCALASSERT(sbPtr);
17325 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17326 	LOCALASSERT(marineStatusPointer);
17327 
17328 	if (marineStatusPointer->Android) {
17329 		return;
17330 	}
17331 
17332 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17333 		/* I figure if you're screaming already, forget it. */
17334 		PlayMarineScream(marineStatusPointer->Voice,SC_Death,marineStatusPointer->VoicePitch,
17335 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17336 	}
17337 
17338 }
17339 
17340 void Marine_ElectrocutionScream(STRATEGYBLOCK *sbPtr) {
17341 
17342 	MARINE_STATUS_BLOCK *marineStatusPointer;
17343 
17344 	LOCALASSERT(sbPtr);
17345 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17346 	LOCALASSERT(marineStatusPointer);
17347 
17348 	if (marineStatusPointer->Android) {
17349 		return;
17350 	}
17351 
17352 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17353 		/* I figure if you're screaming already, forget it. */
17354 		PlayMarineScream(marineStatusPointer->Voice,SC_Electrocution,marineStatusPointer->VoicePitch,
17355 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17356 	}
17357 
17358 }
17359 
17360 void Marine_BurningDeathScream(STRATEGYBLOCK *sbPtr) {
17361 
17362 	MARINE_STATUS_BLOCK *marineStatusPointer;
17363 
17364 	LOCALASSERT(sbPtr);
17365 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17366 	LOCALASSERT(marineStatusPointer);
17367 
17368 	if (marineStatusPointer->Android) {
17369 		return;
17370 	}
17371 
17372 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17373 		/* I figure if you're screaming already, forget it. */
17374 		PlayMarineScream(marineStatusPointer->Voice,SC_OnFire,marineStatusPointer->VoicePitch,
17375 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17376 	}
17377 	/* That too was really quite unpleasant. */
17378 
17379 }
17380 
17381 void Marine_AngryScream(STRATEGYBLOCK *sbPtr) {
17382 
17383 	MARINE_STATUS_BLOCK *marineStatusPointer;
17384 
17385 	LOCALASSERT(sbPtr);
17386 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17387 	LOCALASSERT(marineStatusPointer);
17388 
17389 	if (marineStatusPointer->Android) {
17390 		return;
17391 	}
17392 
17393 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17394 		PlayMarineScream(marineStatusPointer->Voice,SC_Angry,marineStatusPointer->VoicePitch,
17395 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17396 	}
17397 }
17398 
17399 void Marine_PanicScream(STRATEGYBLOCK *sbPtr) {
17400 
17401 	MARINE_STATUS_BLOCK *marineStatusPointer;
17402 
17403 	LOCALASSERT(sbPtr);
17404 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17405 	LOCALASSERT(marineStatusPointer);
17406 
17407 	if (marineStatusPointer->Android) {
17408 		return;
17409 	}
17410 
17411 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17412 		PlayMarineScream(marineStatusPointer->Voice,SC_Panic,marineStatusPointer->VoicePitch,
17413 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17414 	}
17415 }
17416 
17417 void Marine_Sobbing(STRATEGYBLOCK *sbPtr) {
17418 
17419 	MARINE_STATUS_BLOCK *marineStatusPointer;
17420 
17421 	LOCALASSERT(sbPtr);
17422 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17423 	LOCALASSERT(marineStatusPointer);
17424 
17425 	if (marineStatusPointer->Android) {
17426 		return;
17427 	}
17428 
17429 	/* This is getting quite upsetting... */
17430 
17431 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17432 		PlayMarineScream(marineStatusPointer->Voice,SC_Sobbing,marineStatusPointer->VoicePitch,
17433 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17434 	}
17435 }
17436 
17437 void Marine_TauntShout(STRATEGYBLOCK *sbPtr) {
17438 
17439 	MARINE_STATUS_BLOCK *marineStatusPointer;
17440 
17441 	LOCALASSERT(sbPtr);
17442 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17443 	LOCALASSERT(marineStatusPointer);
17444 
17445 	if (marineStatusPointer->Android) {
17446 		return;
17447 	}
17448 
17449 	if (marineStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
17450 		PlayMarineScream(marineStatusPointer->Voice,SC_Taunt,marineStatusPointer->VoicePitch,
17451 			&marineStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
17452 	}
17453 }
17454 
17455 int Marine_HasHisMouthOpen(STRATEGYBLOCK *sbPtr) {
17456 
17457 	MARINE_STATUS_BLOCK *marineStatusPointer;
17458 
17459 	LOCALASSERT(sbPtr);
17460 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17461 	LOCALASSERT(marineStatusPointer);
17462 
17463 	if ((marineStatusPointer->Expression==2)||(marineStatusPointer->Expression==5)) {
17464 		/* yeah, okay, it's hard coded. */
17465 		return(1);
17466 	} else {
17467 		return(0);
17468 	}
17469 
17470 }
17471 
17472 void Marine_QueueNeutralExpression(STRATEGYBLOCK *sbPtr) {
17473 
17474 	MARINE_STATUS_BLOCK *marineStatusPointer;
17475 
17476 	LOCALASSERT(sbPtr);
17477 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17478 	LOCALASSERT(marineStatusPointer);
17479 
17480 	marineStatusPointer->Target_Expression=0;
17481 
17482 }
17483 
17484 void Marine_QueueGrimaceExpression(STRATEGYBLOCK *sbPtr) {
17485 
17486 	MARINE_STATUS_BLOCK *marineStatusPointer;
17487 
17488 	LOCALASSERT(sbPtr);
17489 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17490 	LOCALASSERT(marineStatusPointer);
17491 
17492 	marineStatusPointer->Target_Expression=1;
17493 
17494 }
17495 
17496 void Marine_QueuePanicExpression(STRATEGYBLOCK *sbPtr) {
17497 
17498 	MARINE_STATUS_BLOCK *marineStatusPointer;
17499 
17500 	LOCALASSERT(sbPtr);
17501 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17502 	LOCALASSERT(marineStatusPointer);
17503 
17504 	marineStatusPointer->Target_Expression=2;
17505 
17506 }
17507 
17508 void Marine_QueueWink1Expression(STRATEGYBLOCK *sbPtr) {
17509 
17510 	MARINE_STATUS_BLOCK *marineStatusPointer;
17511 
17512 	LOCALASSERT(sbPtr);
17513 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17514 	LOCALASSERT(marineStatusPointer);
17515 
17516 	marineStatusPointer->Target_Expression=6;
17517 
17518 }
17519 
17520 void Marine_QueueWink2Expression(STRATEGYBLOCK *sbPtr) {
17521 
17522 	MARINE_STATUS_BLOCK *marineStatusPointer;
17523 
17524 	LOCALASSERT(sbPtr);
17525 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17526 	LOCALASSERT(marineStatusPointer);
17527 
17528 	marineStatusPointer->Target_Expression=7;
17529 
17530 }
17531 
17532 void Marine_UpdateFace(STRATEGYBLOCK *sbPtr) {
17533 
17534 	MARINE_STATUS_BLOCK *marineStatusPointer;
17535 
17536 	LOCALASSERT(sbPtr);
17537 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17538 	LOCALASSERT(marineStatusPointer);
17539 
17540 	if (marineStatusPointer->Expression!=marineStatusPointer->Target_Expression) {
17541 		/* Right, consider this. */
17542 		if (Marine_HasHisMouthOpen(sbPtr)) {
17543 			/* Does the target expression also have it's mouth open? */
17544 			if (!((marineStatusPointer->Target_Expression==2)||(marineStatusPointer->Target_Expression==5))) {
17545 				/* Are we screaming? */
17546 				if (marineStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
17547 					/* Can't close our mouth yet. */
17548 					return;
17549 				}
17550 			}
17551 		}
17552 	}
17553 	/* Also ignore if you're in the wink counterpart of the target. */
17554 	switch (marineStatusPointer->Target_Expression) {
17555 		case 0:
17556 			if (marineStatusPointer->Expression==3) {
17557 				return;
17558 			}
17559 			break;
17560 		case 1:
17561 			if (marineStatusPointer->Expression==4) {
17562 				return;
17563 			}
17564 			break;
17565 		case 2:
17566 			if (marineStatusPointer->Expression==5) {
17567 				return;
17568 			}
17569 			break;
17570 		default:
17571 			break;
17572 	}
17573 	/* Exit if current==target? */
17574 	if (marineStatusPointer->Expression==marineStatusPointer->Target_Expression) {
17575 		return;
17576 	}
17577 
17578 	/* If we got here, it must be okay... but do it properly! */
17579 	switch (marineStatusPointer->Target_Expression) {
17580 		case 0:
17581 		case 3:
17582 			Marine_AssumeNeutralExpression(sbPtr);
17583 			break;
17584 		case 1:
17585 		case 4:
17586 			Marine_AssumeGrimaceExpression(sbPtr);
17587 			break;
17588 		case 2:
17589 		case 5:
17590 			Marine_AssumePanicExpression(sbPtr);
17591 			break;
17592 		case 6:
17593 			Marine_AssumeWink1Expression(sbPtr);
17594 			break;
17595 		case 7:
17596 			Marine_AssumeWink2Expression(sbPtr);
17597 			break;
17598 		default:
17599 			GLOBALASSERT(0);
17600 			break;
17601 	}
17602 }
17603 
17604 static void	Marine_MirrorSuspectPoint(STRATEGYBLOCK *sbPtr) {
17605 
17606 	MARINE_STATUS_BLOCK *marineStatusPointer;
17607 
17608 	LOCALASSERT(sbPtr);
17609 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17610 	LOCALASSERT(marineStatusPointer);
17611 
17612 	{
17613 		VECTORCH offset;
17614 
17615 		offset.vx=marineStatusPointer->suspect_point.vx-sbPtr->DynPtr->Position.vx;
17616 		offset.vy=marineStatusPointer->suspect_point.vy-sbPtr->DynPtr->Position.vy;
17617 		offset.vz=marineStatusPointer->suspect_point.vz-sbPtr->DynPtr->Position.vz;
17618 
17619 		marineStatusPointer->suspect_point.vx=sbPtr->DynPtr->Position.vx-offset.vx;
17620 		marineStatusPointer->suspect_point.vy=sbPtr->DynPtr->Position.vy-offset.vy;
17621 		marineStatusPointer->suspect_point.vz=sbPtr->DynPtr->Position.vz-offset.vz;
17622 	}
17623 
17624 }
17625 
17626 
17627 
17628 void SendRequestToMarine(STRATEGYBLOCK* sbPtr,BOOL state,int extended_data)
17629 {
17630 	//handle RequestState (from switches etc.)
17631 
17632 	MARINE_STATUS_BLOCK *marineStatusPointer;
17633 
17634 	LOCALASSERT(sbPtr);
17635 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17636 	LOCALASSERT(marineStatusPointer);
17637 
17638 	if(extended_data & 1)
17639 	{
17640 		//change mission type
17641 		MARINE_MISSION new_mission=MM_Wait_Then_Wander;
17642 		int new_path=-1;
17643 		int new_stepnumber=-1;
17644 		//state must be 1
17645 		if(!state) return;
17646 
17647 		//can't change mission type if non-combatant or if on fire
17648 		if(marineStatusPointer->Mission==MM_NonCom ||
17649 		   marineStatusPointer->Mission==MM_RunAroundOnFire)
17650 			return;
17651 
17652 		switch((extended_data>>7)&0xff)
17653 		{
17654 			case 0:
17655 				new_mission=MM_Wait_Then_Wander;
17656 				break;
17657 			case 1:
17658 				new_mission=MM_Wander;
17659 				break;
17660 			case 2:
17661 				new_mission=MM_Guard;
17662 				//need to cacluculate mission module from 'myspot' guard location
17663 				{
17664 					MODULE* module=ModuleFromPosition(&marineStatusPointer->my_spot,0);
17665 					GLOBALASSERT(module);
17666 					marineStatusPointer->missionmodule=module->m_aimodule;
17667 				}
17668 				break;
17669 			case 3:
17670 				new_mission=MM_LocalGuard;
17671 				break;
17672 			case 4:
17673 				new_mission=MM_Pathfinder;
17674 				break;
17675 
17676 		}
17677 		if(new_mission==MM_Pathfinder)
17678 		{
17679 			//find the path and stepnumber
17680 			new_path=(extended_data>>15)&0xff;
17681 			new_stepnumber=GetClosestStepInPath(new_path,sbPtr->containingModule);
17682 		}
17683 
17684 		marineStatusPointer->path=new_path;
17685 		marineStatusPointer->stepnumber=new_stepnumber;
17686 		InitMission(sbPtr,new_mission);
17687 
17688 	}
17689 
17690 }
17691 
17692 static void	Marine_ConsiderFallingDamage(STRATEGYBLOCK *sbPtr) {
17693 
17694 	MARINE_STATUS_BLOCK *marineStatusPointer;
17695 
17696 	LOCALASSERT(sbPtr);
17697 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17698 	LOCALASSERT(marineStatusPointer);
17699 
17700 	if (sbPtr->DynPtr->IsInContactWithFloor) {
17701 		if (marineStatusPointer->lastframe_fallingspeed>0) {
17702 
17703 			if (marineStatusPointer->lastframe_fallingspeed>Marine_Terminal_Velocity) {
17704 				VECTORCH point,point2;
17705 				enum PARTICLE_ID blood_type;
17706 
17707 				/* Kill marine... */
17708 				CauseDamageToObject(sbPtr,&FallingDamage, (50*ONE_FIXED), NULL);
17709 				/* Experiment with blood. */
17710 				GetTargetingPointOfObject_Far(sbPtr,&point);
17711 				point2=sbPtr->DynPtr->Position;
17712 				point2.vy-=200;
17713 				blood_type=GetBloodType(sbPtr);
17714 				MakeBloodExplosion(&point2,127,&point,50,blood_type);
17715 				/* Crunching sound optional. */
17716 			}
17717 		}
17718 		marineStatusPointer->lastframe_fallingspeed=0;
17719 	} else {
17720 		/* Compute falling speed. */
17721 		if (marineStatusPointer->lastframe_fallingspeed>=0) {
17722 			int offset;
17723 
17724 			offset=sbPtr->DynPtr->Position.vy-sbPtr->DynPtr->PrevPosition.vy;
17725 
17726 			marineStatusPointer->lastframe_fallingspeed=DIV_FIXED(offset,NormalFrameTime);
17727 			if (marineStatusPointer->lastframe_fallingspeed<0) {
17728 				marineStatusPointer->lastframe_fallingspeed=0;
17729 			}
17730 		} else {
17731 			marineStatusPointer->lastframe_fallingspeed=0;
17732 		}
17733 	}
17734 }
17735 
17736 static STATE_RETURN_CONDITION Execute_MNS_DischargeSmartgun(STRATEGYBLOCK *sbPtr)
17737 {
17738 	MARINE_STATUS_BLOCK *marineStatusPointer;
17739 	VECTORCH orientationDirn,relPos,relPos2;
17740 	int correctlyOrientated,range;
17741 
17742 	/* Alternative smartgun function? */
17743 
17744 	LOCALASSERT(sbPtr);
17745 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
17746 	LOCALASSERT(marineStatusPointer);
17747 
17748 	marineStatusPointer->HModelController.Playing=1;
17749 
17750 	#if MARINE_STATE_PRINT
17751 	textprint("Marine firing... ");
17752 	#endif
17753 
17754 	/* zero velocity */
17755 	LOCALASSERT(sbPtr->DynPtr);
17756 	sbPtr->DynPtr->LinVelocity.vx = 0;
17757 	sbPtr->DynPtr->LinVelocity.vy = 0;
17758 	sbPtr->DynPtr->LinVelocity.vz = 0;
17759 
17760 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
17761 	we should switch immediately to wait state*/
17762 	if (marineStatusPointer->volleySize<marineStatusPointer->My_Weapon->MinimumBurstSize) {
17763 		/* Keep firing! */
17764 	} else {
17765 		if(!MarineCanSeeTarget(sbPtr))
17766 		{
17767 
17768 			/* ... and remove the gunflash */
17769 			if(marineStatusPointer->myGunFlash)
17770 			{
17771 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
17772 				marineStatusPointer->myGunFlash = NULL;
17773 			}
17774 
17775 			/* .... and stop the sound */
17776 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
17777 				Sound_Stop(marineStatusPointer->soundHandle);
17778 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
17779 			}
17780 
17781 			#if MARINE_STATE_PRINT
17782 			textprint("Returning no target.\n");
17783 			#endif
17784 			marineStatusPointer->lastroundhit=0;
17785 			marineStatusPointer->lasthitsection=NULL;
17786 			return(SRC_Request_Wait);
17787 		}
17788 	}
17789 
17790 	if (marineStatusPointer->clipammo==0) {
17791 		/* Reload here. */
17792 		return(SRC_Request_Reload);
17793 	}
17794 
17795 
17796 	if (marineStatusPointer->Target) {
17797 		GLOBALASSERT(marineStatusPointer->Target);
17798 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
17799 		/* Fix weapon target! */
17800 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
17801 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
17802 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
17803 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
17804 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
17805 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
17806 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
17807 		}
17808 
17809 		/* Here we must have a target.  Renew suspicion for new arrivals. */
17810 		if (NpcSquad.Squad_Suspicion==0) {
17811 			PointAlert(2,&marineStatusPointer->weaponTarget);
17812 		}
17813 	}
17814 	/* Otherwise, stay facing the same way. */
17815 
17816 	/* orientate to firing point first */
17817 	orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
17818 	orientationDirn.vy = 0;
17819 	orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
17820 	correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
17821 
17822 	/* I have a cunning plan... */
17823 	{
17824 		DELTA_CONTROLLER *delta;
17825 
17826 		delta=Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
17827 		if (delta) {
17828 			if (!(DeltaAnimation_IsFinished(delta))) {
17829 				correctlyOrientated=0;
17830 			}
17831 		}
17832 	}
17833 	/* I have another cunning plan... */
17834 	if ((marineStatusPointer->volleySize>0)&&
17835 		(marineStatusPointer->volleySize<marineStatusPointer->My_Weapon->MinimumBurstSize)) {
17836 		correctlyOrientated=1;
17837 	}
17838 
17839 
17840 	/* we are not correctly orientated to the target: this could happen because we have
17841 	just entered this state, or the target has moved during firing*/
17842 	if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening!=Controller_NoTweening)) {
17843 
17844 		/* stop visual and audio cues: technically, we're not firing at this moment */
17845 		if(marineStatusPointer->myGunFlash)
17846 		{
17847 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
17848 			marineStatusPointer->myGunFlash = NULL;
17849 		}
17850 
17851 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
17852 			Sound_Stop(marineStatusPointer->soundHandle);
17853 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
17854 		}
17855 		#if MARINE_STATE_PRINT
17856 		textprint("Turning to face.\n");
17857 		#endif
17858 		marineStatusPointer->lastroundhit=0;
17859 		marineStatusPointer->lasthitsection=NULL;
17860 		return(SRC_No_Change);
17861 	}
17862 
17863 	if (marineStatusPointer->Target) {
17864 		relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
17865 		relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
17866 		relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
17867 
17868 		relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
17869 		relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
17870 		relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
17871 
17872 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
17873 	}
17874 
17875 	#if 0
17876 	DischargeLOSWeapon_Core(sbPtr);
17877 	#else
17878 	{
17879 		int volleytime,volleyrounds;
17880 
17881 		/* look after the gun flash */
17882 		if(marineStatusPointer->myGunFlash) {
17883 			MaintainMarineGunFlash(sbPtr);
17884 		} else {
17885 			CreateMarineGunFlash(sbPtr);
17886 		}
17887 
17888 		/* look after the sound */
17889 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
17890 		else
17891 		{
17892 			Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
17893 			Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
17894 		}
17895 
17896 		marineStatusPointer->stateTimer -= NormalFrameTime;
17897 
17898 		/* Volleysize is now rounds fired this state. */
17899 
17900 		volleytime=marineStatusPointer->My_Weapon->FiringTime-marineStatusPointer->stateTimer;
17901 		/* It was that or reverse the state timer for this state. */
17902 		volleyrounds=MUL_FIXED(volleytime,marineStatusPointer->My_Weapon->FiringRate);
17903 		volleyrounds>>=ONE_FIXED_SHIFT;
17904 
17905 		volleyrounds-=marineStatusPointer->volleySize;
17906 		marineStatusPointer->volleySize+=volleyrounds;
17907 
17908 		LOCALASSERT(volleyrounds>=0);
17909 
17910 		if (marineStatusPointer->clipammo!=-1) {
17911 			/* We're counting ammo. */
17912 			if (volleyrounds>marineStatusPointer->clipammo) {
17913 				volleyrounds=marineStatusPointer->clipammo;
17914 			}
17915 			marineStatusPointer->clipammo-=volleyrounds;
17916 			LOCALASSERT(marineStatusPointer->clipammo>=0);
17917 		}
17918 
17919 		marineStatusPointer->roundsForThisTarget+=volleyrounds;
17920 
17921 		/* Now hit the target with volleyrounds bullets. */
17922 
17923 		{
17924 			VECTORCH shotvector;
17925 
17926 			shotvector.vx=0;
17927 			shotvector.vy=0;
17928 			shotvector.vz=65535;
17929 			RotateVector(&shotvector,&marineStatusPointer->My_Gunflash_Section->SecMat);
17930 
17931 			CastLOSProjectile(sbPtr,&marineStatusPointer->My_Gunflash_Section->World_Offset,&shotvector, marineStatusPointer->My_Weapon->Ammo_Type, volleyrounds,1);
17932 		}
17933 	}
17934 	#endif
17935 
17936 	if (marineStatusPointer->Target==NULL) {
17937 		/* Getting out of here! */
17938 		return(SRC_No_Change);
17939 	}
17940 
17941 	/* Did we get him? */
17942 	if ((NPC_IsDead(marineStatusPointer->Target))
17943 		&&(marineStatusPointer->volleySize>=marineStatusPointer->My_Weapon->MinimumBurstSize)) {
17944 		if (MarineRetreatsInTheFaceOfDanger(sbPtr)) {
17945 			if (Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr)==NULL) {
17946 				/* Huzzah! */
17947 				if(marineStatusPointer->myGunFlash)
17948 				{
17949 					RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
17950 					marineStatusPointer->myGunFlash = NULL;
17951 				}
17952 				if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
17953 					Sound_Stop(marineStatusPointer->soundHandle);
17954 					Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
17955 				}
17956 				marineStatusPointer->lastroundhit=0;
17957 				marineStatusPointer->lasthitsection=NULL;
17958 				return(SRC_Request_Taunt);
17959 			}
17960 		}
17961 	}
17962 
17963 	if(marineStatusPointer->stateTimer > 0)	{
17964 		#if MARINE_STATE_PRINT
17965 		textprint("Returning continue at range %d.\n",range);
17966 		#endif
17967 		return(SRC_No_Change);
17968 	}
17969 
17970 	if(range < MARINE_CLOSE_APPROACH_DISTANCE)
17971 	{
17972 		/* renew firing, as we are still too close to approach */
17973 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
17974 		marineStatusPointer->volleySize = 0;
17975 		GLOBALASSERT(marineStatusPointer->Target);
17976 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
17977 		#if MARINE_STATE_PRINT
17978 		textprint("Returning too close renewal at range %d.\n",range);
17979 		#endif
17980 		#if 1
17981 		/* stop visual and audio cues: technically, we're not firing at this moment */
17982 		if(marineStatusPointer->myGunFlash)
17983 		{
17984 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
17985 			marineStatusPointer->myGunFlash = NULL;
17986 		}
17987 		#endif
17988 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
17989 			Sound_Stop(marineStatusPointer->soundHandle);
17990 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
17991 		}
17992 		if (marineStatusPointer->Android==0) {
17993 			marineStatusPointer->Courage-=(ONE_FIXED>>3);
17994 		}
17995 		return(SRC_Request_Fire);
17996 	}
17997 	else
17998 	{
17999 		/* we are far enough away, so return to approach */
18000 
18001 		#if 1
18002 		/* ... and remove the gunflash */
18003 		if(marineStatusPointer->myGunFlash)
18004 		{
18005 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18006 			marineStatusPointer->myGunFlash = NULL;
18007 		}
18008 		#endif
18009 		/* .... and stop the sound */
18010 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18011 			Sound_Stop(marineStatusPointer->soundHandle);
18012 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
18013 		}
18014 		#if MARINE_STATE_PRINT
18015 		textprint("Returning too far termination at range %d.\n",range);
18016 		#endif
18017 		return(SRC_Request_Approach);
18018 	}
18019 	return(SRC_No_Change);
18020 }
18021 
18022 int MakeModifiedTargetNum(int targetnum,int dist) {
18023 
18024 	/* Adjust targetnum by range? */
18025 	if (dist>10000) {
18026 		int factor,tdist;
18027 
18028 		tdist=dist-10000;
18029 		if (tdist>100000) {
18030 			tdist=100000;
18031 		}
18032 		factor=DIV_FIXED(tdist,100000);
18033 		factor=ONE_FIXED-factor;
18034 		if (factor<(ONE_FIXED>>3)) {
18035 			factor=(ONE_FIXED>>3);
18036 		}
18037 
18038 		return(MUL_FIXED(factor,targetnum));
18039 	}
18040 	return(targetnum);
18041 }
18042 
18043 
18044 
18045 
18046 
18047 /*--------------------**
18048 ** Loading and Saving **
18049 **--------------------*/
18050 #include "savegame.h"
18051 typedef struct marine_save_block
18052 {
18053 	SAVE_BLOCK_STRATEGY_HEADER header;
18054 
18055  //from marine status block
18056  	signed int health;
18057  	signed int volleySize;
18058  	signed int primaryWeaponDamage;
18059 
18060  	MARINE_BHSTATE behaviourState;
18061  	MARINE_BHSTATE lastState;
18062 
18063 	MARINE_MISSION Mission;
18064 
18065 	VECTORCH my_spot;
18066 	VECTORCH my_facing_point;
18067 
18068 	/* Movement data. */
18069 	signed int nearSpeed;
18070 	int acceleration;
18071 	int speedConstant;
18072 	int accelerationConstant;
18073 	/* Sense data */
18074 	int mtracker_timer;
18075 	VECTORCH suspect_point;
18076 	int suspicious;
18077 	int previous_suspicion;
18078 	int using_squad_suspicion;
18079 	int sawlastframe;
18080 	int gotapoint;
18081 	int lastframe_fallingspeed;
18082 	/* Pathfinder parameters */
18083 	int path;
18084 	int stepnumber;
18085 	/* Pathfinder parameters */
18086 	int stateTimer;
18087 	int internalState;
18088 
18089 	VECTORCH weaponTarget;		/* position for firing weapon at */
18090 
18091 	NPC_OBSTRUCTIONREPORT obstruction;
18092 	NPC_WANDERDATA wanderData;
18093 
18094 	int IAmCrouched;
18095 
18096 	int lastroundhit;
18097 
18098 	int GibbFactor;
18099 	int Wounds;
18100 
18101 	int incidentFlag;
18102 	int incidentTimer;
18103 
18104 	int weapon_variable;
18105 	int weapon_variable2;
18106 	int clipammo;
18107 	int roundsForThisTarget;
18108 
18109 	int Female;
18110 	int Android;
18111 	int Skill;
18112 	int Courage;
18113 	int Voice;
18114 	int VoicePitch;
18115 
18116 	int FiringAnim;
18117 	int Expression;
18118 	int Target_Expression;
18119 	int Blink;
18120 	int SpotFlag;
18121 
18122 
18123 //annoying pointer related things
18124 	int lastmodule_index;
18125 	int destinationmodule_index;
18126 	int missionmodule_index;
18127 	int fearmodule_index;
18128 
18129 
18130 	char Target_SBname[SB_NAME_LENGTH];
18131 	char Generator_SBname[SB_NAME_LENGTH];
18132 
18133 	int weapon_id;
18134 
18135 	//strategyblock stuff
18136 	int integrity;
18137 	DAMAGEBLOCK SBDamageBlock;
18138 	DYNAMICSBLOCK dynamics;
18139 }MARINE_SAVE_BLOCK;
18140 
18141 //defines for load/save macros
18142 #define SAVELOAD_BLOCK block
18143 #define SAVELOAD_BEHAV marineStatusPointer
18144 
18145 
18146 void LoadStrategy_Marine(SAVE_BLOCK_STRATEGY_HEADER* header)
18147 {
18148 	STRATEGYBLOCK* sbPtr;
18149 	MARINE_STATUS_BLOCK* marineStatusPointer;
18150 	MARINE_SAVE_BLOCK* block = (MARINE_SAVE_BLOCK*) header;
18151 
18152 	//check the size of the save block
18153 	if(header->size!=sizeof(*block)) return;
18154 
18155 	//find the existing strategy block
18156 	sbPtr = FindSBWithName(header->SBname);
18157 
18158 	if(sbPtr)
18159 	{
18160 		//make sure the strategy found is of the right type
18161 		if(sbPtr->I_SBtype != I_BehaviourMarine) return;
18162 	}
18163 	else
18164 	{
18165 		//we will have to generate an alien then
18166 		TOOLS_DATA_MARINE tdm;
18167 
18168 		//make sure the marine is in a module
18169 		if(!ModuleFromPosition(&block->dynamics.Position,NULL)) return;
18170 
18171 		sbPtr = CreateActiveStrategyBlock();
18172 		if(!sbPtr) return;
18173 
18174 		sbPtr->I_SBtype = I_BehaviourMarine;
18175 		sbPtr->shapeIndex = 0;
18176 		sbPtr->maintainVisibility = 1;
18177 		COPY_NAME(sbPtr->SBname,block->header.SBname);
18178 
18179 		//create using a fake tools data
18180 		memset(&tdm,0,sizeof(TOOLS_DATA_MARINE));
18181 
18182 		tdm.position = block->dynamics.Position;
18183 		COPY_NAME(tdm.nameID,block->header.SBname);
18184 		tdm. marine_type = block->weapon_id;
18185 
18186  		EnableBehaviourType(sbPtr,I_BehaviourMarine , &tdm );
18187 
18188  	}
18189 
18190 
18191 	marineStatusPointer = (MARINE_STATUS_BLOCK*) sbPtr->SBdataptr;
18192 
18193 	//start copying stuff
18194 
18195  	COPYELEMENT_LOAD(health)
18196  	COPYELEMENT_LOAD(volleySize)
18197  	COPYELEMENT_LOAD(primaryWeaponDamage)
18198  	COPYELEMENT_LOAD(behaviourState)
18199  	COPYELEMENT_LOAD(lastState)
18200 	COPYELEMENT_LOAD(Mission)
18201 	COPYELEMENT_LOAD(my_spot)
18202 	COPYELEMENT_LOAD(my_facing_point)
18203 	COPYELEMENT_LOAD(nearSpeed)
18204 	COPYELEMENT_LOAD(acceleration)
18205 	COPYELEMENT_LOAD(speedConstant)
18206 	COPYELEMENT_LOAD(accelerationConstant)
18207 	COPYELEMENT_LOAD(mtracker_timer)
18208 	COPYELEMENT_LOAD(suspect_point)
18209 	COPYELEMENT_LOAD(suspicious)
18210 	COPYELEMENT_LOAD(previous_suspicion)
18211 	COPYELEMENT_LOAD(using_squad_suspicion)
18212 	COPYELEMENT_LOAD(sawlastframe)
18213 	COPYELEMENT_LOAD(gotapoint)
18214 	COPYELEMENT_LOAD(lastframe_fallingspeed)
18215 	COPYELEMENT_LOAD(path)
18216 	COPYELEMENT_LOAD(stepnumber)
18217 	COPYELEMENT_LOAD(stateTimer)
18218 	COPYELEMENT_LOAD(internalState)
18219 	COPYELEMENT_LOAD(weaponTarget)		/* position for firing weapon at */
18220 	COPYELEMENT_LOAD(obstruction)
18221 	COPYELEMENT_LOAD(wanderData)
18222 	COPYELEMENT_LOAD(IAmCrouched)
18223 	COPYELEMENT_LOAD(lastroundhit)
18224 	COPYELEMENT_LOAD(GibbFactor)
18225 	COPYELEMENT_LOAD(Wounds)
18226 
18227 	COPYELEMENT_LOAD(incidentFlag)
18228 	COPYELEMENT_LOAD(incidentTimer)
18229 
18230 	COPYELEMENT_LOAD(weapon_variable)
18231 	COPYELEMENT_LOAD(weapon_variable2)
18232 	COPYELEMENT_LOAD(clipammo)
18233 	COPYELEMENT_LOAD(roundsForThisTarget)
18234 
18235 	COPYELEMENT_LOAD(Female)
18236 	COPYELEMENT_LOAD(Android)
18237 	COPYELEMENT_LOAD(Skill)
18238 	COPYELEMENT_LOAD(Courage)
18239 	COPYELEMENT_LOAD(Voice)
18240 	COPYELEMENT_LOAD(VoicePitch)
18241 
18242 	COPYELEMENT_LOAD(FiringAnim)
18243 	COPYELEMENT_LOAD(Expression)
18244 	COPYELEMENT_LOAD(Target_Expression)
18245 	COPYELEMENT_LOAD(Blink)
18246 	COPYELEMENT_LOAD(SpotFlag)
18247 
18248 
18249 	//load ai module pointers
18250 	marineStatusPointer->lastmodule = GetPointerFromAIModuleIndex(block->lastmodule_index);
18251 	marineStatusPointer->destinationmodule = GetPointerFromAIModuleIndex(block->destinationmodule_index);
18252 	marineStatusPointer->missionmodule = GetPointerFromAIModuleIndex(block->missionmodule_index);
18253 	marineStatusPointer->fearmodule = GetPointerFromAIModuleIndex(block->fearmodule_index);
18254 
18255 	//load target
18256 	COPY_NAME(marineStatusPointer->Target_SBname,block->Target_SBname);
18257 	marineStatusPointer->Target = FindSBWithName(marineStatusPointer->Target_SBname);
18258 
18259 
18260 	//find the marine's generator
18261 	marineStatusPointer->generator_sbptr = FindSBWithName(block->Generator_SBname);
18262 
18263 	//get marine's weapon
18264 	marineStatusPointer->My_Weapon = GetThisNPCMarineWeapon(block->weapon_id);
18265 
18266 	//copy strategy block stuff
18267 	*sbPtr->DynPtr = block->dynamics;
18268 	sbPtr->integrity = block->integrity;
18269 	sbPtr->SBDamageBlock = block->SBDamageBlock;
18270 
18271 	//load hierarchy
18272 	{
18273 		SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
18274 		if(hier_header)
18275 		{
18276 			LoadHierarchy(hier_header,&marineStatusPointer->HModelController);
18277 		}
18278 	}
18279 
18280 	//get section data pointers
18281 	if(marineStatusPointer->My_Weapon)
18282 	{
18283 		marineStatusPointer->My_Gunflash_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->GunflashName);
18284 		marineStatusPointer->My_Elevation_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ElevationSection);
18285 	}
18286 
18287 	Load_SoundState(&marineStatusPointer->soundHandle);
18288 	Load_SoundState(&marineStatusPointer->soundHandle2);
18289 }
18290 
18291 void SaveStrategy_Marine(STRATEGYBLOCK* sbPtr)
18292 {
18293 	MARINE_SAVE_BLOCK *block;
18294 	MARINE_STATUS_BLOCK* marineStatusPointer;
18295 
18296 	GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
18297 	marineStatusPointer = (MARINE_STATUS_BLOCK*) sbPtr->SBdataptr;
18298 
18299 	//start copying stuff
18300 
18301  	COPYELEMENT_SAVE(health)
18302  	COPYELEMENT_SAVE(volleySize)
18303  	COPYELEMENT_SAVE(primaryWeaponDamage)
18304  	COPYELEMENT_SAVE(behaviourState)
18305  	COPYELEMENT_SAVE(lastState)
18306 	COPYELEMENT_SAVE(Mission)
18307 	COPYELEMENT_SAVE(my_spot)
18308 	COPYELEMENT_SAVE(my_facing_point)
18309 	COPYELEMENT_SAVE(nearSpeed)
18310 	COPYELEMENT_SAVE(acceleration)
18311 	COPYELEMENT_SAVE(speedConstant)
18312 	COPYELEMENT_SAVE(accelerationConstant)
18313 	COPYELEMENT_SAVE(mtracker_timer)
18314 	COPYELEMENT_SAVE(suspect_point)
18315 	COPYELEMENT_SAVE(suspicious)
18316 	COPYELEMENT_SAVE(previous_suspicion)
18317 	COPYELEMENT_SAVE(using_squad_suspicion)
18318 	COPYELEMENT_SAVE(sawlastframe)
18319 	COPYELEMENT_SAVE(gotapoint)
18320 	COPYELEMENT_SAVE(lastframe_fallingspeed)
18321 	COPYELEMENT_SAVE(path)
18322 	COPYELEMENT_SAVE(stepnumber)
18323 	COPYELEMENT_SAVE(stateTimer)
18324 	COPYELEMENT_SAVE(internalState)
18325 	COPYELEMENT_SAVE(weaponTarget)		/* position for firing weapon at */
18326 	COPYELEMENT_SAVE(obstruction)
18327 	COPYELEMENT_SAVE(wanderData)
18328 	COPYELEMENT_SAVE(IAmCrouched)
18329 	COPYELEMENT_SAVE(lastroundhit)
18330 	COPYELEMENT_SAVE(GibbFactor)
18331 	COPYELEMENT_SAVE(Wounds)
18332 
18333 	COPYELEMENT_SAVE(incidentFlag)
18334 	COPYELEMENT_SAVE(incidentTimer)
18335 
18336 	COPYELEMENT_SAVE(weapon_variable)
18337 	COPYELEMENT_SAVE(weapon_variable2)
18338 	COPYELEMENT_SAVE(clipammo)
18339 	COPYELEMENT_SAVE(roundsForThisTarget)
18340 
18341 	COPYELEMENT_SAVE(Female)
18342 	COPYELEMENT_SAVE(Android)
18343 	COPYELEMENT_SAVE(Skill)
18344 	COPYELEMENT_SAVE(Courage)
18345 	COPYELEMENT_SAVE(Voice)
18346 	COPYELEMENT_SAVE(VoicePitch)
18347 
18348 	COPYELEMENT_SAVE(FiringAnim)
18349 	COPYELEMENT_SAVE(Expression)
18350 	COPYELEMENT_SAVE(Target_Expression)
18351 	COPYELEMENT_SAVE(Blink)
18352 	COPYELEMENT_SAVE(SpotFlag)
18353 
18354 	//save ai module pointers
18355 	block->lastmodule_index = GetIndexFromAIModulePointer(marineStatusPointer->lastmodule);
18356 	block->destinationmodule_index = GetIndexFromAIModulePointer(marineStatusPointer->destinationmodule);
18357 	block->missionmodule_index = GetIndexFromAIModulePointer(marineStatusPointer->missionmodule);
18358 	block->fearmodule_index = GetIndexFromAIModulePointer(marineStatusPointer->fearmodule);
18359 
18360 	//save target
18361 	COPY_NAME(block->Target_SBname,marineStatusPointer->Target_SBname);
18362 
18363 	//save the marine's generator name
18364 	if(marineStatusPointer->generator_sbptr)
18365 	{
18366 		COPY_NAME(block->Generator_SBname,marineStatusPointer->generator_sbptr->SBname);
18367 	}
18368 	else
18369 	{
18370 		COPY_NAME(block->Generator_SBname,Null_Name);
18371 	}
18372 
18373 	//save marine's weapon
18374 	if(marineStatusPointer->My_Weapon)
18375 		block->weapon_id = marineStatusPointer->My_Weapon->id;
18376 	else
18377 		block->weapon_id = -1;
18378 
18379 	//copy strategy block stuff
18380 	block->dynamics = *sbPtr->DynPtr;
18381 	block->dynamics.CollisionReportPtr=0;
18382 
18383 	block->integrity = sbPtr->integrity;
18384 	block->SBDamageBlock = sbPtr->SBDamageBlock;
18385 
18386 	//save the hierarchy
18387 	SaveHierarchy(&marineStatusPointer->HModelController);
18388 
18389 	Save_SoundState(&marineStatusPointer->soundHandle);
18390 	Save_SoundState(&marineStatusPointer->soundHandle2);
18391 
18392 }
18393 
18394 
18395 
18396 /*----------------------------**
18397 ** And now the squad state... **
18398 **----------------------------*/
18399 
18400 
18401 typedef struct marine_squad_save_block
18402 {
18403 	SAVE_BLOCK_HEADER header;
18404 
18405 	int alertStatus;
18406 	int responseLevel;
18407 	int alertPriority;
18408 
18409 	int Squad_Suspicion;
18410 	VECTORCH squad_suspect_point;
18411 
18412 	/* Now some stats. */
18413 	int RespondingMarines;
18414 	int Alt_RespondingMarines;
18415 
18416 	int NearUnpanickedMarines;
18417 	int Alt_NearUnpanickedMarines;
18418 
18419 	int NearPanickedMarines;
18420 	int Alt_NearPanickedMarines;
18421 
18422 	int NearBurningMarines;
18423 	int Alt_NearBurningMarines;
18424 
18425 	int Squad_Delta_Morale;
18426 	int Nextframe_Squad_Delta_Morale;
18427 
18428 	int alertZone_index;
18429 
18430 }MARINE_SQUAD_SAVE_BLOCK;
18431 
18432 #undef SAVELOAD_BEHAV
18433 //defines for load/save macros
18434 #define SAVELOAD_BEHAV (&NpcSquad)
18435 
18436 
18437 void LoadMarineSquadState(SAVE_BLOCK_HEADER* header)
18438 {
18439 	MARINE_SQUAD_SAVE_BLOCK *block = (MARINE_SQUAD_SAVE_BLOCK*) header;
18440 
18441 	//check the size of the save block
18442 	if(header->size!=sizeof(*block)) return;
18443 
18444 	//copy stuff
18445 
18446 	COPYELEMENT_LOAD(alertStatus)
18447 	COPYELEMENT_LOAD(responseLevel)
18448 	COPYELEMENT_LOAD(alertPriority)
18449 	COPYELEMENT_LOAD(Squad_Suspicion)
18450 	COPYELEMENT_LOAD(squad_suspect_point)
18451 	COPYELEMENT_LOAD(RespondingMarines)
18452 	COPYELEMENT_LOAD(Alt_RespondingMarines)
18453 	COPYELEMENT_LOAD(NearUnpanickedMarines)
18454 	COPYELEMENT_LOAD(Alt_NearUnpanickedMarines)
18455 	COPYELEMENT_LOAD(NearPanickedMarines)
18456 	COPYELEMENT_LOAD(Alt_NearPanickedMarines)
18457 	COPYELEMENT_LOAD(NearBurningMarines)
18458 	COPYELEMENT_LOAD(Alt_NearBurningMarines)
18459 	COPYELEMENT_LOAD(Squad_Delta_Morale)
18460 	COPYELEMENT_LOAD(Nextframe_Squad_Delta_Morale)
18461 
18462 	//and an aimodule
18463 	NpcSquad.alertZone = GetPointerFromAIModuleIndex(block->alertZone_index);
18464 
18465 }
18466 
18467 void SaveMarineSquadState()
18468 {
18469 	MARINE_SQUAD_SAVE_BLOCK * block;
18470 
18471 	GET_SAVE_BLOCK_POINTER(block);
18472 
18473 	//fill in the header
18474 	block->header.type = SaveBlock_MarineSquad;
18475 	block->header.size = sizeof(*block);
18476 
18477 	//copy stuff
18478 
18479 	COPYELEMENT_SAVE(alertStatus)
18480 	COPYELEMENT_SAVE(responseLevel)
18481 	COPYELEMENT_SAVE(alertPriority)
18482 	COPYELEMENT_SAVE(Squad_Suspicion)
18483 	COPYELEMENT_SAVE(squad_suspect_point)
18484 	COPYELEMENT_SAVE(RespondingMarines)
18485 	COPYELEMENT_SAVE(Alt_RespondingMarines)
18486 	COPYELEMENT_SAVE(NearUnpanickedMarines)
18487 	COPYELEMENT_SAVE(Alt_NearUnpanickedMarines)
18488 	COPYELEMENT_SAVE(NearPanickedMarines)
18489 	COPYELEMENT_SAVE(Alt_NearPanickedMarines)
18490 	COPYELEMENT_SAVE(NearBurningMarines)
18491 	COPYELEMENT_SAVE(Alt_NearBurningMarines)
18492 	COPYELEMENT_SAVE(Squad_Delta_Morale)
18493 	COPYELEMENT_SAVE(Nextframe_Squad_Delta_Morale)
18494 
18495 	//and an aimodule
18496 	block->alertZone_index = GetIndexFromAIModulePointer(NpcSquad.alertZone);
18497 }
18498 
18499 static STATE_RETURN_CONDITION Execute_MNS_DischargeTwoPistols(STRATEGYBLOCK *sbPtr)
18500 {
18501 	MARINE_STATUS_BLOCK *marineStatusPointer;
18502 	VECTORCH orientationDirn,relPos,relPos2;
18503 	int correctlyOrientated,range;
18504 	int mod,hitroll;
18505 
18506 	LOCALASSERT(sbPtr);
18507 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
18508 	LOCALASSERT(marineStatusPointer);
18509 
18510 	LOCALASSERT(marineStatusPointer->My_Weapon->id==MNPCW_TwoPistols);
18511 
18512 	/* zero velocity */
18513 	LOCALASSERT(sbPtr->DynPtr);
18514 	sbPtr->DynPtr->LinVelocity.vx = 0;
18515 	sbPtr->DynPtr->LinVelocity.vy = 0;
18516 	sbPtr->DynPtr->LinVelocity.vz = 0;
18517 
18518 	if(!MarineCanSeeTarget(sbPtr))
18519 	{
18520 		/* Remove the gunflash */
18521 		if(marineStatusPointer->myGunFlash)
18522 		{
18523 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18524 			marineStatusPointer->myGunFlash = NULL;
18525 		}
18526 		/* .... and stop the sound */
18527 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18528 			Sound_Stop(marineStatusPointer->soundHandle);
18529 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
18530 		}
18531 		return(SRC_Request_Wait);
18532 	}
18533 
18534 	if (marineStatusPointer->clipammo==0) {
18535 		/* Remove the gunflash */
18536 		if(marineStatusPointer->myGunFlash)
18537 		{
18538 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18539 			marineStatusPointer->myGunFlash = NULL;
18540 		}
18541 		return(SRC_Request_Reload);
18542 	}
18543 
18544 	#if MARINE_STATE_PRINT
18545 	textprint("Firing pistol... ");
18546 	#endif
18547 
18548 	/* Here we must have a target.  Renew suspicion for new arrivals. */
18549 	if (NpcSquad.Squad_Suspicion==0) {
18550 		PointAlert(2,&marineStatusPointer->weaponTarget);
18551 	}
18552 
18553 	/* first of all, validate this state: if the target suddenly becomes cloaked, then
18554 	we should switch immediately to wait state.*/
18555 
18556 	//if ((marineStatusPointer->HModelController.keyframe_flags)
18557 	//	||(marineStatusPointer->HModelController.Playing==0)) {
18558 
18559 	relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
18560 	relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
18561 	relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
18562 
18563 	relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
18564 	relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
18565 	relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
18566 
18567 	range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
18568 
18569 	if (marineStatusPointer->volleySize==0) {
18570 
18571 		//marineStatusPointer->HModelController.Playing=0;
18572 		//marineStatusPointer->HModelController.sequence_timer=0;
18573 
18574 		/* Only terminate if you haven't fired yet... */
18575 		if(!MarineCanSeeTarget(sbPtr))
18576 		{
18577 			#if 1
18578 			/* ... and remove the gunflash */
18579 			if(marineStatusPointer->myGunFlash)
18580 			{
18581 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18582 				marineStatusPointer->myGunFlash = NULL;
18583 			}
18584 			#endif
18585 
18586 			/* .... and stop the sound */
18587 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18588 				Sound_Stop(marineStatusPointer->soundHandle);
18589 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
18590 			}
18591 
18592 			#if MARINE_STATE_PRINT
18593 			textprint("Returning no target.\n");
18594 			#endif
18595 			return(SRC_Request_Wait);
18596 		}
18597 
18598 		GLOBALASSERT(marineStatusPointer->Target);
18599 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
18600 		/* Fix weapon target! */
18601 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
18602 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
18603 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
18604 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
18605 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
18606 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
18607 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
18608 		}
18609 
18610 		/* orientate to firing point first */
18611 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
18612 		orientationDirn.vy = 0;
18613 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
18614 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
18615 
18616 		/* we are not correctly orientated to the target: this could happen because we have
18617 		just entered this state, or the target has moved during firing*/
18618 		//if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening==Controller_Tweening)) {
18619 		if (!correctlyOrientated) {
18620 
18621 			#if 1
18622 			/* stop visual and audio cues: technically, we're not firing at this moment */
18623 			if(marineStatusPointer->myGunFlash)
18624 			{
18625 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18626 				marineStatusPointer->myGunFlash = NULL;
18627 			}
18628 			#endif
18629 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18630 				Sound_Stop(marineStatusPointer->soundHandle);
18631 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
18632 			}
18633 			#if MARINE_STATE_PRINT
18634 			textprint("Turning to face.\n");
18635 			#endif
18636 			return(SRC_No_Change);
18637 		}
18638 
18639 		/* If you are correctly oriented, you can now fire! */
18640 
18641 		marineStatusPointer->volleySize++;
18642 		marineStatusPointer->HModelController.Playing=1;
18643 		if (marineStatusPointer->clipammo>0) {
18644 			marineStatusPointer->clipammo--;
18645 		}
18646 		marineStatusPointer->roundsForThisTarget++;
18647 
18648 		/* Alternate gun flash. */
18649 		if (strcmp(marineStatusPointer->My_Gunflash_Section->sempai->Section_Name,"dum flash")==0) {
18650 			marineStatusPointer->My_Gunflash_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,"dum L flash");
18651 		} else {
18652 			marineStatusPointer->My_Gunflash_Section=GetThisSectionData(marineStatusPointer->HModelController.section_data,"dum flash");
18653 		}
18654 
18655 		/* look after the gun flash */
18656 		if(marineStatusPointer->myGunFlash) MaintainMarineGunFlash(sbPtr);
18657 		else CreateMarineGunFlash(sbPtr);
18658 
18659 		/* look after the sound */
18660 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
18661 		else
18662 		{
18663 			Sound_Play(marineStatusPointer->My_Weapon->StartSound,"d",&(sbPtr->DynPtr->Position));
18664 			Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
18665 		}
18666 
18667 		/* Now hit the target with one bullet. */
18668 
18669 		mod=SpeedRangeMods(&relPos,&relPos2);
18670 
18671 		hitroll=marineStatusPointer->Skill; /* Marine skill... */
18672 		if (marineStatusPointer->Target==Player->ObStrategyBlock) {
18673 			PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
18674 			LOCALASSERT(playerStatusPtr);
18675 			if ( (AvP.PlayerType==I_Alien)
18676 				||((AvP.PlayerType==I_Predator)&&(playerStatusPtr->cloakOn==1))) {
18677 				/* Vs the player, lighting effects on aliens and cloaked preds. */
18678 				hitroll=MUL_FIXED(hitroll,((CurrentLightAtPlayer>>1)+32767));
18679 			}
18680 		}
18681 		hitroll-=mod;
18682 		hitroll+=marineStatusPointer->My_Weapon->Accuracy;
18683 
18684 		{
18685 
18686 			/* Handle Damage. */
18687 			if ((FastRandom()&65535)<hitroll) {
18688 				/* DO DAMAGE TO TARGET HERE */
18689 
18690 				VECTORCH rel_pos,attack_dir;
18691 				int dist;
18692 				VECTORCH shotvector;
18693 
18694 				shotvector.vx=0;
18695 				shotvector.vy=0;
18696 				shotvector.vz=65535;
18697 				RotateVector(&shotvector,&marineStatusPointer->My_Gunflash_Section->SecMat);
18698 
18699 				rel_pos.vx=marineStatusPointer->Target->DynPtr->Position.vx-sbPtr->DynPtr->Position.vx;
18700 				rel_pos.vy=marineStatusPointer->Target->DynPtr->Position.vy-sbPtr->DynPtr->Position.vy;
18701 				rel_pos.vz=marineStatusPointer->Target->DynPtr->Position.vz-sbPtr->DynPtr->Position.vz;
18702 
18703 				dist=Approximate3dMagnitude(&rel_pos);
18704 
18705 				if (VerifyHitShot(sbPtr,marineStatusPointer->Target,&marineStatusPointer->My_Gunflash_Section->World_Offset,&shotvector, marineStatusPointer->My_Weapon->Ammo_Type, 1,dist)) {
18706 
18707 					GetDirectionOfAttack(marineStatusPointer->Target,&rel_pos,&attack_dir);
18708 					/* Get hit location? */
18709 
18710 					marineStatusPointer->lasthitsection=HitLocationRoll(marineStatusPointer->Target,sbPtr);
18711 
18712 					if (marineStatusPointer->lasthitsection) {
18713 						CauseDamageToHModel(marineStatusPointer->lasthitsection->my_controller, marineStatusPointer->Target,&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage[AvP.Difficulty], ONE_FIXED, marineStatusPointer->lasthitsection,&attack_dir,NULL,0);
18714 					} else {
18715 						CauseDamageToObject(marineStatusPointer->Target,&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage[AvP.Difficulty], ONE_FIXED,&attack_dir);
18716 					}
18717 				}
18718 			} else {
18719 				GLOBALASSERT(marineStatusPointer->My_Gunflash_Section);
18720 				ProjectNPCShot(sbPtr, marineStatusPointer->Target, &marineStatusPointer->My_Gunflash_Section->World_Offset,&marineStatusPointer->My_Gunflash_Section->SecMat, marineStatusPointer->My_Weapon->Ammo_Type, 1);
18721 			}
18722 
18723 			/* Did we get him? */
18724 			if ((NPC_IsDead(marineStatusPointer->Target))&&(marineStatusPointer->My_Weapon->ARealMarine)) {
18725 				/* Only real marines taunt. */
18726 				if ((marineStatusPointer->roundsForThisTarget==1)||(MarineRetreatsInTheFaceOfDanger(sbPtr))) {
18727 					if (Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr)==NULL) {
18728 						/* Huzzah! */
18729 						if(marineStatusPointer->myGunFlash)
18730 						{
18731 							RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18732 							marineStatusPointer->myGunFlash = NULL;
18733 						}
18734 						if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18735 							Sound_Stop(marineStatusPointer->soundHandle);
18736 							Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
18737 						}
18738 						marineStatusPointer->lastroundhit=0;
18739 						marineStatusPointer->lasthitsection=NULL;
18740 						return(SRC_Request_Taunt);
18741 					}
18742 				}
18743 			}
18744 		}
18745 	} else {
18746 		/* Remove the gunflash */
18747 		if(marineStatusPointer->myGunFlash)
18748 		{
18749 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18750 			marineStatusPointer->myGunFlash = NULL;
18751 		}
18752 		/* .... and stop the sound */
18753 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18754 			Sound_Stop(marineStatusPointer->soundHandle);
18755 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
18756 		}
18757 	}
18758 
18759 	marineStatusPointer->stateTimer -= (NormalFrameTime);
18760 
18761 	/* You must have fired already. */
18762 
18763 	if(marineStatusPointer->stateTimer > 0)	{
18764 		#if MARINE_STATE_PRINT
18765 		textprint("Returning continue at range %d.\n",range);
18766 		#endif
18767 		return(SRC_No_Change);
18768 	}
18769 
18770 	if ((range < MARINE_CLOSE_APPROACH_DISTANCE)||(marineStatusPointer->Android)
18771 		//||(marineStatusPointer->volleySize<marineStatusPointer->My_Weapon->MinimumBurstSize))
18772 		)
18773 	{
18774 		/* renew firing, as we are still too close to approach */
18775 		marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
18776 		marineStatusPointer->volleySize = 0;
18777 		GLOBALASSERT(marineStatusPointer->Target);
18778 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
18779 		#if MARINE_STATE_PRINT
18780 		textprint("Returning too close renewal at range %d.\n",range);
18781 		#endif
18782 		if (marineStatusPointer->Android==0) {
18783 		//	marineStatusPointer->Courage-=(ONE_FIXED>>3);
18784 		}
18785 		return(SRC_No_Change);
18786 	}
18787 	else
18788 	{
18789 		/* we are far enough away, so return to approach */
18790 
18791 		#if MARINE_STATE_PRINT
18792 		textprint("Returning too far termination at range %d.\n",range);
18793 		#endif
18794 		/* Remove the gunflash */
18795 		if(marineStatusPointer->myGunFlash)
18796 		{
18797 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18798 			marineStatusPointer->myGunFlash = NULL;
18799 		}
18800 		marineStatusPointer->volleySize = 0;
18801 		return(SRC_Request_Approach);
18802 	}
18803 	return(SRC_No_Change);
18804 }
18805 
18806 static STATE_RETURN_CONDITION Execute_MNS_DischargeSkeeter(STRATEGYBLOCK *sbPtr)
18807 {
18808 	MARINE_STATUS_BLOCK *marineStatusPointer;
18809 	VECTORCH orientationDirn,relPos,relPos2;
18810 	int correctlyOrientated,range;
18811 
18812 	LOCALASSERT(sbPtr);
18813 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
18814 	LOCALASSERT(marineStatusPointer);
18815 
18816 	#if MARINE_STATE_PRINT
18817 	textprint("Firing Skeeter... ");
18818 	#endif
18819 
18820 	/* zero velocity */
18821 	LOCALASSERT(sbPtr->DynPtr);
18822 	sbPtr->DynPtr->LinVelocity.vx = 0;
18823 	sbPtr->DynPtr->LinVelocity.vy = 0;
18824 	sbPtr->DynPtr->LinVelocity.vz = 0;
18825 
18826 	/* If a skeeter launcher has started firing, he can't stop! */
18827 
18828 	if (marineStatusPointer->clipammo==0) {
18829 		/* Reload here. */
18830 		return(SRC_Request_Reload);
18831 	}
18832 
18833 	if (marineStatusPointer->Target) {
18834 		/* Here we must have a target.  Renew suspicion for new arrivals. */
18835 		if (NpcSquad.Squad_Suspicion==0) {
18836 			PointAlert(2,&marineStatusPointer->weaponTarget);
18837 		}
18838 	}
18839 
18840 	if (marineStatusPointer->stateTimer==marineStatusPointer->My_Weapon->FiringTime) {
18841 
18842 		/* First cycle. */
18843 		if (marineStatusPointer->HModelController.Tweening==Controller_NoTweening) {
18844 			marineStatusPointer->HModelController.Playing=0;
18845 		}
18846 
18847 		/* Only terminate if you haven't begun firing yet... */
18848 
18849 		if (marineStatusPointer->Target==NULL) {
18850 			#if MARINE_STATE_PRINT
18851 			textprint("Returning no target.\n");
18852 			#endif
18853 			return(SRC_Request_Wait);
18854 		}
18855 
18856 		if(!MarineCanSeeTarget(sbPtr))
18857 		{
18858 			#if 1
18859 			/* ... and remove the gunflash */
18860 			if(marineStatusPointer->myGunFlash)
18861 			{
18862 				RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18863 				marineStatusPointer->myGunFlash = NULL;
18864 			}
18865 			#endif
18866 
18867 			/* .... and stop the sound */
18868 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18869 				Sound_Stop(marineStatusPointer->soundHandle);
18870 				Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
18871 			}
18872 
18873 			#if MARINE_STATE_PRINT
18874 			textprint("Returning no target.\n");
18875 			#endif
18876 			return(SRC_Request_Wait);
18877 		}
18878 
18879 		GLOBALASSERT(marineStatusPointer->Target);
18880 		NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
18881 		/* Fix weapon target! */
18882 		if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
18883 			marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
18884 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
18885 			marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
18886 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
18887 			marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
18888 				marineStatusPointer->My_Weapon->TargetCallibrationShift);
18889 		}
18890 
18891 		/* orientate to firing point first */
18892 		orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
18893 		orientationDirn.vy = 0;
18894 		orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
18895 		correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
18896 
18897 		/* Consider range. */
18898 
18899 		relPos.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(sbPtr->DynPtr->Position.vx);
18900 		relPos.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(sbPtr->DynPtr->Position.vy);
18901 		relPos.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(sbPtr->DynPtr->Position.vz);
18902 
18903 		relPos2.vx=(marineStatusPointer->Target->DynPtr->Position.vx)-(marineStatusPointer->Target->DynPtr->PrevPosition.vx);
18904 		relPos2.vy=(marineStatusPointer->Target->DynPtr->Position.vy)-(marineStatusPointer->Target->DynPtr->PrevPosition.vy);
18905 		relPos2.vz=(marineStatusPointer->Target->DynPtr->Position.vz)-(marineStatusPointer->Target->DynPtr->PrevPosition.vz);
18906 
18907 		range=VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
18908 
18909 		/* Are they, by some chance, really close? */
18910 		if (range<marineStatusPointer->My_Weapon->MinRange) {
18911 			/* Even a complete idiot wouldn't fire this thing by reflex. */
18912 			return(SRC_Request_PullPistol);
18913 		}
18914 
18915 		if (correctlyOrientated) {
18916 			/* If you are correctly oriented, you can now fire! */
18917 			marineStatusPointer->HModelController.Playing=1;
18918 			marineStatusPointer->HModelController.sequence_timer=0;
18919 			marineStatusPointer->stateTimer-=NormalFrameTime;
18920 
18921 			if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18922 				Sound_Stop(marineStatusPointer->soundHandle);
18923 			}
18924 			if(marineStatusPointer->soundHandle==SOUND_NOACTIVEINDEX) {
18925 				Sound_Play(marineStatusPointer->My_Weapon->StartSound,"de",&(sbPtr->DynPtr->Position),&(marineStatusPointer->soundHandle));
18926 			}
18927 		}
18928 		return(SRC_No_Change);
18929 	} else if (marineStatusPointer->stateTimer>0) {
18930 
18931 		/* We must be in the build up. */
18932 		if (marineStatusPointer->Target) {
18933 			NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
18934 			/* Fix weapon target! */
18935 			if (marineStatusPointer->My_Weapon->TargetCallibrationShift) {
18936 				marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
18937 					marineStatusPointer->My_Weapon->TargetCallibrationShift);
18938 				marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
18939 					marineStatusPointer->My_Weapon->TargetCallibrationShift);
18940 				marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
18941 					marineStatusPointer->My_Weapon->TargetCallibrationShift);
18942 			}
18943 
18944 			/* orientate to firing point first */
18945 			orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
18946 			orientationDirn.vy = 0;
18947 			orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
18948 			correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE,NULL);
18949 		} else {
18950 			/* Tough! */
18951 			correctlyOrientated = 1;
18952 		}
18953 
18954 		/* look after the gun flash */
18955 		if(marineStatusPointer->myGunFlash) {
18956 			MaintainMarineGunFlash(sbPtr);
18957 		} else {
18958 			CreateMarineGunFlash(sbPtr);
18959 		}
18960 
18961 		/* look after the sound */
18962 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18963 			Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
18964 		}
18965 
18966 		marineStatusPointer->stateTimer -= NormalFrameTime;
18967 
18968 		#if MARINE_STATE_PRINT
18969 		textprint("Turning to face.\n");
18970 		#endif
18971 		return(SRC_No_Change);
18972 
18973 	} else {
18974 		/* Now fire a skeeter. */
18975 
18976 		/* Remove the gunflash */
18977 		if(marineStatusPointer->myGunFlash)
18978 		{
18979 			RemoveNPCGunFlashEffect(marineStatusPointer->myGunFlash);
18980 			marineStatusPointer->myGunFlash = NULL;
18981 		}
18982 		/* .... and stop the sound */
18983 		if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
18984 			Sound_Stop(marineStatusPointer->soundHandle);
18985 			Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d",&(sbPtr->DynPtr->Position));
18986 		}
18987 
18988 		{
18989 			SECTION_DATA *rocket_section;
18990 
18991 			rocket_section=GetThisSectionData(marineStatusPointer->HModelController.section_data,"dum flash");
18992 
18993 			LOCALASSERT(rocket_section);
18994 
18995 			CreateFrisbeeKernel(&rocket_section->World_Offset, &rocket_section->SecMat,0);
18996 
18997 			if (marineStatusPointer->clipammo>0) {
18998 				marineStatusPointer->clipammo--;
18999 			}
19000 		}
19001 
19002 		/* You must have fired already. */
19003 
19004 		if(range < MARINE_CLOSE_APPROACH_DISTANCE)
19005 		{
19006 			/* renew firing, as we are still too close to approach */
19007 			marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
19008 			marineStatusPointer->volleySize = 0;
19009 			GLOBALASSERT(marineStatusPointer->Target);
19010 			NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
19011 			#if MARINE_STATE_PRINT
19012 			textprint("Returning too close renewal at range %d.\n",range);
19013 			#endif
19014 			return(SRC_No_Change);
19015 		}
19016 		else
19017 		{
19018 			/* we are far enough away, so return to approach */
19019 
19020 			#if MARINE_STATE_PRINT
19021 			textprint("Returning too far termination at range %d.\n",range);
19022 			#endif
19023 			return(SRC_Request_Approach);
19024 		}
19025 
19026 	}
19027 
19028 	return(SRC_No_Change);
19029 }
19030 
19031 static STATE_RETURN_CONDITION Execute_MNS_AcidAvoidance(STRATEGYBLOCK *sbPtr)
19032 {
19033 	MARINE_STATUS_BLOCK *marineStatusPointer;
19034 	DYNAMICSBLOCK *dynPtr;
19035 	VECTORCH velocityDirection = {0,0,0};
19036 
19037 	/* Your mission: to advance out of the acid. */
19038 
19039 	LOCALASSERT(sbPtr);
19040 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
19041 	dynPtr = sbPtr->DynPtr;
19042 	LOCALASSERT(marineStatusPointer);
19043 	LOCALASSERT(dynPtr);
19044 
19045 	/* Where are we going? */
19046 
19047 	marineStatusPointer->stateTimer-=NormalFrameTime;
19048 	if (marineStatusPointer->stateTimer<0) {
19049 		return(SRC_Request_Approach);
19050 	}
19051 
19052 	/* Ok: should have a current target at this stage... */
19053 	NPCGetMovementDirection(sbPtr, &velocityDirection, &(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
19054 	NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);
19055 	HandleMovingAnimations(sbPtr);
19056 
19057 	if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager)) {
19058 		/* Go to all new avoidance. */
19059 		return(SRC_Request_Avoidance);
19060 	}
19061 	return(SRC_No_Change);
19062 
19063 }
19064 
19065 void Marine_Activate_AcidAvoidance_State(STRATEGYBLOCK *sbPtr, VECTORCH *incidence) {
19066 
19067 	MARINE_STATUS_BLOCK *marineStatusPointer;
19068 
19069 	LOCALASSERT(sbPtr);
19070 	marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
19071 	LOCALASSERT(marineStatusPointer);
19072 
19073 	marineStatusPointer->gotapoint=0;
19074 
19075 	NPC_InitMovementData(&(marineStatusPointer->moveData));
19076 	NPC_InitWanderData(&(marineStatusPointer->wanderData));
19077 	InitWaypointManager(&marineStatusPointer->waypointManager);
19078 	marineStatusPointer->volleySize = 0;
19079 	marineStatusPointer->lastState=marineStatusPointer->behaviourState;
19080 	marineStatusPointer->behaviourState = MBS_AcidAvoidance;
19081 	marineStatusPointer->stateTimer = ONE_FIXED;
19082 
19083 	/* Get a destination. */
19084 	{
19085 		VECTORCH dest;
19086 		if (incidence) {
19087 			dest=*incidence;
19088 		} else {
19089 			/* Boo. */
19090 			dest.vx=sbPtr->DynPtr->OrientMat.mat11;
19091 			dest.vy=sbPtr->DynPtr->OrientMat.mat12;
19092 			dest.vy=sbPtr->DynPtr->OrientMat.mat13;
19093 		}
19094 		AlignVelocityToGravity(sbPtr,&dest);
19095 		if (Approximate3dMagnitude(&dest)==0) {
19096 			/* Boo. */
19097 			dest.vx=sbPtr->DynPtr->OrientMat.mat11;
19098 			dest.vy=sbPtr->DynPtr->OrientMat.mat12;
19099 			dest.vy=sbPtr->DynPtr->OrientMat.mat13;
19100 		}
19101 		marineStatusPointer->wanderData.worldPosition=sbPtr->DynPtr->Position;
19102 
19103 		marineStatusPointer->wanderData.worldPosition.vx+=(dest.vx>>6);
19104 		marineStatusPointer->wanderData.worldPosition.vy+=(dest.vy>>6);
19105 		marineStatusPointer->wanderData.worldPosition.vz+=(dest.vz>>6);
19106 
19107 	}
19108 
19109 	/* Not sure we need an expression for this one. */
19110 	#if 0
19111 	Marine_QueueNeutralExpression(sbPtr);
19112 	#endif
19113 
19114 	HandleMovingAnimations(sbPtr);
19115 
19116 }
19117