View difference between Paste ID: WKV0uCaN and i693j0an
SHOW: | | - or go back to the newest paste.
1
//=============================================================================
2
// SpaceMarine.
3
//=============================================================================
4
class SpaceMarine expands MaleBot;
5
6
#exec obj load file="UPakModels.u" Package="UPak"
7
#exec obj load file="Textures\UPakCloak.utx" Package="UPak"
8
9
#exec MESHMAP SETTEXTURE MESHMAP=marine NUM=1 TEXTURE=JMarine7
10
#exec MESHMAP SETTEXTURE MESHMAP=marine NUM=2 TEXTURE=JMarine8
11
12
#exec AUDIO IMPORT FILE="Sounds\Marine\UStatic.wav" NAME="UStatic" GROUP="Marines"
13
14
var weapon myWeapon;
15
var UPakShieldEffect BeamEffect;
16
var bool bFemale;
17
var PathNodeIterator pni;
18
19
struct MarineSound
20
{
21
	var() float Duration;
22
	var() name UsedInState;
23
	var() Sound SoundName;
24
	var byte bPlayed;
25
	var SpaceMarine LastSaidBy;
26
}; 
27
28
var() MarineSound VoiceList[20];
29
30
var Pawn SaluteTarget;
31
var Pawn CommunicateTarget, MsgReceivedFrom;
32
var int Counting;
33
var bool bWarnedFriends;
34
var bool bTransmissionDead;
35
var bool bCommunicateTargetInRange;
36
var bool bCommunicating;
37
var float IncomingMessageLength;
38
39
var bool bHuntingTransmitted;
40
41
var MarineVoiceController PhraseDirector;
42
43
var MarineWaveInfo MarineBeamController;
44
var bool bBeamingIn;
45
var class< Weapon > StartWeapon;
46
var MarineVoicePack MyVoicePack;
47
48
function PostBeginPlay()
49
{
50
	if( pni == None )
51
	{
52
		pni = Spawn( class'PathNodeIterator' );
53
	}
54
	pni.CheckUPak();
55
	
56
	if( !Level.Game.bDeathMatch || MarineWaveInfo(Owner)!=none )
57
	{
58
		if( PlayerReplicationInfo!=None )
59
		{
60
			PlayerReplicationInfo.Destroy();
61
			PlayerReplicationInfo = None;
62
		}
63
		AttitudeToPlayer = ATTITUDE_Hate;
64
		bIsPlayer = False;
65
		CombatStyle = 1;
66
	}
67
	if( !Level.Game.bDeathMatch && FRand() < 0.15 )
68
		SetFemaleGender();
69
	
70
	if( MarineWaveInfo( Owner ) != none )
71
	{
72
		MarineBeamController = MarineWaveInfo( Owner );		
73
		StartWeapon = MarineBeamController.MarineWeapons[ MarineBeamController.CurrentMarine ];
74
	}
75
	else StartWeapon = class'CARifle';
76
	ForEach AllActors(Class'MarineVoicePack',MyVoicePack)
77
		Break;
78
	if( MyVoicePack==None )
79
		MyVoicePack = Spawn(Class'MarineVoicePack');
80
	Super.PostBeginPlay();
81
}
82
83
function SetFemaleGender()
84
{
85
	drown=Sound'UnrealShare.Female.mdrown2fem';
86
	breathagain=Sound'UnrealShare.Female.hgasp3fem';
87
	HitSound3=Sound'UnrealShare.Female.linjur3fem';
88
	HitSound4=Sound'UnrealShare.Female.hinjur4fem';
89
	Die2=Sound'UnrealShare.Female.death3cfem';
90
	Die3=Sound'UnrealShare.Female.death2afem';
91
	Die4=Sound'UnrealShare.Female.death4cfem';
92
	GaspSound=Sound'UnrealShare.Female.lgasp1fem';
93
	UWHit1=Sound'UnrealShare.Female.FUWHit1';
94
	UWHit2=Sound'UnrealShare.Male.MUWHit2';
95
	LandGrunt=Sound'UnrealShare.Female.lland1fem';
96
	JumpSound=Sound'UnrealShare.Female.jump1fem';
97
	HitSound1=Sound'UnrealShare.Female.linjur1fem';
98-
	bIsFemale=True;
98+
99
	Die=Sound'UnrealShare.Female.death1dfem';
100
	bFemale = true;
101
	bIsFemale = true;
102
	if (PlayerReplicationInfo != none)
103
		PlayerReplicationInfo.bIsFemale = true;
104
}
105
106
function PlayTurning()
107
{
108
	BaseEyeHeight = Default.BaseEyeHeight;
109
	if ( (Weapon == None) || (Weapon.Mass < 20) )
110
		PlayAnim('TurnLG', 0.3, 0.3);
111
	else
112
		PlayAnim('TurnLG', 0.3, 0.3);
113
}
114
115
function TweenToWalking(float tweentime)
116
{
117
	if ( Physics == PHYS_Swimming )
118
	{
119
		if ( (vector(Rotation) Dot Acceleration) > 0 )
120
			TweenToSwimming(tweentime);
121
		else
122
			TweenToWaiting(tweentime);
123
	}
124
		
125
	BaseEyeHeight = Default.BaseEyeHeight;
126
	if (Weapon == None)
127
		TweenAnim('Walk', tweentime);
128
	else if ( Weapon.bPointing ) 
129
	{
130
		if (Weapon.Mass < 20)
131
			TweenAnim('WalkSMFR', tweentime);
132
		else
133
			TweenAnim('WalkLGFR', tweentime);
134
	}
135
	else
136
	{
137
		if (Weapon.Mass < 20)
138
			TweenAnim('WalkSM', tweentime);
139
		else
140
			TweenAnim('WalkLG', tweentime);
141
	} 
142
}
143
144
function TweenToRunning(float tweentime)
145
{
146
	if ( Physics == PHYS_Swimming )
147
	{
148
		if ( (vector(Rotation) Dot Acceleration) > 0 )
149
			TweenToSwimming(tweentime);
150
		else TweenToWaiting(tweentime);
151
		return;
152
	}
153
	BaseEyeHeight = Default.BaseEyeHeight;
154
155
	if (Weapon == None)
156
		TweenAnim('RunLG', tweentime);
157
	else if ( Weapon.bPointing ) 
158
	{
159
		if (Weapon.Mass < 20)
160
			TweenAnim('RunLGFR', tweentime);
161
		else
162
			TweenAnim('RunLGFR', tweentime);
163
	}
164
	else
165
	{
166
		if (Weapon.Mass < 20)
167
			TweenAnim('RunLG', tweentime);
168
		else
169
			TweenAnim('RunLG', tweentime);
170
	} 
171
}
172
173
function PlayWalking()
174
{
175
	if ( Physics == PHYS_Swimming )
176
	{
177
		if ( (vector(Rotation) Dot Acceleration) > 0 )
178
			PlaySwimming();
179
		else
180
			PlayWaiting();
181
		return;
182
	}
183
184
	BaseEyeHeight = Default.BaseEyeHeight;
185
	if (Weapon == None)
186
		LoopAnim('Walk');
187
	else if ( Weapon.bPointing ) 
188
	{
189
		if (Weapon.Mass < 20)
190
			LoopAnim('WalkSMFR');
191
		else
192
			LoopAnim('WalkLGFR');
193
	}
194
	else
195
	{
196
		if (Weapon.Mass < 20)
197
			LoopAnim('WalkSM');
198
		else
199
			LoopAnim('WalkLG');
200
	}
201
}
202
203
204
function PlayRunning()
205
{
206
	if ( Physics == PHYS_Swimming )
207
	{
208
		if ( (vector(Rotation) Dot Acceleration) > 0 )
209
			PlaySwimming();
210
		else
211
			PlayWaiting();
212
		return;
213
	}
214
215
	BaseEyeHeight = Default.BaseEyeHeight;
216
	if (Weapon == None)
217
		LoopAnim('RunLG');
218
	else if ( Weapon.bPointing ) 
219
	{
220
		if (Weapon.Mass < 20)
221
			LoopAnim('RunLGFR');
222
		else
223
			LoopAnim('RunLGFR');
224
	}
225
	else
226
	{
227
		if (Weapon.Mass < 20)
228
			LoopAnim('RunLG');
229
		else
230
			LoopAnim('RunLG');
231
	}
232
}
233
234
function PlayRising()
235
{
236
	BaseEyeHeight = 0.4 * Default.BaseEyeHeight;
237
	TweenAnim('DuckWlkS', 0.7);
238
}
239
240
function PlayFeignDeath()
241
{
242
	local float decision;
243
244
	BaseEyeHeight = 0;
245
	if ( decision < 0.33 )
246
		TweenAnim('DeathEnd', 0.5);
247
	else if ( decision < 0.67 )
248
		TweenAnim('DeathEnd2', 0.5);
249
	else 
250
		TweenAnim('DeathEnd2', 0.5);
251
}
252
253
function PlayDying(name DamageType, vector HitLoc)
254
{
255
	local vector X,Y,Z, HitVec, HitVec2D;
256
	local float dotp;
257
	local carcass carc;
258
259
	BaseEyeHeight = Default.BaseEyeHeight;
260
	PlayDyingSound();
261
			
262
	if ( FRand() < 0.15 )
263
	{
264
		PlayAnim('Dead3',0.7,0.1);
265
		return;
266
	}
267
268
	// check for big hit
269
	if ( (Velocity.Z > 250) && (FRand() < 0.7) )
270
	{
271
		PlayAnim('Dead2', 0.7, 0.1);
272
		return;
273
	}
274
275
	// check for head hit
276
	if ( ((DamageType == 'Decapitated') || (HitLoc.Z - Location.Z > 0.6 * CollisionHeight))
277
		 && !Level.Game.bVeryLowGore )
278
	{
279
		DamageType = 'Decapitated';
280
		if ( Level.NetMode != NM_Client )
281
		{
282
			if (bFemale)
283
				carc = Spawn(class 'FemaleHead',,, Location + CollisionHeight * vect(0,0,0.8), Rotation + rot(3000,0,16384) );
284
			else
285
				carc = Spawn(class 'MaleHead',,, Location + CollisionHeight * vect(0,0,0.8), Rotation + rot(3000,0,16384) );
286
			if (carc != None)
287
			{
288
				carc.Initfor(self);
289
				carc.Velocity = Velocity + VSize(Velocity) * VRand();
290
				carc.Velocity.Z = FMax(carc.Velocity.Z, Velocity.Z);
291
			}
292
		}
293
		PlayAnim('Dead3', 0.7, 0.1);
294
		return;
295
	}
296
297
	
298
	if ( FRand() < 0.15)
299
	{
300
		PlayAnim('Dead2', 0.7, 0.1);
301
		return;
302
	}
303
304
	GetAxes(Rotation,X,Y,Z);
305
	X.Z = 0;
306
	HitVec = Normal(HitLoc - Location);
307
	HitVec2D= HitVec;
308
	HitVec2D.Z = 0;
309
	dotp = HitVec2D dot X;
310
	
311
	if (Abs(dotp) > 0.71) //then hit in front or back
312
		PlayAnim('Dead3', 0.7, 0.1);
313
	else
314
	{
315
		dotp = HitVec dot Y;
316
		if ( (dotp > 0.0) && !Level.Game.bVeryLowGore )
317
		{
318
			PlayAnim('Dead2', 0.7, 0.1);
319
			carc = Spawn(class 'Arm1');
320
			if (carc != None)
321
			{
322
				carc.Initfor(self);
323
				carc.Velocity = Velocity + VSize(Velocity) * VRand();
324
				carc.Velocity.Z = FMax(carc.Velocity.Z, Velocity.Z);
325
			}
326
		}
327
		else
328
			PlayAnim('Dead3', 0.7, 0.1);
329
	}
330
}
331
332
function PlayGutHit(float tweentime)
333
{
334
	if ( (AnimSequence == 'GutHit') || (AnimSequence == 'Dead2') )
335
	{
336
		if (FRand() < 0.5)
337
			TweenAnim('LeftHit', tweentime);
338
		else
339
			TweenAnim('RightHit', tweentime);
340
	}
341
	else if ( FRand() < 0.6 )
342
		TweenAnim('GutHit', tweentime);
343
	else
344
		TweenAnim('Dead2', tweentime);
345
346
}
347
348
function PlayHeadHit(float tweentime)
349
{
350
	if ( (AnimSequence == 'HeadHit') || (AnimSequence == 'Dead3') )
351
		TweenAnim('GutHit', tweentime);
352
	else if ( FRand() < 0.6 )
353
		TweenAnim('HeadHit', tweentime);
354
	else
355
		TweenAnim('Dead2', tweentime);
356
}
357
358
function PlayLeftHit(float tweentime)
359
{
360
	if ( (AnimSequence == 'LeftHit') || (AnimSequence == 'Dead3') )
361
		TweenAnim('GutHit', tweentime);
362
	else if ( FRand() < 0.6 )
363
		TweenAnim('LeftHit', tweentime);
364
	else 
365
		TweenAnim('Dead3', tweentime);
366
}
367
368
function PlayRightHit(float tweentime)
369
{
370
	if ( (AnimSequence == 'RightHit') || (AnimSequence == 'Dead2') )
371
		TweenAnim('GutHit', tweentime);
372
	else if ( FRand() < 0.6 )
373
		TweenAnim('RightHit', tweentime);
374
	else
375
		TweenAnim('Dead3', tweentime);
376
}	
377
	
