‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_straferun.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\challenges_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\scoreevents_shared;
6 #using scripts\shared\util_shared;
7 #using scripts\shared\weapons\_heatseekingmissile;
8 #using scripts\shared\weapons\_weaponobjects;
9 
10 #using scripts\mp\gametypes\_battlechatter;
11 #using scripts\mp\_challenges;
12 #using scripts\mp\_util;
13 #using scripts\mp\_vehicle;
14 #using scripts\mp\killstreaks\_airsupport;
15 #using scripts\mp\killstreaks\_dogs;
16 #using scripts\mp\killstreaks\_killstreakrules;
17 #using scripts\mp\killstreaks\_killstreaks;
18 
19 #insert scripts\mp\_hacker_tool.gsh;
20 #insert scripts\shared\shared.gsh;
21 
22 #define STRAFERUN_MAX_HEALTH 1000
23 
24 #precache( "string", "MP_EARNED_STRAFERUN" );
25 #precache( "string", "KILLSTREAK_STRAFERUN_NOT_AVAILABLE" );
26 #precache( "string", "MP_WAR_STRAFERUN_INBOUND" );
27 #precache( "string", "MP_WAR_STRAFERUN_INBOUND_NEAR_YOUR_POSITION" );
28 #precache( "string", "KILLSTREAK_STRAFERUN_HACKED" );
29 #precache( "eventstring", "mpl_killstreak_straferun" );
30 #precache( "fx", "killstreaks/fx_wh_contrail" );
31 #precache( "fx", "killstreaks/fx_vtol_exp" );
32 
33 #namespace straferun;
34 
35 function ‪init()
36 {
37  level.strafeRunNumRockets = 8;
38  level.strafeRunRocketDelay = 0.35;
39  level.strafeRunGunLookahead = 4000;
40  level.strafeRunGunOffset = -800;
41  level.strafeRunGunRadius = 500;
42  level.strafeRunExitUnits = 20000;
43  level.strafeRunMaxStrafes = 6;
44  level.strafeRunFlareDelay = 2;
45  level.strafeRunShellShockDuration = 2.5;
46  level.strafeRunShellShockRadius = 512;
47  level.strafeRunKillsBeforeExit = 10;
48  level.strafeRunNumKillcams = 5;
49 
50  level.strafeRunModel = "veh_t6_air_a10f";
51  level.strafeRunModelEnemy = "veh_t6_air_a10f_alt";
52  level.strafeRunVehicle = "vehicle_straferun_mp";
53  level.strafeRunGunWeapon = GetWeapon( "straferun_gun" );
54  level.strafeRunGunSound = "wpn_a10_shot_loop_npc";
55  level.strafeRunRocketWeapon = GetWeapon( "straferun_rockets" );
56  level.strafeRunRocketTags = [];
57  level.strafeRunRocketTags[0] = "tag_rocket_left";
58  level.strafeRunRocketTags[1] = "tag_rocket_right";
59  level.strafeRunContrailFX = "killstreaks/fx_wh_contrail";
60  level.strafeRunChaffFX = "killstreaks/fx_wh_chaff_trail";
61  level.strafeRunExplodeFX = "killstreaks/fx_vtol_exp";
62  level.strafeRunExplodeSound = "evt_helicopter_midair_exp";
63  level.strafeRunShellShock = "straferun";
64 
65  //killstreaks::register( "straferun", "straferun", "killstreak_straferun", "straferun_used",&useKillstreakStrafeRun, true);
66  //killstreaks::register_strings( "straferun", &"MP_EARNED_STRAFERUN", &"KILLSTREAK_STRAFERUN_NOT_AVAILABLE", &"MP_WAR_STRAFERUN_INBOUND", &"MP_WAR_STRAFERUN_INBOUND_NEAR_YOUR_POSITION", &"KILLSTREAK_STRAFERUN_HACKED" );
67  //killstreaks::register_dialog( "straferun", "mpl_killstreak_straferun", "kls_straferun_used", "","kls_straferun_enemy", "", "kls_straferun_ready");
68  //killstreaks::register_tos_dvar( "scr_teamops" );
69  //killstreaks::register_alt_weapon( "straferun", level.strafeRunGunWeapon.name );
70  //killstreaks::register_alt_weapon( "straferun", level.strafeRunRocketWeapon.name );
71  //killstreaks::set_team_kill_penalty_scale( "straferun", 0.0 );
72 
73  // killcams are created on level start and live all game
74  ‪createKillcams( level.strafeRunNumKillcams, level.strafeRunNumRockets );
75 }
76 
77 function ‪PlayPilotDialog( dialog )
78 {
79 
80  soundAlias = level.teamPrefix[self.team] + self.pilotVoiceNumber + "_" + dialog;
81 
82  while( isdefined( self.owner ) && self.owner.pilotisSpeaking )
83  {
84  wait ( .2 );
85  }
86 
87  if ( isdefined( self.owner ) )
88  {
89  self.owner playLocalSound(soundAlias);
90  self.owner.pilotisSpeaking = true;
91  self.owner thread ‪battlechatter::wait_playback_time( soundAlias );
92  self.owner ‪util::waittill_any( soundAlias, "death", "disconnect" );
93  if ( isdefined( self.owner ) )
94  {
95  self.owner.pilotisSpeaking = false;
96  }
97  }
98 
99 
100 }
101 
102 function ‪useKillstreakStrafeRun( hardpointType )
103 {
104  startNode = GetVehicleNode( "warthog_start", "targetname" );
105  if ( !isdefined( startNode ) )
106  {
107 /# println( "ERROR: Strafe run vehicle spline not found!" ); #/
108  return false;
109  }
110 
111  killstreak_id = self ‪killstreakrules::killstreakStart( "straferun", self.team, false, false );
112  if ( killstreak_id == -1 )
113  {
114  return false;
115  }
116 
117 
118  // Spawn and setup vehicle
119  plane = SpawnVehicle( level.strafeRunVehicle, startNode.origin, (0,0,0), "straferun" );
120 
121  if( GetDvarInt( "teamOpsEnabled" ) == 1 )
122  plane.teamops = true;
123 
124  plane.attackers = [];
125  plane.attackerData = [];
126  plane.attackerDamage = [];
127  plane.flareAttackerDamage = [];
128  plane SetTeam( self.team );
129  plane SetEnemyModel( level.strafeRunModelEnemy );
130  plane.team = self.team;
131  plane MakeVehicleUnusable();
132  plane thread ‪cleanupOnDeath( plane.team );
133  plane.health = 999999;
134  plane.maxhealth = 999999;
135  plane ‪clientfield::set( "enemyvehicle", ‪ENEMY_VEHICLE_ACTIVE );
136 
137  plane SetOwner( self );
138  plane.owner = self;
139 
140 
141  plane.numStrafes = 0;
142  plane.killstreak_id = killstreak_id;
143  plane.numFlares = 2;
144  //plane.fx_flare = "killstreaks/fx_wh_chaff_trail";
145  plane.soundMod = "straferun";
146  plane SetDrawInfrared( true );
147 
148  if( GetDvarInt( "teamOpsEnabled" ) == 1 )
149  {
150  plane.straferunKills = 0;
151  plane.strafeRunbda = 0;
152  }
153  else
154  {
155  self.straferunKills = 0;
156  self.strafeRunbda = 0;
157  }
158 
159  self.pilotisSpeaking = false;
160  plane.pilotVoiceNumber = self.bcVoiceNumber + 1;
161  if (plane.pilotVoiceNumber > 3)
162  {
163  plane.pilotVoiceNumber = 0;
164  }
165  self ‪killstreaks::play_killstreak_start_dialog( "straferun", self.pers["team"], killstreak_id );
166  self AddWeaponStat( GetWeapon( "straferun" ), "used", 1 );
167 
168  //play pilot dialog
169  plane thread ‪PilotDialogWait ("a10_used", 2.5);
170 
171  // make targetable
172  Target_Set( plane, (0,0,0) );
173  Target_SetTurretAquire( plane, false );
174 
175  //plane thread playContrail();
176 
177  // Setup vehicle weapons
178  //plane setVehWeapon( level.strafeRunGunWeapon );
179  plane.gunSoundEntity = ‪spawn( "script_model", plane GetTagOrigin( "tag_flash" ) );
180  plane.gunSoundEntity LinkTo( plane, "tag_flash", (0,0,0), (0,0,0) );
181 
182  //plane.killCamEntities = level.strafeRunKillcams.strafes;
183 
184  plane ‪resetKillcams();
185 
186 
187  if( GetDvarInt( "teamOpsEnabled" ) == 0 )
188  plane thread ‪watchForOtherKillstreaks();
189 
190  plane thread ‪watchForKills();
191  plane thread ‪watchdamage();
192  plane thread ‪doStrafeRuns();
193  plane thread ‪vehicle::follow_path( startNode );
195 
196  if( GetDvarInt( "teamOpsEnabled" ) == 0 )
197  plane thread ‪watchForOwnerExit( self );
198 
199  return true;
200 }
201 
202 function ‪playContrail()
203 {
204  self endon( "death" );
205 
206  wait( 0.1 );
207  PlayFXOnTag( level.strafeRunContrailFX, self, "tag_origin" );
208  self playloopsound ("veh_a10_engine_loop", 1);
209 }
210 
211 function ‪cleanupOnDeath( team )
212 {
213  self waittill( "death" );
214 
215  ‪killstreakrules::killstreakStop( "straferun", team, self.killstreak_id );
216 
217  if( isdefined( self.gunSoundEntity ) )
218  {
219  self.gunSoundEntity StopLoopSound();
220  self.gunSoundEntity Delete();
221  self.gunSoundEntity = undefined;
222  }
223 }
224 
225 function ‪watchdamage()
226 {
227  self endon( "death" );
228 
229  self.maxhealth = 999999;
230  self.health = self.maxhealth;
231  self.maxhealth = ‪STRAFERUN_MAX_HEALTH;
232 
233  low_health = false;
234  damage_taken = 0;
235 
236  for ( ;; )
237  {
238  self waittill( "damage", ‪damage, attacker, dir, point, mod, model, tag, part, weapon, flags );
239 
240  if( !isdefined( attacker ) || !isplayer( attacker ) )
241  continue;
242 
243 /#
244  self.damage_debug = ( ‪damage + " (" + weapon.name + ")" );
245 #/
246 
247  if ( mod == "MOD_PROJECTILE" || mod == "MOD_PROJECTILE_SPLASH" || mod == "MOD_EXPLOSIVE" )
248  {
250  }
251 
252  self.attacker = attacker;
253 
254  damage_taken += ‪damage;
255 
256 
257  if ( damage_taken >= ‪STRAFERUN_MAX_HEALTH )
258  {
259  self thread ‪explode();
260 
261  if( GetDvarInt( "teamOpsEnabled" ) == 0 )
262  {
263  if ( self.owner ‪util::IsEnemyPlayer( attacker ) )
264  {
265  attacker ‪challenges::addFlySwatterStat( weapon, self );
266  }
267  else
268  {
269  //Destroyed Friendly Killstreak
270  }
271  }
272 
273  return;
274  }
275  }
276 }
277 
279 {
280  self endon( "death" );
281 
282  for ( ;; )
283  {
284  level waittill( "killstreak_started", hardpointType, teamName, attacker );
285  if ( !isdefined ( self.owner ) )
286  {
287  self thread ‪explode();
288  return;
289  }
290 
291  if ( hardpointType == "emp" )
292  {
293  if ( self.owner ‪util::IsEnemyPlayer( attacker ) )
294  {
295  self thread ‪explode();
296  attacker ‪challenges::addFlySwatterStat( hardpointType, self );
297  return;
298  }
299  }
300  else if ( hardpointType == "missile_swarm" )
301  {
302  if ( self.owner ‪util::IsEnemyPlayer( attacker ) )
303  {
304  self.leaveNextTime = true;
305  }
306  }
307  }
308 }
309 
311 {
312  self endon( "death" );
313 
314  for ( ;; )
315  {
316  self waittill( "killed", player );
317  if ( IsPlayer( player ) )
318  {
319  //IPrintLnBold( "STRAFE RUN KILLED PLAYER\n" );
320 
321  }
322  else
323  {
324  //IPrintLnBold( "STRAFE RUN KILLED SOMETHING ELSE\n" );
325  //self.bda = self.bda + 1;
326  }
327  }
328 }
329 
330 function ‪watchForOwnerExit( owner )
331 {
332  self endon( "death" );
333 
334  owner ‪util::waittill_any( "disconnect", "joined_team", "joined_spectators");
335  self.leaveNextTime = true;
336 }
337 
339 {
340  if ( !isdefined( self.straferunKills ) )
341  {
342  self.straferunKills = 0;
343  }
344  self.straferunKills++;
345 }
346 
347 function ‪doStrafeRuns()
348 {
349  self endon( "death" );
350 
351  //self thread fireFlares();
352 
353  for ( ;; )
354  {
355  self waittill( "noteworthy", noteworthy, noteworthyNode );
356  if ( noteworthy == "strafe_start" )
357  {
358  self.strafeRunGunLookahead = level.strafeRunGunLookahead;
359  self.strafeRunGunRadius = level.strafeRunGunRadius;
360  self.strafeRunGunOffset = level.strafeRunGunOffset;
361 
362 /#
363  self.strafeRunGunLookahead = GetDvarInt( #"scr_straferunlookahead", level.strafeRunGunLookahead );
364  self.strafeRunGunRadius = GetDvarInt( #"scr_straferunradius", level.strafeRunGunRadius ); ;
365  self.strafeRunGunOffset = GetDvarInt( #"scr_straferunoffset", level.strafeRunGunOffset ); ;
366 #/
367 
368  if ( isdefined( noteworthyNode ) )
369  {
370  if ( isdefined( noteworthyNode.script_parameters ) )
371  {
372  self.strafeRunGunLookahead = float( noteworthyNode.script_parameters );
373  }
374 
375  if ( isdefined( noteworthyNode.script_radius ) )
376  {
377  self.strafeRunGunRadius = float( noteworthyNode.script_radius );
378  }
379 
380  if ( isdefined( noteworthyNode.script_float ) )
381  {
382  self.strafeRunGunOffset = float( noteworthyNode.script_float );
383  }
384  }
385  if( isdefined( self.owner ) )
386  {
387  self thread ‪startStrafe( );
388  }
389  }
390  else if ( noteworthy == "strafe_stop" )
391  {
392  self ‪stopStrafe();
393 
394  }
395  else if ( noteworthy == "strafe_leave" )
396  {
397 
398  if ( self ‪shouldLeaveMap() )
399  {
400  self thread ‪leaveMap();
401  //play pilot dialog
402  self thread ‪PilotDialogWait( "a10_leave", 5 );
403  }
404  else
405  {
406  //play pilot dialog
407  self thread ‪PilotDialogWait( "a10_strafe", 3 );
408  }
409  }
410  }
411 }
412 
413 function ‪fireFlares()
414 {
415  self endon( "death" );
416  self endon( "strafe_start" );
417 
418  wait( 0.1 );
419 
420  for ( ;; )
421  {
422  chaff_fx = ‪spawn( "script_model", self.origin );
423  chaff_fx.angles = (0,180,0);
424  chaff_fx SetModel( "tag_origin" );
425  chaff_fx LinkTo( self , "tag_origin", (0,0,0), (0,0,0) );
426 
427  wait( 0.1 );
428 
429  PlayFXOnTag( level.strafeRunChaffFX, chaff_fx, "tag_origin" );
430  chaff_fx playsound ("wpn_a10_drop_chaff");
431 
432  chaff_fx thread ‪util::deleteAfterTimeThread( level.strafeRunFlareDelay );
433 
434  wait( level.strafeRunFlareDelay );
435  }
436 }
437 
438 function ‪startStrafe( )
439 {
440  self endon( "death" );
441  self endon( "strafe_stop" );
442 
443  if ( isdefined( self.strafing ) )
444  {
445  IPrintLnBold( "TRYING TO STRAFE WHEN ALREADY STRAFING!\n" );
446  return;
447  }
448  self.strafing = true;
449 
450  //PlayPilotDialog("kls_hit");
451  self thread ‪PilotDialogWait ("kls_hit", 3.5);
452 
453  // First strafe
454  if ( self.numStrafes == 0 )
455  {
456  self ‪firstStrafe();
457  }
458 
459  self thread ‪fireRockets();
460 
461  self thread ‪startStrafeKillcams();
462 
463 // self planeSounds( undefined, "evt_flyby_apex_2362", "evt_flyby_wash_2362", 2362 );
464 
465  count = 0;
466  weaponShootTime = level.strafeRunGunWeapon.fireTime;
467  for ( ;; )
468  {
469  gunOrigin = self GetTagOrigin( "tag_flash" );
470  gunOrigin += ( 0, 0, self.strafeRunGunOffset );
471  forward = AnglesToForward( self.angles );
472  forwardNoZ = VectorNormalize( (forward[0],forward[1],0) );
473  right = VectorCross( forwardNoZ, (0,0,1) );
474  perfectAttackStartVector = gunOrigin + VectorScale( forwardNoZ, self.strafeRunGunLookahead );
475  attackStartVector = perfectAttackStartVector + VectorScale( right, RandomFloatRange( 0-self.strafeRunGunRadius, self.strafeRunGunRadius ) );
476 
477  ‪trace = BulletTrace( attackStartVector, (attackStartVector[0],attackStartVector[1],-500), false, self, false, true );
478  self SetTurretTargetVec( ‪trace["position"] );
479  self FireWeapon();
480  //self.gunSoundEntity PlayLoopSound( level.strafeRunGunSound );
481  self ‪shellShockPlayers( ‪trace["position"] );
482 
483 /#
484  if ( GetDvarInt( #"scr_devStrafeRunBulletsDebugDraw", 0 ) )
485  {
486  time = 300;
487  ‪airsupport::debug_line( attackStartVector, ‪trace["position"] - ( 0,0,20 ), (1,0,0), time, false );
488  if( count % 30 == 0 )
489  {
490  ‪trace = BulletTrace( perfectAttackStartVector, (perfectAttackStartVector[0],perfectAttackStartVector[1],-100000), false, self, false, true );
491  ‪airsupport::debug_line( ‪trace["position"] + ( 0,0,20 ), ‪trace["position"] - ( 0,0,20 ), (0,0,1), time, false );
492  }
493  }
494 #/
495  count++;
496  wait weaponShootTime;
497  }
498 
499 }
500 
501 function ‪firstStrafe()
502 {
503  /*Target_Set( self );
504  Target_SetTurretAquire( self, true );*/
505 }
506 
507 function ‪fireRockets()
508 {
509  self notify( "firing_rockets" );
510 
511  self endon( "death" );
512  self endon( "strafe_stop" );
513  self endon( "firing_rockets" );
514 
515  if( GetDvarInt( "teamOpsEnabled" ) == 0 )
516  self.owner endon( "disconnect" );
517 
518  forward = anglesToForward( self.angles );
519 
520  self.firedRocketTargets = [];
521 
522  for ( rocketIndex = 0 ; rocketIndex < level.strafeRunNumRockets ; rocketIndex++ )
523  {
524  rocketTag = level.strafeRunRocketTags[rocketIndex%level.strafeRunRocketTags.size];
525 
526  // If possible, choose the highest priority target we haven't already fired a rocket at, otherwise just choose the highest priority target
527  targets = ‪getValidTargets();
528  rocketOrigin = self GetTagOrigin( rocketTag );
529  targetOrigin = rocketOrigin + forward * 10000;
530  if ( targets.size > 0 )
531  {
532  selectedTarget = undefined;
533  foreach( target in targets )
534  {
535  alreadyAttacked = false;
536  foreach( oldTarget in self.firedRocketTargets )
537  {
538  if ( oldTarget == target )
539  {
540  alreadyAttacked = true;
541  break;
542  }
543  }
544  if ( !alreadyAttacked )
545  {
546  selectedTarget = target;
547  break;
548  }
549  }
550 
551  if ( isdefined( selectedTarget ) )
552  {
553  self.firedRocketTargets[self.firedRocketTargets.size] = selectedTarget;
554 
555  // do dead reconing on the target
556  targetOrigin = ‪deadReconTargetOrigin( rocketOrigin, selectedTarget );
557  }
558  }
559 
560  rocketOrigin = self GetTagOrigin( rocketTag );
561 
562  rocket = MagicBullet( level.strafeRunRocketWeapon, rocketOrigin, rocketOrigin + forward, self.owner );
563  if( GetDvarInt( "teamOpsEnabled" ) == 1 )
564  rocket.teamops = true;
565 
566  if ( isdefined( selectedTarget ) )
567  {
568  rocket missile_settarget( selectedTarget, (0,0,0) );
569  }
570  rocket.soundMod = "straferun";
571 
572  rocket ‪attachKillcamToRocket( level.strafeRunKillcams.rockets[rocketIndex], selectedTarget, targetOrigin );
573 
574 /#
575  if ( GetDvarInt( #"scr_devStrafeRunKillcamsDebugDraw", 0 ) )
576  rocket thread ‪airsupport::debug_draw_bomb_path( undefined, (0,0.5,0), 400 );
577 #/
578 
579  wait level.strafeRunRocketDelay;
580  }
581 }
582 
583 function ‪stopStrafe()
584 {
585  self notify( "strafe_stop" );
586 
587  self.strafing = undefined;
588 
589  // after the strafe run is done reset the killcams for the next strafe
590  self thread ‪resetKillcams( 3 );
591 
592  self ClearTurretTarget();
593 
594  if( GetDvarInt( "teamOpsEnabled" ) == 1 )
595  owner = self;
596  else
597  owner = self.owner;
598 
599  if( !isdefined( owner ) )
600  return;
601 
602  //self thread fireFlares();
603 
604  //TODO Add the negative BDA lines after they are recorded.
605  if( GetDvarInt( "teamOpsEnabled" ) == 0 )
606  {
607  if (owner.strafeRunbda == 0)
608  {
609  bdaDialog = "kls_killn";
610  }
611  if (owner.strafeRunbda == 1)
612  {
613  bdaDialog = "kls_kill1";
614  }
615  if (owner.strafeRunbda == 2)
616  {
617  bdaDialog = "kls_kill2";
618  }
619  if (owner.strafeRunbda == 3)
620  {
621  bdaDialog = "kls_kill3";
622  }
623  if (owner.strafeRunbda > 3)
624  {
625  bdaDialog = "kls_killm";
626  }
627 
628  if (isdefined(bdaDialog))
629  {
630  //play pilot dialog
631  self thread ‪PilotDialogWait( bdaDialog, 3.5 );
632  }
633  }
634 
635  owner.strafeRunbda = 0;
636 
637  self.gunSoundEntity StopLoopSound();
638  self.gunSoundEntity playsound ("wpn_a10_shot_decay_npc");
639  self.numStrafes++;
640 }
641 
642 function ‪PilotDialogWait( Dialog, time )
643 {
644  self endon( "death" );
645  if (isdefined(time))
646  {
647  wait time;
648  }
649 
650  if( GetDvarInt( "teamOpsEnabled" ) == 0 )
651  ‪PlayPilotDialog( Dialog );
652 }
653 
655 {
656  if ( isdefined( self.leaveNextTime ) && self.leaveNextTime )
657  {
658  return true;
659 
660  //PlayPilotDialog("a10_used");
661 
662  }
663 
664  if ( self.numStrafes >= level.strafeRunMaxStrafes )
665  {
666  return true;
667  }
668 
669  if( GetDvarInt( "teamOpsEnabled" ) == 1)
670  {
671  if( self.straferunKills >= level.strafeRunKillsBeforeExit )
672  {
673  return true;
674  }
675  }
676  else
677  {
678  if( self.owner.straferunKills >= level.strafeRunKillsBeforeExit )
679  {
680  return true;
681  }
682  }
683 
684  return false;
685 }
686 
687 function ‪leaveMap()
688 {
689  self ‪unlinkKillcams();
690 
691  exitOrigin = self.origin + VectorScale( AnglesToForward( self.angles ), level.strafeRunExitUnits );
692 
693  /*self ClearTargetYaw();
694  self ClearGoalYaw();*/
695  self SetYawSpeed( 5, 999, 999 );
696  self SetVehGoalPos( exitOrigin, 1 );
697 
698  wait 5;
699  if ( isdefined ( self ) )
700  {
701  self Delete();
702  }
703 }
704 
705 function ‪explode()
706 {
707  self endon( "delete" );
708 
709  forward = ( self.origin + ( 0, 0, 100 ) ) - self.origin;
710  PlayFX( level.strafeRunExplodeFX, self.origin, forward );
711 
712  // play heli explosion sound
713  self PlaySound( level.strafeRunExplodeSound );
714 
715  wait( 0.1 );
716 
717  if ( IsDefined( self ) )
718  {
719  self Delete();
720  }
721 }
722 
723 function ‪canTargetEntity( entity )
724 {
725  /*if ( distance( entity.origin, self.origin ) > level.heli_visual_range )
726  {
727  return false;
728  }*/
729 
730  heli_centroid = self.origin + ( 0, 0, -160 );
731  heli_forward_norm = anglestoforward( self.angles );
732  heli_turret_point = heli_centroid + 144*heli_forward_norm;
733 
734  visible_amount = entity sightConeTrace( heli_turret_point, self );
735 
736  if ( visible_amount < level.heli_target_recognition )
737  {
738  return false;
739  }
740 
741  return true;
742 }
743 
744 function ‪canTargetPlayer( player )
745 {
746  if ( !IsAlive( player ) || player.sessionstate != "playing" )
747  {
748  return false;
749  }
750 
751  if ( player == self.owner )
752  {
753  return false;
754  }
755 
756  if ( player ‪airsupport::canTargetPlayerWithSpecialty() == false )
757  {
758  return false;
759  }
760 
761  if ( !isdefined( player.team ) )
762  {
763  return false;
764  }
765 
766  if ( level.teamBased && player.team == self.team )
767  {
768  return false;
769  }
770 
771  if ( player.team == "spectator" )
772  {
773  return false;
774  }
775 
776  if ( isdefined( player.spawntime ) && ( GetTime() - player.spawntime )/1000 <= level.heli_target_spawnprotection )
777  {
778  return false;
779  }
780 
781  if ( !‪targetInFrontOfPlane( player ) )
782  {
783  return false;
784  }
785 
786  if ( player IsInMoveMode( "noclip" ))
787  {
788  return false;
789  }
790 
791  return ‪canTargetEntity( player );
792 }
793 
794 function ‪canTargetActor( actor )
795 {
796  if ( !isdefined( actor ) )
797  {
798  return false;
799  }
800 
801  if ( level.teamBased && ( actor.team == self.team ) )
802  {
803  return false;
804  }
805 
806  if ( isdefined( actor.script_owner ) && self.owner == actor.script_owner )
807  {
808  return false;
809  }
810 
811  if ( !‪targetInFrontOfPlane( actor ) )
812  {
813  return false;
814  }
815 
816  return ‪canTargetEntity( actor );
817 }
818 
819 function ‪targetInFrontOfPlane( target )
820 {
821  forward_dir = AnglesToForward(self.angles);
822  target_delta = VectorNormalize( target.origin - self.origin );
823  dot = VectorDot( forward_dir, target_delta );
824 
825  // 60 degrees
826  if ( dot < 0.5 )
827  return true;
828 
829  return true;
830 }
831 
833 {
834  targets = [];
835  foreach( player in level.players )
836  {
837  if ( self ‪canTargetPlayer( player ) )
838  {
839  if( isdefined( player ) )
840  targets[targets.size] = player;
841  }
842 
843  }
844 
846 
847  foreach( dog in dogs )
848  {
849  if ( self ‪canTargetActor( dog ) )
850  {
851  targets[targets.size] = dog;
852  }
853  }
854 
855  tanks = GetEntArray( "talon", "targetname" );
856 
857  foreach( tank in tanks )
858  {
859  if ( self ‪canTargetActor( tank ) )
860  {
861  targets[targets.size] = tank;
862  }
863  }
864 
865  return targets;
866 }
867 
868 function ‪deadReconTargetOrigin( rocket_start, target )
869 {
870  target_velocity = target GetVelocity();
871 
872  // would be nice to get this from the gdt.
873  missile_speed = 7000;
874 
875  target_delta = target.origin - rocket_start;
876 
877  target_dist = Length( target_delta );
878 
879  time_to_target = target_dist / missile_speed;
880 
881  return target.origin + target_velocity * time_to_target;
882 }
883 
884 function ‪shellShockPlayers( origin )
885 {
886  foreach( player in level.players )
887  {
888  if ( !IsAlive( player ) )
889  {
890  continue;
891  }
892 
893  if ( player == self.owner )
894  {
895  continue;
896  }
897 
898  if ( !isdefined( player.team ) )
899  {
900  continue;
901  }
902 
903  if ( level.teamBased && player.team == self.team )
904  {
905  continue;
906  }
907 
908  if ( DistanceSquared( player.origin, origin ) <= level.strafeRunShellShockRadius * level.strafeRunShellShockRadius )
909  {
910  player thread ‪strafeRunShellShock();
911  }
912  }
913 }
914 
916 {
917  self endon( "disconnect" );
918 
919  if ( isdefined( self.beingStrafeRunShellShocked ) && self.beingStrafeRunShellShocked )
920  {
921  return;
922  }
923 
924  self.beingStrafeRunShellShocked = true;
925 
926  self ShellShock( level.strafeRunShellShock, level.strafeRunShellShockDuration );
927  wait( level.strafeRunShellShockDuration + 1 );
928 
929  self.beingStrafeRunShellShocked = false;
930 }
931 
932 function ‪createKillcams( numKillcams, numRockets )
933 {
934  // killcams are only created once per level
935  if ( !isdefined(level.strafeRunKillcams) )
936  {
937  level.strafeRunKillcams = SpawnStruct();
938 
939  level.strafeRunKillcams.rockets = [];
940  for ( i = 0; i < numRockets; i++ )
941  {
942  level.strafeRunKillcams.rockets[level.strafeRunKillcams.rockets.size] = ‪createKillcamEnt( );
943  }
944 
945  level.strafeRunKillcams.strafes = [];
946  for ( i = 0; i < numKillcams; i++ )
947  {
948  level.strafeRunKillcams.strafes[level.strafeRunKillcams.strafes.size] = ‪createKillcamEnt( );
949 /#
950  if ( GetDvarInt( #"scr_devStrafeRunKillcamsDebugDraw", 0 ) )
951  level.strafeRunKillcams.strafes[i] thread ‪airsupport::debug_draw_bomb_path( undefined, (0,0,0.5), 200 );
952 #/
953  }
954  }
955 
956 }
957 
958 function ‪resetKillcams( time )
959 {
960  self endon( "death" );
961 
962  if ( isdefined( time ) )
963  wait( time );
964 
965  for ( i = 0; i < level.strafeRunKillcams.rockets.size; i++ )
966  {
967  level.strafeRunKillcams.rockets[i] ‪resetRocketKillcamEnt( self, i );
968  }
969 
970  for ( i = 0; i < level.strafeRunKillcams.strafes.size; i++ )
971  {
972  level.strafeRunKillcams.strafes[i] ‪resetKillcamEnt( self );
973  }
974 }
975 
977 {
978  for ( i = 0; i < level.strafeRunKillcams.rockets.size; i++ )
979  {
980  level.strafeRunKillcams.rockets[i] unlink();
981  }
982 
983  for ( i = 0; i < level.strafeRunKillcams.strafes.size; i++ )
984  {
985  level.strafeRunKillcams.strafes[i] unlink();
986  }
987 }
988 
990 {
991  killCamEnt = ‪spawn( "script_model", (0,0,0) );
992  //killCamEnt thread deleteWhenParentDies( self );
993 
994  killCamEnt SetFOVForKillcam( 25 );
995 
996  return killCamEnt;
997 }
998 
999 function ‪resetKillcamEnt( parent )
1000 {
1001  self notify( "reset" );
1002  parent endon( "death" );
1003 
1004  offset_x = GetDvarInt( #"scr_killcamplaneoffsetx", -3000 );
1005  offset_y = GetDvarInt( #"scr_killcamplaneoffsety", 0 );
1006  offset_z = GetDvarInt( #"scr_killcamplaneoffsetz", 740 );
1007 
1008  self linkto( parent, "tag_origin", (offset_x, offset_y, offset_z), (10,0,0) );
1009  self thread ‪unlinkWhenParentDies( parent );
1010 }
1011 
1012 function ‪resetRocketKillcamEnt( parent, rocketIndex )
1013 {
1014  self notify( "reset" );
1015  parent endon( "death" );
1016 
1017  offset_x = GetDvarInt( #"scr_killcamplaneoffsetx", -3000 );
1018  offset_y = GetDvarInt( #"scr_killcamplaneoffsety", 0 );
1019  offset_z = GetDvarInt( #"scr_killcamplaneoffsetz", 740 );
1020 
1021  rocketTag = level.strafeRunRocketTags[rocketIndex%level.strafeRunRocketTags.size];
1022 
1023  self linkto( parent, rocketTag, (offset_x, offset_y, offset_z), (10,0,0) );
1024  self thread ‪unlinkWhenParentDies( parent );
1025 }
1026 
1027 function ‪deleteWhenParentDies( parent )
1028 {
1029  parent waittill("death");
1030 
1031  self delete();
1032 }
1033 
1034 function ‪unlinkWhenParentDies( parent )
1035 {
1036  self endon("reset");
1037  self endon("unlink");
1038 
1039  parent waittill("death");
1040 
1041  self unlink();
1042 }
1043 
1044 function ‪attachKillcamToRocket( killCamEnt, selectedTarget, targetOrigin )
1045 {
1046  offset_x = GetDvarInt( #"scr_killcamrocketoffsetx", -400 );
1047  offset_y = GetDvarInt( #"scr_killcamrocketoffsety", 0 );
1048  offset_z = GetDvarInt( #"scr_killcamrocketoffsetz", 110 );
1049 
1050  self.killCamEnt = killCamEnt;
1051 
1052  forward = VectorScale( AnglesToForward( self.angles ), offset_x );
1053  right = VectorScale( AnglesToRight( self.angles ), offset_y );
1054  up = VectorScale( AnglesToUp( self.angles ), offset_z );
1055 
1056  killCamEnt unlink();
1057  killCamEnt.angles = (0,0,0);
1058  killCamEnt.origin = self.origin;
1059 
1060  killCamEnt linkto( self, "", (offset_x,offset_y,offset_z), (9, 0, 0) );
1061 
1062  killCamEnt thread ‪unlinkWhenClose( selectedTarget, targetOrigin, self );
1063 }
1064 
1065 function ‪unlinkWhenClose( selectedTarget, targetOrigin, plane )
1066 {
1067  plane endon( "death" );
1068  self notify( "unlink_when_close" );
1069  self endon( "unlink_when_close" );
1070 
1071  distSqr = 1000 * 1000;
1072 
1073  while ( 1 )
1074  {
1075  if ( isdefined( selectedTarget ) )
1076  {
1077  if ( DistanceSquared( self.origin, selectedTarget.origin ) < distSqr )
1078  {
1079  self unlink();
1080  self.angles = (0,0,0);
1081  return;
1082  }
1083  }
1084  else
1085  {
1086  if ( DistanceSquared( self.origin, targetOrigin ) < distSqr )
1087  {
1088  self unlink();
1089  self.angles = (0,0,0);
1090  return;
1091  }
1092  }
1093  wait( 0.1 );
1094  }
1095 }
1096 
1097 function ‪getLookaheadOrigin( previous_origin, next_origin, lookAhead )
1098 {
1099  delta = next_origin - previous_origin;
1100  forwardNoZ = VectorNormalize( (delta[0],delta[1],0) );
1101  origin = next_origin + VectorScale( forwardNoZ, lookAhead );
1102  return origin;
1103 }
1104 
1105 function ‪strafeKillcam( parent, node, distance )
1106 {
1107  parent endon("death");
1108  self endon( "reset" );
1109 
1110  // let the plane start firing
1112 
1113  self notify( "unlink" );
1114  self Unlink();
1115  self.angles = (0,0,0);
1116 
1117  accel_time = 0.2;
1118  speed = 20000;
1119 
1120  start_height_offset = -800;
1121  stop_height = level.mapCenter[2] - 500;
1122 
1123  start_origin_struct = ‪getOriginAlongStrafePath( node, self.origin, distance );
1124  start_origin = start_origin_struct.origin;
1125  node = start_origin_struct.node;
1126 
1127  previous_origin = self.origin;
1128 
1129  start_origin = ‪getLookaheadOrigin( previous_origin, start_origin, parent.strafeRunGunLookahead + 1000);
1130 
1131  ‪trace = BulletTrace( (start_origin[0], start_origin[1], start_origin[2] + start_height_offset), (start_origin[0], start_origin[1], stop_height), false, parent, false, true );
1132 
1133  pathHeight = ‪trace["position"][2];
1134 
1135  self ‪killcamMoveto( ‪trace["position"], speed, accel_time, pathHeight );
1136 
1137  speed = 500;
1138 
1139  while( isdefined(node) )
1140  {
1141  previous_origin = node.origin;
1142  node = GetVehicleNode( node.target, "targetname" );
1143 
1144  start_origin = ‪getLookaheadOrigin( previous_origin, node.origin, parent.strafeRunGunLookahead + 1000 );
1145 
1146  ‪trace = BulletTrace( (start_origin[0], start_origin[1], start_origin[2] + start_height_offset), (start_origin[0], start_origin[1], stop_height), false, parent, false, true );
1147  self ‪killcamMoveto( ‪trace["position"], speed, 0, pathHeight );
1148  }
1149 }
1150 
1151 function ‪killcamMoveto( goal, speed, accel, pathHeight )
1152 {
1153  self endon( "reset" );
1154 
1155  height_offset = RandomIntRange(350,450);
1156  origin = (goal[0], goal[1], goal[2] + height_offset );
1157  dist = Distance( origin, self.origin );
1158  time = dist / speed ;
1159 
1160  if ( accel > time )
1161  accel = time;
1162 
1163  self MoveTo( origin, time, accel, 0 );
1164  self waittill( "movedone" );
1165 }
1166 
1168 {
1169  node = GetVehicleNode( self.currentNode.target, "targetname" );
1170  strafe_dist = ‪getStrafeDistance(node);
1171 
1172  strafe_increment = strafe_dist / (level.strafeRunKillcams.strafes.size + 1);
1173  current_dist = 10; // so we dont get a zero length delta on first point
1174 
1175  for ( i = 0; i < level.strafeRunKillcams.strafes.size; i++ )
1176  {
1177  level.strafeRunKillcams.strafes[i] thread ‪strafeKillcam( self, node, current_dist );
1178  current_dist += strafe_increment;
1179  //wait( 0.5 );
1180  }
1181 }
1182 
1183 function ‪getStrafeDistance(node)
1184 {
1185  previous_node = node;
1186  next_node = GetVehicleNode( previous_node.target, "targetname" );
1187 
1188  dist = 0;
1189 
1190  //dist = Distance( ( self.origin[0], self.origin[1], 0 ), ( node.origin[0], node.origin[1], 0 ) );
1191 
1192  while ( (!isdefined(previous_node.script_noteworthy) || previous_node.script_noteworthy != "strafe_stop") && next_node != node )
1193  {
1194  dist += Distance( (previous_node.origin[0], previous_node.origin[1], 0) , ( next_node.origin[0], next_node.origin[1], 0 ) );
1195 
1196  previous_node = next_node;
1197  next_node = GetVehicleNode( previous_node.target, "targetname" );
1198  }
1199 
1200  return dist;
1201 }
1202 
1203 function ‪getOriginAlongStrafePath(node, start_origin, distance_along)
1204 {
1205  origin_node = SpawnStruct();
1206 
1207 // previous_node = node;
1208 // next_node = GetVehicleNode( previous_node.target, "targetname" );
1209 
1210 // seg_dist = Distance( (previous_node.origin[0], previous_node.origin[1], 0) , ( next_node.origin[0], next_node.origin[1], 0 ) );
1211 
1212  seg_dist = Distance( (start_origin[0], start_origin[1], 0) , ( node.origin[0], node.origin[1], 0 ) );
1213 
1214  dist = 0;
1215 
1216  if ( (dist + seg_dist) > distance_along )
1217  {
1218  forwardVec = VectorNormalize( ( node.origin[0], node.origin[1], 0 ) - (start_origin[0], start_origin[1], 0) );
1219  origin_node.origin = start_origin + forwardVec * ( distance_along - dist );
1220  origin_node.node = node;
1221  return origin_node;
1222  }
1223 
1224  dist = seg_dist;
1225 
1226  previous_node = node;
1227  next_node = GetVehicleNode( previous_node.target, "targetname" );
1228 
1229  while ( (!isdefined(previous_node.script_noteworthy) || previous_node.script_noteworthy != "strafe_stop") && next_node != node )
1230  {
1231  seg_dist = Distance( (previous_node.origin[0], previous_node.origin[1], 0) , ( next_node.origin[0], next_node.origin[1], 0 ) );
1232 
1233  if ( (dist + seg_dist) > distance_along )
1234  {
1235  forwardVec = VectorNormalize( next_node.origin - previous_node.origin );
1236  origin_node.origin = previous_node.origin + forwardVec * ( distance_along - dist );
1237  origin_node.node = previous_node;
1238  return origin_node;
1239  }
1240 
1241  dist += seg_dist;
1242  previous_node = next_node;
1243  next_node = GetVehicleNode( previous_node.target, "targetname" );
1244  }
1245 }
‪startStrafe
‪function startStrafe()
Definition: _straferun.gsc:438
‪useKillstreakStrafeRun
‪function useKillstreakStrafeRun(hardpointType)
Definition: _straferun.gsc:102
‪resetRocketKillcamEnt
‪function resetRocketKillcamEnt(parent, rocketIndex)
Definition: _straferun.gsc:1012
‪canTargetActor
‪function canTargetActor(actor)
Definition: _straferun.gsc:794
‪watchdamage
‪function watchdamage()
Definition: _straferun.gsc:225
‪killcamMoveto
‪function killcamMoveto(goal, speed, accel, pathHeight)
Definition: _straferun.gsc:1151
‪createKillcamEnt
‪function createKillcamEnt()
Definition: _straferun.gsc:989
‪createKillcams
‪function createKillcams(numKillcams, numRockets)
Definition: _straferun.gsc:932
‪wait_playback_time
‪function wait_playback_time(soundAlias)
Definition: _battlechatter.gsc:1044
‪MissileTarget_ProximityDetonateIncomingMissile
‪function MissileTarget_ProximityDetonateIncomingMissile(endon1, endon2, allowDirectDamage)
Definition: _heatseekingmissile.gsc:1085
‪shouldLeaveMap
‪function shouldLeaveMap()
Definition: _straferun.gsc:654
‪addStraferunKill
‪function addStraferunKill()
Definition: _straferun.gsc:338
‪attachKillcamToRocket
‪function attachKillcamToRocket(killCamEnt, selectedTarget, targetOrigin)
Definition: _straferun.gsc:1044
‪play_killstreak_start_dialog
‪function play_killstreak_start_dialog(killstreakType, team, killstreakId)
Definition: _killstreaks.gsc:1905
‪shellShockPlayers
‪function shellShockPlayers(origin)
Definition: _straferun.gsc:884
‪cleanupOnDeath
‪function cleanupOnDeath(team)
Definition: _straferun.gsc:211
‪deleteWhenParentDies
‪function deleteWhenParentDies(parent)
Definition: _straferun.gsc:1027
‪trace
‪function trace(from, to, target)
Definition: grapple.gsc:369
‪addFlySwatterStat
‪function addFlySwatterStat(weapon, aircraft)
Definition: challenges_shared.gsc:86
‪ENEMY_VEHICLE_ACTIVE
‪#define ENEMY_VEHICLE_ACTIVE
Definition: _hacker_tool.gsh:2
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪strafeKillcam
‪function strafeKillcam(parent, node, distance)
Definition: _straferun.gsc:1105
‪PlayPilotDialog
‪function PlayPilotDialog(dialog)
Definition: _straferun.gsc:77
‪deleteAfterTimeThread
‪function deleteAfterTimeThread(time)
Definition: util_shared.gsc:2719
‪IsEnemyPlayer
‪function IsEnemyPlayer(player)
Definition: util_shared.csc:1220
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪canTargetPlayerWithSpecialty
‪function canTargetPlayerWithSpecialty()
Definition: _airsupport.gsc:1228
‪resetKillcams
‪function resetKillcams(time)
Definition: _straferun.gsc:958
‪init
‪function init()
Definition: _straferun.gsc:35
‪watchForOwnerExit
‪function watchForOwnerExit(owner)
Definition: _straferun.gsc:330
‪dog_manager_get_dogs
‪function dog_manager_get_dogs()
Definition: _dogs.gsc:625
‪explode
‪function explode()
Definition: _straferun.gsc:705
‪playContrail
‪function playContrail()
Definition: _straferun.gsc:202
‪getValidTargets
‪function getValidTargets()
Definition: _straferun.gsc:832
‪debug_draw_bomb_path
‪function debug_draw_bomb_path(projectile, color, time)
Definition: _airsupport.gsc:1008
‪firstStrafe
‪function firstStrafe()
Definition: _straferun.gsc:501
‪watchForKills
‪function watchForKills()
Definition: _straferun.gsc:310
‪leaveMap
‪function leaveMap()
Definition: _straferun.gsc:687
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪stopStrafe
‪function stopStrafe()
Definition: _straferun.gsc:583
‪canTargetPlayer
‪function canTargetPlayer(player)
Definition: _straferun.gsc:744
‪targetInFrontOfPlane
‪function targetInFrontOfPlane(target)
Definition: _straferun.gsc:819
‪unlinkKillcams
‪function unlinkKillcams()
Definition: _straferun.gsc:976
‪killstreakStop
‪function killstreakStop(hardpointType, team, id)
Definition: _killstreakrules.gsc:293
‪getLookaheadOrigin
‪function getLookaheadOrigin(previous_origin, next_origin, lookAhead)
Definition: _straferun.gsc:1097
‪killstreakStart
‪function killstreakStart(hardpointType, team, hacked, displayTeamMessage)
Definition: _killstreakrules.gsc:184
‪unlinkWhenParentDies
‪function unlinkWhenParentDies(parent)
Definition: _straferun.gsc:1034
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪getOriginAlongStrafePath
‪function getOriginAlongStrafePath(node, start_origin, distance_along)
Definition: _straferun.gsc:1203
‪unlinkWhenClose
‪function unlinkWhenClose(selectedTarget, targetOrigin, plane)
Definition: _straferun.gsc:1065
‪strafeRunShellShock
‪function strafeRunShellShock()
Definition: _straferun.gsc:915
‪resetKillcamEnt
‪function resetKillcamEnt(parent)
Definition: _straferun.gsc:999
‪watchForOtherKillstreaks
‪function watchForOtherKillstreaks()
Definition: _straferun.gsc:278
‪deadReconTargetOrigin
‪function deadReconTargetOrigin(rocket_start, target)
Definition: _straferun.gsc:868
‪debug_line
‪function debug_line(from, to, color, time, depthTest)
Definition: _airsupport.gsc:1089
‪PilotDialogWait
‪function PilotDialogWait(Dialog, time)
Definition: _straferun.gsc:642
‪fireFlares
‪function fireFlares()
Definition: _straferun.gsc:413
‪follow_path
‪function follow_path(node)
Definition: _vehicle.gsc:1903
‪canTargetEntity
‪function canTargetEntity(entity)
Definition: _straferun.gsc:723
‪doStrafeRuns
‪function doStrafeRuns()
Definition: _straferun.gsc:347
‪STRAFERUN_MAX_HEALTH
‪#define STRAFERUN_MAX_HEALTH
Definition: _straferun.gsc:22
‪fireRockets
‪function fireRockets()
Definition: _straferun.gsc:507
‪startStrafeKillcams
‪function startStrafeKillcams()
Definition: _straferun.gsc:1167
‪getStrafeDistance
‪function getStrafeDistance(node)
Definition: _straferun.gsc:1183
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265