‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_hacker_tool.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\killstreaks_shared;
6 #using scripts\shared\scoreevents_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\weapons\_heatseekingmissile;
10 #using scripts\shared\weapons\_weaponobjects;
11 
12 #insert scripts\shared\shared.gsh;
13 #insert scripts\shared\version.gsh;
14 
15 #precache( "triggerstring", "MP_GENERIC_HACKING" );
16 
17 #namespace hacker_tool;
18 
19 function ‪init_shared()
20 {
21  level.weaponHackerTool = GetWeapon( "pda_hack" );
22 
23  level.hackerToolLostSightLimitMs = 1000;
24  level.hackerToolLockOnRadius = 25;
25  level.hackerToolLockOnFOV = 65;
26  level.hackerToolHackTimeMs = 0.4;
27 
28  // equipment
29  level.equipmentHackerToolRadius = 20;
30  level.equipmentHackerToolTimeMs = 100;
31 
32  // care packages
33  level.carePackageHackerToolRadius = 60;
34  level.carePackageHackerToolTimeMs = GetGametypeSetting("crateCaptureTime") * 500;
35  level.carePackageFriendlyHackerToolTimeMs = GetGametypeSetting("crateCaptureTime") * 2000 ;
36  level.carePackageOwnerHackerToolTimeMs = 250;
37 
38  // vehicles
39  level.vehicleHackerToolRadius = 80;
40  level.vehicleHackerToolTimeMs = 5000;
41 
42  ‪clientfield::register( "toplayer", "hacker_tool", ‪VERSION_SHIP, 2, "int" );
43  //thread tunables();
45 }
46 
47 //******************************************************************
48 // *
49 // *
50 //******************************************************************
52 {
53  self endon( "disconnect" );
54 
55  self ‪clearHackerTarget( undefined, false, true);
56 
57  self thread ‪watchHackerToolUse();
58  self thread ‪watchHackerToolFired();
59 }
60 
61 //******************************************************************
62 // *
63 // *
64 //******************************************************************
65 function ‪clearHackerTarget( weapon, successfulHack, ‪spawned ) // self == player
66 {
67  self notify( "stop_lockon_sound" );
68  self notify( "stop_locked_sound" );
69  self notify( "clearHackerTarget" );
70 
71  self.stingerlocksound = undefined;
72  self StopRumble( "stinger_lock_rumble" );
73 
74  self.hackerToolLockStartTime = 0;
75  self.hackerToolLockStarted = false;
76  self.hackerToolLockFinalized = false;
77  self.hackerToolLockTimeElapsed = 0.0;
78 
79  if ( isdefined( weapon ) )
80  {
81  if ( weapon.isHackToolWeapon )
82  {
83  self SetWeaponHackPercent( weapon, 0.0 );
84  }
85 
86  if( isdefined( self.hackerToolTarget ))
87  {
88  ‪heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
89  }
90  }
91 
92  if ( successfulHack == false )
93  {
94  if ( ‪spawned == false )
95  {
96  if( isdefined( self.hackerToolTarget ) )
97  self playsoundtoplayer( "evt_hacker_hack_lost", self ); // hacking failed
98  }
101  }
102 
103  if( isdefined( self.hackerToolTarget ))
104  {
105  ‪heatseekingmissile::TargetingHacking( self.hackerToolTarget, false );
106  }
107  self.hackerToolTarget = undefined;
108 
109  self WeaponLockFree();
110  self WeaponLockTargetTooClose( false );
111  self WeaponLockNoClearance( false );
112 
113  self StopLocalSound( game["locking_on_sound"] );
114  self StopLocalSound( game["locked_on_sound"] );
115 
117 }
118 
119 //******************************************************************
120 // *
121 // *
122 //******************************************************************
123 function ‪watchHackerToolFired() // self == player
124 {
125  self endon( "disconnect" );
126  self endon ( "death" );
127  self endon ("killHackerMonitor");
128 
129  while ( true )
130  {
131  self waittill( "hacker_tool_fired", hackerToolTarget, weapon );
132 
133  if( isdefined( hackerToolTarget ))
134  {
135  if ( ‪isEntityHackableCarePackage( hackerToolTarget ) )
136  {
137  ‪scoreevents::giveCrateCaptureMedal( hackerToolTarget, self );
138  hackerToolTarget notify( "captured", self, true );
139 
140  if ( isdefined( hackerToolTarget.owner ) && isplayer( hackerToolTarget.owner ) && hackerToolTarget.owner.team != self.team && isdefined( level.play_killstreak_hacked_dialog ) )
141  {
142  hackerToolTarget.owner [[level.play_killstreak_hacked_dialog]]( hackerToolTarget.killstreakType,hackerToolTarget.killstreakId, self );
143  }
144  }
145  else if ( ‪isEntityHackableWeaponObject( hackerToolTarget ) && isdefined( hackerToolTarget.hackerTrigger ))
146  {
147  // turrets and weapon objects
148  hackerToolTarget.hackerTrigger notify( "trigger", self, true );
149  hackerToolTarget.previouslyHacked = true;
150  self.throwinggrenade = false;
151  }
152  else if ( isdefined( hackerToolTarget.killstreak_hackedCallback ) && ( !isdefined( hackerToolTarget.killstreakTimedOut ) || hackerToolTarget.killstreakTimedOut == false ) )
153  {
154  if ( hackerToolTarget.killstreak_hackedProtection == false )
155  {
156  if ( isdefined( hackerToolTarget.owner ) && isplayer( hackerToolTarget.owner ) )
157  {
158  // Hack complete
159  if ( isdefined( level.play_killstreak_hacked_dialog ) )
160  {
161  hackerToolTarget.owner [[level.play_killstreak_hacked_dialog]]( hackerToolTarget.killstreakType,hackerToolTarget.killstreakId, self );
162  }
163  }
164  self playsoundtoplayer( "evt_hacker_fw_success", self ); // hacked firewall successfully
165  hackerToolTarget notify( "killstreak_hacked", self );
166  hackerToolTarget.previouslyHacked = true;
167  hackerToolTarget [[ hackerToolTarget.killstreak_hackedCallback ]]( self );
168 
170  {
171  self AddPlayerStat( "hack_streak_with_blindeye_or_engineer", 1 );
172  }
173  }
174  else
175  {
176  if ( isdefined( hackerToolTarget.owner ) && isplayer( hackerToolTarget.owner ) )
177  {
178  // Breach complete
179  if ( isdefined( level.play_killstreak_firewall_hacked_dialog ) )
180  {
181  self.hackerToolTarget.owner [[level.play_killstreak_firewall_hacked_dialog]]( self.hackerToolTarget.killstreakType, self.hackerToolTarget.killstreakId );
182  }
183  }
184  self playsoundtoplayer( "evt_hacker_ks_success", self ); // hacked killstreak successfully
185  scoreevents::processscoreevent( "hacked_killstreak_protection", self, hackerToolTarget, level.weaponHackerTool );
186  }
187  hackerToolTarget.killstreak_hackedProtection = false;
188  }
189  else
190  {
191  if ( isdefined( hackerToolTarget.classname ) && hackerToolTarget.classname == "grenade" )
192  {
193  ‪damage = 1;
194  }
195  else if ( isdefined( hackerToolTarget.hackerToolDamage ))
196  {
197  ‪damage = hackerToolTarget.hackerToolDamage;
198  }
199  else if ( isdefined( hackerToolTarget.maxhealth ))
200  {
201  ‪damage = hackerToolTarget.maxhealth + 1;
202  }
203  else
204  {
205  ‪damage = 999999;
206  }
207 
208  if ( isdefined( hackerToolTarget.numFlares ) && hackerToolTarget.numFlares > 0 )
209  {
210  ‪damage = 1;
211  hackerToolTarget.numFlares--;
213  }
214 
215  hackerToolTarget DoDamage( ‪damage, self.origin, self, self, 0, "MOD_UNKNOWN", 0, weapon );
216  }
217  if ( self ‪util::is_item_purchased( "pda_hack" ) )
218  {
219  self AddPlayerStat( "hack_enemy_target", 1 );
220  }
221  self AddWeaponStat( weapon, "used", 1 );
222  }
223 
224  ‪clearHackerTarget( weapon, true, false );
225  self forceoffhandend();
226 
227  if ( GetDvarint( "player_sustainAmmo" ) == 0 )
228  {
229  clip_ammo = self GetWeaponAmmoClip( weapon );
230  clip_ammo--;
231  /#assert( clip_ammo >= 0);#/
232 
233  self setWeaponAmmoClip( weapon, clip_ammo );
234  }
235 
236 
237  self ‪killstreaks::switch_to_last_non_killstreak_weapon(); // won't switch weapons while the shoulder button is held
238  }
239 }
240 
241 //******************************************************************
242 // *
243 // *
244 //******************************************************************
245 function ‪watchHackerToolUse() // self == player
246 {
247  self endon( "disconnect" );
248  self endon ( "death" );
249 
250  for (;;)
251  {
252  self waittill ( "grenade_pullback", weapon );
253 
254  if ( weapon.rootWeapon == level.weaponHackerTool )
255  {
257  currentOffhand = self getCurrentOffhand();
258  if ( self isUsingOffhand() && ( currentOffhand.rootWeapon == level.weaponHackerTool ) )
259  {
260  self thread ‪hackerToolTargetLoop( weapon );
261  self thread ‪watchHackerToolEnd( weapon );
262  self thread ‪watchForGrenadeFire( weapon );
263  self thread ‪watchHackerToolInterrupt(weapon );
264  }
265  }
266  }
267 }
268 
269 //******************************************************************
270 // *
271 // *
272 //******************************************************************
273 function ‪watchHackerToolInterrupt( weapon ) // self == player
274 {
275  self endon( "disconnect" );
276  self endon( "hacker_tool_fired" );
277  self endon( "death" );
278  self endon( "weapon_change" );
279  self endon( "grenade_fire" );
280 
281  while( true )
282  {
283  level waittill( "use_interrupt", interruptTarget );
284 
285  if( self.hackerToolTarget == interruptTarget )
286  {
287  ‪clearHackerTarget( weapon, false, false );
288  }
290  }
291 }
292 
293 
294 function ‪watchHackerToolEnd( weapon ) // self == player
295 {
296  self endon( "disconnect" );
297  self endon( "hacker_tool_fired" );
298 
299  msg = self ‪util::waittill_any_return( "weapon_change", "death", "hacker_tool_fired", "disconnect" );
300  ‪clearHackerTarget( weapon, false, false );
303 }
304 
305 
306 function ‪watchForGrenadeFire( weapon ) // self == player
307 {
308  self endon( "disconnect" );
309  self endon( "hacker_tool_fired" );
310  self endon( "weapon_change" );
311  self endon( "death" );
312 
313  while( true )
314  {
315  //This notify will be called when a weapon object gets hacked to reboot the watcher. We don't want to give the player ammo for this.
316  self waittill( "grenade_fire", grenade_instance, grenade_weapon, respawnFromHack );
317 
318  if( isDefined( respawnFromHack ) && respawnFromHack )
319  continue;
320 
321  ‪clearHackerTarget( grenade_weapon, false, false );
322 
323  clip_ammo = self GetWeaponAmmoClip( grenade_weapon );
324  clip_max_ammo = grenade_weapon.clipSize;
325 
326  if( clip_ammo < clip_max_ammo )
327  {
328  clip_ammo++;
329  }
330  self setWeaponAmmoClip( grenade_weapon, clip_ammo );
331  break;
332  }
333 }
334 
335 
336 function ‪playHackerToolSoundLoop() // self == player
337 {
338  if ( !isdefined( self.hacker_sound_ent ) || ( isdefined( self.hacker_alreadyhacked ) && self.hacker_alreadyhacked == true ) )
339  {
340  self playloopsound ("evt_hacker_device_loop");
341  self.hacker_sound_ent = true;
342  self.hacker_alreadyhacked = false;
343  }
344 }
345 
346 function ‪stopHackerToolSoundLoop() // self == player
347 {
348  self StopLoopSound( 0.5 );
349  self.hacker_sound_ent = undefined;
350  self.hacker_alreadyhacked = undefined;
351 }
352 
353 
354 function ‪hackerToolTargetLoop( weapon ) // self == player
355 {
356  self endon( "disconnect" );
357  self endon( "death" );
358  self endon( "weapon_change" );
359  self endon( "grenade_fire" );
360 
362 
364 
365  while ( true )
366  {
369 
370  if ( self.hackerToolLockFinalized )
371  {
372  if ( !self ‪isValidHackerToolTarget( self.hackerToolTarget, weapon, false ))
373  {
374  self ‪clearHackerTarget( weapon, false, false );
375  continue;
376  }
377 
378  passed = self ‪hackerSoftSightTest( weapon );
379 
380  if ( !passed )
381  {
382  continue;
383  }
386  ‪heatseekingmissile::TargetingHacking( self.hackerToolTarget, false);
387  ‪heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
388 
389  thread ‪heatseekingmissile::LoopLocalLockSound( game["locked_on_sound"], 0.75 );
390 
391  self notify( "hacker_tool_fired", self.hackerToolTarget, weapon );
392  return;
393  }
394 
395  if ( self.hackerToolLockStarted )
396  {
397  if ( !self ‪isValidHackerToolTarget( self.hackerToolTarget, weapon, false ) )
398  {
399  self ‪clearHackerTarget( weapon, false, false );
400  continue;
401  }
402 
403  lockOnTime = self ‪getLockOnTime( self.hackerToolTarget, weapon );
404 
405  if ( lockOnTime == 0 )
406  {
407  self ‪clearHackerTarget( weapon, false, false );
408  continue;
409  }
410 
411  if ( self.hackerToolLockTimeElapsed == 0.0 )
412  {
413  self PlayLocalSound ( "evt_hacker_hacking" );
414 
415  if ( isdefined( self.hackerToolTarget.owner ) && isplayer( self.hackerToolTarget.owner ) )
416  {
417  if ( isdefined( self.hackerToolTarget.killstreak_hackedCallback ) && ( !isdefined( self.hackerToolTarget.killstreakTimedOut ) || self.hackerToolTarget.killstreakTimedOut == false ) )
418  {
419  if ( self.hackerToolTarget.killstreak_hackedProtection == false )
420  {
421  // hacking started, regular hack
422  //self.hackerToolTarget.owner
423  if ( isdefined( level.play_killstreak_being_hacked_dialog ) )
424  {
425  self.hackerToolTarget.owner [[level.play_killstreak_being_hacked_dialog]]( self.hackerToolTarget.killstreakType, self.hackerToolTarget.killstreakId );
426  }
427  }
428  else
429  {
430  // breaching firewall started
431  if ( isdefined( level.play_killstreak_firewall_being_hacked_dialog ) )
432  {
433  self.hackerToolTarget.owner [[level.play_killstreak_firewall_being_hacked_dialog]]( self.hackerToolTarget.killstreakType, self.hackerToolTarget.killstreakId );
434  }
435  }
436  }
437  }
438  }
439 
440  self WeaponLockStart( self.hackerToolTarget );
442  if ( isdefined( self.hackerToolTarget.killstreak_hackedProtection ) && self.hackerToolTarget.killstreak_hackedProtection == true )
443  {
445  }
446  else
447  {
449  }
450 
451  ‪heatseekingmissile::TargetingHacking( self.hackerToolTarget, true );
452  ‪heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
453 
454  passed = self ‪hackerSoftSightTest( weapon );
455 
456  if ( !passed )
457  {
458  continue;
459  }
460 
461  if ( self.hackerToolLostSightlineTime == 0 )
462  {
463  self.hackerToolLockTimeElapsed += 0.1 * ‪hackingTimeScale( self.hackerToolTarget );
464  hackPercentage = (self.hackerToolLockTimeElapsed / ( lockOnTime )) * 100;
465  self SetWeaponHackPercent( weapon, hackPercentage );
466  ‪heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
467  }
468  else
469  {
470  self.hackerToolLockTimeElapsed -= 0.1 * ‪hackingTimeNoLineOfSightScale( self.hackerToolTarget );
471  if ( self.hackerToolLockTimeElapsed < 0 )
472  {
473  self.hackerToolLockTimeElapsed = 0;
474  self ‪clearHackerTarget( weapon, false, false );
475  continue;
476  }
477  hackPercentage = (self.hackerToolLockTimeElapsed / ( lockOnTime )) * 100;
478 
479  self SetWeaponHackPercent( weapon, hackPercentage );
480  ‪heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
481  }
482 
483  if ( self.hackerToolLockTimeElapsed < lockOnTime )
484  {
485  continue;
486  }
487 
488  assert( isdefined( self.hackerToolTarget ));
489 
490  self notify( "stop_lockon_sound" );
491  self.hackerToolLockFinalized = true;
492 
493  self WeaponLockFinalize( self.hackerToolTarget );
494 
495  continue;
496  }
497 
498 
499  if ( self IsEMPJammed() )
500  {
502  continue;
503  }
504 
505  bestTarget = self ‪getBestHackerToolTarget( weapon );
506 
507  if ( !isdefined( bestTarget ))
508  {
511  continue;
512  }
513 
514  if ( !self ‪heatseekingmissile::LockSightTest( bestTarget ) )
515  {
518  continue;
519  }
520 
521  //check for delay allowing helicopters to enter the play area
522  if( self ‪heatseekingmissile::LockSightTest( bestTarget ) && isdefined( bestTarget.lockOnDelay ) && bestTarget.lockOnDelay )
523  {
526  continue;
527  }
528 
530 
531  if ( ‪isEntityPreviouslyHacked( bestTarget ) )
532  {
533  if ( !isdefined( self.hacker_sound_ent ) || ( isdefined( self.hacker_alreadyhacked ) && self.hacker_alreadyhacked == false ) )
534  {
535  self.hacker_sound_ent = true;
536  self.hacker_alreadyhacked = true;
537  self playloopsound( "evt_hacker_unhackable_loop" );
538  }
539  continue;
540  }
541  else
542  {
544  }
545 
547 
548  self.hackerToolTarget = bestTarget;
549 
550  self thread ‪watchTargetEntityUpdate( bestTarget );
551  self.hackerToolLockStartTime = getTime();
552  self.hackerToolLockStarted = true;
553  self.hackerToolLostSightlineTime = 0;
554  self.hackerToolLockTimeElapsed = 0.0;
555  self SetWeaponHackPercent( weapon, 0.0 );
556  if ( isdefined( self.hackerToolTarget ) )
557  {
558  ‪heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
559  }
560  }
561 }
562 
563 function ‪watchTargetEntityUpdate( bestTarget )
564 {
565  self endon( "death" );
566  self endon( "disconnect" );
567 
568  self notify( "watchTargetEntityUpdate" );
569  self endon( "watchTargetEntityUpdate" );
570 
571  self endon( "clearHackerTarget" );
572 
573  bestTarget endon( "death" );
574 
575  bestTarget waittill( "hackertool_update_ent", newEntity );
577  self.hackerToolTarget = newEntity;
578 }
579 
580 function ‪getBestHackerToolTarget( weapon )
581 {
582  targetsValid = [];
583 
584  targetsAll = ArrayCombine( target_getArray(), level.MissileEntities, false, false );
585  targetsAll = ArrayCombine( targetsAll, level.hackerToolTargets, false, false );
586 
587  for ( idx = 0; idx < targetsAll.size; idx++ )
588  {
589  target_ent = targetsAll[ idx ];
590 
591  if ( !isdefined( target_ent ) || !isdefined( target_ent.owner ) )
592  {
593  continue;
594  }
595 
596  /#
597  //This variable is set and managed by the 'dev_friendly_lock' function, which works with the dev_gui
598  if( GetDvarString( "scr_freelock") == "1" )
599  {
600  //If the dev_gui dvar is set, only check if the target is in the reticule.
601  if( self ‪isWithinHackerToolReticle( targetsAll[idx], weapon ) )
602  {
603  targetsValid[targetsValid.size] = targetsAll[idx];
604  }
605  continue;
606  }
607  #/
608 
609  if ( level.teamBased || level.use_team_based_logic_for_locking_on === true ) //team based game modes
610  {
611  if ( ‪isEntityHackableCarePackage( target_ent ))
612  {
613  if ( self ‪canTargetEntity( target_ent, weapon ) )
614  {
615  targetsValid[ targetsValid.size ] = target_ent;
616  }
617  }
618  else if ( isdefined( target_ent.team ))
619  {
620  if ( target_ent.team != self.team )
621  {
622  if ( self ‪canTargetEntity( target_ent, weapon ) )
623  {
624  targetsValid[ targetsValid.size ] = target_ent;
625  }
626  }
627  }
628  else if ( isdefined( target_ent.owner.team ) )
629  {
630  if ( target_ent.owner.team != self.team )
631  {
632  if ( self ‪canTargetEntity( target_ent, weapon ) )
633  {
634  targetsValid[ targetsValid.size ] = target_ent;
635  }
636  }
637  }
638  }
639  else
640  {
641  if( self ‪isWithinHackerToolReticle( target_ent, weapon )) //Free for all
642  {
643  if ( ‪isEntityHackableCarePackage( target_ent ))
644  {
645  if ( self ‪canTargetEntity( target_ent, weapon ) )
646  {
647  targetsValid[ targetsValid.size ] = target_ent;
648  }
649  }
650  else if( isdefined( target_ent.owner ) && self != target_ent.owner )
651  {
652  if ( self ‪canTargetEntity( target_ent, weapon ) )
653  {
654  targetsValid[ targetsValid.size ] = target_ent;
655  }
656  }
657  }
658  }
659  }
660 
661  chosenEnt = undefined;
662 
663  if ( targetsValid.size != 0 )
664  {
665  //TODO: find the closest
666  chosenEnt = targetsValid[0];
667  }
668 
669  return chosenEnt;
670 }
671 
672 function ‪canTargetEntity( target, weapon )
673 {
674  if ( !self ‪isWithinHackerToolReticle( target, weapon ) )
675  return false;
676  if ( !‪isValidHackerToolTarget( target, weapon, true ) )
677  return false;
678 
679  return true;
680 }
681 
682 function ‪isWithinHackerToolReticle( target, weapon )
683 {
684  radiusInner = ‪getHackerToolInnerRadius( target );
685  radiusOuter = ‪getHackerToolOuterRadius( target );
686 
687  if( Target_ScaleMinMaxRadius( target, self, level.hackerToolLockOnFOV, radiusInner, radiusOuter ) > 0.0 )
688  {
689  return true;
690  }
691 
692  return Target_BoundingIsUnderReticle( self, target, weapon.lockOnMaxRange );
693 }
694 
695 //******************************************************************
696 // *
697 // *
698 //******************************************************************
699 function ‪hackingTimeScale( target )
700 {
701  hackRatio = 1;
702  radiusInner = ‪getHackerToolInnerRadius( target );
703  radiusOuter = ‪getHackerToolOuterRadius( target );
704 
705  if ( radiusInner != radiusOuter )
706  {
707 
708  scale = Target_ScaleMinMaxRadius( target, self, level.hackerToolLockOnFOV, radiusInner, radiusOuter );
709  scale = scale * scale * scale * scale;
710  hackTime = LerpFloat( ‪getHackOuterTime( target ), ‪getHackTime( target ), scale );
711 /#
712  hackerToolDebugText = GetDvarInt( "hackertoolDebugText", 0 ) ;
713  if ( hackerToolDebugText )
714  {
715  print3d( target.origin, "scale: " + scale + "\nInner: " + radiusInner + " Outer: " + radiusOuter, ( 0, 0, 0 ), 1, hackerToolDebugText, 2 );
716  }
717  assert( hacktime > 0 );
718 #/
719 
720  hackRatio = ‪getHackTime( target ) / hackTime;
721  if ( !isdefined( hackRatio ) )
722  {
723  hackRatio = 1;
724  }
725  }
726 
727  return hackRatio;
728 }
729 
731 {
732  hackRatio = 1;
733 
734  if ( isdefined( target.killstreakHackLostLineOfSightTimeMs ) && target.killstreakHackLostLineOfSightTimeMs > 0 )
735  {
736 /#
737  assert( target.killstreakHackLostLineOfSightTimeMs > 0 );
738 #/
739  hackRatio = 1000 / target.killstreakHackLostLineOfSightTimeMs;
740  }
741 
742 
743  return hackRatio;
744 }
745 
746 
747 //******************************************************************
748 // *
749 // *
750 //******************************************************************
752 {
753  if ( isdefined( entity.classname ) && entity.classname == "grenade" )
754  {
755  if ( isdefined( entity.weapon ) )
756  {
757  watcher = ‪weaponobjects::getWeaponObjectWatcherByWeapon( entity.weapon );
758  if ( isdefined( watcher ))
759  {
760  if ( watcher.hackable )
761  {
762  /#
763  assert( isdefined( watcher.hackerToolRadius ));
764  assert( isdefined( watcher.hackerToolTimeMs ));
765  #/
766 
767  return true;
768  }
769  }
770  }
771  }
772 
773  return false;
774 }
775 
776 //******************************************************************
777 // *
778 // *
779 //******************************************************************
781 {
782  /#
783  assert( isdefined( entity.classname ));
784  assert( isdefined( entity.weapon ));
785  #/
786 
787  watcher = ‪weaponobjects::getWeaponObjectWatcherByWeapon( entity.weapon );
788 
789  /#
790  assert( watcher.hackable );
791  assert( isdefined( watcher.hackerToolRadius ));
792  #/
793 
794  return watcher.hackerToolRadius;
795 }
796 
797 //******************************************************************
798 // *
799 // *
800 //******************************************************************
802 {
803  /#
804  assert( isdefined( entity.classname ));
805  assert( isdefined( entity.weapon ));
806  #/
807 
808  watcher = ‪weaponobjects::getWeaponObjectWatcherByWeapon( entity.weapon );
809 
810  /#
811  assert( watcher.hackable );
812  assert( isdefined( watcher.hackerToolTimeMs ));
813  #/
814 
815  return watcher.hackerToolTimeMs;
816 }
817 
818 //******************************************************************
819 // *
820 // *
821 //******************************************************************
823 {
824  if ( isdefined( entity.model ))
825  {
826  return entity.model == "wpn_t7_care_package_world";
827  }
828  else
829  {
830  return false;
831  }
832 }
833 
834 //******************************************************************
835 // *
836 // *
837 //******************************************************************
838 function ‪isValidHackerToolTarget( ent, weapon, allowHacked ) // self == hacking player
839 {
840  if ( !isdefined( ent ))
841  {
842  return false;
843  }
844 
845  if ( self ‪util::isUsingRemote() )
846  {
847  return false;
848  }
849 
850  if ( self IsEMPJammed() )
851  {
852  return false;
853  }
854 
855  if ( !( target_isTarget( ent ) || isdefined( ent.allowHackingAfterCloak ) && ent.allowHackingAfterCloak == true )
857  && !IsInArray( level.hackerToolTargets, ent ) )
858  {
859  return false;
860  }
861 
863  {
864  if ( DistanceSquared( self.origin, ent.origin ) > ( weapon.lockOnMaxRange * weapon.lockOnMaxRange ) )
865  {
866  return false;
867  }
868  }
869 
870  if ( allowHacked == false && ‪isEntityPreviouslyHacked( ent ) )
871  {
872  return false;
873  }
874 
875  return true;
876 }
877 
878 
879 function ‪isEntityPreviouslyHacked( entity )
880 {
881  if ( ‪IS_TRUE( entity.previouslyHacked ) )
882  {
883  return true;
884  }
885 
886  return false;
887 }
888 
889 //******************************************************************
890 // *
891 // *
892 //******************************************************************
893 function ‪hackerSoftSightTest( weapon ) // self == player
894 {
895  passed = true;
896  lockOnTime = 0;
897 
898  if ( isdefined( self.hackerToolTarget ) )
899  {
900  lockOnTime = self ‪getLockOnTime( self.hackerToolTarget, weapon );
901  }
902 
903  if ( lockOnTime == 0 || self IsEMPJammed() )
904  {
905  self ‪clearHackerTarget( weapon, false, false );
906  passed = false;
907  }
908  else
909  {
910  if ( ‪isWithinHackerToolReticle( self.hackerToolTarget, weapon ) && self ‪heatseekingmissile::LockSightTest( self.hackerToolTarget ) )
911  {
912  self.hackerToolLostSightlineTime = 0;
913  }
914  else
915  {
916  if ( self.hackerToolLostSightlineTime == 0 )
917  {
918  // pause the progress bar
919  self.hackerToolLostSightlineTime = getTime();
920  }
921 
922  timePassed = GetTime() - self.hackerToolLostSightlineTime;
923  lostLineOfSightTimeLimitMsec = level.hackerToolLostSightLimitMs;
924  if ( isdefined( self.hackerToolTarget.killstreakHackLostLineOfSightLimitMs ) )
925  {
926  lostLineOfSightTimeLimitMsec = self.hackerToolTarget.killstreakHackLostLineOfSightLimitMs;
927  }
928 
929  if ( timePassed >= lostLineOfSightTimeLimitMsec )
930  {
931  self ‪clearHackerTarget( weapon, false, false );
932  passed = false;
933  }
934  }
935  }
936 
937  return passed;
938 }
939 
940 //******************************************************************
941 // *
942 // *
943 //******************************************************************
944 function ‪registerWithHackerTool( radius, hackTimeMs ) // self == some hackable entity
945 {
946  self endon( "death" );
947 
948  if ( isdefined( radius ))
949  {
950  self.hackerToolRadius = radius;
951  }
952  else
953  {
954  self.hackerToolRadius = level.hackerToolLockOnRadius;
955  }
956 
957  if ( isdefined( hackTimeMs ))
958  {
959  self.hackerToolTimeMs = hackTimeMs;
960  }
961  else
962  {
963  self.hackerToolTimeMs = level.hackerToolHackTimeMs;
964  }
965 
966  self thread ‪watchHackableEntityDeath();
967  level.hackerToolTargets[ level.hackerToolTargets.size ] = self;
968 }
969 
970 //******************************************************************
971 // *
972 // *
973 //******************************************************************
975 {
976  self waittill( "death" );
977  ArrayRemoveValue( level.hackerToolTargets, self );
978 }
979 
980 //******************************************************************
981 // *
982 // *
983 //******************************************************************
984 function ‪getHackerToolInnerRadius( target )
985 {
986  radius = level.hackerToolLockOnRadius;
987 
988  if ( ‪isEntityHackableCarePackage( target ))
989  {
990  /#assert( isdefined( target.hackerToolRadius ));#/
991  radius = target.hackerToolRadius;
992  }
993  else if ( ‪isEntityHackableWeaponObject( target ))
994  {
995  radius = ‪getWeaponObjectHackerRadius( target );
996  }
997  else if ( isdefined( target.hackerToolInnerRadius ))
998  {
999  radius = target.hackerToolInnerRadius;
1000  }
1001  else if ( isdefined( target.hackerToolRadius ))
1002  {
1003  radius = target.hackerToolRadius;
1004  }
1005 
1006  return radius;
1007 }
1008 
1009 //******************************************************************
1010 // *
1011 // *
1012 //******************************************************************
1014 {
1015  radius = level.hackerToolLockOnRadius;
1016 
1017  if ( ‪isEntityHackableCarePackage( target ))
1018  {
1019  /#assert( isdefined( target.hackerToolRadius ));#/
1020  radius = target.hackerToolRadius;
1021  }
1022  else if ( ‪isEntityHackableWeaponObject( target ))
1023  {
1024  radius = ‪getWeaponObjectHackerRadius( target );
1025  }
1026  else if ( isdefined( target.hackerToolOuterRadius ))
1027  {
1028  radius = target.hackerToolOuterRadius;
1029  }
1030  else if ( isdefined( target.hackerToolRadius ))
1031  {
1032  radius = target.hackerToolRadius;
1033  }
1034 
1035  return radius;
1036 }
1037 
1038 //******************************************************************
1039 // *
1040 // *
1041 //******************************************************************
1042 function ‪getHackTime( target ) // self == player
1043 {
1044  time = 500;
1045 
1046  if ( ‪isEntityHackableCarePackage( target ))
1047  {
1048  /#assert( isdefined( target.hackerToolTimeMs ));#/
1049  //time = target.hackerToolTimeMs;
1050 
1051  if ( isdefined( target.owner ) && ( target.owner == self ))
1052  {
1053  time = level.carePackageOwnerHackerToolTimeMs;
1054  }
1055  else if ( isdefined(target.owner) && (target.owner.team == self.team) )
1056  {
1057  time = level.carePackageFriendlyHackerToolTimeMs;
1058  }
1059  else
1060  {
1061  time = level.carePackageHackerToolTimeMs;
1062  }
1063  }
1064  else if ( ‪isEntityHackableWeaponObject( target ))
1065  {
1066  time = ‪getWeaponObjectHackTimeMs( target );
1067  }
1068  else if ( isdefined( target.hackerToolInnerTimeMs ))
1069  {
1070  time = target.hackerToolInnerTimeMs;
1071  }
1072  else
1073  {
1074  // vehicles/targets from the target array
1075  time = level.vehicleHackerToolTimeMs;
1076  }
1077 
1078  return time;
1079 }
1080 
1081 function ‪getHackOuterTime( target ) // self == player
1082 {
1083  time = 500;
1084 
1085  if ( ‪isEntityHackableCarePackage( target ))
1086  {
1087  /#assert( isdefined( target.hackerToolTimeMs ));#/
1088  //time = target.hackerToolTimeMs;
1089 
1090  if ( isdefined( target.owner ) && ( target.owner == self ))
1091  {
1092  time = level.carePackageOwnerHackerToolTimeMs;
1093  }
1094  else if ( isdefined(target.owner) && (target.owner.team == self.team) )
1095  {
1096  time = level.carePackageFriendlyHackerToolTimeMs;
1097  }
1098  else
1099  {
1100  time = level.carePackageHackerToolTimeMs;
1101  }
1102  }
1103  else if ( ‪isEntityHackableWeaponObject( target ))
1104  {
1105  time = ‪getWeaponObjectHackTimeMs( target );
1106  }
1107  else if ( isdefined( target.hackerToolOuterTimeMs ))
1108  {
1109  time = target.hackerToolOuterTimeMs;
1110  }
1111  else
1112  {
1113  // vehicles/targets from the target array
1114  time = level.vehicleHackerToolTimeMs;
1115  }
1116 
1117  return time;
1118 }
1119 
1120 
1121 function ‪getLockOnTime( target, weapon ) // self is the player, weapon is the hacker tool
1122 {
1123  lockLengthMs = self ‪getHackTime( self.hackerToolTarget );
1124 
1125  if ( lockLengthMs == 0 )
1126  {
1127  return 0;
1128  }
1129 
1130  lockOnSpeed = weapon.lockOnSpeed;
1131 
1132  if ( lockOnSpeed <= 0 )
1133  {
1134  lockOnSpeed = 1000;
1135  }
1136 
1137  return lockLengthMs / lockOnSpeed;
1138 }
1139 
1140 /#
1141 function ‪tunables()
1142 {
1143  while(1)
1144  {
1145  level.hackerToolLostSightLimitMs = GetDvarInt( "scr_hackerToolLostSightLimitMs", 1000 );
1146  level.hackerToolLockOnRadius = GetDvarFloat( "scr_hackerToolLockOnRadius", 20 );
1147  level.hackerToolLockOnFOV = GetDvarInt( "scr_hackerToolLockOnFOV", 65 );
1148 
1149  wait(1.0);
1150  }
1151 }
1152 #/
‪registerWithHackerTool
‪function registerWithHackerTool(radius, hackTimeMs)
Definition: _hacker_tool.gsc:944
‪stopHackerToolSoundLoop
‪function stopHackerToolSoundLoop()
Definition: _hacker_tool.gsc:346
‪watchHackerToolInterrupt
‪function watchHackerToolInterrupt(weapon)
Definition: _hacker_tool.gsc:273
‪has_hacker_perk_purchased_and_equipped
‪function has_hacker_perk_purchased_and_equipped()
Definition: util_shared.gsc:4110
‪MissileTarget_PlayFlareFx
‪function MissileTarget_PlayFlareFx()
Definition: _heatseekingmissile.gsc:1178
‪watchHackableEntityDeath
‪function watchHackableEntityDeath()
Definition: _hacker_tool.gsc:974
‪DisplayLockOnCanceledMessage
‪function DisplayLockOnCanceledMessage()
Definition: _heatseekingmissile.gsc:386
‪hackingTimeNoLineOfSightScale
‪function hackingTimeNoLineOfSightScale(target)
Definition: _hacker_tool.gsc:730
‪watchHackerToolFired
‪function watchHackerToolFired()
Definition: _hacker_tool.gsc:123
‪getHackerToolInnerRadius
‪function getHackerToolInnerRadius(target)
Definition: _hacker_tool.gsc:984
‪set_to_player
‪function set_to_player(str_field_name, n_value)
Definition: clientfield_shared.gsc:58
‪on_player_spawned
‪function on_player_spawned()
Definition: _hacker_tool.gsc:51
‪watchTargetEntityUpdate
‪function watchTargetEntityUpdate(bestTarget)
Definition: _hacker_tool.gsc:563
‪LoopLocalLockSound
‪function LoopLocalLockSound(alias, interval)
Definition: _heatseekingmissile.gsc:603
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪waittill_any_return
‪function waittill_any_return(string1, string2, string3, string4, string5, string6, string7)
Definition: util_shared.csc:212
‪getBestHackerToolTarget
‪function getBestHackerToolTarget(weapon)
Definition: _hacker_tool.gsc:580
‪isEntityHackableWeaponObject
‪function isEntityHackableWeaponObject(entity)
Definition: _hacker_tool.gsc:751
‪watchHackerToolUse
‪function watchHackerToolUse()
Definition: _hacker_tool.gsc:245
‪hackerToolTargetLoop
‪function hackerToolTargetLoop(weapon)
Definition: _hacker_tool.gsc:354
‪init_shared
‪function init_shared()
Definition: _hacker_tool.gsc:19
‪isEntityPreviouslyHacked
‪function isEntityPreviouslyHacked(entity)
Definition: _hacker_tool.gsc:879
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪getLockOnTime
‪function getLockOnTime(target, weapon)
Definition: _hacker_tool.gsc:1121
‪clearHackerTarget
‪function clearHackerTarget(weapon, successfulHack, spawned)
Definition: _hacker_tool.gsc:65
‪isUsingRemote
‪function isUsingRemote()
Definition: util_shared.gsc:2705
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪has_blind_eye_perk_purchased_and_equipped
‪function has_blind_eye_perk_purchased_and_equipped()
Definition: util_shared.gsc:4093
‪HACKER_TOOL_ACTIVE
‪#define HACKER_TOOL_ACTIVE
Definition: shared.gsh:829
‪is_item_purchased
‪function is_item_purchased(ref)
Definition: util_shared.gsc:4063
‪switch_to_last_non_killstreak_weapon
‪function switch_to_last_non_killstreak_weapon(immediate, awayfromBall)
Definition: killstreaks_shared.gsc:36
‪on_spawned
‪function on_spawned(func, obj)
Definition: callbacks_shared.csc:245
‪getHackOuterTime
‪function getHackOuterTime(target)
Definition: _hacker_tool.gsc:1081
‪InitLockField
‪function InitLockField(target)
Definition: _heatseekingmissile.gsc:695
‪DestroyLockOnCanceledMessage
‪function DestroyLockOnCanceledMessage()
Definition: _heatseekingmissile.gsc:380
‪isWithinHackerToolReticle
‪function isWithinHackerToolReticle(target, weapon)
Definition: _hacker_tool.gsc:682
‪watchHackerToolEnd
‪function watchHackerToolEnd(weapon)
Definition: _hacker_tool.gsc:294
‪canTargetEntity
‪function canTargetEntity(target, weapon)
Definition: _hacker_tool.gsc:672
‪getWeaponObjectHackerRadius
‪function getWeaponObjectHackerRadius(entity)
Definition: _hacker_tool.gsc:780
‪spawned
‪function spawned(localClientNum)
Definition: _claymore.csc:24
‪hackerSoftSightTest
‪function hackerSoftSightTest(weapon)
Definition: _hacker_tool.gsc:893
‪isValidHackerToolTarget
‪function isValidHackerToolTarget(ent, weapon, allowHacked)
Definition: _hacker_tool.gsc:838
‪TargetingHacking
‪function TargetingHacking(target, lock)
Definition: _heatseekingmissile.gsc:753
‪HACKER_TOOL_HACKING
‪#define HACKER_TOOL_HACKING
Definition: shared.gsh:830
‪HACKER_TOOL_FIREWALL
‪#define HACKER_TOOL_FIREWALL
Definition: shared.gsh:831
‪tunables
‪function tunables()
Definition: _hacker_tool.gsc:1141
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪giveCrateCaptureMedal
‪function giveCrateCaptureMedal(crate, capturer)
Definition: scoreevents_shared.gsc:279
‪getHackTime
‪function getHackTime(target)
Definition: _hacker_tool.gsc:1042
‪HACKER_TOOL_INACTIVE
‪#define HACKER_TOOL_INACTIVE
Definition: shared.gsh:828
‪isEntityHackableCarePackage
‪function isEntityHackableCarePackage(entity)
Definition: _hacker_tool.gsc:822
‪hackingTimeScale
‪function hackingTimeScale(target)
Definition: _hacker_tool.gsc:699
‪getHackerToolOuterRadius
‪function getHackerToolOuterRadius(target)
Definition: _hacker_tool.gsc:1013
‪watchForGrenadeFire
‪function watchForGrenadeFire(weapon)
Definition: _hacker_tool.gsc:306
‪getWeaponObjectHackTimeMs
‪function getWeaponObjectHackTimeMs(entity)
Definition: _hacker_tool.gsc:801
‪LockSightTest
‪function LockSightTest(target)
Definition: _heatseekingmissile.gsc:636
‪setFriendlyFlags
‪function setFriendlyFlags(weapon, target)
Definition: _heatseekingmissile.gsc:783
‪playHackerToolSoundLoop
‪function playHackerToolSoundLoop()
Definition: _hacker_tool.gsc:336
‪getWeaponObjectWatcherByWeapon
‪function getWeaponObjectWatcherByWeapon(weapon)
Definition: _weaponobjects.gsc:1194
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265