378
function PlayLanded(float impactVel)
379
{	
380
	impactVel = impactVel/JumpZ;
381
	impactVel = 0.1 * impactVel * impactVel;
382
	BaseEyeHeight = Default.BaseEyeHeight;
383
384
	if ( impactVel > 0.17 )
385
		PlaySound(LandGrunt, SLOT_Talk, FMin(4, 5 * impactVel),false,1600,FRand()*0.4+0.8);
386
	if ( !FootRegion.Zone.bWaterZone && (impactVel > 0.01) )
387
		PlaySound(Land, SLOT_Interact, FClamp(4 * impactVel,0.2,4.5), false,1600, 1.0);
388
389
	if ( (impactVel > 0.06) || (GetAnimGroup(AnimSequence) == 'Jumping') )
390
	{
391
		if ( (Weapon == None) || (Weapon.Mass < 20) )
392
			TweenAnim('LandLGFr', 0.12);
393
		else
394
			TweenAnim('LandLGFR', 0.12);
395
	}
396
	else if ( !IsAnimating() )
397
	{
398
		if ( GetAnimGroup(AnimSequence) == 'TakeHit' )
399
			AnimEnd();
400
		else 
401
		{
402
			if ( (Weapon == None) || (Weapon.Mass < 20) )
403
				TweenAnim('LandLGFr', 0.12);
404
			else
405
				TweenAnim('LandLGFR', 0.12);
406
		}
407
	}
408
}
409
	
410
function PlayInAir()
411
{
412
	BaseEyeHeight =  0.7 * Default.BaseEyeHeight;
413
	if ( (Weapon == None) || (Weapon.Mass < 20) )
414
		TweenAnim('JumpLgl', 0.8);
415
	else
416
		TweenAnim('JumpLgl', 0.8); 
417
}
418
419
function PlayDuck()
420
{
421
	BaseEyeHeight = 0;
422
	if ( (Weapon == None) || (Weapon.Mass < 20) )
423
		TweenAnim('LandLgFr', 0.25);
424
	else
425
		TweenAnim('LandLgFr', 0.25);
426
}
427
428
function PlayCrawling()
429
{
430
	//log("Play duck");
431
	BaseEyeHeight = 0;
432
	if ( (Weapon == None) || (Weapon.Mass < 20) )
433
		LoopAnim('DuckWlkS');
434
	else
435
		LoopAnim('DuckWlkL');
436
}
437
438
function TweenToWaiting(float tweentime)
439
{
440
	if ( Physics == PHYS_Swimming )
441
	{
442
		BaseEyeHeight = 0.7 * Default.BaseEyeHeight;
443
		if ( (Weapon == None) || (Weapon.Mass < 20) )
444
			TweenAnim('TreadSM', tweentime);
445
		else
446
			TweenAnim('TreadLG', tweentime);
447
	}
448
	else
449
	{
450
		BaseEyeHeight = Default.BaseEyeHeight;
451
		if ( Enemy != None )
452
			ViewRotation = Rotator(Enemy.Location - Location);
453
		else
454
			ViewRotation.Pitch = 0;
455
		ViewRotation.Pitch = ViewRotation.Pitch & 65535;
456
		If ( (ViewRotation.Pitch > RotationRate.Pitch) 
457
			&& (ViewRotation.Pitch < 65536 - RotationRate.Pitch) )
458
		{
459
			If (ViewRotation.Pitch < 32768) 
460
			{
461
				if ( (Weapon == None) || (Weapon.Mass < 20) )
462
					TweenAnim('AimUpL', 0.3);
463
				else
464
					TweenAnim('AimUpL', 0.3);
465
			}
466
			else
467
			{
468
				if ( (Weapon == None) || (Weapon.Mass < 20) )
469
					TweenAnim('AimDnL', 0.3);
470
				else
471
					TweenAnim('AimDnL', 0.3);
472
			}
473
		}
474
		else if ( (Weapon == None) || (Weapon.Mass < 20) )
475
		{
476
			TweenAnim('StillFirL', tweentime);
477
		}
478
		else
479
		{
480
			TweenAnim('StillFirL', tweentime);
481
		}
482
	}
483
}
484
485
function TweenToFighter(float tweentime)
486
{
487
	TweenToWaiting(tweentime);
488
}
489
	
490
function PlayChallenge()
491
{
492
	local float decision;
493
494
	decision = FRand();
495
	if ( decision < 0.6 )
496
		TweenToWaiting(0.1);
497
	else
498
		PlayAnim('TauntL');
499
}	
500
	
501
function PlayWaiting()
502
{
503
	local name newAnim;
504
	// Rate to play anim at;
505
	local float PlayRate;
506
	
507
	if ( Physics == PHYS_Swimming )
508
	{
509
		BaseEyeHeight = 0.7 * Default.BaseEyeHeight;
510
		if ( (Weapon == None) || (Weapon.Mass < 20) )
511
			LoopAnim('TreadSM');
512
		else
513
			LoopAnim('TreadLG');
514
	}
515
	else
516
	{	
517
		BaseEyeHeight = Default.BaseEyeHeight;
518
		if ( (Weapon != None) && Weapon.bPointing )
519
		{
520
			if ( Weapon.Mass < 20 )
521
			{
522
				TweenAnim( 'WalkLgFr', 0.001 );
523
			}
524
			else
525
			{
526
				TweenAnim( 'WalkLgFr', 0.001 );
527
			}
528
		}
529
		else
530
		{
531
			if ( FRand() < 0.005 )
532
			{
533
			}
534
			else
535
			{
536
				if ( (Weapon == None) || (Weapon.Mass < 20) )
537
				{
538
					if ( Health > 50 )
539
					{
540
						newAnim = 'Breath1L';
541
						PlayRate = 0.05;
542
					}
543
					else
544
						newAnim = 'Breath2L';
545
				}
546
				else
547
				{
548
					if ( Health > 50 )
549
						newAnim = 'Breath1L';
550
					else
551
						newAnim = 'Breath2L';
552
				}
553
								
554
555
				if ( AnimSequence == newAnim )
556
				{
557
					if ( PlayRate != 0 )
558
					{
559
						LoopAnim( newAnim, PlayRate );
560
					}
561
					else
562
					{
563
						LoopAnim(newAnim, 0.3 + 0.7 * FRand());
564
					}
565
				}
566
				else
567
				{
568
				
569
					if ( PlayRate != 0 )
570
					{
571
						PlayAnim( newAnim, PlayRate, 0.25 );
572
					}
573
					else
574
					{
575
						PlayAnim(newAnim, 0.3 + 0.7 * FRand(), 0.25);
576
577
					}
578
				}
579
			}
580
		}
581
	}
582
}	
583
	
584
function PlayFiring()
585
{
586
	// switch animation sequence mid-stream if needed
587
	if (AnimSequence == 'RunLG')
588
		AnimSequence = 'RunLGFR';
589
	else if (AnimSequence == 'RunLG')
590
		AnimSequence = 'RunLGFR';
591
	else if (AnimSequence == 'WalkLG')
592
		AnimSequence = 'WalkLGFR';
593
	else if (AnimSequence == 'WalkSM')
594
		AnimSequence = 'WalkSMFR';
595
	else if ( AnimSequence == 'JumpSMFR' )
596
		TweenAnim('JumpSMFR', 0.03);
597
	else if ( AnimSequence == 'JumpLGFR' )
598
		TweenAnim('JumpLGFR', 0.03);
599
	else if ( (GetAnimGroup(AnimSequence) == 'Waiting') || (GetAnimGroup(AnimSequence) == 'Gesture') 
600
		&& (AnimSequence != 'TreadLG') && (AnimSequence != 'TreadSM') )
601
	{
602
		if ( Weapon.Mass < 20 )
603
			TweenAnim('StillFrRP', 0.02);
604
		else
605
			TweenAnim('StillFirL', 0.03 );
606
	}
607
}
608
609
function PlayWeaponSwitch(Weapon NewWeapon)
610
{
611
	if ( (Weapon == None) || (Weapon.Mass < 20) )
612
	{
613
		if ( (NewWeapon != None) && (NewWeapon.Mass > 20) )
614
		{
615
			if ( (AnimSequence == 'RunLG') || (AnimSequence == 'RunLGFR') )
616
				AnimSequence = 'RunLG';
617
			else if ( (AnimSequence == 'WalkSM') || (AnimSequence == 'WalkSMFR') )
618
				AnimSequence = 'WalkLG';	
619
		 	else if ( AnimSequence == 'JumpSMFR' )
620
		 		AnimSequence = 'JumpLGFR';
621
			else if ( AnimSequence == 'DuckWlkL' )
622
				AnimSequence = 'DuckWlkS';
623
		 	else if ( AnimSequence == 'StillFrRP' )
624
		 		AnimSequence = 'StillFRRP';
625
			else if ( AnimSequence == 'AimDnSm' )
626
				AnimSequence = 'AimDnLg';
627
			else if ( AnimSequence == 'AimUpSm' )
628
				AnimSequence = 'AimUpLg';
629
		 }	
630
	}
631
	else if ( (NewWeapon == None) || (NewWeapon.Mass < 20) )
632
	{		
633
		if ( (AnimSequence == 'RunLG') || (AnimSequence == 'RunLGFR') )
634
			AnimSequence = 'RunLG';
635
		else if ( (AnimSequence == 'WalkLG') || (AnimSequence == 'WalkLGFR') )
636
			AnimSequence = 'WalkSM';
637
	 	else if ( AnimSequence == 'JumpLGFR' )
638
	 		AnimSequence = 'JumpSMFR';
639
		else if ( AnimSequence == 'DuckWlkS' )
640
			AnimSequence = 'DuckWlkL';
641
	 	else if (AnimSequence == 'StillFRRP')
642
	 		AnimSequence = 'StillFrRP';
643
		else if ( AnimSequence == 'AimDnLg' )
644
			AnimSequence = 'AimDnSm';
645
		else if ( AnimSequence == 'AimUpLg' )
646
			AnimSequence = 'AimUpSm';
647
	}
648
}
649
650
function PlaySwimming()
651
{
652
	BaseEyeHeight = 0.7 * Default.BaseEyeHeight;
653
	if ((Weapon == None) || (Weapon.Mass < 20) )
654
		LoopAnim('SwimSM');
655
	else
656
		LoopAnim('SwimLG');
657
}
658
659
function TweenToSwimming(float tweentime)
660
{
661
	BaseEyeHeight = 0.7 * Default.BaseEyeHeight;
662
	if ((Weapon == None) || (Weapon.Mass < 20) )
663
		TweenAnim('SwimSM',tweentime);
664
	else
665
		TweenAnim('SwimLG',tweentime);
666
}
667
668
////////////////////////////////////////////////////////////////////////////////
669
// Non Animation stuff
670
////////////////////////////////////////////////////////////////////////////////
671
672
function eAttitude AttitudeTo(Pawn Other)
673
{
674
	if ( Level.Game.bTeamGame && (PlayerReplicationInfo.Team == Other.PlayerReplicationInfo.Team) )
675
		return ATTITUDE_Friendly; //teammate
676
	else if ( Other.IsA( 'SpaceMarine' ) )
677
		return ATTITUDE_Friendly;
678
	return ATTITUDE_Hate;
679
}
680
681
function damageAttitudeTo( pawn Other )
682
{
683
	Super.damageAttitudeTo(Other);
684
	if( Other==Enemy && MyVoicePack!=None )
685
		MyVoicePack.RequestBackup(Self);
686
}
687
function Killed(pawn Killer, pawn Other, name damageType)
688
{
689
	if( Other==Enemy && Enemy!=None && MyVoicePack!=None )
690
		MyVoicePack.TalkVictory(Self);
691
	Super.Killed(Killer,Other,damageType);
692
}
693
state Acquisition
694
{
695
	function BeginState()
696
	{
697
		if( MyVoicePack!=None && MyVoicePack.LastTalker!=self )
698
		{
699
			MyVoicePack.Talker = self;
700
			MyVoicePack.SetTimer( 0.1, false );
701
			MyVoicePack.bAcquirePhrase = true;
702
		}
703
		Super.BeginState();
704
	}
705
}
706
707
708
state WarnFriends expands Acquisition
709
{
710
	ignores SeePlayer;
711
	
712
	function BeginState()
713
	{
714
		bCommunicating = True;
715
	}
716
	
717
	function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, 
718
							Vector momentum, name damageType)
719
	{
720
		LastSeenPos = Enemy.Location;
721
		Global.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType);
722
		if ( health <= 0 )
723
		{
724
			if( !bTransmissionDead )
725
			{
726
				PlaySound( sound'hiss1pp', SLOT_Talk, 200, True, 256 );
727
				bTransmissionDead = True;
728
			}
729
			
730
			return;
731
		}
732
		if (NextState == 'TakeHit')
733
		{
734
			NextState = 'Attacking'; 
735
			NextLabel = 'Begin';
736
			GotoState('TakeHit'); 
737
		}
738
		else
739
			GotoState('Attacking');
740
	}
741
742
	function MessagePlayers()
743
	{
744
		local PlayerPawn P;
745
		
746
		foreach allactors( class'PlayerPawn', P )
747
		{
748
			P.ClientMessage( self$": I've found a target!" );
749
		}
750
	}
751
752
Begin:
753
	
754
/*	if( PhraseDirector.InitiatePlay( Self ) )
755
	{
756
		FinishAnim();
757
		Velocity *= 0;
758
		Acceleration *= 0;
759
		if( !bCommunicateTargetInRange )
760
		{
761
			PlayAnim( 'TalkREM', 0.25 );
762
		}
763
		else
764
		{
765
			TurnToward( CommunicateTarget );
766
			PlayAnim( 'WaveL', 0.25 );
767
		}
768
		Sleep( 0.15 );
769
		PlaySound( PhraseDirector.GetCurrentSoundName(), SLOT_Talk,, False );
770
		Sleep( PhraseDirector.GetCurrentSoundDuration() - 1 );
771
		MessagePlayers();
772
		PhraseDirector.Finished();
773
		bCommunicating = False;
774
		GotoState( 'Attacking' );
775
	}*/
776
	FinishAnim();
777
	PhraseDirector.Marine = Self;
778
	PhraseDirector.GotoState( 'BroadcastingSound' );
779
	Velocity *= 0;
780
	Acceleration *= 0;
781
	bCommunicating = True;
782
	if( !PhraseDirector.bReceiverInRange )
783
	{
784
		PlayAnim( 'TalkREM', 0.25 );
785
	}
786
	else
787
	{
788
		TurnToward( PhraseDirector.Receiver );
789
		PlayAnim( 'WaveL', 0.25 );
790
	}
791
	Sleep( 0.15 );
792
	PhraseDirector.Broadcast();
793
	FinishAnim();
794
	Sleep( PhraseDirector.GetCurrentSoundDuration() - 1 );
795
	bCommunicating = False;
796
	GotoState( 'Attacking' );
797
798
		
799
/*Begin:
800
	if ( FindCommunicateTarget() != None && !bWarnedFriends && !bTransmissionDead )
801
	{
802
		FinishAnim();
803
		Velocity *= 0;
804
		Acceleration *= 0;
805
		if( !bCommunicateTargetInRange )
806
		{
807
			PlayAnim( 'TalkREM', 0.25 );
808
		}
809
		else
810
		{
811
			TurnToward( CommunicateTarget );
812
			PlayAnim( 'WaveL', 0.25 );
813
		}
814
		Sleep( 0.15 );
815
		PlaySound( GetPhrase().SoundName, SLOT_Talk,, False );
816
		MessagePlayers();		
817
818
		if( !bCommunicateTargetInRange )
819
		{
820
			SpaceMarine( CommunicateTarget ).PlaySound( GetPhrase().SoundName, SLOT_Misc, 200, False, 256 );		
821
			SpaceMarine( CommunicateTarget ).MsgReceivedFrom = Self;
822
			SpaceMarine( CommunicateTarget ).bWarnedFriends = True;
823
		}
824
		SpaceMarine( CommunicateTarget ).Enemy = Enemy;
825
		SpaceMarine( CommunicateTarget ).IncomingMessageLength = 3.5;
826
		SpaceMarine( CommunicateTarget ).GotoState( 'AcknowledgeWarning' );
827
		FinishAnim();
828
		bWarnedFriends = True;
829
		CommunicateTarget = None;
830
	}
831
	bCommunicating = False;
832
	Gotostate('Attacking' );*/			
833
}
834
835
836
state AcknowledgeWarning expands Acquisition
837
{
838
	ignores SeePlayer;
839
	
840
	function BeginState()
841
	{
842
		bCommunicating = True;
843
	}
844
845
	function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, 
846
							Vector momentum, name damageType)
847
	{
848
		LastSeenPos = Enemy.Location;
849
		Global.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType);
850
		if ( health <= 0 && !bTransmissionDead )
851
		{
852
			PlaySound( sound'hiss1pp', SLOT_Talk, 200, True, 256 );
853
			bTransmissionDead = True;
854
			return;
855
		}
856
		if (NextState == 'TakeHit')
857
		{
858
			NextState = 'Attacking'; 
859
			NextLabel = 'Begin';
860
			GotoState('TakeHit'); 
861
		}
862
		else
863
			GotoState('Attacking');
864
	}
865
866
	function MessagePlayers()
867
	{
868
		local PlayerPawn P;
869
		
870
		foreach allactors( class'PlayerPawn', P )
871
		{
872
			P.ClientMessage( self$": Target data received." );
873
		}
874
	}
875
876
	// each sound should have an estimated length associated with it, to insure sleep durations are accurate enough.
877
	
878
	// acknowledge delay set by communicator based on message length, passed to receiver who sleeps(?) for that duration.
879
	
880
Begin:
881
882
	if ( MsgReceivedFrom != None && !bTransmissionDead )
883
	{
884
		FinishAnim();
885
		if( IncomingMessageLength > 0 )
886
		{
887
			Sleep( IncomingMessageLength );
888
		}
889
		Velocity *= 0;
890
		Acceleration *= 0;
891
		PlayAnim( 'TalkREM', 0.25 );
892
		MessagePlayers();
893
		PlaySound( GetPhrase().SoundName, SLOT_Talk,, False );
894
		SpaceMarine( MsgReceivedFrom ).PlaySound( GetPhrase().SoundName, SLOT_Misc, 200, False, 256 );		
895
		FinishAnim();
896
		bWarnedFriends = True;
897
		CommunicateTarget = None;
898
		Sleep( 1.4 );
899
	}
900
	bCommunicating = False;
901
	GotoState( 'Attacking' );
902
}
903
		
904
function Pawn FindCommunicateTarget()
905
{
906
	local SpaceMarine Marine;
907
	local Actor HitActor;
908
	local vector HitNormal, HitLocation;
909
		
910
	foreach allactors( class'SpaceMarine', Marine )
911
	{
912
		if( Marine != Self && !Marine.bCommunicating )
913
		{
914
			CommunicateTarget = Marine;
915
		}
916
	} 
917
	if( CommunicateTarget != None )
918
	{
919
		HitActor = Trace( HitLocation, HitNormal, CommunicateTarget.Location, Location, True );
920
		if ( HitActor == Self || HitActor == CommunicateTarget )
921
		{
922
			bCommunicateTargetInRange = True;
923
		}
924
		else
925
		{
926
			bCommunicateTargetInRange = False;
927
		}
928
	}
929
	return CommunicateTarget;
930
}
931
932
function Pawn GetCommunicateTarget()
933
{
934
	return CommunicateTarget;
935
}
936
937
938
function PlayDyingSound()
939
{
940
	local float rnd;
941
942
	if ( HeadRegion.Zone.bWaterZone )
943
	{
944
		if ( FRand() < 0.5 )
945
			PlaySound(UWHit1, SLOT_Pain,2.0,,,Frand()*0.2+0.9);
946
		else
947
			PlaySound(UWHit2, SLOT_Pain,2.0,,,Frand()*0.2+0.9);
948
		return;
949
	}
950
951
	rnd = FRand();
952
	if (rnd < 0.25)
953
		PlaySound(Die, SLOT_Talk,2.0);
954
	else if (rnd < 0.5)
955
		PlaySound(Die2, SLOT_Talk,2.0);
956
	else if (rnd < 0.75)
957
		PlaySound(Die3, SLOT_Talk,2.0);
958
	else 
959
		PlaySound(Die4, SLOT_Talk,2.0);
960
961
	if( bTransmissionDead && ( MsgReceivedFrom != None || CommunicateTarget != None ) )
962
	{
963
		if( MsgReceivedFrom != None )
964
		{
965
			MsgReceivedFrom.PlaySound( Die, SLOT_Talk, 2.0 );
966
		}
967
		else
968
		{
969
			CommunicateTarget.PlaySound( Die, SLOT_Talk, 2.0 );
970
		}
971
	}
972
}
973
974
975
976
//====================================================================================================
977
// Hunting State Overrides
978
//====================================================================================================
979
980
state Hunting
981
{
982
ignores EnemyNotVisible; 
983
984
	/* MayFall() called by engine physics if walking and bCanJump, and
985
		is about to go off a ledge.  Pawn has opportunity (by setting 
986
		bCanJump to false) to avoid fall
987
	*/
988
	function MayFall()
989
	{
990
		bCanJump = ( (MoveTarget != None) || PointReachable(Destination) );
991
	}
992
993
	function Bump(actor Other)
994
	{
995
		if (Pawn(Other) != None)
996
		{
997
			if (Enemy == Other)
998
				bReadyToAttack = True; //can melee right away
999
			SetEnemy(Pawn(Other));
1000
			LastSeenPos = Enemy.Location;
1001
		}
1002
		setTimer(2.0, false);
1003
		Disable('Bump');
1004
	}
1005
	
1006
    function FearThisSpot(Actor aSpot)
1007
	{
1008
		Destination = Location + 120 * Normal(Location - aSpot.Location); 
1009
		GotoState('Wandering', 'Moving');
1010
	}
1011
1012
	function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, 
1013
							Vector momentum, name damageType)
1014
	{
1015
		Global.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType);
1016
		if ( health <= 0 )
1017
			return;
1018
		bFrustrated = true;
1019
		if (NextState == 'TakeHit')
1020
		{
1021
			if (AttitudeTo(Enemy) == ATTITUDE_Fear)
1022
			{
1023
				NextState = 'Retreating';
1024
				NextLabel = 'Begin';
1025
			}
1026
			else
1027
			{
1028
				NextState = 'Hunting';
1029
				NextLabel = 'AfterFall';
1030
			}
1031
			GotoState('TakeHit'); 
1032
		}
1033
	}
1034
1035
	function HearNoise(float Loudness, Actor NoiseMaker)
1036
	{
1037
		if ( SetEnemy(NoiseMaker.instigator) )
1038
			LastSeenPos = Enemy.Location; 
1039
	}
1040
1041
	function SetFall()
1042
	{
1043
		NextState = 'Hunting'; 
1044
		NextLabel = 'AfterFall';
1045
		NextAnim = AnimSequence;
1046
		GotoState('FallingState'); 
1047
	}
1048
1049
	function bool SetEnemy(Pawn NewEnemy)
1050
	{
1051
		local float rnd;
1052
1053
		if (Global.SetEnemy(NewEnemy))
1054
		{
1055
			rnd = FRand();
1056
			bReadyToAttack = true;
1057
			DesiredRotation = Rotator(Enemy.Location - Location);
1058
			if ( CombatStyle > FRand() )
1059
				GotoState('Charging'); 
1060
			else
1061
				GotoState('Attacking');
1062
			return true;
1063
		}
1064
		return false;
1065
	} 
1066
1067
	function AnimEnd()
1068
	{
1069
		PlayRunning();
1070
		bFire = 0;
1071
		bAltFire = 0;
1072
		bReadyToAttack = true;
1073
		Disable('AnimEnd');
1074
	}
1075
	
1076
	function Timer()
1077
	{
1078
		bReadyToAttack = true;
1079
		Enable('Bump');
1080
		SetTimer(1.0, false);
1081
	}
1082
1083
	function HitWall(vector HitNormal, actor Wall)
1084
	{
1085
		if (Physics == PHYS_Falling)
1086
			return;
1087
		if ( Wall.IsA('Mover') && Mover(Wall).HandleDoor(self) )
1088
		{
1089
			if ( SpecialPause > 0 )
1090
				Acceleration = vect(0,0,0);
1091
			GotoState('Hunting', 'SpecialNavig');
1092
			return;
1093
		}
1094
		Focus = Destination;
1095
		if (PickWallAdjust())
1096
			GotoState('Hunting', 'AdjustFromWall');
1097
		else
1098
			MoveTimer = -1.0;
1099
	}
1100
1101
	function PickDestination()
1102
	{
1103
		local actor HitActor;
1104
		local vector HitNormal, HitLocation, nextSpot, ViewSpot;
1105
		local float posZ, elapsed;
1106
		local bool bCanSeeLastSeen;
1107
	
1108
		// If no enemy, or I should see him but don't, then give up		
1109
		if ( (Enemy == None) || (Enemy.Health <= 0) )
1110
		{
1111
			WhatToDoNext('','');
1112
			return;
1113
		}
1114
	
1115
		bAvoidLedges = false;
1116
		elapsed = Level.TimeSeconds - HuntStartTime;
1117
		if ( elapsed > 30 )
1118
		{
1119
				WhatToDoNext('','');
1120
				return;
1121
		}
1122
1123
		if ( JumpZ > 0 )
1124
			bCanJump = true;
1125
		
1126
		if ( ActorReachable(Enemy) )
1127
		{
1128
			if ( (numHuntPaths < 8 + Skill) || (elapsed < 15)
1129
				|| ((Normal(Enemy.Location - Location) Dot vector(Rotation)) > -0.5) )
1130
			{
1131
				Destination = Enemy.Location;
1132
				MoveTarget = None;
1133
				numHuntPaths++;
1134
			}
1135
			else
1136
				WhatToDoNext('','');
1137
			return;
1138
		}
1139
		numHuntPaths++;
1140
1141
		ViewSpot = Location + EyeHeight * vect(0,0,1);
1142
		bCanSeeLastSeen = false;
1143
		HitActor = Trace(HitLocation, HitNormal, LastSeenPos, ViewSpot, false);
1144
		bCanSeeLastSeen = (HitActor == None);
1145
		if ( bCanSeeLastSeen )
1146
		{
1147
			HitActor = Trace(HitLocation, HitNormal, LastSeenPos, Enemy.Location, false);
1148
			bHunting = (HitActor != None);
1149
		}
1150
		else
1151
			bHunting = true;
1152
1153
		if ( FindBestPathToward(Enemy) )
1154
			return;
1155
		MoveTarget = None;
1156
		if ( bFromWall )
1157
		{
1158
			bFromWall = false;
1159
			if ( !PickWallAdjust() )
1160
			{
1161
				if ( CanStakeOut() )
1162
					GotoState('StakeOut');
1163
				else
1164
					WhatToDoNext('', '');
1165
			}
1166
			return;
1167
		}
1168
		
1169
		if ( NumHuntPaths > 60 )
1170
		{
1171
			WhatToDoNext('', '');
1172
			return;
1173
		}
1174
1175
		if ( LastSeeingPos != vect(1000000,0,0) )
1176
		{
1177
			Destination = LastSeeingPos;
1178
			LastSeeingPos = vect(1000000,0,0);		
1179
			HitActor = Trace(HitLocation, HitNormal, Enemy.Location, ViewSpot, false);
1180
			if ( HitActor == None )
1181
			{
1182
				If (VSize(Location - Destination) < 20)
1183
				{
1184
					HitActor = Trace(HitLocation, HitNormal, Enemy.Location, ViewSpot, false);
1185
					if (HitActor == None)
1186
					{
1187
						SetEnemy(Enemy);
1188
						return;
1189
					}
1190
				}
1191
				return;
1192
			}
1193
		}
1194
1195
		bAvoidLedges = (CollisionRadius > 42);
1196
		posZ = LastSeenPos.Z + CollisionHeight - Enemy.CollisionHeight;
1197
		nextSpot = LastSeenPos - Normal(Enemy.Location - Enemy.OldLocation) * CollisionRadius;
1198
		nextSpot.Z = posZ;
1199
		HitActor = Trace(HitLocation, HitNormal, nextSpot , ViewSpot, false);
1200
		if ( HitActor == None )
1201
			Destination = nextSpot;
1202
		else if ( bCanSeeLastSeen )
1203
			Destination = LastSeenPos;
1204
		else
1205
		{
1206
			Destination = LastSeenPos;
1207
			HitActor = Trace(HitLocation, HitNormal, LastSeenPos , ViewSpot, false);
1208
			if ( HitActor != None )
1209
			{
1210
				// check if could adjust and see it
1211
				if ( PickWallAdjust() || FindViewSpot() )
1212
					GotoState('Hunting', 'AdjustFromWall');
1213
				else if ( VSize(Enemy.Location - Location) < 1200 )
1214
					GotoState('StakeOut');
1215
				else
1216
				{
1217
					WhatToDoNext('Waiting', 'TurnFromWall');
1218
					return;
1219
				}
1220
			}
1221
		}
1222
		LastSeenPos = Enemy.Location;				
1223
	}	
1224
1225
	function bool FindViewSpot()
1226
	{
1227
		local vector X,Y,Z, HitLocation, HitNormal;
1228
		local actor HitActor;
1229
		local bool bAlwaysTry;
1230
		GetAxes(Rotation,X,Y,Z);
1231
1232
		// try left and right
1233
		// if frustrated, always move if possible
1234
		bAlwaysTry = bFrustrated;
1235
		bFrustrated = false;
1236
		
1237
		HitActor = Trace(HitLocation, HitNormal, Enemy.Location, Location + 2 * Y * CollisionRadius, false);
1238
		if ( HitActor == None )
1239
		{
1240
			Destination = Location + 2.5 * Y * CollisionRadius;
1241
			return true;
1242
		}
1243
1244
		HitActor = Trace(HitLocation, HitNormal, Enemy.Location, Location - 2 * Y * CollisionRadius, false);
1245
		if ( HitActor == None )
1246
		{
1247
			Destination = Location - 2.5 * Y * CollisionRadius;
1248
			return true;
1249
		}
1250
		if ( bAlwaysTry )
1251
		{
1252
			if ( FRand() < 0.5 )
1253
				Destination = Location - 2.5 * Y * CollisionRadius;
1254
			else
1255
				Destination = Location - 2.5 * Y * CollisionRadius;
1256
			return true;
1257
		}
1258
1259
		return false;
1260
	}
1261
1262
	function BeginState()
1263
	{
1264
		if ( health <= 0 )
1265
			log(self$" hunting while dead");
1266
		SpecialGoal = None;
1267
		SpecialPause = 0.0;
1268
		bFromWall = false;
1269
		SetAlertness(0.5);
1270
		// Changed
1271
//		if( !bHuntingTransmitted )
1272
//		{
1273
//			GotoState( 'TransmitHuntingMessage' );
1274
//		}
1275
	}
1276
1277
	function EndState()
1278
	{
1279
		bAvoidLedges = false;
1280
		bHunting = false;
1281
		if ( JumpZ > 0 )
1282
			bCanJump = true;
1283
	}
1284
1285
AdjustFromWall:
1286
	StrafeTo(Destination, Focus); 
1287
	Destination = Focus; 
1288
	if ( MoveTarget != None )
1289
		Goto('SpecialNavig');
1290
	else
1291
		Goto('Follow');
1292
1293
Begin:
1294
	numHuntPaths = 0;
1295
	HuntStartTime = Level.TimeSeconds;
1296
AfterFall:
1297
	TweenToRunning(0.15);
1298
	bFromWall = false;
1299
1300
Follow:
1301
	WaitForLanding();
1302
	if ( CanSee(Enemy) )
1303
		SetEnemy(Enemy);
1304
	PickDestination();
1305
SpecialNavig:
1306
	if ( SpecialPause > 0.0 )
1307
	{
1308
		Disable('AnimEnd');
1309
		Acceleration = vect(0,0,0);
1310
		PlayChallenge();
1311
		Sleep(SpecialPause);
1312
		SpecialPause = 0.0;
1313
		Enable('AnimEnd');
1314
		Goto('AfterFall');
1315
	}
1316
	if (MoveTarget == None)
1317
		MoveTo(Destination);
1318
	else
1319
		MoveToward(MoveTarget); 
1320
1321
	Goto('Follow');
1322
}
1323
1324
//====================================================================================================
1325
// Hunting State Expansion
1326
//====================================================================================================
1327
1328
state TransmitHuntingMessage expands Hunting
1329
{
1330
	function BeginState()
1331
	{
1332
//		log( Self$" transmitting Hunting message." );
1333
	}
1334
	
1335
	function MessagePlayers()
1336
	{
1337
		local PlayerPawn P;
1338
		
1339
		foreach allactors( class'PlayerPawn', P )
1340
		{
1341
			P.ClientMessage( self$": I'm hunting!" );
1342
		}
1343
	}
1344
	
1345
Begin:
1346
	if ( FindCommunicateTarget() != None && !bTransmissionDead )
1347
	{
1348
		FinishAnim();
1349
		Velocity *= 0;
1350
		Acceleration *= 0;
1351
		if( !bCommunicateTargetInRange )
1352
		{
1353
			PlayAnim( 'TalkREM', 0.25 );
1354
		}
1355
		else
1356
		{
1357
			TurnToward( CommunicateTarget );
1358
			PlayAnim( 'WaveL', 0.25 );
1359
		}
1360
		Sleep( 0.15 );
1361
//		log( "Playing Hunting Notification to "$CommunicateTarget );
1362
		PlaySound( GetPhrase().SoundName, SLOT_Talk,, False );
1363
1364
		MessagePlayers();
1365
		
1366
		if( !bCommunicateTargetInRange )
1367
		{
1368
			SpaceMarine( CommunicateTarget ).PlaySound( GetPhrase().SoundName, SLOT_Misc, 200, False, 256 );
1369
			SpaceMarine( CommunicateTarget ).MsgReceivedFrom = Self;
1370
			SpaceMarine( CommunicateTarget ).bWarnedFriends = True;
1371
		}
1372
		FinishAnim();
1373
		CommunicateTarget = None;
1374
	}
1375
	bCommunicating = False;
1376
	bHuntingTransmitted = True;
1377
	Gotostate('Hunting' );			
1378
}
1379
		
1380
1381
function MarineSound GetPhrase()
1382
{
1383
	local int VoiceIncrementer;
1384
	local MarineSound Match;
1385
	
1386
	for( VoiceIncrementer = 0; VoiceIncrementer <= 19; VoiceIncrementer++ )
1387
	{
1388
		if( VoiceList[ VoiceIncrementer ].SoundName != None )
1389
		{
1390
			if( VoiceList[ VoiceIncrementer ].bPlayed == 0 )
1391
			{
1392
				if( VoiceList[ VoiceIncrementer ].UsedInState == GetStateName() && VoiceList[ VoiceIncrementer ].LastSaidBy != Self )
1393
				{
1394
					Match = VoiceList[ VoiceIncrementer ];
1395
					Match.LastSaidby = Self;
1396
					break;
1397
				}
1398
			}
1399
		}
1400
	}
1401
	
1402
	return Match;
1403
}
1404
1405
function bool MultipleMarineCheck()
1406
{
1407
	local SpaceMarine Marine;
1408
	foreach allactors( class'SpaceMarine', Marine )
1409
	{
1410
		if( Marine.Health > 0 && Marine != self )
1411
		{
1412
			return true;
1413
		}
1414
	}
1415
	
1416
	return false;
1417
}
1418
1419
		
1420
1421
state ReceiveIncomingMessage expands Acquisition
1422
{
1423
1424
	function BeginState()
1425
	{
1426
//		log( "ReceiveIncomingMessage state entered by "$Self$" at: "$Level.TimeSeconds );
1427
	}
1428
	
1429
	function EndState()
1430
	{
1431
//		log( "ReceiveIncomingMessage state exited by "$Self$" at: "$Level.TimeSeconds );
1432
	}
1433
1434
Receiving:
1435
	if( PhraseDirector.Marine.Enemy != Enemy )
1436
	{
1437
		Enemy = PhraseDirector.Marine.Enemy;
1438
	}	
1439
	
1440
	While( SpaceMarine( PhraseDirector.Marine ).bCommunicating )	
1441
	{
1442
		Sleep( 0.1 );
1443
	}			
1444
	
1445
	bCommunicating = True;
1446
1447
	PhraseDirector.Marine = Self;
1448
	PhraseDirector.GotoState( 'BroadcastingSound' );
1449
	if( !PhraseDirector.bReceiverInRange )
1450
	{
1451
		PlayAnim( 'TalkREM', 0.25 );
1452
	}
1453
	else
1454
	{
1455
		TurnToward( PhraseDirector.Receiver );
1456
		PlayAnim( 'WaveL', 0.25 );
1457
	}
1458
	Sleep( 0.15 );	
1459
	PhraseDirector.Broadcast();
1460
	Sleep( PhraseDirector.GetCurrentSoundDuration() - 1 );
1461
	bCommunicating = False;
1462
	GotoState( 'Hunting' );
1463
}
1464
1465
1466
// make sure the marine starts with the right weapon
1467
auto state StartUp
1468
{
1469
	ignores bump, takedamage, WarnTarget;
1470
	
1471
	function BeginState()
1472
	{
1473
		
1474
		if( bBeamingIn )
1475
		{
1476
			Style = STY_Translucent;
1477
			bMeshEnviroMap = True;
1478
			Texture = Texture'CloakTexture';
1479
			ScaleGlow = 0.01;
1480
			Fatness = 250;
1481
		}
1482
		
1483
		SetMovementPhysics(); 
1484
		if ( Physics == PHYS_Walking )
1485
		{
1486
			SetPhysics( PHYS_Falling );
1487
		}
1488
		if( StartWeapon == none )
1489
		{
1490
			StartWeapon = class'CARifle';
1491
		}
1492
		
1493
		if ( StartWeapon != None )
1494
		{
1495
			myWeapon = Spawn( StartWeapon );
1496
			myWeapon.PickupSound = none;
1497
			myWeapon.SelectSound = none;
1498
			myWeapon.CockingSound = none;
1499
			if ( myWeapon != None )
1500
			{
1501
				myWeapon.ReSpawnTime = 0.0;
1502
			}
1503
		}
1504
	}
1505
1506
Begin:
1507
	if( !bIsPlayer )
1508
	{
1509
		bIsPlayer = True;
1510
		myWeapon.Touch( self );
1511
		bIsPlayer = False;
1512
	}
1513
	else myWeapon.Touch( self );
1514
	myWeapon.PickupSound = myWeapon.Default.PickupSound;
1515
	myWeapon.SelectSound = myWeapon.Default.SelectSound;
1516
	myWeapon.CockingSound = myWeapon.Default.CockingSound;
1517
1518
	if (bIsFemale && !bFemale)
1519
		SetFemaleGender();
1520
1521
	if( MarineBeamController != none )
1522
	{
1523
		bHidden = true;
1524
		Land = none;
1525
		LandGrunt = none;
1526
		Spawn( class'Octagon',,, Location );
1527
		Sleep( 2.0 );
1528
		GotoState( 'BeamingIn' );
1529
	}
1530
	else
1531
	{
1532
		Mesh = default.Mesh;
1533
		Style = STY_Normal;
1534
		bMeshEnviroMap = False;
1535
		Texture = Default.Texture;
1536
		Skin = Default.Skin;
1537
		ScaleGlow = Default.ScaleGlow;
1538
		Fatness = Default.Fatness;
1539
		if( Weapon != none )
1540
		{
1541
			Weapon.Style = STY_Normal;
1542
			Weapon.bMeshEnviroMap = false;
1543
			Weapon.Texture = Weapon.Default.Texture;
1544
			Weapon.Scaleglow = Weapon.Default.ScaleGlow;
1545
			Weapon.Fatness = Weapon.Default.Fatness;
1546
		}
1547
1548
		WhatToDoNext('','');
1549
	}
1550
}
1551
event Touch( Actor Other )
1552
{
1553
	if( Inventory(Other)!=None && !bIsPlayer )
1554
	{
1555
		bIsPlayer = True;
1556
		Other.Touch(self);
1557
		bIsPlayer = False;
1558
	}
1559
	Super.Touch(Other);
1560
}
1561
function HidePlayer()
1562
{
1563
	if( !bIsPlayer )
1564
		Destroy();
1565
	else Super.HidePlayer();
1566
}
1567
state Dying
1568
{
1569
ignores SeePlayer, EnemyNotVisible, HearNoise, Died, Bump, Trigger, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, LongFall, SetFall, PainTimer;
1570
1571
	function ReStartPlayer()
1572
	{
1573
		if( bHidden && Level.Game.RestartPlayer(self) )
1574
		{
1575
			Velocity = vect(0,0,0);
1576
			Acceleration = vect(0,0,0);
1577
			ViewRotation = Rotation;
1578
			ReSetSkill();
1579
			SetPhysics(PHYS_Falling);
1580
			GotoState('Roaming');
1581
		}
1582
		else
1583
			GotoState('Dying', 'TryAgain');
1584
	}
1585
	
1586
	function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, 
1587
							Vector momentum, name damageType)
1588
	{
1589
		if ( !bHidden )
1590
			Super.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType);
1591
	}
1592
	
1593
	function BeginState()
1594
	{
1595
		if( Weapon != none )
1596
			Weapon.Destroy();
1597
		SetTimer(0, false);
1598
		Enemy = None;
1599
		AmbushSpot = None;
1600
		bFire = 0;
1601
		bAltFire = 0;
1602
		if( Weapon != none )
1603
			Weapon.AmmoType.AmmoAmount = Weapon.Default.AmmoType.AmmoAmount - Rand( 4 );
1604
		if( MarineBeamController != none )
1605
			MarineBeamController.SubtractMarine( Self );
1606
		bHidden = true;
1607
		SpawnCarcass();
1608
		if( !Level.Game.IsA( 'MarineMatch' ) )
1609
			Destroy();
1610
	}
1611
1612
	function EndState()
1613
	{
1614
		if ( Health <= 0 )
1615
			log(self$" health still <0");
1616
}
1617
1618
/*Begin:
1619
	Sleep(0.2);
1620
	if ( !bHidden )
1621
	{
1622
		SpawnCarcass();
1623
		HidePlayer();
1624
	}
1625
TryAgain:
1626
	Sleep(0.25 + DeathMatchGame(Level.Game).NumBots * FRand());
1627
	ReStartPlayer();
1628
	Goto('TryAgain');
1629
WaitingForStart:
1630
	bHidden = true;*/
1631
}
1632
1633
1634
// Beaming in effect is a placeholder
1635
1636
state BeamingIn
1637
{
1638
	ignores TakeDamage, Bump, SeePlayer, WarnTarget;
1639
	
1640
	function BeginState()
1641
	{
1642
		Mass = 20000;
1643
		Fatness = 5;
1644
		Land = default.Land;
1645
		LandGrunt = default.LandGrunt;
1646
		bHidden = false;		
1647
		LoopAnim( 'Breath2l', 0.3 );
1648
//		Style = STY_Translucent;
1649
//		bMeshEnviroMap = True;
1650
//		Texture = Texture'CloakTexture';
1651
//		Skin = Texture'CloakTexture';
1652
//		ScaleGlow = 0.01;
1653
//		Fatness = 250;
1654
		Style = STY_Translucent;
1655
		ScaleGlow = 0.0;
1656
		PlaySound( sound'CloakOff' );	
1657
		BeamEffect = Spawn( class'UPakShieldEffect', Self,, Location, Rotation );
1658
		BeamEffect.Mesh = Mesh;	
1659
		BeamEffect.DrawScale = DrawScale;	
1660
//		if( Weapon != none )
1661
//		{
1662
//			UPSE = Spawn( class'UPakShieldEffect', Weapon,, Weapon.Location, Weapon.Rotation );
1663
//		}
1664
		if( Weapon != none )
1665
		{
1666
			Weapon.Style = STY_Translucent;
1667
			Weapon.bMeshEnviroMap = true;
1668
			Weapon.Texture = Texture'upak.beamtexture';
1669
			Weapon.ScaleGlow = 0.01;
1670
			Weapon.Fatness = 250;
1671
		}
1672
		
1673
		SetTimer( 3.5, False );
1674
	}
1675
	
1676
	function Tick( float DeltaTime )
1677
	{
1678
//		if( ScaleGlow < 1.5 )
1679
//		{
1680
//			ScaleGlow += 0.01;
1681
			if( Weapon != none && Weapon.ScaleGlow < 1.5 )
1682
			{
1683
				Weapon.ScaleGlow += 0.001;
1684
			}
1685
			else
1686
			{
1687
				Weapon.Style = STY_Normal;
1688
				Weapon.bMeshEnviroMap = false;
1689
				Weapon.ScaleGlow = Weapon.Default.ScaleGlow;
1690
				Weapon.Texture = Weapon.Default.Texture;
1691
				Weapon.Fatness = Weapon.Default.Fatness;
1692
			}
1693
			
1694
	if( bHidden )
1695
		{
1696
			bHidden = false;
1697
			Weapon.bHidden = false;
1698
		}
1699
		
1700
		else
1701
		
1702
		if( FRand() < 0.2 && !bHidden )
1703
		{
1704
			bHidden = true;
1705
			Weapon.bHidden = true;
1706
		}
1707
		
1708
1709
//			if( Fatness > Default.Fatness )
1710
//	{
1711
//		Fatness -= 10;
1712
				if( Weapon != none && Weapon.Fatness > Weapon.Default.Fatness )
1713
				{
1714
					Weapon.Fatness -= 10;
1715
				}
1716
//	}
1717
//}
1718
		if( Fatness < 128 )
1719
		{
1720
			Fatness++;
1721
		}
1722
		
1723
	}
1724
	
1725
	function Timer()
1726
	{
1727
		BeamEffect.GotoState( 'OwnerFadeIn' );
1728
//		bHidden = false;
1729
//		Disable( 'Tick' );
1730
//		Style = STY_Normal;
1731
		bHidden = false;
1732
		bMeshEnviroMap = False;
1733
//		Texture = Default.Texture;
1734
//		Skin = Default.Skin;
1735
//		ScaleGlow = Default.ScaleGlow;
1736
//		Fatness = Default.Fatness;
1737
//		if( Weapon != none )
1738
//		{
1739
//			Weapon.Style = STY_Normal;
1740
//			Weapon.bMeshEnviroMap = false;
1741
//			Weapon.Texture = Weapon.Default.Texture;
1742
//			Weapon.Scaleglow = Weapon.Default.ScaleGlow;
1743
//			Weapon.Fatness = Weapon.Default.Fatness;
1744
//		}
1745
	}
1746
1747
Begin:
1748
	if( Enemy != none )
1749
	{
1750
		TurnToward( Enemy );
1751
	}
1752
	
1753
	else
1754
	{
1755
		TurnToward( MarineBeamController.GetPlayerPawn() );
1756
//		Enemy = MarineBeamController.GetPlayerPawn();
1757
	}
1758
	
1759
	sleep( 5.5 );
1760
	bHidden = false;
1761
	Style=STY_Normal;
1762
	Weapon.Texture = Weapon.Default.Texture;
1763
	Weapon.ScaleGlow = Weapon.Default.ScaleGlow;
1764
	Mass = Default.Mass;
1765
	Weapon.Fatness = Weapon.Default.Fatness;
1766
	Weapon.bMeshEnviroMap = false;
1767
	Weapon.Style=STY_Normal;
1768
//	BeamEffect.Fatness = 129;
1769
	BeamEffect.LifeSpan = 1;
1770
	BeamEffect.Texture = texture'upak.Beam2';
1771
	Enemy = MarineBeamController.GetPlayerPawn();
1772
	Target = MarineBeamController.GetPlayerPawn();
1773
	Fatness = Default.Fatness;
1774
	GotoState( 'Hunting' );
1775
//	WhatToDoNext( '', '' );
1776
}
1777
1778
		
1779
function FireWeapon()
1780
{
1781
	local bool bUseAltMode;
1782
1783
	if( Weapon != none )
1784
	{
1785
		Weapon.AmmoType.AmmoAmount = 999;
1786
	}
1787
	
1788
	if ( (Enemy == None) && bShootSpecial )
1789
	{
1790
		//fake use dispersion pistol
1791
		Spawn(class'DispersionAmmo',,, Location,Rotator(Target.Location - Location));
1792
		return;
1793
	}
1794
1795
	bUseAltMode = SwitchToBestWeapon();
1796
1797
	if( Weapon!=None )
1798
	{
1799
		if ( (Weapon.AmmoType != None) && (Weapon.AmmoType.AmmoAmount <= 0) )
1800
		{
1801
			bReadyToAttack = true;
1802
			return;
1803
		}
1804
1805
 		if ( !bFiringPaused && !bShootSpecial && (Enemy != None) )
1806
 			Target = Enemy;
1807
		ViewRotation = Rotation;
1808
		if ( bUseAltMode )
1809
		{
1810
			bFire = 0;
1811
			bAltFire = 1;
1812
			Weapon.AltFire(1.0);
1813
		}
1814
		else
1815
		{
1816
			bFire = 1;
1817
			bAltFire = 0;
1818
			Weapon.Fire(1.0);
1819
		}
1820
		PlayFiring();
1821
	}
1822
	bShootSpecial = false;
1823
}
1824
1825
1826
function Died(pawn Killer, name damageType, vector HitLocation)
1827
{
1828
	if( MarineBeamController != none )
1829
	{
1830
		MarineBeamController.SubtractMarine( Self );
1831
		MarineBeamController = None;
1832
	}
1833
	if( Weapon != none && Weapon.AmmoType != none )
1834
		Weapon.AmmoType.AmmoAmount =
1835
			Max(int(Weapon.PickupAmmoCount > 0 || Weapon.AmmoType.Default.AmmoAmount > 0),
1836
				Weapon.AmmoType.Default.AmmoAmount - Rand(3));
1837
	Super.Died(Killer,damageType,HitLocation);
1838
} 
1839
1840
1841
state Charging
1842
{
1843
	function BeginState()
1844
	{
1845
		if( MarinesTalk() && FRand() < 0.3 && Health > 50 )
1846
		{		
1847
			MyVoicePack.Talker = self;
1848
			MyVoicePack.SetTimer( 0.1, false );
1849
			MyVoicePack.bChargePhrase = true;
1850
		}
1851
		Super.BeginState();
1852
	}
1853
}
1854
1855
1856
1857
function bool MarinesTalk()
1858
{
1859
	if( MyVoicePack!=None && MyVoicePack.LastTalker!=self )
1860
		return true;
1861
	else return false;
1862
}
1863
1864
1865
function PlayVictoryDance()
1866
{
1867
	if( MyVoicePack!=None )
1868
	{
1869
		GotoState( 'Victory' );
1870
	}
1871
}
1872
1873
state Victory
1874
{
1875
	Begin:
1876
	
1877
	FinishAnim();
1878
	Acceleration = vect( 0, 0, 0 );
1879
	Velocity = vect( 0, 0, 0 );
1880
	PlayAnim( 'TalkREM', 0.3 );
1881
	FinishAnim();
1882
	if( FRand() < 0.5 )
1883
	{
1884
		PlayAnim( 'TauntL', 3.3 );
1885
		FinishAnim();
1886
	}
1887
	GotoState( 'Roaming' );
1888
}
1889
1890
	
1891
state TacticalMove
1892
{
1893
ignores SeePlayer, HearNoise;
1894
1895
	function SetFall()
1896
	{
1897
		Acceleration = vect(0,0,0);
1898
		Destination = Location;
1899
		NextState = 'Attacking'; 
1900
		NextLabel = 'Begin';
1901
		NextAnim = 'Breath1l';
1902
		GotoState('FallingState');
1903
	}
1904
1905
	function WarnTarget(Pawn shooter, float projSpeed, vector FireDir)
1906
	{	
1907
		if ( bCanFire && (FRand() < 0.4) ) 
1908
			return;
1909
1910
		Super.WarnTarget(shooter, projSpeed, FireDir);
1911
	}
1912
1913
	function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, 
1914
						Vector momentum, name damageType)
1915
	{
1916
		Global.TakeDamage(Damage, instigatedBy, hitlocation, momentum, damageType);
1917
		if ( health <= 0 )
1918
			return;
1919
		if ( NextState == 'TakeHit' )
1920
		{
1921
			NextState = 'TacticalMove'; 
1922
			NextLabel = 'TakeHit';
1923
			GotoState('TakeHit'); 
1924
		}
1925
	}
1926
1927
	function HitWall(vector HitNormal, actor Wall)
1928
	{
1929
		if (Physics == PHYS_Falling)
1930
			return;
1931
		Focus = Destination;
1932
		//if (PickWallAdjust())
1933
		//	GotoState('TacticalMove', 'AdjustFromWall');
1934
		if ( bChangeDir || (FRand() < 0.5) 
1935
			|| (((Enemy.Location - Location) Dot HitNormal) < 0) )
1936
		{
1937
			DesiredRotation = Rotator(Enemy.Location - location);
1938
			GiveUpTactical(false);
1939
		}
1940
		else
1941
		{
1942
			bChangeDir = true;
1943
			Destination = Location - HitNormal * FRand() * 500;
1944
		}
1945
	}
1946
1947
	function FearThisSpot(Actor aSpot)
1948
	{
1949
		Destination = Location + 120 * Normal(Location - aSpot.Location); 
1950
	}
1951
1952
	function AnimEnd() 
1953
	{
1954
		PlayCombatMove();
1955
	}
1956
1957
	function Timer()
1958
	{
1959
		bReadyToAttack = True;
1960
		Enable('Bump');
1961
		Target = Enemy;
1962
		if (VSize(Enemy.Location - Location) 
1963
				<= (MeleeRange + Enemy.CollisionRadius + CollisionRadius))
1964
			GotoState('RangedAttack');		 
1965
		else if ( FRand() > 0.5 + 0.17 * skill ) 
1966
			GotoState('RangedAttack');
1967
	}
1968
1969
	function EnemyNotVisible()
1970
	{
1971
		if ( !bGathering && (aggressiveness > relativestrength(enemy)) )
1972
		{
1973
			if (ValidRecovery())
1974
				GotoState('TacticalMove','RecoverEnemy');
1975
			else
1976
				GotoState('Attacking');
1977
		}
1978
		Disable('EnemyNotVisible');
1979
	}
1980
1981
	function bool ValidRecovery()
1982
	{
1983
		local actor HitActor;
1984
		local vector HitLocation, HitNormal;
1985
		
1986
		HitActor = Trace(HitLocation, HitNormal, Enemy.Location, LastSeeingPos, false);
1987
		return (HitActor == None);
1988
	}
1989
		
1990
	function GiveUpTactical(bool bNoCharge)
1991
	{	
1992
		if ( !bNoCharge && (2 * CombatStyle > (3 - Skill) * FRand()) )
1993
			GotoState('Charging');
1994
		else if ( bReadyToAttack && (skill > 3 * FRand() - 1) )
1995
			GotoState('RangedAttack');
1996
		else
1997
			GotoState('RangedAttack', 'Challenge'); 
1998
	}		
1999
2000
	function bool TryToward(inventory Inv, float Weight)
2001
	{
2002
		local bool success; 
2003
		local vector pickdir, collSpec, minDest, HitLocation, HitNormal;
2004
		local Actor HitActor;
2005
2006
		if ( (Weight < 0.0008) && ((Weight < 0.0008 - 0.0002 * skill) 
2007
				|| !Enemy.LineOfSightTo(Inv)) )
2008
			return false;
2009
2010
		pickdir = Inv.Location - Location;
2011
		if ( Physics == PHYS_Walking )
2012
			pickDir.Z = 0;
2013
		pickDir = Normal(PickDir);
2014
2015
		collSpec.X = CollisionRadius;
2016
		collSpec.Y = CollisionRadius;
2017
		collSpec.Z = FMax(6, CollisionHeight - 18);
2018
		
2019
		minDest = Location + FMin(160.0, 3*CollisionRadius) * pickDir;
2020
		HitActor = Trace(HitLocation, HitNormal, minDest, Location, false, collSpec);
2021
		if (HitActor == None)
2022
		{
2023
			success = (Physics != PHYS_Walking);
2024
			if ( !success )
2025
			{
2026
				collSpec.X = FMin(14, 0.5 * CollisionRadius);
2027
				collSpec.Y = collSpec.X;
2028
				HitActor = Trace(HitLocation, HitNormal, minDest - (18 + MaxStepHeight) * vect(0,0,1), minDest, false, collSpec);
2029
				success = (HitActor != None);
2030
			}
2031
			if ( success )
2032
			{
2033
				Destination = Inv.Location;
2034
				bGathering = true;
2035
				if ( 2.7 * FRand() < skill )
2036
					GotoState('TacticalMove','DoStrafeMove');
2037
				else
2038
					GotoState('TacticalMove','DoDirectMove');
2039
				return true;
2040
			}
2041
		}
2042
2043
		return false;
2044
	}
2045
2046
	function PainTimer()
2047
	{
2048
		if ( (FootRegion.Zone.bPainZone) && (FootRegion.Zone.DamagePerSec > 0)
2049
			&& (FootRegion.Zone.DamageType != ReducedDamageType) )
2050
			GotoState('Retreating');
2051
		Super.PainTimer();
2052
	}
2053
2054
2055
/* PickDestination()
2056
Choose a destination for the tactical move, based on aggressiveness and the tactical
2057
situation. Make sure destination is reachable
2058
*/
2059
	function PickDestination(bool bNoCharge)
2060
	{
2061
		local inventory Inv, BestInv, SecondInv;
2062
		local float Bestweight, NewWeight, MaxDist, SecondWeight;
2063
2064
		// possibly pick nearby inventory
2065
		// higher skill bots will always strafe, lower skill
2066
		// both do this less, and strafe less
2067
2068
		if ( !bReadyToAttack && (TimerRate == 0.0) )
2069
			SetTimer(0.7, false);
2070
		if ( Level.TimeSeconds - LastInvFind < 2.5 - 0.5 * skill )
2071
		{
2072
			PickRegDestination(bNoCharge);
2073
			return;
2074
		}
2075
2076
		LastInvFind = Level.TimeSeconds;
2077
		bGathering = false;
2078
		BestWeight = 0;
2079
		MaxDist = 600 + 70 * skill;
2080
		foreach visiblecollidingactors(class'Inventory', Inv, MaxDist)
2081
			if ( (Inv.IsInState('PickUp')) && (Inv.MaxDesireability/200 > BestWeight)
2082
				&& (Inv.Location.Z < Location.Z + MaxStepHeight + CollisionHeight)
2083
				&& (Inv.Location.Z > FMin(Location.Z, Enemy.Location.Z) - CollisionHeight) )
2084
			{
2085
				NewWeight = inv.BotDesireability(self)/VSize(Inv.Location - Location);
2086
				if ( NewWeight > BestWeight )
2087
				{
2088
					SecondWeight = BestWeight;
2089
					BestWeight = NewWeight;
2090
					SecondInv = BestInv;
2091
					BestInv = Inv;
2092
				}
2093
			}
2094
2095
		if ( BestInv == None )
2096
		{
2097
			PickRegDestination(bNoCharge);
2098
			return;
2099
		}
2100
2101
		if ( TryToward(BestInv, BestWeight) )
2102
			return;
2103
2104
		if ( SecondInv == None )
2105
		{
2106
			PickRegDestination(bNoCharge);
2107
			return;
2108
		}
2109
2110
		if ( TryToward(SecondInv, SecondWeight) )
2111
			return;
2112
2113
		PickRegDestination(bNoCharge);
2114
	}
2115
2116
	function PickRegDestination(bool bNoCharge)
2117
	{
2118
		local vector pickdir, enemydir, enemyPart, Y, minDest;
2119
		local actor HitActor;
2120
		local vector HitLocation, HitNormal, collSpec;
2121
		local float Aggression, enemydist, minDist, strafeSize, optDist;
2122
		local bool success, bNoReach;
2123
	
2124
		bChangeDir = false;
2125
		if (Region.Zone.bWaterZone && !bCanSwim && bCanFly)
2126
		{
2127
			Destination = Location + 75 * (VRand() + vect(0,0,1));
2128
			Destination.Z += 100;
2129
			return;
2130
		}
2131
		if ( Enemy.Region.Zone.bWaterZone )
2132
			bNoCharge = bNoCharge || !bCanSwim;
2133
		else 
2134
			bNoCharge = bNoCharge || (!bCanFly && !bCanWalk);
2135
		
2136
		success = false;
2137
		enemyDist = VSize(Location - Enemy.Location);
2138
		Aggression = 2 * (CombatStyle + FRand()) - 1.1;
2139
		if ( Enemy.bIsPlayer && (AttitudeTo(Enemy) == ATTITUDE_Fear) && (CombatStyle > 0) )
2140
			Aggression = Aggression - 2 - 2 * CombatStyle;
2141
		if ( Weapon != None )
2142
			Aggression += 2 * Weapon.SuggestAttackStyle();
2143
		if ( Enemy.Weapon != None )
2144
			Aggression += 2 * Enemy.Weapon.SuggestDefenseStyle();
2145
2146
		if ( enemyDist > 1000 )
2147
			Aggression += 1;
2148
		if ( !bNoCharge )
2149
			bNoCharge = ( Aggression < FRand() );
2150
2151
		if ( (Physics == PHYS_Walking) || (Physics == PHYS_Falling) )
2152
		{
2153
			if (Location.Z > Enemy.Location.Z + 140) //tactical height advantage
2154
				Aggression = FMax(0.0, Aggression - 1.0 + CombatStyle);
2155
			else if (Location.Z < Enemy.Location.Z - CollisionHeight) // below enemy
2156
			{
2157
				if ( !bNoCharge && (Aggression > 0) && (FRand() < 0.6) )
2158
				{
2159
					GotoState('Charging');
2160
					return;
2161
				}
2162
				else if ( (enemyDist < 1.1 * (Enemy.Location.Z - Location.Z)) 
2163
						&& !actorReachable(Enemy) ) 
2164
				{
2165
					bNoReach = true;
2166
					aggression = -1.5 * FRand();
2167
				}
2168
			}
2169
		}
2170
	
2171
		if (!bNoCharge && (Aggression > 2 * FRand()))
2172
		{
2173
			if ( bNoReach && (Physics != PHYS_Falling) )
2174
			{
2175
				TweenToRunning(0.15);
2176
				GotoState('Charging', 'NoReach');
2177
			}
2178
			else
2179
				GotoState('Charging');
2180
			return;
2181
		}
2182
2183
		if (enemyDist > FMax(VSize(OldLocation - Enemy.OldLocation), 240))
2184
			Aggression += 0.4 * FRand();
2185
			 
2186
		enemydir = (Enemy.Location - Location)/enemyDist;
2187
		minDist = FMin(160.0, 3*CollisionRadius);
2188
		optDist = 80 + FMin(EnemyDist, 250 * (FRand() + FRand()));  
2189
		Y = (enemydir Cross vect(0,0,1));
2190
		if ( Physics == PHYS_Walking )
2191
		{
2192
			Y.Z = 0;
2193
			enemydir.Z = 0;
2194
		}
2195
		else 
2196
			enemydir.Z = FMax(0,enemydir.Z);
2197
			
2198
		strafeSize = FMax(-0.7, FMin(0.85, (2 * Aggression * FRand() - 0.3)));
2199
		enemyPart = enemydir * strafeSize;
2200
		strafeSize = FMax(0.0, 1 - Abs(strafeSize));
2201
		pickdir = strafeSize * Y;
2202
		if ( bStrafeDir )
2203
			pickdir *= -1;
2204
		bStrafeDir = !bStrafeDir;
2205
		collSpec.X = CollisionRadius;
2206
		collSpec.Y = CollisionRadius;
2207
		collSpec.Z = FMax(6, CollisionHeight - 18);
2208
		
2209
		minDest = Location + minDist * (pickdir + enemyPart);
2210
		HitActor = Trace(HitLocation, HitNormal, minDest, Location, false, collSpec);
2211
		if (HitActor == None)
2212
		{
2213
			success = (Physics != PHYS_Walking);
2214
			if ( !success )
2215
			{
2216
				collSpec.X = FMin(14, 0.5 * CollisionRadius);
2217
				collSpec.Y = collSpec.X;
2218
				HitActor = Trace(HitLocation, HitNormal, minDest - (18 + MaxStepHeight) * vect(0,0,1), minDest, false, collSpec);
2219
				success = (HitActor != None);
2220
			}
2221
			if (success)
2222
				Destination = minDest + (pickdir + enemyPart) * optDist;
2223
		}
2224
	
2225
		if ( !success )
2226
		{					
2227
			collSpec.X = CollisionRadius;
2228
			collSpec.Y = CollisionRadius;
2229
			minDest = Location + minDist * (enemyPart - pickdir); 
2230
			HitActor = Trace(HitLocation, HitNormal, minDest, Location, false, collSpec);
2231
			if (HitActor == None)
2232
			{
2233
				success = (Physics != PHYS_Walking);
2234
				if ( !success )
2235
				{
2236
					collSpec.X = FMin(14, 0.5 * CollisionRadius);
2237
					collSpec.Y = collSpec.X;
2238
					HitActor = Trace(HitLocation, HitNormal, minDest - (18 + MaxStepHeight) * vect(0,0,1), minDest, false, collSpec);
2239
					success = (HitActor != None);
2240
				}
2241
				if (success)
2242
					Destination = minDest + (enemyPart - pickdir) * optDist;
2243
			}
2244
			else 
2245
			{
2246
				if ( (CombatStyle <= 0) || (Enemy.bIsPlayer && (AttitudeTo(Enemy) == ATTITUDE_Fear)) )
2247
					enemypart = vect(0,0,0);
2248
				else if ( (enemydir Dot enemyPart) < 0 )
2249
					enemyPart = -1 * enemyPart;
2250
				pickDir = Normal(enemyPart - pickdir + HitNormal);
2251
				minDest = Location + minDist * pickDir;
2252
				collSpec.X = CollisionRadius;
2253
				collSpec.Y = CollisionRadius;
2254
				HitActor = Trace(HitLocation, HitNormal, minDest, Location, false, collSpec);
2255
				if (HitActor == None)
2256
				{
2257
					success = (Physics != PHYS_Walking);
2258
					if ( !success )
2259
					{
2260
						collSpec.X = FMin(14, 0.5 * CollisionRadius);
2261
						collSpec.Y = collSpec.X;
2262
						HitActor = Trace(HitLocation, HitNormal, minDest - (18 + MaxStepHeight) * vect(0,0,1), minDest, false, collSpec);
2263
						success = (HitActor != None);
2264
					}
2265
					if (success)
2266
						Destination = minDest + pickDir * optDist;
2267
				}
2268
			}	
2269
		}
2270
					
2271
		if ( !success )
2272
			GiveUpTactical(bNoCharge);
2273
		else 
2274
		{
2275
			pickDir = (Destination - Location);
2276
			enemyDist = VSize(pickDir);
2277
			if ( enemyDist > minDist + 2 * CollisionRadius )
2278
			{
2279
				pickDir = pickDir/enemyDist;
2280
				HitActor = Trace(HitLocation, HitNormal, Destination + 2 * CollisionRadius * pickdir, Location, false);
2281
				if ( (HitActor != None) && ((HitNormal Dot pickDir) < -0.6) )
2282
					Destination = HitLocation - 2 * CollisionRadius * pickdir;
2283
			}
2284
		}
2285
	}
2286
2287
	function BeginState()
2288
	{
2289
		if( MarinesTalk() && FRand() < 0.3 && Health > 50 )
2290
		{		
2291
			MyVoicePack.Talker = self;
2292
			MyVoicePack.SetTimer( 0.1, false );
2293
			MyVoicePack.bChargePhrase = true;
2294
		}
2295
		MinHitWall += 0.15;
2296
		bAvoidLedges = ( !bCanJump && (CollisionRadius > 40) );
2297
		bCanJump = false;
2298
		bCanFire = false;
2299
	}
2300
	
2301
	function EndState()
2302
	{
2303
		bAvoidLedges = false;
2304
		MinHitWall -= 0.15;
2305
		if (JumpZ > 0)
2306
			bCanJump = true;
2307
	}
2308
2309
//FIXME - what if bReadyToAttack at start
2310
TacticalTick:
2311
	Sleep(0.02);	
2312
Begin:
2313
	TweenToRunning(0.15);
2314
	Enable('AnimEnd');
2315
	if (Physics == PHYS_Falling)
2316
	{
2317
		DesiredRotation = Rotator(Enemy.Location - Location);
2318
		Focus = Enemy.Location;
2319
		Destination = Enemy.Location;
2320
		WaitForLanding();
2321
	}
2322
	PickDestination(false);
2323
2324
DoMove:
2325
	if ( !bCanStrafe )
2326
	{ 
2327
DoDirectMove:
2328
		Enable('AnimEnd');
2329
		if ( GetAnimGroup(AnimSequence) == 'MovingAttack' )
2330
		{
2331
			AnimSequence = '';
2332
			TweenToRunning(0.12);
2333
		}
2334
		HaltFiring();
2335
		MoveTo(Destination);
2336
	}
2337
	else
2338
	{
2339
DoStrafeMove:
2340
		Enable('AnimEnd');
2341
		bCanFire = true;
2342
		StrafeFacing(Destination, Enemy);	
2343
	}
2344
2345
	if ( (Enemy != None) && !LineOfSightTo(Enemy) && ValidRecovery() )
2346
		Goto('RecoverEnemy');
2347
	else
2348
	{
2349
		bReadyToAttack = true;
2350
		GotoState('Attacking');
2351
	}
2352
	
2353
NoCharge:
2354
	TweenToRunning(0.15);
2355
	Enable('AnimEnd');
2356
	if (Physics == PHYS_Falling)
2357
	{
2358
		DesiredRotation = Rotator(Enemy.Location - Location);
2359
		Focus = Enemy.Location;
2360
		Destination = Enemy.Location;
2361
		WaitForLanding();
2362
	}
2363
	PickDestination(true);
2364
	Goto('DoMove');
2365
	
2366
AdjustFromWall:
2367
	Enable('AnimEnd');
2368
	StrafeTo(Destination, Focus); 
2369
	Destination = Focus; 
2370
	Goto('DoMove');
2371
2372
TakeHit:
2373
	TweenToRunning(0.12);
2374
	Goto('DoMove');
2375
2376
RecoverEnemy:
2377
	Enable('AnimEnd');
2378
	bReadyToAttack = true;
2379
	HidingSpot = Location;
2380
	bCanFire = false;
2381
	Destination = LastSeeingPos + 3 * CollisionRadius * Normal(LastSeeingPos - Location);
2382
	if ( bCanStrafe || (VSize(LastSeeingPos - Location) < 3 * CollisionRadius) )
2383
		StrafeFacing(Destination, Enemy);
2384
	else
2385
		MoveTo(Destination);
2386
	if ( Weapon == None ) 
2387
		Acceleration = vect(0,0,0);
2388
	if ( NeedToTurn(Enemy.Location) )
2389
	{
2390
		PlayTurning();
2391
		TurnToward(Enemy);
2392
	}
2393
	if ( CanFireAtEnemy() )
2394
	{
2395
		Disable('AnimEnd');
2396
		DesiredRotation = Rotator(Enemy.Location - Location);
2397
		if ( Weapon == None ) 
2398
		{
2399
			PlayRangedAttack();
2400
			FinishAnim();
2401
			TweenToRunning(0.1);
2402
			bReadyToAttack = false;
2403
			SetTimer(TimeBetweenAttacks, false);
2404
		}
2405
		else
2406
		{
2407
			FireWeapon();
2408
			if ( Weapon.bSplashDamage )
2409
			{
2410
				bFire = 0;
2411
				bAltFire = 0;
2412
				Acceleration = vect(0,0,0);
2413
				Sleep(0.1);
2414
			}
2415
		}
2416
2417
		if ( (FRand() + 0.1 > CombatStyle) )
2418
		{
2419
			Enable('EnemyNotVisible');
2420
			Enable('AnimEnd');
2421
			Destination = HidingSpot + 4 * CollisionRadius * Normal(HidingSpot - Location);
2422
			Goto('DoMove');
2423
		}
2424
	}
2425
2426
	GotoState('Attacking');
2427
}
2428
2429
function Destroyed()
2430
{
2431
	if( MarineBeamController != none )
2432
	{
2433
		MarineBeamController.SubtractMarine( Self );
2434
		MarineBeamController = None;
2435
	}
2436
	Super.Destroyed();
2437
}
2438
2439
defaultproperties
2440
{
2441
				VoiceList(0)=(duration=3.500000,UsedInState="WarnFriends")
2442
				VoiceList(1)=(duration=2.500000,UsedInState="TransmitHuntingMessage")
2443
				VoiceList(2)=(duration=2.500000,UsedInState="AcknowledgeWarning")
2444
				CarcassType=Class'UPak.SpaceMarineCarcass'
2445
				RefireRate=0.700000
2446
				bIsWuss=True
2447
				bLeadTarget=False
2448
				GroundSpeed=300.000000
2449
				AccelRate=1500.000000
2450
				JumpZ=300.000000
2451
				SightRadius=1000.000000
2452
				Health=80
2453
				AttitudeToPlayer=ATTITUDE_Ignore
2454
				AnimSequence="Breath1L"
2455
				Mesh=LodMesh'UPak.marine'
2456
				MultiSkins(1)=Texture'UPak.Skins.JMarine7'
2457
				MultiSkins(2)=Texture'UPak.Skins.JMarine8'
2458
				CollisionRadius=20.500000
2459
				CollisionHeight=41.000000
2460
				Mass=125.000000
2461
}