‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_killstreaks.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\abilities\_ability_player;
4 #using scripts\shared\array_shared;
5 #using scripts\shared\callbacks_shared;
6 #using scripts\shared\challenges_shared;
7 #using scripts\shared\clientfield_shared;
8 #using scripts\shared\damagefeedback_shared;
9 #using scripts\shared\hostmigration_shared;
10 #using scripts\shared\hud_shared;
11 #using scripts\shared\hud_message_shared;
12 #using scripts\shared\hud_util_shared;
13 #using scripts\shared\killstreaks_shared;
14 #using scripts\shared\popups_shared;
15 #using scripts\shared\system_shared;
16 #using scripts\shared\util_shared;
17 #using scripts\shared\weapons_shared;
18 #using scripts\shared\weapons\_weaponobjects;
19 #using scripts\shared\weapons\_weapons;
20 
21 #using scripts\mp\_teamops;
22 #using scripts\mp\_util;
23 #using scripts\mp\gametypes\_battlechatter;
24 #using scripts\mp\gametypes\_globallogic_audio;
25 #using scripts\mp\gametypes\_globallogic_score;
26 #using scripts\mp\gametypes\_globallogic_utils;
27 #using scripts\mp\gametypes\_hostmigration;
28 #using scripts\mp\gametypes\_hud_message;
29 #using scripts\mp\gametypes\_loadout;
30 #using scripts\mp\gametypes\_spawning;
31 #using scripts\mp\killstreaks\_ai_tank;
32 #using scripts\mp\killstreaks\_airsupport;
33 #using scripts\mp\killstreaks\_combat_robot;
34 #using scripts\mp\killstreaks\_counteruav;
35 #using scripts\mp\killstreaks\_dart;
36 #using scripts\mp\killstreaks\_dogs;
37 #using scripts\mp\killstreaks\_drone_strike;
38 #using scripts\mp\killstreaks\_emp;
39 #using scripts\mp\killstreaks\_flak_drone;
40 #using scripts\mp\killstreaks\_helicopter;
41 #using scripts\mp\killstreaks\_helicopter_gunner;
42 #using scripts\mp\killstreaks\_killstreak_bundles;
43 #using scripts\mp\killstreaks\_killstreak_detect;
44 #using scripts\mp\killstreaks\_killstreak_hacking;
45 #using scripts\mp\killstreaks\_killstreakrules;
46 #using scripts\mp\killstreaks\_killstreaks;
47 #using scripts\mp\killstreaks\_microwave_turret;
48 #using scripts\mp\killstreaks\_planemortar;
49 #using scripts\mp\killstreaks\_qrdrone;
50 #using scripts\mp\killstreaks\_raps;
51 #using scripts\mp\killstreaks\_rcbomb;
52 #using scripts\mp\killstreaks\_remote_weapons;
53 #using scripts\mp\killstreaks\_remotemissile;
54 #using scripts\mp\killstreaks\_satellite;
55 #using scripts\mp\killstreaks\_sentinel;
56 #using scripts\mp\killstreaks\_supplydrop;
57 #using scripts\mp\killstreaks\_turret;
58 #using scripts\mp\killstreaks\_uav;
59 
60 #insert scripts\mp\_hacker_tool.gsh;
61 #insert scripts\shared\shared.gsh;
62 #insert scripts\shared\clientfields.gsh;
63 #insert scripts\shared\statstable_shared.gsh;
64 #insert scripts\shared\version.gsh;
65 #insert scripts\shared\abilities\_ability_util.gsh;
66 
67 #define TAACOM_KILLSTREAK_READY_WAIT 2.4
68 
69 #precache( "string", "MP_KILLSTREAK_N" );
70 
71 #namespace killstreaks;
72 
73 ‪REGISTER_SYSTEM( "killstreaks", &‪__init__, undefined )
74 
75 function ‪__init__()
76 {
77  level.killstreaks = [];
78  level.killstreakWeapons = [];
79  level.dropLocations = [];
80  level.zOffsetCounter = 0;
81 
82  ‪clientfield::register( "vehicle", "timeout_beep", ‪VERSION_SHIP, 2, "int" );
83 
85 }
86 
87 function ‪init()
88 {
89  if ( GetDvarString( "scr_allow_killstreak_building") == "" )
90  {
91  SetDvar( "scr_allow_killstreak_building", "0" );
92  }
93 
94  level.menuReferenceForKillStreak = [];
95  level.numKillstreakReservedObjectives = 0;
96  level.killstreakCounter = 0;
97  level.play_killstreak_firewall_being_hacked_dialog = &‪play_killstreak_firewall_being_hacked_dialog;
98  level.play_killstreak_firewall_hacked_dialog = &‪play_killstreak_firewall_hacked_dialog;
99  level.play_killstreak_being_hacked_dialog = &‪play_killstreak_being_hacked_dialog;
100  level.play_killstreak_hacked_dialog = &‪play_killstreak_hacked_dialog;
101 
102  if( !isdefined(level.roundStartKillstreakDelay) )
103  {
104  level.roundStartKillstreakDelay = 0;
105  }
106 
107  level.isKillstreakWeapon =&‪killstreaks::is_killstreak_weapon;
108 
109  level.killstreakCoreBundle = ‪struct::get_script_bundle( "killstreak", "killstreak_core" );
110 
112 
117  ‪dart::init();
119  ‪emp::init();
128  ‪rcbomb::init();
132  ‪turret::init();
133  ‪uav::init();
134 
136 
139 
140  if( GetDvarint( "teamOpsEnabled" ) == 1 )
141  {
142  level ‪teamops::main();
143  }
144 }
145 
146 function register( killstreakType, // killstreak name
147  killstreakWeaponName, // weapon name associated with deploying this killstreak
148  killstreakMenuName, // killstreak name from the cac loadout (could be merged with the type name)
149  killstreakUsageKey, // variable that shows the usage for the killstreak ( could be merged with type name )
150  killstreakUseFunction, // function that gets called when the killstreak gets activated
151  killstreakDelayStreak, // weather or not to delay the killstreak at round start
152  weaponHoldAllowed = false, // if this killstreak weapon can be held by the player, as opposed to activate and remove (i.e. UAV)
153  killstreakStatsName = undefined, // Stats name for killstreak weapons (optional)
154  ‪registerDvars = true,
155  registerInventory = true )
156 {
157  assert( isdefined(killstreakType), "Can not register a killstreak without a valid type name.");
158  assert( !isdefined(level.killstreaks[killstreakType]), "Killstreak " + killstreakType + " already registered");
159  assert( isdefined(killstreakUseFunction), "No use function defined for killstreak " + killstreakType);
160 
161  level.killstreaks[killstreakType] = SpawnStruct();
162 
163  statsTableName = ‪util::getStatsTableName();
164 
165  // number of kills required to achieve killstreak
166  level.killstreaks[killstreakType].killstreakLevel = int( tablelookup( statsTableName, ‪STATS_TABLE_COL_REFERENCE, killstreakMenuName, ‪STATS_TABLE_COL_COUNT ) );
167  level.killstreaks[killstreakType].momentumCost = int( tablelookup( statsTableName, ‪STATS_TABLE_COL_REFERENCE, killstreakMenuName, ‪STATS_TABLE_COL_MOMENTUM ) );
168  level.killstreaks[killstreakType].iconMaterial = tablelookup( statsTableName, ‪STATS_TABLE_COL_REFERENCE, killstreakMenuName, ‪STATS_TABLE_COL_IMAGE );
169  level.killstreaks[killstreakType].quantity = int( tablelookup( statsTableName, ‪STATS_TABLE_COL_REFERENCE, killstreakMenuName, ‪STATS_TABLE_COL_COUNT ) );
170  level.killstreaks[killstreakType].usageKey = killstreakUsageKey;
171  level.killstreaks[killstreakType].useFunction = killstreakUseFunction;
172  level.killstreaks[killstreakType].menuName = killstreakMenuName;
173  level.killstreaks[killstreakType].delayStreak = killstreakDelayStreak;
174  level.killstreaks[killstreakType].allowAssists = false;
175  level.killstreaks[killstreakType].overrideEntityCameraInDemo = false;
176  level.killstreaks[killstreakType].teamKillPenaltyScale = 1.0;
177 
178  if ( isdefined( killstreakWeaponName ) )
179  {
180  killstreakWeapon = GetWeapon( killstreakWeaponName );
181  assert( killstreakWeapon != level.weaponNone );
182  assert( !isdefined(level.killstreakWeapons[killstreakWeapon]), "Can not have a weapon associated with multiple killstreaks.");
183  level.killstreaks[killstreakType].weapon = killstreakWeapon;
184  level.killstreakWeapons[killstreakWeapon] = killstreakType;
185  }
186 
187  if( isdefined( killstreakStatsName ) )
188  {
189  level.killstreaks[killstreakType].killstreakStatsName = killstreakStatsName;
190  }
191 
192  level.killstreaks[killstreakType].weaponHoldAllowed = weaponHoldAllowed;
193 
194  if( ‪IS_TRUE( registerInventory ) )
195  {
196  level.menuReferenceForKillStreak[killstreakMenuName] = killstreakType;
198  }
199 
200  if( ‪IS_TRUE( registerInventory ) )
201  {
203  ‪register_dev_dvars( killstreakType );
204 
205  register( "inventory_" + killstreakType,
206  "inventory_" + killstreakWeaponName,
207  killstreakMenuName,
208  killstreakUsageKey,
209  killstreakUseFunction,
210  killstreakDelayStreak,
211  weaponHoldAllowed,
212  killstreakStatsName,
214  false );
215  }
216 }
217 
218 function ‪is_registered(killstreakType)
219 {
220  return isdefined(level.killstreaks[killstreakType]);
221 }
222 
223 function ‪register_strings( killstreakType, receivedText, notUsableText, inboundText, inboundNearPlayerText, hackedText, utilizesAirspace = true, isInventory = false )
224 {
225  assert( isdefined(killstreakType), "Can not register a killstreak without a valid type name.");
226  assert( isdefined(level.killstreaks[killstreakType]), "Killstreak needs to be registered before calling register_strings.");
227 
228  level.killstreaks[killstreakType].receivedText = receivedText;
229  level.killstreaks[killstreakType].notAvailableText = notUsableText;
230  level.killstreaks[killstreakType].inboundText = inboundText;
231  level.killstreaks[killstreakType].inboundNearPlayerText = inboundNearPlayerText;
232  level.killstreaks[killstreakType].hackedText = hackedText;
233  level.killstreaks[killstreakType].utilizesAirspace = utilizesAirspace; // does the killstreak utilize airspace when deployed or while active?
234 
235  if( !‪IS_TRUE( isInventory ) )
236  ‪register_strings( "inventory_" + killstreakType, receivedText, notUsableText, inboundText, inboundNearPlayerText, hackedText, utilizesAirspace, true );
237 }
238 
240  killstreakType,
241  informDialog,
242  taacomDialogBundleKey,
243  pilotDialogArrayKey,
244  startDialogKey, // Commander
245  enemyStartDialogKey, // Commander
246  enemyStartMultipleDialogKey, // Commander
247  hackedDialogKey, // Commander
248  hackedStartDialogKey, // Commander
249  requestDialogKey, // Player
250  threatDialogKey, // Player
251  isInventory
252  )
253 {
254  assert( isdefined(killstreakType), "Can not register a killstreak without a valid type name.");
255  assert( isdefined(level.killstreaks[killstreakType]), "Killstreak needs to be registered before calling register_dialog.");
256 
257  level.killstreaks[killstreakType].informDialog = informDialog;
258 
259  level.killstreaks[killstreakType].taacomDialogBundleKey = taacomDialogBundleKey;
260 
261  level.killstreaks[killstreakType].startDialogKey = startDialogKey;
262  level.killstreaks[killstreakType].enemyStartDialogKey = enemyStartDialogKey;
263  level.killstreaks[killstreakType].enemyStartMultipleDialogKey = enemyStartMultipleDialogKey;
264 
265  level.killstreaks[killstreakType].hackedDialogKey = hackedDialogKey;
266  level.killstreaks[killstreakType].hackedStartDialogKey = hackedStartDialogKey;
267 
268  level.killstreaks[killstreakType].requestDialogKey = requestDialogKey;
269  level.killstreaks[killstreakType].threatDialogKey = threatDialogKey;
270 
271  if ( isdefined( pilotDialogarrayKey ) )
272  {
273  // Set up Pilot Dialog Arrays
274  taacomBundles = ‪struct::get_script_bundles( "mpdialog_taacom" );
275 
276  foreach ( bundle in taacomBundles )
277  {
278  if ( !isdefined( bundle.pilotBundles ) )
279  {
280  bundle.pilotBundles = [];
281  }
282 
283  bundle.pilotBundles[killstreakType] = [];
284 
285  i = 0;
286  field = pilotDialogArrayKey + i;
287  fieldValue = GetStructField( bundle, field );
288 
289  while ( isdefined( fieldValue ) )
290  {
291  bundle.pilotBundles[killstreakType][i] = fieldValue;
292 
293  i++;
294  field = pilotDialogArrayKey + i;
295  fieldValue = GetStructField( bundle, field );
296  }
297  }
298  }
299 
300  if( !‪IS_TRUE( isInventory ) )
302  "inventory_" + killstreakType,
303  informDialog,
304  taacomDialogBundleKey,
305  pilotDialogArrayKey,
306  startDialogKey,
307  enemyStartDialogKey,
308  enemyStartMultipleDialogKey,
309  hackedDialogKey,
310  hackedStartDialogKey,
311  requestDialogKey,
312  threatDialogKey,
313  true );
314 
315 }
316 
317 // additional weapons associated with this killstreak
318 function ‪register_alt_weapon( killstreakType, weaponName, isInventory )
319 {
320  assert( isdefined(killstreakType), "Can not register a killstreak without a valid type name.");
321  assert( isdefined(level.killstreaks[killstreakType]), "Killstreak needs to be registered before calling register_alt_weapon.");
322 
323  weapon = GetWeapon( weaponName );
324 
325  if( weapon == level.weaponNone )
326  return;
327 
328  if ( level.killstreaks[killstreakType].weapon == weapon )
329  {
330  return;
331  }
332 
333  if ( !isdefined( level.killstreaks[killstreakType].altWeapons ) )
334  {
335  level.killstreaks[killstreakType].altWeapons = [];
336  }
337 
338  if( !isdefined( level.killstreakWeapons[weapon] ) )
339  {
340  level.killstreakWeapons[weapon] = killstreakType;
341  }
342  level.killstreaks[killstreakType].altWeapons[level.killstreaks[killstreakType].altWeapons.size] = weapon;
343 
344  if( !‪IS_TRUE( isInventory ) )
345  ‪register_alt_weapon( "inventory_" + killstreakType, weaponName, true );
346 }
347 
348 // remote override weapons associated with this killstreak
349 function ‪register_remote_override_weapon( killstreakType, weaponName, isInventory )
350 {
351  assert( isdefined(killstreakType), "Can not register a killstreak without a valid type name.");
352  assert( isdefined(level.killstreaks[killstreakType]), "Killstreak needs to be registered before calling register_remote_override_weapon.");
353 
354  weapon = GetWeapon( weaponName );
355  if ( level.killstreaks[killstreakType].weapon == weapon )
356  {
357  return;
358  }
359 
360  if ( !isdefined( level.killstreaks[killstreakType].remoteOverrideWeapons ) )
361  {
362  level.killstreaks[killstreakType].remoteOverrideWeapons = [];
363  }
364 
365  if( !isdefined( level.killstreakWeapons[weapon] ) )
366  {
367  level.killstreakWeapons[weapon] = killstreakType;
368  }
369  level.killstreaks[killstreakType].remoteOverrideWeapons[level.killstreaks[killstreakType].remoteOverrideWeapons.size] = weapon;
370 
371  if( !‪IS_TRUE( isInventory ) )
372  ‪register_remote_override_weapon( "inventory_" + killstreakType, weaponName, true );
373 }
374 
375 function ‪is_remote_override_weapon( killstreakType, weapon )
376 {
377  if ( isdefined( level.killstreaks[killstreakType].remoteOverrideWeapons ) )
378  {
379  for ( i=0; i<level.killstreaks[killstreakType].remoteOverrideWeapons.size; i++)
380  {
381  if ( level.killstreaks[killstreakType].remoteOverrideWeapons[i] == weapon)
382  {
383  return true;
384  }
385  }
386  }
387  return false;
388 }
389 
390 function ‪register_dev_dvars( killstreakType )
391 {
392 }
393 
394 function ‪register_tos_dvar(dvar)
395 {
396  level.teamops_dvar = dvar;
397 }
398 
399 function ‪allow_assists( killstreakType, allow )
400 {
401  level.killstreaks[killstreakType].allowAssists = allow;
402 }
403 
404 function ‪set_team_kill_penalty_scale( killstreakType, scale, isInventory )
405 {
406  level.killstreaks[killstreakType].teamKillPenaltyScale = scale;
407  if( !‪IS_TRUE( isInventory ) )
408  ‪set_team_kill_penalty_scale( "inventory_" + killstreakType, scale, true );
409 }
410 
411 function ‪override_entity_camera_in_demo( killstreakType, value, isInventory )
412 {
413  level.killstreaks[killstreakType].overrideEntityCameraInDemo = value;
414  if( !‪IS_TRUE( isInventory ) )
415  ‪override_entity_camera_in_demo( "inventory_" + killstreakType, value, true );
416 }
417 
418 function ‪is_available( killstreak )
419 {
420  if ( isdefined( level.menuReferenceForKillStreak[killstreak] ) )
421  {
422  return true;
423  }
424  else
425  {
426  return false;
427  }
428 }
429 
430 function ‪get_by_menu_name( killstreak )
431 {
432  return level.menuReferenceForKillStreak[killstreak];
433 }
434 
435 function ‪get_menu_name( killstreakType )
436 {
437  Assert( isdefined(level.killstreaks[killstreakType] ) );
438  return level.killstreaks[killstreakType].menuName;
439 }
440 
441 function ‪get_level( index, killstreak )
442 {
443  killstreakLevel = level.killstreaks[ ‪get_by_menu_name( killstreak ) ].killstreakLevel;
444  if( GetDvarInt( "custom_killstreak_mode" ) == 2 )
445  {
446  if ( isdefined( self.killstreak[ index ] ) && ( killstreak == self.killstreak[ index ] ) )
447  {
448  killsRequired = GetDvarInt( "custom_killstreak_" + index + 1 + "_kills" );
449  if ( killsRequired )
450  {
451  killstreakLevel = GetDvarInt( "custom_killstreak_" + index + 1 + "_kills" );
452  }
453  }
454  }
455  return killstreakLevel;
456 }
457 
458 function ‪give_if_streak_count_matches( index, killstreak, streakCount )
459 {
460  if( self.pers["killstreaksEarnedThisKillstreak"] > index && ‪util::isRoundBased() )
461  {
462  hasAlreadyEarnedKillstreak = true;
463  }
464  else
465  {
466  hasAlreadyEarnedKillstreak = false;
467  }
468 
469  if ( isdefined( killstreak ) && ‪is_available(killstreak) && !hasAlreadyEarnedKillstreak )
470  {
471  killstreakLevel = ‪get_level( index, killstreak );
472 
473  if ( self HasPerk( "specialty_killstreak" ) )
474  {
475  reduction = GetDvarint( "perk_killstreakReduction" );
476  killstreakLevel -= reduction;
477 
478  // a fix for custom game types being able to adjust the killstreak reduction perk
479  if( killstreakLevel <= 0 )
480  {
481  killstreakLevel = 1;
482  }
483  }
484 
485  if ( killstreakLevel == streakCount )
486  {
487  self ‪give( ‪get_by_menu_name( killstreak ), streakCount );
488  self.pers["killstreaksEarnedThisKillstreak"] = index + 1;
489  return true;
490  }
491  }
492 
493  return false;
494 }
495 
496 //Self is the player. This function looks at the player current killstreak and decides if he should be award a killstreak reward.
497 //It also manages the prompt that appears when the player gets killstreaks at intervals of 5 kills once they reach 10 kills. -Leif
499 {
501  {
502  return;
503  }
504 
505  //Equals total kills within one life
506  if( !isdefined(self.pers["totalKillstreakCount"]) )
507  {
508  self.pers["totalKillstreakCount"] = 0;
509  }
510 
511  // send the running tally to see what kill streak we should get
512  given = false;
513 
514  for ( i = 0; i < self.killstreak.size; i++ )
515  {
516  given |= ‪give_if_streak_count_matches( i, self.killstreak[i], self.pers["cur_kill_streak"] );
517  }
518 }
519 
521 {
522  onKillstreak = false;
523  if( !isdefined( self.pers["kill_streak_before_death"] ) )
524  {
525  self.pers["kill_streak_before_death"] = 0;
526  }
527 
528  streakPlusOne = self.pers["kill_streak_before_death"] + 1;
529 
530  if ( self.pers["kill_streak_before_death"] >= 5 )
531  {
532  onKillstreak = true;
533  }
534 
535 
536  return onKillstreak;
537 }
538 
539 function ‪give( killstreakType, streak, suppressNotification, noXP, toBottom )
540 {
541  self endon("disconnect");
542  level endon( "game_ended" );
543 
544  had_to_delay = false;
545 
546  killstreakGiven = false;
547  if( isdefined( noXP ) )
548  {
549  if ( self ‪give_internal( killstreakType, undefined, noXP, toBottom ) )
550  {
551  killstreakGiven = true;
552  if ( self.just_given_new_inventory_killstreak === true )
553  {
554  self ‪add_to_notification_queue( level.killstreaks[killstreakType].menuname, streak, killstreakType, noXP );
555  }
556  }
557  }
558  else if ( self ‪give_internal( killstreakType, noXP ) )
559  {
560  killstreakGiven = true;
561  if ( self.just_given_new_inventory_killstreak === true )
562  {
563  self ‪add_to_notification_queue( level.killstreaks[killstreakType].menuname, streak, killstreakType, noXP );
564  }
565  }
566 }
567 
568 function ‪take( killstreak )
569 {
570  self endon( "disconnect" );
571 
572  killstreak_weapon = ‪get_killstreak_weapon( killstreak );
573  ‪remove_used_killstreak( killstreak );
574 
575  if ( self GetInventoryWeapon() == killstreak_weapon )
576  {
577  self SetInventoryWeapon( level.weaponNone );
578  }
579 
580  waittillframeend;
581 
582  currentWeapon = self GetCurrentWeapon();
583  if( currentWeapon != killstreak_weapon || killstreak_weapon.isCarriedKillstreak )
584  {
585  return;
586  }
587 
590 }
591 
593 {
594  if( isdefined( self.pers["killstreaks"][0] ) )
595  {
596  currentWeapon = self getCurrentWeapon();
597 
598  if( currentWeapon == ‪get_killstreak_weapon( self.pers["killstreaks"][0] ) )
599  {
600  primaries = self GetWeaponsListPrimaries();
601 
602  if( primaries.size > 0 )
603  {
604  self SwitchToWeapon( primaries[0] );
605  }
606  }
607 
608  self notify("oldest_killstreak_removed", self.pers["killstreaks"][0], self.pers["killstreak_unique_id"][0] );
609  self ‪remove_used_killstreak( self.pers["killstreaks"][0], self.pers["killstreak_unique_id"][0], false );
610  }
611 }
612 
613 function ‪give_internal( killstreakType, do_not_update_death_count, noXP, toBottom )
614 {
615  self.just_given_new_inventory_killstreak = undefined;
616 
617  if ( level.gameEnded )
618  {
619  return false;
620  }
621 
623  {
624  return false;
625  }
626 
627  if ( !isdefined( level.killstreaks[killstreakType] ) )
628  {
629  return false;
630  }
631 
632  if ( !isdefined( self.pers["killstreaks"] ) )
633  {
634  self.pers["killstreaks"] = [];
635  }
636  if( !isdefined( self.pers["killstreak_has_been_used"] ) )
637  {
638  self.pers["killstreak_has_been_used"] = [];
639  }
640  if( !isdefined( self.pers["killstreak_unique_id"] ) )
641  {
642  self.pers["killstreak_unique_id"] = [];
643  }
644  if( !isdefined( self.pers["killstreak_ammo_count"] ) )
645  {
646  self.pers["killstreak_ammo_count"] = [];
647  }
648 
649  just_max_stack_removed_inventory_killstreak = undefined;
650 
651  if( isdefined( toBottom ) && toBottom )
652  {
653  size = self.pers["killstreaks"].size;
654 
655  if( self.pers["killstreaks"].size >= level.maxInventoryScoreStreaks )
656  {
657  self ‪remove_oldest();
658  just_max_stack_removed_inventory_killstreak = self.just_removed_used_killstreak;
659  }
660 
661  for( i = size; i > 0; i-- )
662  {
663  self.pers["killstreaks"][i] = self.pers["killstreaks"][i - 1];
664  self.pers["killstreak_has_been_used"][i] = self.pers["killstreak_has_been_used"][i - 1];
665  self.pers["killstreak_unique_id"][i] = self.pers["killstreak_unique_id"][i - 1];
666  self.pers["killstreak_ammo_count"][i] = self.pers["killstreak_ammo_count"][i - 1];
667  }
668  self.pers["killstreaks"][0] = killstreakType;
669  self.pers["killstreak_unique_id"][0] = level.killstreakCounter;
670  level.killstreakCounter++;
671 
672  if( isdefined(noXP) )
673  {
674  self.pers["killstreak_has_been_used"][0] = noXP;
675  }
676  else
677  {
678  self.pers["killstreak_has_been_used"][0] = false;
679  }
680 
681 
682  if( size == 0 )
683  {
684  weapon = ‪get_killstreak_weapon( killstreakType );
685  ammoCount = ‪give_weapon( weapon, true );
686  }
687 
688  self.pers["killstreak_ammo_count"][0] = 0;
689  }
690  else
691  {
692  self.pers["killstreaks"][self.pers["killstreaks"].size] = killstreakType;
693  self.pers["killstreak_unique_id"][self.pers["killstreak_unique_id"].size] = level.killstreakCounter;
694  level.killstreakCounter++;
695 
696  if( self.pers["killstreaks"].size > level.maxInventoryScoreStreaks )
697  {
698  self ‪remove_oldest();
699  just_max_stack_removed_inventory_killstreak = self.just_removed_used_killstreak;
700  }
701 
702  if( isdefined(noXP) )
703  {
704  self.pers["killstreak_has_been_used"][self.pers["killstreak_has_been_used"].size] = noXP;
705  }
706  else
707  {
708  self.pers["killstreak_has_been_used"][self.pers["killstreak_has_been_used"].size] = false;
709  }
710 
711  weapon = ‪get_killstreak_weapon( killstreakType );
712 
713  ammoCount = ‪give_weapon( weapon, true );
714 
715  self.pers["killstreak_ammo_count"][self.pers["killstreak_ammo_count"].size] = ammoCount;
716  }
717 
718  self.just_given_new_inventory_killstreak = ( killstreakType !== just_max_stack_removed_inventory_killstreak );
719 
720  return true;
721 }
722 
723 function ‪add_to_notification_queue( menuName, streakCount, hardpointType, noNotify )
724 {
725  killstreakTableNumber = level.killStreakIndices[ menuName ];
726 
727  if ( !isdefined( killstreakTableNumber ) )
728  {
729  return;
730  }
731 
732  if( isdefined( noNotify ) && noNotify )
733  {
734  return;
735  }
736 
737  informDialog = ‪get_killstreak_inform_dialog( hardpointType );
738 
739  if( GetDvarInt( "teamOpsEnabled" ) == 0 )
740  {
742  self thread ‪play_killstreak_ready_sfx ( hardpointType );
743  self LUINotifyEvent( &"killstreak_received", 2, killstreakTableNumber, istring( informDialog ) );
744  self LUINotifyEventToSpectators( &"killstreak_received", 2, killstreakTableNumber, istring( informDialog ) );
745  }
746 
747 }
748 
749 
750 function ‪has_equipped( )
751 {
752  currentWeapon = self getCurrentWeapon();
753 
754  keys = getarraykeys( level.killstreaks );
755  for ( i = 0; i < keys.size; i++ )
756  {
757  if ( level.killstreaks[keys[i]].weapon == currentWeapon )
758  {
759  return true;
760  }
761  }
762 
763  return false;
764 }
765 
766 function ‪_get_from_weapon( weapon )
767 {
768  keys = getarraykeys( level.killstreaks );
769 
770  foreach( key in keys )
771  {
772  killstreak = level.killstreaks[ key ];
773 
774  if ( killstreak.weapon == weapon )
775  {
776  return key;
777  }
778 
779  if ( isdefined( killstreak.altweapons ) )
780  {
781  foreach( altweapon in killstreak.altweapons )
782  {
783  if ( altweapon == weapon )
784  {
785  return key;
786  }
787  }
788  }
789 
790  if ( isdefined( killstreak.remoteoverrideweapons ) )
791  {
792  foreach( remoteOverrideWeapon in killstreak.remoteoverrideweapons )
793  {
794  if( remoteOverrideWeapon == weapon )
795  {
796  return key;
797  }
798  }
799  }
800  }
801 
802  return undefined;
803 }
804 
805 
806 function ‪get_from_weapon( weapon )
807 {
808  if( weapon == level.weaponNone )
809  {
810  return undefined;
811  }
812 
813  res = ‪_get_from_weapon( weapon );
814  if( !isdefined( res ) )
815  return ‪_get_from_weapon( weapon.rootweapon );
816  else
817  return res;
818 }
819 
820 // dont need the isinventory it will be inventory they all are
821 function ‪give_weapon( weapon, isinventory, useStoredAmmo )
822 {
823  currentWeapon = self GetCurrentWeapon();
824 
825  if ( currentWeapon != level.weaponNone && !‪IS_TRUE( level.usingMomentum ) )
826  {
827  weaponsList = self GetWeaponsList();
828  for( idx = 0; idx < weaponsList.size; idx++ )
829  {
830  carriedWeapon = weaponsList[idx];
831 
832  if ( currentWeapon == carriedWeapon )
833  {
834  continue;
835  }
836 
837  // special case weapons that are killstreak weapons but shouldn't be taken from the player
838  switch ( carriedWeapon.name )
839  {
840  case "minigun":
841  case "m32":
842  continue;
843  }
844 
845  if ( ‪killstreaks::is_killstreak_weapon( carriedWeapon ) )
846  {
847  self TakeWeapon( carriedWeapon );
848  }
849  }
850  }
851 
852  // take the weapon in-case we already have it.
853  // otherwise giveweapon will not give the weapon or ammo
854  if( currentWeapon != weapon && ( self hasWeapon(weapon) == false ) )
855  {
856  self TakeWeapon( weapon );
857  self GiveWeapon( weapon );
858  }
859 
860  if ( ‪IS_TRUE( level.usingMomentum ) )
861  {
862  self SetInventoryWeapon( weapon );
863 
864  if( weapon.isCarriedKillstreak )
865  {
866  if( !isdefined( self.pers["held_killstreak_ammo_count"][weapon] ) )
867  {
868  self.pers["held_killstreak_ammo_count"][weapon] = 0;
869  }
870 
871  if( !isdefined( self.pers["held_killstreak_clip_count"][weapon] ) )
872  {
873  self.pers["held_killstreak_clip_count"][weapon] = weapon.clipSize;
874  }
875 
876  if( !isdefined( self.pers["killstreak_quantity"][weapon] ) )
877  {
878  self.pers["killstreak_quantity"][weapon] = 0;
879  }
880 
881  if( currentWeapon == weapon && !‪killstreaks::isHeldInventoryKillstreakWeapon( weapon ) )
882  {
883  return weapon.maxAmmo;
884  }
885  else if( ‪IS_TRUE( useStoredAmmo ) && self.pers["killstreak_ammo_count"][self.pers["killstreak_ammo_count"].size - 1] > 0 )
886  {
887  switch( weapon.name )
888  {
889  case "inventory_minigun":
890  if( ‪IS_TRUE( self.minigunActive ) )
891  {
892  return self.pers["held_killstreak_ammo_count"][weapon];
893  }
894  break;
895  case "inventory_m32":
896  if( ‪IS_TRUE( self.m32Active ) )
897  {
898  return self.pers["held_killstreak_ammo_count"][weapon];
899  }
900  break;
901  default:
902  break;
903  }
904  self.pers["held_killstreak_ammo_count"][weapon] = self.pers["killstreak_ammo_count"][self.pers["killstreak_ammo_count"].size - 1];
905  self ‪loadout::setWeaponAmmoOverall( weapon, self.pers["killstreak_ammo_count"][self.pers["killstreak_ammo_count"].size - 1] );
906  }
907  else
908  {
909  self.pers["held_killstreak_ammo_count"][weapon] = weapon.maxAmmo;
910  self.pers["held_killstreak_clip_count"][weapon] = weapon.clipSize;
911  self ‪loadout::setWeaponAmmoOverall( weapon, self.pers["held_killstreak_ammo_count"][weapon] );
912  }
913  return self.pers["held_killstreak_ammo_count"][weapon];
914  }
915  else
916  {
917  switch ( weapon.name )
918  {
919  case "inventory_minigun_drop":
920  case "inventory_m32_drop":
921  case "inventory_missile_drone":
922 
923  case "combat_robot_marker":
924  case "inventory_combat_robot_marker":
925 
926  case "dart":
927  case "inventory_dart":
928 
929  case "ai_tank_marker":
930  case "inventory_ai_tank_marker":
931 
932  case "supplydrop_marker":
933  case "inventory_supplydrop_marker":
934  delta = 1;
935  break;
936  default:
937  delta = 0;
938  break;
939  }
940 
941  return ‪change_killstreak_quantity( weapon, delta );
942  }
943  }
944  else
945  {
946  self setActionSlot( 4, "weapon", weapon );
947  return 1;
948  }
949 }
950 
951 function ‪activate_next( do_not_update_death_count )
952 {
953  if ( level.gameEnded )
954  {
955  return false;
956  }
957 
958  if ( ‪IS_TRUE( level.usingMomentum ) )
959  {
960  self SetInventoryWeapon( level.weaponNone );
961  }
962  else
963  {
964  self setActionSlot( 4, "" );
965  }
966 
967  if ( !isdefined( self.pers["killstreaks"] ) || self.pers["killstreaks"].size == 0 )
968  {
969  return false;
970  }
971 
972  killstreakType = self.pers["killstreaks"][self.pers["killstreaks"].size - 1];
973 
974  if ( !isdefined( level.killstreaks[killstreakType] ) )
975  {
976  return false;
977  }
978 
979  weapon = level.killstreaks[killstreakType].weapon;
981 
982  ammoCount = ‪give_weapon( weapon, false, true );
983 
984  //Set the ammo now so we don't get a flash on the HUD when we use this weapon later
985  if( weapon.isCarriedKillstreak )
986  {
987  self setWeaponAmmoClip( weapon, self.pers["held_killstreak_clip_count"][weapon] );
988  self setWeaponAmmoStock( weapon, ammoCount - self.pers["held_killstreak_clip_count"][weapon] );
989  }
990 
991  if ( !isdefined( do_not_update_death_count ) || do_not_update_death_count != false )
992  {
993  self.pers["killstreakItemDeathCount"+killstreakType] = self.deathCount;
994  }
995 
996  return true;
997 }
998 
999 function ‪give_owned()
1000 {
1001  if ( isdefined( self.pers["killstreaks"] ) && self.pers["killstreaks"].size > 0 )
1002  {
1003  self ‪activate_next( false );
1004  }
1005 }
1006 
1007 function ‪get_killstreak_quantity( killstreakWeapon )
1008 {
1009  return ‪VAL( self.pers["killstreak_quantity"][killstreakWeapon], 0 );
1010 }
1011 
1012 function ‪change_killstreak_quantity( killstreakWeapon, delta )
1013 {
1014  quantity = ‪get_killstreak_quantity( killstreakWeapon );
1015 
1016  previousQuantity = quantity;
1017  quantity += delta;
1018 
1019  if ( quantity > level.scoreStreaksMaxStacking )
1020  {
1021  quantity = level.scoreStreaksMaxStacking;
1022  }
1023 
1024  // take the weapon in-case we already have it.
1025  // otherwise giveweapon will not give the weapon or ammo
1026  if(self hasWeapon( killstreakWeapon ) == false )
1027  {
1028  self TakeWeapon( killstreakWeapon );
1029  self GiveWeapon( killstreakWeapon );
1030  self SetEverHadWeaponAll( true );
1031  }
1032 
1033  self.pers["killstreak_quantity"][killstreakWeapon] = quantity;
1034  self SetWeaponAmmoClip( killstreakWeapon, quantity );
1035  return quantity;
1036 }
1037 
1038 function ‪has_killstreak_in_class( killstreakMenuName )
1039 {
1040  foreach ( equippedKillstreak in self.killstreak )
1041  {
1042  if ( equippedKillstreak == killstreakMenuName )
1043  {
1044  return true;
1045  }
1046  }
1047  return false;
1048 }
1049 
1050 function ‪has_killstreak( killstreak )
1051 {
1052  player = self;
1053 
1054  if( !isdefined( killstreak ) || !isdefined( player.pers["killstreaks"] ) )
1055  return false;
1056 
1057  for( i = 0; i < self.pers["killstreaks"].size; i++ )
1058  {
1059  if( player.pers["killstreaks"][i] == killstreak )
1060  return true;
1061  }
1062  return false;
1063 }
1064 
1065 function ‪RecordKillstreakBeginDirect(recordStreakIndex)
1066 {
1067  player = self;
1068  if(!isPlayer(player) || !isDefined(recordstreakindex))
1069  {
1070  return;
1071  }
1072 
1073  if( !isdefined(self.killstreakEvents) )
1074  player.killstreakEvents = associativeArray();
1075 
1076  // Already defined means the End happened first, so lets call both start and end.
1077  // Note that in this case, the killstreakEvents is storing the number of kills
1078  if(isDefined(self.killstreakEvents[recordStreakIndex]))
1079  {
1080  kills = player.killstreakEvents[recordStreakIndex];
1081  eventIndex = player RecordKillStreakEvent( recordStreakIndex );
1082  player ‪killstreakrules::RecordKillstreakEndDirect(eventIndex, recordStreakIndex, kills);
1083 
1084  player.killstreakEvents[recordStreakIndex] = undefined;
1085  }
1086  else
1087  {
1088  // Should be called in correct order
1089  eventIndex = player RecordKillStreakEvent( recordStreakIndex );
1090  player.killstreakEvents[recordStreakIndex] = eventIndex;
1091  }
1092 }
1093 
1094 function ‪remove_when_done( killstreak, hasKillstreakBeenUsed, isFromInventory )
1095 {
1096  self endon( "disconnect" );
1097 
1098  continue_wait = true;
1099 
1100  while( continue_wait )
1101  {
1102  self waittill( "killstreak_done", successful, killstreakType );
1103 
1104  if ( killstreakType == killstreak )
1105  continue_wait = false;
1106  }
1107 
1108  if ( successful )
1109  {
1110  // good place to hook into killstreak usage
1111  killstreak_weapon = ‪get_killstreak_weapon( killstreak );
1112  recordStreakIndex = undefined;
1113  if( isdefined( level.killstreaks[killstreak].menuname ) )
1114  {
1115  recordStreakIndex = level.killstreakindices[level.killstreaks[killstreak].menuname];
1116  self ‪RecordKillstreakBeginDirect(recordStreakIndex);
1117  }
1118 
1119  if ( ‪IS_TRUE( level.usingScoreStreaks ) )
1120  {
1121  if ( ‪IS_TRUE( isFromInventory ) )
1122  {
1123  ‪remove_used_killstreak( killstreak );
1124  if ( self GetInventoryWeapon() == killstreak_weapon )
1125  {
1126  self SetInventoryWeapon( level.weaponNone );
1127  }
1128  }
1129  else
1130  {
1131  self ‪change_killstreak_quantity( killstreak_weapon, -1 );
1132  }
1133  }
1134  else if ( ‪IS_TRUE( level.usingMomentum ) )
1135  {
1136  if ( ‪IS_TRUE( isFromInventory ) && ( self GetInventoryWeapon() == killstreak_weapon ) )
1137  {
1138  ‪remove_used_killstreak( killstreak );
1139  self SetInventoryWeapon( level.weaponNone );
1140  }
1141  else
1142  {
1143  ‪globallogic_score::_setPlayerMomentum( self, self.momentum - level.killstreaks[killstreakType].momentumCost );
1144  }
1145  }
1146  else
1147  {
1148  ‪remove_used_killstreak( killstreak );
1149  }
1150 
1151  if ( !‪IS_TRUE( level.usingMomentum ) )
1152  {
1153  self setActionSlot( 4, "" );
1154  }
1155 
1156  success = true;
1157  }
1158 
1159  waittillframeend;
1160 
1161  // each killstreak should hide the compass via this clientfield if so desired
1162  self ‪unhide_compass();
1163 
1164  currentWeapon = self GetCurrentWeapon();
1165  killstreak_weapon = ‪get_killstreak_weapon( killstreakType );
1166  if( currentWeapon == killstreak_weapon && killstreak_weapon.isCarriedKillstreak )
1167  {
1168  return;
1169  }
1170 
1171  if ( successful && ( !self ‪has_killstreak_in_class( ‪get_menu_name( killstreak ) ) || ‪IS_TRUE( isFromInventory ) ) )
1172  {
1174  }
1175  else
1176  {
1177  // the killstreak could have failed because we switched to another killstreak weapon
1178  killstreakForCurrentWeapon = ‪get_from_weapon( currentWeapon );
1179 
1180  if ( currentWeapon.isGameplayWeapon )
1181  {
1182  if ( ‪IS_TRUE( self.isPlanting ) || ‪IS_TRUE( self.isDefusing ) )
1183  {
1184  return;
1185  }
1186  }
1187 
1188  // not sure why we would switch when !isdefined( killstreakForCurrentWeapon ) so this is so we don't when we have switched to a HeroWeapon
1189  if ( !isdefined( killstreakForCurrentWeapon ) && currentWeapon.isHeroWeapon )
1190  {
1191  return;
1192  }
1193 
1194  if ( successful || !isdefined( killstreakForCurrentWeapon ) || killstreakForCurrentWeapon == killstreak )
1195  {
1197  }
1198  }
1199 
1200  if ( !‪IS_TRUE( level.usingMomentum ) || ‪IS_TRUE( isFromInventory ) )
1201  {
1202  if ( successful )
1203  {
1204  ‪activate_next();
1205  }
1206  }
1207 }
1208 
1209 function ‪useKillstreak( killstreak, isFromInventory )
1210 {
1211  hasKillstreakBeenUsed = ‪get_if_top_killstreak_has_been_used();
1212 
1213  if ( isdefined( self.selectingLocation ) )
1214  {
1215  return;
1216  }
1217 
1218  self thread ‪remove_when_done( killstreak, hasKillstreakBeenUsed, isFromInventory );
1219  self thread ‪trigger_killstreak( killstreak, isFromInventory );
1220 }
1221 
1222 function ‪remove_used_killstreak( killstreak, killstreakId, ‪take_weapon_after_use = true )
1223 {
1224  self.just_removed_used_killstreak = undefined;
1225 
1226  if( !isdefined( self.pers["killstreaks"] ) )
1227  return;
1228 
1229  // the killstreak stack is a lifo stack
1230  // find the top most killstreak in the list
1231  // remove it
1232  killstreakIndex = undefined;
1233 
1234  for ( i = self.pers["killstreaks"].size - 1; i >= 0; i-- )
1235  {
1236  if ( self.pers["killstreaks"][i] == killstreak )
1237  {
1238  if( isdefined( killstreakId ) && self.pers["killstreak_unique_id"][i] != killstreakId )
1239  {
1240  continue;
1241  }
1242 
1243  killstreakIndex = i;
1244  break;
1245  }
1246  }
1247 
1248  if ( !isdefined(killstreakIndex) )
1249  {
1250  return false;
1251  }
1252 
1253  self.just_removed_used_killstreak = killstreak;
1254 
1256  {
1257  self thread ‪take_weapon_after_use( ‪get_killstreak_weapon( killstreak ) );
1258  }
1259 
1260  arraySize = self.pers["killstreaks"].size;
1261  for ( i = killstreakIndex; i < arraySize - 1; i++ )
1262  {
1263  self.pers["killstreaks"][i] = self.pers["killstreaks"][i + 1];
1264  self.pers["killstreak_has_been_used"][i] = self.pers["killstreak_has_been_used"][i + 1];
1265  self.pers["killstreak_unique_id"][i] = self.pers["killstreak_unique_id"][i + 1];
1266  self.pers["killstreak_ammo_count"][i] = self.pers["killstreak_ammo_count"][i + 1];
1267  }
1268 
1269  self.pers["killstreaks"][arraySize-1] = undefined;
1270  self.pers["killstreak_has_been_used"][arraySize-1] = undefined;
1271  self.pers["killstreak_unique_id"][arraySize-1] = undefined;
1272  self.pers["killstreak_ammo_count"][arraySize-1] = undefined;
1273 
1274  return true;
1275 }
1276 
1277 function ‪take_weapon_after_use( killstreakWeapon )
1278 {
1279  self endon("disconnect");
1280  self endon("death");
1281  self endon( "joined_team" );
1282  self endon( "joined_spectators" );
1283 
1284  self waittill( "weapon_change" );
1285 
1286  inventoryWeapon = self GetInventoryWeapon();
1287  if ( inventoryWeapon != killstreakWeapon )
1288  {
1289  self TakeWeapon( killstreakWeapon );
1290  }
1291 }
1292 
1294 {
1295  if ( self.pers["killstreaks"].size == 0 )
1296  {
1297  return undefined;
1298  }
1299 
1300  return self.pers["killstreaks"][self.pers["killstreaks"].size-1];
1301 }
1302 
1304 {
1305  if ( !‪IS_TRUE( level.usingMomentum ) )
1306  {
1307  if ( self.pers["killstreak_has_been_used"].size == 0 )
1308  {
1309  return undefined;
1310  }
1311 
1312  return self.pers["killstreak_has_been_used"][self.pers["killstreak_has_been_used"].size-1];
1313  }
1314 }
1315 
1317 {
1318  if ( self.pers["killstreak_unique_id"].size == 0 )
1319  {
1320  return undefined;
1321  }
1322 
1323  return self.pers["killstreak_unique_id"][self.pers["killstreak_unique_id"].size-1];
1324 }
1325 
1326 function ‪get_killstreak_index_by_id( killstreakId )
1327 {
1328  for( index = self.pers["killstreak_unique_id"].size - 1; index >= 0; index-- )
1329  {
1330  if( self.pers["killstreak_unique_id"][index] == killstreakId )
1331  {
1332  return index;
1333  }
1334  }
1335 
1336  return undefined;
1337 }
1338 
1339 
1340 function ‪get_killstreak_momentum_cost( killstreak )
1341 {
1342  if ( !‪IS_TRUE( level.usingMomentum ) )
1343  {
1344  return 0;
1345  }
1346 
1347  if ( !isdefined( killstreak ) )
1348  {
1349  return 0;
1350  }
1351 
1352  Assert( isdefined(level.killstreaks[killstreak]) );
1353 
1354  return level.killstreaks[killstreak].momentumCost;
1355 }
1356 
1358 {
1359  if( isdefined( level.killstreakWeapons[weapon] ) )
1360  return level.killstreakWeapons[weapon];
1361  else
1362  return level.killstreakWeapons[weapon.rootweapon];
1363 }
1364 
1366 {
1367  prefix = "inventory_";
1368 
1369  killstreak = ‪get_killstreak_for_weapon( weapon );
1370 
1371  if ( isdefined( killstreak ) )
1372  {
1373  if ( StrStartsWith( killstreak, prefix ) )
1374  killstreak = getSubStr( killstreak, prefix.size );
1375  }
1376 
1377  return killstreak;
1378 }
1379 
1381 {
1382  killstreak = ‪get_killstreak_for_weapon( weapon );
1383 
1384  if ( !isdefined( killstreak ) )
1385  {
1386  return false;
1387  }
1388 
1389  if ( level.killstreaks[killstreak].allowAssists )
1390  {
1391  return true;
1392  }
1393 
1394  return false;
1395 }
1396 
1398 {
1399  killstreak = ‪get_killstreak_for_weapon( weapon );
1400 
1401  if ( !isdefined( killstreak ) )
1402  {
1403  return 1.0;
1404  }
1405 
1406  return level.killstreaks[killstreak].teamKillPenaltyScale;
1407 }
1408 
1410 {
1411  killstreak = ‪get_killstreak_for_weapon( weapon );
1412 
1413  if ( !isdefined( killstreak ) )
1414  {
1415  return false;
1416  }
1417 
1418  if ( level.killstreaks[killstreak].overrideEntityCameraInDemo )
1419  {
1420  return true;
1421  }
1422 
1423  if ( isdefined( player.remoteWeapon ) && ‪IS_TRUE( player.remoteWeapon.controlled ) )
1424  {
1425  return true;
1426  }
1427 
1428  return false;
1429 }
1430 
1432 {
1433  self endon( "death" );
1434  self endon( "disconnect" );
1435  self endon( "weapon_change" );
1436 
1437  slot = self GadgetGetSlot( weapon );
1438 
1439  while (1)
1440  {
1441  if ( self ‪ability_player::gadget_is_in_use( slot ) )
1442  {
1443  self.lastNonKillstreakWeapon = weapon;
1444  return;
1445  }
1447  }
1448 }
1449 
1451 {
1452  self endon( "death" );
1453  self endon( "disconnect" );
1454 
1455  self.lastNonKillstreakWeapon = self GetCurrentWeapon();
1456  lastValidPimary = self GetCurrentWeapon();
1457  if ( self.lastNonKillstreakWeapon == level.weaponNone )
1458  {
1459  weapons = self GetWeaponsListPrimaries();
1460  if ( weapons.size > 0 )
1461  {
1462  self.lastNonKillstreakWeapon = weapons[0];
1463  }
1464  else
1465  {
1466  self.lastNonKillstreakWeapon = level.weaponBaseMelee;
1467  }
1468  }
1469  Assert( self.lastNonKillstreakWeapon != level.weaponNone );
1470 
1471  for ( ;; )
1472  {
1473  currentWeapon = self GetCurrentWeapon();
1474  self waittill( "weapon_change", weapon );
1475 
1476  if ( ‪weapons::is_primary_weapon( weapon ) )
1477  {
1478  lastValidPimary = weapon;
1479  }
1480 
1481  if ( weapon == self.lastNonKillstreakWeapon || weapon == level.weaponNone || weapon == level.weaponBaseMelee )
1482  {
1483  continue;
1484  }
1485 
1486  if ( weapon.isGameplayWeapon )
1487  {
1488  continue;
1489  }
1490 
1491  if( isdefined( self.resurrect_weapon ) && ( weapon == self.resurrect_weapon ) )
1492  {
1493  continue;
1494  }
1495 
1497 
1498  if ( isdefined( ‪name ) && !weapon.isCarriedKillstreak )
1499  {
1500  killstreak = level.killstreaks[ ‪name ];
1501  continue;
1502  }
1503 
1504  if ( currentWeapon.isEquipment )
1505  {
1506  if ( self.lastNonKillstreakWeapon.isCarriedKillstreak )
1507  {
1508  self.lastNonKillstreakWeapon = lastValidPimary;
1509  }
1510  continue;
1511  }
1512 
1513  if ( weapon.isHeroWeapon )
1514  {
1515  if ( weapon.gadget_heroversion_2_0 )
1516  {
1517  if ( weapon.isGadget && self GetAmmoCount(weapon ) > 0 )
1518  {
1519  self thread ‪wait_till_hero_weapon_is_fully_on( weapon );
1520  continue;
1521  }
1522  }
1523  }
1524 
1525 
1526  self.lastNonKillstreakWeapon = weapon;
1527  }
1528 }
1529 
1531 {
1532  self endon ( "death" );
1533  self endon ( "disconnect" );
1534  level endon ( "game_ended" );
1535 
1536  self thread ‪track_weapon_usage();
1537 
1538  self ‪give_owned();
1539 
1540  for ( ;; )
1541  {
1542  self waittill( "weapon_change", weapon );
1543 
1544  if( !‪killstreaks::is_killstreak_weapon( weapon ) )
1545  {
1546  continue;
1547  }
1548 
1549  killstreak = ‪get_killstreak_for_weapon( weapon );
1550 
1551  if ( !‪IS_TRUE( level.usingMomentum ) )
1552  {
1553  killstreak = ‪get_top_killstreak();
1554  if( weapon != ‪get_killstreak_weapon(killstreak) )
1555  continue;
1556  }
1557 
1558  if( ‪is_remote_override_weapon( killstreak, weapon ) )
1559  {
1560  continue;
1561  }
1562 
1563  inventoryButtonPressed = ( self InventoryButtonPressed() ) || ( isdefined( self.pers["isBot"] ) );
1564 
1565  waittillframeend;
1566 
1567  if( ‪IS_TRUE( self.usingKillstreakHeldWeapon ) && weapon.isCarriedKillstreak )
1568  {
1569  continue;
1570  }
1571 
1572  isFromInventory = undefined;
1573 
1574  if ( ‪IS_TRUE( level.usingScoreStreaks ) )
1575  {
1576  if ( ( weapon == self GetInventoryWeapon() ) )
1577  {
1578  isFromInventory = true;
1579  }
1580  else if (( self GetAmmoCount( weapon ) <= 0 ) && (weapon.name != "killstreak_ai_tank"))
1581  {
1583  continue;
1584  }
1585  }
1586  else if ( ‪IS_TRUE( level.usingMomentum ) )
1587  {
1588  if ( ( weapon == self GetInventoryWeapon() ) && inventoryButtonPressed )
1589  {
1590  isFromInventory = true;
1591  }
1592  else if ( self.momentum < level.killstreaks[killstreak].momentumCost )
1593  {
1595  continue;
1596  }
1597  }
1598 
1599  // this catches the between round cases
1600  if ( !isdefined( level.startTime ) && ( level.roundStartKillstreakDelay > 0 ) )
1601  {
1603  continue;
1604  }
1605 
1606  thread ‪useKillstreak( killstreak, isFromInventory );
1607  }
1608 }
1609 
1610 function ‪should_delay_killstreak( killstreakType )
1611 {
1612  if( !isdefined(level.startTime) )
1613  {
1614  return false;
1615  }
1616 
1617  if( level.roundStartKillstreakDelay < ( ( ( gettime() - level.startTime ) - level.discardTime ) / 1000 ) )
1618  {
1619  return false;
1620  }
1621 
1622  if( !‪is_delayable_killstreak(killstreakType) )
1623  {
1624  return false;
1625  }
1626 
1627  killstreakWeapon = ‪get_killstreak_weapon( killstreakType );
1628  if( killstreakWeapon.isCarriedKillstreak )
1629  {
1630  return false;
1631  }
1632 
1634  {
1635  return false;
1636  }
1637 
1638  return true;
1639 }
1640 
1641 //check if this is a killstreak we want to delay at the start of a round
1642 function ‪is_delayable_killstreak( killstreakType )
1643 {
1644  if( isdefined( level.killstreaks[killstreakType] ) && ‪IS_TRUE( level.killstreaks[killstreakType].delayStreak ) )
1645  {
1646  return true;
1647  }
1648 
1649  return false;
1650 }
1651 
1652 function ‪get_xp_amount_for_killstreak( killstreakType )
1653 {
1654  // looks like only the rcxd does this
1655  // all killstreaks need this?
1656  xpAmount = 0;
1657  switch( level.killstreaks[killstreakType].killstreakLevel )
1658  {
1659  case 1:
1660  case 2:
1661  case 3:
1662  case 4:
1663  xpAmount = 100;
1664  break;
1665  case 5:
1666  xpAmount = 150;
1667  break;
1668  case 6:
1669  case 7:
1670  xpAmount = 200;
1671  break;
1672  case 8:
1673  xpAmount = 250;
1674  break;
1675  case 9:
1676  xpAmount = 300;
1677  break;
1678  case 10:
1679  case 11:
1680  xpAmount = 350;
1681  break;
1682  case 12:
1683  case 13:
1684  case 14:
1685  case 15:
1686  xpAmount = 500;
1687  break;
1688  }
1689 
1690  return xpAmount;
1691 }
1692 
1694 {
1695  timeLeft = Int( level.roundStartKillstreakDelay - (‪globallogic_utils::getTimePassed() / 1000) );
1696 
1697  if ( timeLeft <= 0 )
1698  {
1699  timeLeft = 1;
1700  }
1701 
1702  self iPrintLnBold( &"MP_UNAVAILABLE_FOR_N", " " + timeLeft + " ", &"EXE_SECONDS" );
1703 }
1704 
1705 function ‪trigger_killstreak( killstreakType, isFromInventory )
1706 {
1707  assert( isdefined(level.killstreaks[killstreakType].useFunction), "No use function defined for killstreak " + killstreakType);
1708 
1709  self.usingKillstreakFromInventory = isFromInventory;
1710 
1711  if ( level.inFinalKillcam )
1712  {
1713  return false;
1714  }
1715 
1716  if( ‪should_delay_killstreak( killstreakType ) )
1717  {
1719  }
1720  else if ( [[level.killstreaks[killstreakType].useFunction]](killstreakType) )
1721  {
1722  //Killstreak of 3-4:+100, 5: +150, 6-7 +200, 8: +250, 9: +300, 11: +350, Above: +500
1723 
1724  if ( isdefined( self ) )
1725  {
1726 
1727  if ( !isdefined( self.pers[level.killstreaks[killstreakType].usageKey] ) )
1728  {
1729  self.pers[level.killstreaks[killstreakType].usageKey] = 0;
1730  }
1731 
1732  self.pers[level.killstreaks[killstreakType].usageKey]++;
1733  self notify( "killstreak_used", killstreakType );
1734  self notify( "killstreak_done", true, killstreakType );
1735  }
1736 
1737  self.usingKillstreakFromInventory = undefined;
1738 
1739  return true;
1740  }
1741 
1742  self.usingKillstreakFromInventory = undefined;
1743 
1744  if ( isdefined( self ) )
1745  {
1746  self notify( "killstreak_done", false, killstreakType );
1747  }
1748  return false;
1749 }
1750 
1751 function ‪add_to_killstreak_count( weapon )
1752 {
1753  if ( !isdefined( self.pers["totalKillstreakCount"] ) )
1754  {
1755  self.pers["totalKillstreakCount"] = 0;
1756  }
1757 
1758 // The check is now done further up the stack to see if this should be counted
1759  self.pers["totalKillstreakCount"]++;
1760 }
1761 
1763 {
1764  assert( isdefined(level.killstreaks[killstreakType]), "Killstreak not registered.");
1765 
1766  if( isdefined( level.killstreaks[killstreakType].altWeapons ) )
1767  {
1768  for( i = 0; i < level.killstreaks[killstreakType].altWeapons.size; i++ )
1769  {
1770  if( isdefined( level.killstreaks[killstreakType].altWeapons[i] ) )
1771  {
1772  return level.killstreaks[killstreakType].altWeapons[i];
1773  }
1774  }
1775  }
1776 
1777  return level.weaponNone;
1778 }
1779 
1780 function ‪should_give_killstreak( weapon )
1781 {
1782  if( GetDvarInt( "teamOpsEnabled" ) == 1 )
1783  return false;
1784 
1785  killstreakBuilding = GetDvarint( "scr_allow_killstreak_building" );
1786 
1787  if ( killstreakBuilding == 0 )
1788  {
1790  {
1791  return false;
1792  }
1793  }
1794 
1795  return true;
1796 }
1797 
1798 function ‪point_is_in_danger_area( point, targetpos, radius )
1799 {
1800  return distance2d( point, targetpos ) <= radius * 1.25;
1801 }
1802 
1803 function ‪print_killstreak_start_text( killstreakType, owner, team, targetpos, dangerRadius )
1804 {
1805  if ( !isdefined( level.killstreaks[killstreakType] ) )
1806  {
1807  return;
1808  }
1809 
1810  if ( level.teambased )
1811  {
1812  players = level.players;
1813  if ( !level.hardcoreMode && isdefined(level.killstreaks[killstreakType].inboundNearPlayerText))
1814  {
1815  for(i = 0; i < players.size; i++)
1816  {
1817  if(isalive(players[i]) && (isdefined(players[i].pers["team"])) && (players[i].pers["team"] == team))
1818  {
1819  if ( ‪point_is_in_danger_area( players[i].origin, targetpos, dangerRadius ) )
1820  {
1821  players[i] iprintlnbold(level.killstreaks[killstreakType].inboundNearPlayerText);
1822  }
1823  }
1824  }
1825  }
1826 
1827  if ( isdefined(level.killstreaks[killstreakType]) )
1828  {
1829  for ( i = 0; i < level.players.size; i++ )
1830  {
1831  player = level.players[i];
1832  playerteam = player.pers["team"];
1833  if ( isdefined( playerteam ) )
1834  {
1835  if ( playerteam == team )
1836  {
1837  player iprintln( level.killstreaks[killstreakType].inboundText, owner );
1838  }
1839  }
1840  }
1841  }
1842  }
1843  else
1844  {
1845  if ( !level.hardcoreMode && isdefined(level.killstreaks[killstreakType].inboundNearPlayerText) )
1846  {
1847  if ( ‪point_is_in_danger_area( owner.origin, targetpos, dangerRadius ) )
1848  {
1849  owner iprintlnbold(level.killstreaks[killstreakType].inboundNearPlayerText);
1850  }
1851  }
1852  }
1853 }
1854 
1855 function ‪play_killstreak_firewall_being_hacked_dialog( killstreakType, killstreakId )
1856 {
1857  if ( self ‪globallogic_audio::killstreak_dialog_queued( "firewallBeingHacked", killstreakType, killstreakId ) )
1858  {
1859  return;
1860  }
1861 
1862  self ‪globallogic_audio::play_taacom_dialog( "firewallBeingHacked", killstreakType, killstreakId );
1863 }
1864 
1865 function ‪play_killstreak_firewall_hacked_dialog( killstreakType, killstreakId )
1866 {
1867  if ( self ‪globallogic_audio::killstreak_dialog_queued( "firewallHacked", killstreakType, killstreakId ) )
1868  {
1869  return;
1870  }
1871 
1872  self ‪globallogic_audio::play_taacom_dialog( "firewallHacked", killstreakType, killstreakId );
1873 }
1874 
1875 function ‪play_killstreak_being_hacked_dialog( killstreakType, killstreakId )
1876 {
1877  if ( self ‪globallogic_audio::killstreak_dialog_queued( "beingHacked", killstreakType, killstreakId ) )
1878  {
1879  return;
1880  }
1881 
1882  self ‪globallogic_audio::play_taacom_dialog( "beingHacked", killstreakType, killstreakId );
1883 }
1884 
1885 function ‪play_killstreak_hacked_dialog( killstreakType, killstreakId, hacker )
1886 {
1888  self ‪globallogic_audio::play_taacom_dialog( "hacked", killstreakType );
1889 
1890  excludeSelf = [];
1891  excludeSelf[0] = self;
1892 
1893  if ( level.teambased )
1894  {
1895  ‪globallogic_audio::leader_dialog( level.killstreaks[killstreakType].hackedDialogKey, self.team, excludeSelf );
1896  ‪globallogic_audio::leader_dialog_for_other_teams( level.killstreaks[killstreakType].hackedStartDialogKey, self.team, undefined, killstreakId );
1897  }
1898  else
1899  {
1900  self ‪globallogic_audio::leader_dialog_on_player( level.killstreaks[killstreakType].hackedDialogKey );
1901  hacker ‪globallogic_audio::leader_dialog_on_player( level.killstreaks[killstreakType].hackedStartDialogKey );
1902  }
1903 }
1904 
1905 function ‪play_killstreak_start_dialog( killstreakType, team, killstreakId )
1906 {
1907  if ( !isdefined( killstreakType ) ||
1908  !isdefined( killstreakId ) )
1909  {
1910  return;
1911  }
1912 
1913  // Kill any waiting 'scorestreak ready' taacom threads
1914  self notify ( "killstreak_start_" + killstreakType );
1915  self notify ( "killstreak_start_inventory_" + killstreakType );
1916 
1917  dialogKey = level.killstreaks[killstreakType].requestDialogKey;
1918 
1919  if ( !isdefined( self.currentKillstreakDialog ) && isdefined( dialogKey ) && isdefined( level.heroPlayDialog ) )
1920  {
1921  self thread [[level.heroPlayDialog]]( dialogKey );
1922  }
1923 
1924  excludeSelf = [];
1925  excludeSelf[0] = self;
1926 
1927  if ( level.teambased )
1928  {
1929  // Don't play the friendly incoming audio over your own request
1930  ‪globallogic_audio::leader_dialog( level.killstreaks[killstreakType].startDialogKey, team, excludeSelf, undefined, killstreakId );
1931 
1932  ‪globallogic_audio::leader_dialog_for_other_teams( level.killstreaks[killstreakType].enemyStartDialogKey, team, undefined, killstreakId );
1933  }
1934  else
1935  {
1936  ‪globallogic_audio::leader_dialog( level.killstreaks[killstreakType].enemyStartDialogKey, undefined, excludeSelf, undefined, killstreakId );
1937  }
1938 }
1939 
1940 function ‪play_killstreak_ready_sfx (killstreaktype)
1941 {
1942  if ( !isdefined( level.gameEnded ) || !level.gameEnded )
1943  {
1944  ready_sfx_alias = "mpl_killstreak_" + killstreaktype;
1945 
1946  if ( isdefined (ready_sfx_alias))
1947  {
1948  self playsoundtoplayer (ready_sfx_alias, self );
1949  }
1950  }
1951 }
1952 
1953 function ‪play_killstreak_ready_dialog( killstreakType, taacomWaitTime )
1954 {
1955  self notify( "killstreak_ready_" + killstreakType );
1956 
1957  self endon( "death" );
1958  self endon( "killstreak_start_" + killstreakType );
1959  self endon( "killstreak_ready_" + killstreakType );
1960 
1961  level endon( "game_ended" );
1962 
1963  if ( isdefined( level.gameEnded ) && level.gameEnded )
1964  {
1965  return;
1966  }
1967 
1968  if ( ‪globallogic_audio::killstreak_dialog_queued( "ready", killstreakType ) )
1969  {
1970  return;
1971  }
1972 
1973  if ( isdefined( taacomWaitTime ) )
1974  {
1975  wait ( taacomWaitTime );
1976  }
1977 
1978  self ‪globallogic_audio::play_taacom_dialog( "ready", killstreakType );
1979 }
1980 
1981 // Self is killstreak
1982 function ‪play_destroyed_dialog_on_owner( killstreakType, killstreakId )
1983 {
1984  if ( !isdefined( self.owner ) ||
1985  !isdefined( self.team ) ||
1986  self.team != self.owner.team )
1987  {
1988  return;
1989  }
1990 
1992 
1993  self.owner ‪globallogic_audio::play_taacom_dialog( "destroyed", killstreakType );
1994 }
1995 
1996 // Self is killstreak
1997 function ‪play_taacom_dialog_on_owner( dialogKey, killstreakType, killstreakId )
1998 {
1999  if ( !isdefined( self.owner ) ||
2000  !isdefined( self.team ) ||
2001  self.team != self.owner.team )
2002  {
2003  return;
2004  }
2005 
2006  self.owner ‪globallogic_audio::play_taacom_dialog( dialogKey, killstreakType, killstreakId );
2007 }
2008 
2009 // Self is killstreak
2010 function ‪play_pilot_dialog_on_owner( dialogKey, killstreakType, killstreakId )
2011 {
2012  if ( !isdefined( self.owner ) ||
2013  !isdefined( self.owner.team ) ||
2014  !isdefined( self.team ) ||
2015  self.team != self.owner.team )
2016  {
2017  return;
2018  }
2019 
2020  self.owner ‪play_pilot_dialog( dialogKey, killstreakType, killstreakId, self.pilotIndex );
2021 }
2022 
2023 // self is player
2024 function ‪play_pilot_dialog( dialogKey, killstreakType, killstreakId, pilotIndex )
2025 {
2026  if ( !isdefined( killstreakType ) ||
2027  !isdefined( pilotIndex ) )
2028  {
2029  return;
2030  }
2031 
2032  self ‪globallogic_audio::killstreak_dialog_on_player( dialogKey, killstreakType, killstreakId, pilotIndex );
2033 }
2034 
2035 // Self is killstreak
2036 function ‪play_taacom_dialog_response_on_owner( dialogKey, killstreakType, killstreakId )
2037 {
2038  assert( isdefined( dialogKey ) );
2039  assert( isdefined( killstreakType ) );
2040 
2041  if ( !isdefined( self.owner ) ||
2042  !isdefined( self.team ) ||
2043  self.team != self.owner.team )
2044  {
2045  return;
2046  }
2047 
2048  self.owner ‪play_taacom_dialog_response( dialogKey, killstreakType, killstreakId, self.pilotIndex );
2049 }
2050 
2051 // self is player
2052 function ‪play_taacom_dialog_response( dialogKey, killstreakType, killstreakId, pilotIndex )
2053 {
2054  assert( isdefined( dialogKey ) );
2055  assert( isdefined( killstreakType ) );
2056 
2057  if ( !isdefined( pilotIndex ) )
2058  {
2059  return;
2060  }
2061 
2062  self ‪globallogic_audio::play_taacom_dialog( dialogKey + pilotIndex, killstreakType, killstreakId );
2063 }
2064 
2065 
2066 // Self is player
2067 function ‪get_random_pilot_index( killstreakType )
2068 {
2069  if ( !isdefined( killstreakType ) )
2070  {
2071  return undefined;
2072  }
2073 
2074  taacomBundle = ‪struct::get_script_bundle( "mpdialog_taacom", self.pers["mptaacom"] );
2075 
2076  if( !isdefined( taacomBundle.pilotBundles[killstreakType] ) )
2077  {
2078  return undefined;
2079  }
2080 
2081  numPilots = taacomBundle.pilotBundles[killStreakType].size;
2082 
2083  if ( numPilots <= 0 )
2084  {
2085  return undefined;
2086  }
2087 
2088  return RandomInt( numPilots );
2089 }
2090 
2091 // Self is killstreak
2092 function ‪player_killstreak_threat_tracking( killstreakType )
2093 {
2094  assert( isdefined( killstreakType ) );
2095 
2096  self endon ( "death" );
2097  self endon ( "delete" );
2098  self endon ( "leaving" );
2099  level endon( "game_ended" );
2100 
2101  while( 1 )
2102  {
2103  if ( !isdefined( self.owner ) )
2104  {
2105  return;
2106  }
2107 
2108  players = self.owner ‪battlechatter::get_enemy_players();
2109  players = array::randomize( players );
2110 
2111  foreach( player in players )
2112  {
2113  if ( !player ‪battlechatter::can_play_dialog( true ) )
2114  {
2115  continue;
2116  }
2117 
2118  lookAngles = player GetPlayerAngles();
2119 
2120  if ( lookAngles[0] < 270 || lookAngles[0] > 330 )
2121  {
2122  continue;
2123  }
2124 
2125  lookDir = AnglesToForward( lookAngles );
2126  eyePoint = player getEye();
2127 
2128  streakDir = VectorNormalize( self.origin - eyePoint );
2129 
2130  dot = VectorDot( streakDir, lookDir );
2131 
2132  if ( dot < 0.94 )
2133  {
2134  continue;
2135  }
2136 
2137  traceResult = BulletTrace( eyePoint, self.origin, true, player );
2138  if ( traceResult["fraction"] >= 1.0 || traceResult["entity"] === self )
2139  {
2140  if ( ‪battlechatter::dialog_chance( "killstreakSpotChance" ) )
2141  {
2142  player ‪battlechatter::play_killstreak_threat( killstreakType );
2143  }
2144  wait ( ‪battlechatter::mpdialog_value( "killstreakSpotDelay", 0 ) );
2145  break;
2146  }
2147  }
2148 
2149  wait ( ‪battlechatter::mpdialog_value( "killstreakSpotInterval", ‪SERVER_FRAME ) );
2150  }
2151 }
2152 
2153 function ‪get_killstreak_inform_dialog( killstreakType )
2154 {
2155  // please add inform dialog to killstreak
2156  //assert( isdefined ( level.killstreaks[killstreakType].informDialog ) );
2157 
2158  if ( isdefined( level.killstreaks[killstreakType].informDialog ) )
2159  {
2160  return level.killstreaks[killstreakType].informDialog;
2161  }
2162  return "";
2163 }
2164 
2166 {
2167  assert( isdefined(level.killstreaks[killstreakType]), "Killstreak needs to be registered before calling get_killstreak_usage.");
2168 
2169  return ‪get_killstreak_usage( level.killstreaks[killstreakType].usageKey );
2170 }
2171 
2172 function ‪get_killstreak_usage(usageKey)
2173 {
2174  if ( !isdefined( self.pers[usageKey] ) )
2175  {
2176  return 0;
2177  }
2178 
2179  return self.pers[usageKey];
2180 }
2181 
2183 {
2184  self endon("disconnect");
2185 
2186  ‪give_owned();
2187 
2188  if ( !isdefined( self.pers["killstreaks"] ) )
2189  {
2190  self.pers["killstreaks"] = [];
2191  }
2192  if ( !isdefined( self.pers["killstreak_has_been_used"] ) )
2193  {
2194  self.pers["killstreak_has_been_used"] = [];
2195  }
2196  if ( !isdefined( self.pers["killstreak_unique_id"] ) )
2197  {
2198  self.pers["killstreak_unique_id"] = [];
2199  }
2200  if( !isdefined( self.pers["killstreak_ammo_count"] ) )
2201  {
2202  self.pers["killstreak_ammo_count"] = [];
2203  }
2204 
2205  size = self.pers["killstreaks"].size;
2206 
2207  if ( size > 0 )
2208  {
2209  self thread ‪play_killstreak_ready_dialog( self.pers["killstreaks"][size - 1] );
2210  }
2211 
2212  self.killcamKilledByEnt = undefined;
2213 }
2214 
2216 {
2217  self endon("disconnect");
2218 
2219  self SetInventoryWeapon( level.weaponNone );
2220  self.pers["cur_kill_streak"] = 0;
2221  self.pers["cur_total_kill_streak"] = 0;
2222  self setplayercurrentstreak( 0 );
2223  self.pers["totalKillstreakCount"] = 0;
2224  self.pers["killstreaks"] = [];
2225  self.pers["killstreak_has_been_used"] = [];
2226  self.pers["killstreak_unique_id"] = [];
2227  self.pers["killstreak_ammo_count"] = [];
2228 
2229  if ( ‪IS_TRUE( level.usingScoreStreaks ) )
2230  {
2231  self.pers["killstreak_quantity"] = [];
2232  self.pers["held_killstreak_ammo_count"] = [];
2233  self.pers["held_killstreak_clip_count"] = [];
2234  }
2235 }
2236 
2237 function ‪init_ride_killstreak( streak, always_allow = false )
2238 {
2239  self disableUsability();
2240  ‪result = self ‪init_ride_killstreak_internal( streak, always_allow );
2241 
2242  if ( isdefined( self ) )
2243  {
2244  self enableUsability();
2245  }
2246 
2247  return ‪result;
2248 }
2249 
2251 {
2252  self endon( "endWatchForRemoveRemoteWeapon" );
2253  for ( ;; )
2254  {
2255  self waittill( "remove_remote_weapon" );
2257  self enableUsability();
2258  }
2259 }
2260 
2261 function ‪init_ride_killstreak_internal( streak, always_allow )
2262 {
2263  if ( isdefined( streak ) && ( ( streak == "qrdrone" ) || ( streak == "dart" ) || ( streak == "killstreak_remote_turret" ) || ( streak == "killstreak_ai_tank" ) || (streak == "qrdrone") || (streak == "sentinel") ) )
2264  {
2265  laptopWait = "timeout";
2266  }
2267  else
2268  {
2269  laptopWait = self ‪util::waittill_any_timeout( 0.6, "disconnect", "death", "weapon_switch_started" );
2270  }
2271 
2273 
2274  if ( laptopWait == "weapon_switch_started" )
2275  {
2276  return ( "fail" );
2277  }
2278 
2279  if ( !isAlive( self ) && !always_allow )
2280  {
2281  return "fail";
2282  }
2283 
2284  if ( laptopWait == "disconnect" || laptopWait == "death" )
2285  {
2286  if ( laptopWait == "disconnect" )
2287  {
2288  return ( "disconnect" );
2289  }
2290 
2291  if ( self.team == "spectator" )
2292  {
2293  return "fail";
2294  }
2295 
2296  return ( "success" );
2297  }
2298 
2299  if ( self IsEMPJammed() && !‪IS_TRUE( self.ignoreEMPJammed ) )
2300  {
2301  return ( "fail" );
2302  }
2303 
2304  if ( self ‪is_interacting_with_object() )
2305  {
2306  return "fail";
2307  }
2308 
2309  self thread ‪hud::fade_to_black_for_x_sec( 0, 0.2, 0.4, 0.25 );
2310  self thread ‪watch_for_remove_remote_weapon();
2311  blackOutWait = self ‪util::waittill_any_timeout( 0.60, "disconnect", "death" );
2312  self notify( "endWatchForRemoveRemoteWeapon" );
2313 
2315 
2316  if ( blackOutWait != "disconnect" )
2317  {
2318  self thread ‪clear_ride_intro( 1.0 );
2319 
2320  if ( self.team == "spectator" )
2321  {
2322  return "fail";
2323  }
2324  }
2325 
2326  if ( always_allow )
2327  {
2328  if ( blackOutWait == "disconnect" )
2329  {
2330  return ( "disconnect" );
2331  }
2332  else
2333  {
2334  return ( "success" );
2335  }
2336  }
2337 
2338  if ( self isOnLadder() )
2339  {
2340  return "fail";
2341  }
2342 
2343  if ( !isAlive( self ) )
2344  {
2345  return "fail";
2346  }
2347 
2348  if ( self IsEMPJammed() && !‪IS_TRUE( self.ignoreEMPJammed ) )
2349  {
2350  return ( "fail" );
2351  }
2352 
2353  if ( ‪IS_TRUE( self.laststand ) )
2354  {
2355  return "fail";
2356  }
2357 
2358  if ( self ‪is_interacting_with_object() )
2359  {
2360  return "fail";
2361  }
2362 
2363  if ( blackOutWait == "disconnect" )
2364  {
2365  return ( "disconnect" );
2366  }
2367  else
2368  {
2369  return ( "success" );
2370  }
2371 }
2372 
2374 {
2375  self endon( "disconnect" );
2376 
2377  if ( isdefined( ‪delay ) )
2378  wait( ‪delay );
2379 
2380 
2381  self thread ‪hud::screen_fade_in( 0 );
2382 }
2383 
2385 {
2386  if ( self isCarryingTurret() )
2387  {
2388  return true;
2389  }
2390  if ( ‪IS_TRUE( self.isPlanting ) )
2391  {
2392  return true;
2393  }
2394  if ( ‪IS_TRUE( self.isDefusing ) )
2395  {
2396  return true;
2397  }
2398 
2399  return false;
2400 }
2401 
2402 
2403 function ‪clear_using_remote( immediate, skipNotify )
2404 {
2405  if ( !isdefined( self ) )
2406  {
2407  return;
2408  }
2409 
2410  self.dofutz = false;
2411  self.no_fade2black = false;
2412  self ‪clientfield::set_to_player( "static_postfx", 0 );
2413 
2414  if ( isdefined( self.carryIcon ) )
2415  {
2416  self.carryIcon.alpha = 1;
2417  }
2418 
2419  self.usingRemote = undefined;
2421  self enableOffhandWeapons();
2422  self enableWeaponCycling();
2423 
2424  curWeapon = self getCurrentWeapon();
2425 
2426  if ( isalive( self ) )
2427  {
2429  }
2430 
2431  if( !level.gameEnded )
2432  self ‪util::freeze_player_controls( false );
2433  if( !‪IS_TRUE( skipNotify ))
2434  self notify( "stopped_using_remote" );
2435 
2436  thread ‪hide_tablet();
2437 }
2438 
2439 function ‪hide_tablet()
2440 {
2441  self endon("disconnect");
2442  wait .2;
2443  self ‪clientfield::set_player_uimodel( "hudItems.remoteKillstreakActivated", 0 );
2444 }
2445 
2446 function ‪set_killstreak_delay_killcam( killstreak_name )
2447 {
2448  self.killstreak_delay_killcam = killstreak_name;
2449 }
2450 
2451 function ‪reset_killstreak_delay_killcam() // self == player
2452 {
2453  self.killstreak_delay_killcam = undefined;
2454 }
2455 
2457 {
2459 }
2460 
2462 {
2464 }
2465 
2466 function ‪setup_health( killstreak_ref, max_health, low_health )
2467 {
2468  self.maxhealth = max_health;
2469  self.lowhealth = low_health;
2470 
2471  self.hackedHealthUpdateCallback = &‪defaultHackedHealthUpdateCallback;
2472 
2473  tableMaxHealth = ‪killstreak_bundles::get_max_health( killstreak_ref );
2474 
2475  if ( isdefined( tableMaxHealth ) )
2476  {
2477  self.maxhealth = tableMaxHealth;
2478  }
2479 
2480  tableLowHealth = ‪killstreak_bundles::get_low_health( killstreak_ref );
2481 
2482  if ( isdefined( tableLowHealth ) )
2483  {
2484  self.lowhealth = tableLowHealth;
2485  }
2486 
2487  tableHackedHealth = ‪killstreak_bundles::get_hacked_health( killstreak_ref );
2488 
2489  if ( isdefined( tableHackedHealth ) )
2490  {
2491  self.hackedHealth = tableHackedHealth;
2492  }
2493  else
2494  {
2495  self.hackedHealth = self.maxhealth;
2496  }
2497 }
2498 
2499 function ‪MonitorDamage( killstreak_ref,
2500  max_health, destroyed_callback,
2501  low_health, low_health_callback,
2502  emp_damage, emp_callback,
2503  allow_bullet_damage )
2504 {
2505  self endon( "death" );
2506  self endon( "delete" );
2507 
2508  self.health = 9999999;
2509  self.damageTaken = 0;
2510 
2511  self ‪setup_health( killstreak_ref, max_health, low_health );
2512 
2513  assert( ( !IsVehicle( self ) || !IsSentient( self ) ), "MonitorDamage should not be called on a sentient vehicle. For sentient vehicles, use overrideVehicleDamage instead.");
2514 
2515  while( true )
2516  {
2517  weapon_damage = undefined;
2518  // this damage is done to self.health which isnt used to determine the helicopter's health, damageTaken is.
2519  self waittill( "damage", ‪damage, attacker, direction, point, type, tagName, modelName, partname, weapon, flags, inflictor, chargeLevel );
2520 
2521  if( ‪IS_TRUE( self.invulnerable ) )
2522  {
2523  continue;
2524  }
2525 
2526  if( !isdefined( attacker ) || !isplayer( attacker ) )
2527  {
2528  continue;
2529  }
2530 
2531  friendlyfire = ‪weaponobjects::friendlyFireCheck( self.owner, attacker );
2532  if( !friendlyfire )
2533  {
2534  continue;
2535  }
2536 
2537  if( isdefined( self.owner ) && attacker == self.owner )
2538  {
2539  continue;
2540  }
2541 
2542  isValidAttacker = true;
2543  if( level.teambased )
2544  {
2545  isValidAttacker = ( isdefined( attacker.team ) && attacker.team != self.team );
2546  }
2547 
2548  if( !isValidAttacker )
2549  {
2550  continue;
2551  }
2552 
2553  if ( isdefined( self.‪killstreakDamageModifier ) )
2554  {
2555  ‪damage = [[self.killstreakDamageModifier]]( ‪damage, attacker, direction, point, type, tagName, modelName, partname, weapon, flags, inflictor, chargeLevel );
2556  if ( ‪damage <= 0 )
2557  continue;
2558  }
2559 
2560  if( weapon.isEmp && type == "MOD_GRENADE_SPLASH" )
2561  {
2562  emp_damage_to_apply = ‪killstreak_bundles::get_emp_grenade_damage( killstreak_ref, self.maxhealth );
2563 
2564  if ( !isdefined( emp_damage_to_apply ) )
2565  emp_damage_to_apply = ( isdefined( emp_damage ) ? emp_damage : 1 );
2566 
2567  if( isdefined( emp_callback ) && emp_damage_to_apply > 0 )
2568  {
2569  self [[ emp_callback ]]( attacker );
2570  }
2571 
2572  weapon_damage = emp_damage_to_apply;
2573  }
2574 
2575  if ( ‪IS_TRUE( self.selfDestruct ) )
2576  {
2577  weapon_damage = self.maxhealth + 1;
2578  }
2579 
2580  if ( !isdefined( weapon_damage ) )
2581  {
2582  weapon_damage = ‪killstreak_bundles::get_weapon_damage( killstreak_ref, self.maxhealth, attacker, weapon, type, ‪damage, flags, chargeLevel );
2583 
2584  if ( !isdefined( weapon_damage ) )
2585  {
2586  weapon_damage = ‪get_old_damage( attacker, weapon, type, ‪damage, allow_bullet_damage );
2587  }
2588  }
2589 
2590  if ( weapon_damage > 0 )
2591  {
2592  if( ‪damagefeedback::doDamageFeedback( weapon, attacker ) )
2593  {
2594  attacker thread ‪damagefeedback::update( type );
2595  }
2596 
2597  self ‪challenges::trackAssists( attacker, weapon_damage, false );
2598  }
2599 
2600  self.damageTaken += weapon_damage;
2601 
2602  if ( !IsSentient( self ) && weapon_damage > 0 )
2603  self.attacker = attacker;
2604 
2605  if( self.damageTaken > self.maxhealth )
2606  {
2607  weaponStatName = "destroyed";
2608  switch( weapon.name )
2609  {
2610  case "auto_tow":
2611  case "tow_turret":
2612  case "tow_turret_drop":
2613  weaponStatName = "kills";
2614  break;
2615  }
2616 
2617  level.globalKillstreaksDestroyed++;
2618  attacker AddWeaponStat( GetWeapon( killstreak_ref ), "destroyed", 1 );
2619 
2620  if( isdefined( destroyed_callback ) )
2621  {
2622  self thread [[ destroyed_callback ]]( attacker, weapon );
2623  }
2624 
2625  return;
2626  }
2627 
2628  remaining_health = ( max_health - self.damageTaken );
2629 
2630  if( ( remaining_health < low_health ) && weapon_damage > 0 )
2631  {
2632  if( isdefined( low_health_callback ) && ( !isdefined( self.currentState ) || self.currentState != "damaged" ) )
2633  {
2634  self [[ low_health_callback ]]( attacker, weapon );
2635  }
2636 
2637  self.currentstate = "damaged";
2638  }
2639 
2640  if( isdefined( self.extra_low_health ) && ( remaining_health < self.extra_low_health ) && weapon_damage > 0 )
2641  {
2642  if( isdefined( self.extra_low_health_callback ) && ( !isdefined( self.extra_low_damage_notified ) ) )
2643  {
2644  self [[ self.extra_low_health_callback ]]( attacker, weapon );
2645 
2646  self.extra_low_damage_notified = true;
2647  }
2648  }
2649  }
2650 }
2651 
2653 {
2654  killstreak = self;
2655 
2656  assert( isdefined( self.maxHealth ) );
2657  assert( isdefined( self.hackedHealth ) );
2658  assert( isdefined( self.damageTaken ) );
2659 
2660  damageAfterHacking = self.maxHealth - self.hackedHealth;
2661  if ( self.damageTaken < damageAfterHacking )
2662  {
2663  self.damageTaken = damageAfterHacking;
2664  }
2665 }
2666 
2667 function ‪OnDamagePerWeapon( killstreak_ref,
2668  attacker, ‪damage, flags, type, weapon,
2669  max_health, destroyed_callback,
2670  low_health, low_health_callback,
2671  emp_damage, emp_callback,
2672  allow_bullet_damage, chargeLevel )
2673 {
2674  self.maxhealth = max_health;
2675  self.lowhealth = low_health;
2676 
2677  tableHealth = ‪killstreak_bundles::get_max_health( killstreak_ref );
2678 
2679  if ( isdefined( tableHealth ) )
2680  {
2681  self.maxhealth = tableHealth;
2682  }
2683 
2684  tableHealth = ‪killstreak_bundles::get_low_health( killstreak_ref );
2685 
2686  if ( isdefined( tableHealth ) )
2687  {
2688  self.lowhealth = tableHealth;
2689  }
2690 
2691  if( ‪IS_TRUE( self.invulnerable ) )
2692  {
2693  return 0;
2694  }
2695 
2696  if( !isdefined( attacker ) || !isplayer( attacker ) )
2697  {
2698  return ‪get_old_damage( attacker, weapon, type, ‪damage, allow_bullet_damage );
2699  }
2700 
2701  friendlyfire = ‪weaponobjects::friendlyFireCheck( self.owner, attacker );
2702  if( !friendlyfire )
2703  {
2704  return 0;
2705  }
2706 
2707  isValidAttacker = true;
2708  if( level.teambased )
2709  {
2710  isValidAttacker = ( isdefined( attacker.team ) && attacker.team != self.team );
2711  }
2712 
2713  if( !isValidAttacker )
2714  {
2715  return 0;
2716  }
2717 
2718  if( weapon.isEmp && type == "MOD_GRENADE_SPLASH" )
2719  {
2720  emp_damage_to_apply = ‪killstreak_bundles::get_emp_grenade_damage( killstreak_ref, self.maxhealth );
2721 
2722  if ( !isdefined( emp_damage_to_apply ) )
2723  emp_damage_to_apply = ( isdefined( emp_damage ) ? emp_damage : 1 );
2724 
2725  if( isdefined( emp_callback ) && emp_damage_to_apply > 0 )
2726  {
2727  self [[ emp_callback ]]( attacker, weapon );
2728  }
2729 
2730  return emp_damage_to_apply;
2731  }
2732 
2733  weapon_damage = ‪killstreak_bundles::get_weapon_damage( killstreak_ref, self.maxhealth, attacker, weapon, type, ‪damage, flags, chargeLevel );
2734 
2735  if ( !isdefined( weapon_damage ) )
2736  {
2737  weapon_damage = ‪get_old_damage( attacker, weapon, type, ‪damage, allow_bullet_damage );
2738  }
2739 
2740  if ( weapon_damage <= 0 )
2741  {
2742  return 0;
2743  }
2744 
2745  iDamage = int( weapon_damage );
2746  if( iDamage > self.health )
2747  {
2748  if( isdefined( destroyed_callback ) )
2749  {
2750  self thread [[ destroyed_callback ]]( attacker, weapon );
2751  }
2752  }
2753 
2754  return iDamage;
2755 }
2756 
2757 function ‪get_old_damage( attacker, weapon, type, ‪damage, allow_bullet_damage)
2758 {
2759  switch( type )
2760  {
2761  case "MOD_RIFLE_BULLET":
2762  case "MOD_PISTOL_BULLET":
2763  {
2764  if( !allow_bullet_damage )
2765  {
2766  ‪damage = 0;
2767  break;
2768  }
2769 
2770  if ( isdefined( attacker ) && isplayer( attacker ) )
2771  {
2772  hasFMJ = attacker HasPerk( "specialty_armorpiercing" );
2773  }
2774 
2775  if ( ‪IS_TRUE( hasFMJ ) )
2776  {
2777  ‪damage = int( ‪damage * level.cac_armorpiercing_data );
2778  }
2779  }
2780  break;
2781 
2782  case "MOD_PROJECTILE":
2783  case "MOD_EXPLOSIVE":
2784  case "MOD_PROJECTILE_SPLASH":
2785  if ( ( weapon.statIndex == level.weaponPistolEnergy.statIndex ) || ( weapon.statIndex != level.weaponShotgunEnergy.statIndex ) || ( weapon.statIndex == level.weaponSpecialCrossbow.statIndex ) )
2786  break;
2787 
2788  if( isdefined( self.remoteMissileDamage ) && isdefined( weapon ) && weapon.name == "remote_missile_missile")
2789  {
2790  ‪damage = self.remoteMissileDamage;
2791  }
2792  else if( isdefined( self.rocketDamage ) )
2793  {
2794  ‪damage = self.rocketDamage;
2795  }
2796  break;
2797  default:
2798  break;
2799  }
2800 
2801  return ‪damage;
2802 }
2803 
2804 
2805 
2806 function ‪configure_team( killstreakType, killstreakId, owner, influencerType, configureTeamPreFunction, configureTeamPostFunction, ‪isHacked = false )
2807 {
2808  killstreak = self;
2809 
2810  killstreak.killstreakType = killstreakType;
2811  killstreak.killstreakId = killstreakId;
2812  killstreak ‪_setup_configure_team_callbacks( influencerType, configureTeamPreFunction, configureTeamPostFunction );
2813  killstreak ‪configure_team_internal( owner, ‪isHacked );
2814 
2815  owner thread ‪trackActiveKillstreak( killstreak );
2816 }
2817 
2818 
2819 function ‪trackActiveKillstreak( killstreak )
2820 {
2821  self endon( "disconnect" );
2822 
2823  killstreakIndex = killstreak.killstreakID;
2824  if( isdefined( killstreakIndex ) )
2825  {
2826  self.pers["activeKillstreaks"][ killstreakIndex ] = killstreak;
2827 
2828  killstreak ‪util::waittill_any( "killstreak_hacked", "death" );
2829 
2830  self.pers["activeKillstreaks"][ killstreakIndex ] = undefined;
2831  }
2832 }
2833 
2835 {
2836  return self.pers["activeKillstreaks"];
2837 }
2838 
2840 {
2841  killstreak = self;
2842  if ( ‪isHacked == false )
2843  {
2844  killstreak.originalOwner = owner;
2845  killstreak.originalteam = owner.team;
2846  }
2847  else
2848  {
2849  assert( killstreak.killstreakTeamConfigured, "configure_team must be called before a killstreak can be hacked" );
2850  }
2851 
2852  if ( isdefined( killstreak.killstreakConfigureTeamPreFunction ) )
2853  {
2854  killstreak thread [[killstreak.killstreakConfigureTeamPreFunction]]( owner, ishacked );
2855  }
2856 
2857  if ( isdefined( killstreak.killstreakInfluencerType ) )
2858  {
2859  killstreak ‪spawning::remove_influencers();
2860  }
2861 
2862  killstreak SetTeam( owner.team );
2863  killstreak.team = owner.team;
2864  if ( !IsAI( killstreak ) )
2865  {
2866  killstreak SetOwner( owner );
2867  }
2868  killstreak.owner = owner;
2869  killstreak.ownerEntnum = owner.entnum;
2870 
2871  killstreak.pilotIndex = killstreak.owner ‪get_random_pilot_index( killstreak.killstreakType );
2872 
2873  if ( isdefined( killstreak.killstreakInfluencerType ) )
2874  {
2875  killstreak ‪spawning::create_entity_enemy_influencer( killstreak.killstreakInfluencerType, owner.team );
2876  }
2877 
2878  if ( isdefined( killstreak.killstreakConfigureTeamPostFunction ) )
2879  {
2880  killstreak thread [[killstreak.killstreakConfigureTeamPostFunction]]( owner, ishacked );
2881  }
2882 }
2883 
2884 function private ‪_setup_configure_team_callbacks( influencerType, configureTeamPreFunction, configureTeamPostFunction )
2885 {
2886  killstreak = self;
2887 
2888  killstreak.killstreakTeamConfigured = true;
2889  killstreak.killstreakInfluencerType = influencerType;
2890  killstreak.killstreakConfigureTeamPreFunction = configureTeamPreFunction;
2891  killstreak.killstreakConfigureTeamPostFunction = configureTeamPostFunction;
2892 }
2893 
2894 
2895 function ‪WatchTeamChange( teamChangeNotify )
2896 {
2897  self notify( teamChangeNotify+ "_Singleton" );
2898  self endon ( teamChangeNotify+ "_Singleton" );
2899 
2900  killstreak = self;
2901  killstreak endon( "death" );
2902 
2903  killstreak endon( teamChangeNotify );
2904  killstreak.owner ‪util::waittill_any( "joined_team", "disconnect", "joined_spectators", "emp_jammed" );
2905  killstreak notify( teamChangeNotify );
2906 }
2907 
2908 function ‪should_not_timeout( killstreak )
2909 {
2910  return false;
2911 }
2912 
2913 function ‪WaitForTimeout( killstreak, duration, ‪callback, endCondition1, endCondition2, endCondition3 )
2914 {
2915  self endon( "killstreak_hacked" );
2916 
2917  if( isdefined( endCondition1 ) )
2918  self endon( endCondition1 );
2919  if( isdefined( endCondition2 ) )
2920  self endon( endCondition2 );
2921  if( isdefined( endCondition3 ) )
2922  self endon( endCondition3 );
2923 
2924  self thread waitForTimeoutHacked( killstreak, ‪callback, endCondition1, endCondition2, endCondition3 );
2925 
2926  killstreakBundle = level.killstreakBundle[self.killstreakType];
2927  self.killstreakEndTime = getTime() + duration;
2928  if ( isdefined( killstreakBundle ) && isdefined( killstreakBundle.ksTimeoutBeepDuration ) )
2929  {
2930  self ‪WaitForTimeoutBeep( killstreakBundle, duration );
2931  }
2932  else
2933  {
2935  }
2936 
2937  self notify( "kill_WaitForTimeoutHacked_thread" );
2938  self.killstreakTimedOut = true;
2939  self.killstreakEndTime = 0;
2940  self notify( "timed_out" );
2941  self [[ ‪callback ]]();
2942 }
2943 
2944 
2945 function ‪WaitForTimeoutBeep( killstreakBundle, duration )
2946 {
2947  self endon("death");
2948  beepDuration = killstreakBundle.ksTimeoutBeepDuration * 1000;
2949  ‪hostmigration::MigrationAwareWait( max( duration - beepDuration, 0 ) );
2950 
2951  if ( IsVehicle( self ) )
2952  {
2953  self ‪clientfield::set( "timeout_beep", 1 );
2954  }
2955 
2956  if ( isdefined( killstreakBundle.ksTimeoutFastBeepDuration ) )
2957  {
2958  fastBeepDuration = killstreakBundle.ksTimeoutFastBeepDuration * 1000;
2959  ‪hostmigration::MigrationAwareWait( max( beepDuration - fastBeepDuration, 0 ) );
2960 
2961  if ( IsVehicle( self ) )
2962  {
2963  self ‪clientfield::set( "timeout_beep", 2 );
2964  }
2965 
2966  ‪hostmigration::MigrationAwareWait( fastBeepDuration );
2967  }
2968 
2969  if ( IsVehicle( self ) )
2970  {
2971  self ‪clientfield::set( "timeout_beep", 0 );
2972  }
2973 }
2974 
2975 
2976 function ‪WaitForTimeoutHacked( killstreak, ‪callback, endCondition1, endCondition2, endCondition3 )
2977 {
2978  self endon( "kill_WaitForTimeoutHacked_thread" );
2979 
2980  if( isdefined( endCondition1 ) )
2981  self endon( endCondition1 );
2982  if( isdefined( endCondition2 ) )
2983  self endon( endCondition2 );
2984  if( isdefined( endCondition3 ) )
2985  self endon( endCondition3 );
2986 
2987  self waittill( "killstreak_hacked" );
2988 
2990  self.killstreakEndTime = getTime() + hackedDuration;
2991  ‪hostmigration::MigrationAwareWait( hackedDuration );
2992  self.killstreakEndTime = 0;
2993  self notify( "timed_out" );
2994  self [[ ‪callback ]]();
2995 }
2996 
2997 function ‪update_player_threat( player )
2998 {
2999  heli = self;
3000 
3001  player.threatlevel = 0;
3002 
3003  // distance factor
3004  dist = distance( player.origin, heli.origin );
3005  player.threatlevel += ( ( level.heli_visual_range - dist ) / level.heli_visual_range ) * 100; // inverse distance % with respect to helicopter targeting range
3006 
3007  // behavior factor
3008  if( isdefined( heli.attacker ) && player == heli.attacker )
3009  player.threatlevel += 100;
3010 
3011  if( isdefined( player.carryObject ) ) //flag carrier
3012  player.threatlevel += 200;
3013 
3014  // player score factor
3015  if( isdefined( player.score ) )
3016  player.threatlevel += player.score * 2;
3017 
3018  if( player ‪weapons::has_launcher() )
3019  {
3020  if( player ‪weapons::has_lockon( heli ) )
3021  player.threatlevel += 1000;
3022  else
3023  player.threatlevel += 500;
3024  }
3025 
3026  if( player ‪weapons::has_hero_weapon() )
3027  player.threatlevel += 300;
3028 
3029  if( player ‪weapons::has_lmg() )
3030  player.threatlevel += 200;
3031 
3032  if( isdefined( player.antithreat ) )
3033  player.threatlevel -= player.antithreat;
3034 
3035  if( player.threatlevel <= 0 )
3036  player.threatlevel = 1;
3037 }
3038 
3039 function ‪update_non_player_threat( non_player )
3040 {
3041  heli = self;
3042 
3043  non_player.threatlevel = 0;
3044 
3045  // distance factor
3046  dist = distance( non_player.origin, heli.origin );
3047  non_player.threatlevel += ( ( level.heli_visual_range - dist ) / level.heli_visual_range ) * 100; // inverse distance % with respect to helicopter targeting range
3048 
3049  if( non_player.threatlevel <= 0 )
3050  non_player.threatlevel = 1;
3051 }
3052 
3053 function ‪update_actor_threat( actor )
3054 {
3055  heli = self;
3056  actor.threatlevel = 0;
3057 
3058  // distance factor
3059  dist = distance( actor.origin, heli.origin );
3060  actor.threatlevel += ( ( level.heli_visual_range - dist ) / level.heli_visual_range ) * 100; // inverse distance % with respect to helicopter targeting range
3061 
3062  // player score factor
3063  if( isdefined( actor.owner ) )
3064  {
3065  // behavior factor
3066  if( isdefined( heli.attacker ) && actor.owner == heli.attacker )
3067  actor.threatlevel += 100;
3068 
3069  if( isdefined( actor.owner.carryObject ) ) //flag carrier
3070  actor.threatlevel += 200;
3071 
3072  if( isdefined( actor.owner.score ) )
3073  actor.threatlevel += actor.owner.score * 4;
3074 
3075  if( isdefined( actor.owner.antithreat ) )
3076  actor.threatlevel -= actor.owner.antithreat;
3077  }
3078 
3079  if( actor.threatlevel <= 0 )
3080  actor.threatlevel = 1;
3081 }
3082 
3083 function ‪update_dog_threat( dog )
3084 {
3085  heli = self;
3086  dog.threatlevel = 0;
3087 
3088  // distance factor
3089  dist = distance( dog.origin, heli.origin );
3090  dog.threatlevel += ( ( level.heli_visual_range - dist ) / level.heli_visual_range ) * 100; // inverse distance % with respect to helicopter targeting range
3091 }
3092 
3093 // check if missile is in hittable sight zone
3094 function ‪missile_valid_target_check( missiletarget )
3095 {
3096  heli2target_normal = vectornormalize( missiletarget.origin - self.origin );
3097  heli2forward = anglestoforward( self.angles );
3098  heli2forward_normal = vectornormalize( heli2forward );
3099 
3100  heli_dot_target = vectordot( heli2target_normal, heli2forward_normal );
3101 
3102  if ( heli_dot_target >= level.heli_valid_target_cone )
3103  {
3104  return true;
3105  }
3106  return false;
3107 }
3108 
3110 {
3111  player.missilethreatlevel = 0;
3112 
3113  // distance factor
3114  dist = distance( player.origin, self.origin );
3115  player.missilethreatlevel += ( (level.heli_missile_range - dist)/level.heli_missile_range )*100; // inverse distance % with respect to helicopter targeting range
3116 
3117 
3118  if( self ‪missile_valid_target_check( player ) == false )
3119  {
3120  player.missilethreatlevel = 1;
3121  return;
3122  }
3123 
3124  // behavior factor
3125  if ( isdefined( self.attacker ) && player == self.attacker )
3126  player.missilethreatlevel += 100;
3127 
3128  // player score factor
3129  player.missilethreatlevel += player.score*4;
3130 
3131  if( isdefined( player.antithreat ) )
3132  player.missilethreatlevel -= player.antithreat;
3133 
3134  if( player.missilethreatlevel <= 0 )
3135  player.missilethreatlevel = 1;
3136 }
3137 
3138 // threat missile factors
3140 {
3141  dog.missilethreatlevel = 1;
3142 }
3143 
3144 function ‪killstreak_assist(victim, assister, killstreak)
3145 {
3146  victim RecordKillstreakAssist(victim, assister, killstreak);
3147 }
3148 
3149 function ‪add_ricochet_protection( killstreak_id, owner, origin, ricochet_distance )
3150 {
3151  testing = false;
3152 
3153  if ( !level.hardcoreMode && !testing )
3154  return;
3155 
3156  if ( !isdefined( ricochet_distance ) || ricochet_distance == 0 )
3157  return;
3158 
3159  ‪DEFAULT( owner.ricochet_protection, [] );
3160 
3161  owner.ricochet_protection[ killstreak_id ] = SpawnStruct();
3162  owner.ricochet_protection[ killstreak_id ].origin = origin;
3163  owner.ricochet_protection[ killstreak_id ].distanceSq = ‪SQR( ricochet_distance );
3164 }
3165 
3166 function ‪set_ricochet_protection_endtime( killstreak_id, owner, endTime )
3167 {
3168  if ( !isdefined( owner ) || !isdefined( owner.ricochet_protection ) || !isdefined( killstreak_id ) )
3169  return;
3170 
3171  if ( !isdefined( owner.ricochet_protection[ killstreak_id ] ) )
3172  return;
3173 
3174  owner.ricochet_protection[ killstreak_id ].endTime = endTime;
3175 }
3176 
3177 function ‪remove_ricochet_protection( killstreak_id, owner )
3178 {
3179  if ( !isdefined( owner ) || !isdefined( owner.ricochet_protection ) || !isdefined( killstreak_id ) )
3180  return;
3181 
3182  owner.ricochet_protection[ killstreak_id ] = undefined;
3183 }
3184 
3185 function ‪is_ricochet_protected( player )
3186 {
3187  if ( !isdefined( player ) || !isdefined( player.ricochet_protection ) )
3188  return false;
3189 
3190  foreach( protection in player.ricochet_protection )
3191  {
3192  if ( !isdefined( protection ) )
3193  continue;
3194 
3195  if ( isdefined( protection.endTime ) && protection.endTime < GetTime() )
3196  continue;
3197 
3198  if ( DistanceSquared( protection.origin, player.origin ) < protection.distanceSq )
3199  return true;
3200  }
3201 
3202  return false;
3203 }
3204 
3206 {
3207  return ( isdefined( self.dart_thrown_time ) && ( GetTime() - self.dart_thrown_time < 1500 ) );
3208 }
‪init_ride_killstreak
‪function init_ride_killstreak(streak, always_allow=false)
Definition: _killstreaks.gsc:2237
‪on_joined_team
‪function on_joined_team()
Definition: _killstreaks.gsc:2215
‪dialog_chance
‪function dialog_chance(chanceKey)
Definition: _battlechatter.gsc:237
‪trackActiveKillstreak
‪function trackActiveKillstreak(killstreak)
Definition: _killstreaks.gsc:2819
‪give_internal
‪function give_internal(killstreakType, do_not_update_death_count, noXP, toBottom)
Definition: _killstreaks.gsc:613
‪waitTillHostMigrationDone
‪function waitTillHostMigrationDone()
Definition: hostmigration_shared.gsc:193
‪get_killstreak_index_by_id
‪function get_killstreak_index_by_id(killstreakId)
Definition: _killstreaks.gsc:1326
‪add_ricochet_protection
‪function add_ricochet_protection(killstreak_id, owner, origin, ricochet_distance)
Definition: _killstreaks.gsc:3149
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪get_script_bundles
‪function get_script_bundles(str_type)
Definition: struct.csc:77
‪leader_dialog_for_other_teams
‪function leader_dialog_for_other_teams(dialogKey, skipTeam, objectiveKey, killstreakId, dialogBufferKey)
Definition: _globallogic_audio.gsc:422
‪hide_compass
‪function hide_compass()
Definition: _killstreaks.gsc:2456
‪isOneRound
‪function isOneRound()
Definition: util_shared.gsc:3497
‪is_interacting_with_object
‪function is_interacting_with_object()
Definition: _killstreaks.gsc:2384
‪is_remote_override_weapon
‪function is_remote_override_weapon(killstreakType, weapon)
Definition: _killstreaks.gsc:375
‪give_owned
‪function give_owned()
Definition: _killstreaks.gsc:999
‪get_hacked_timeout_duration_ms
‪function get_hacked_timeout_duration_ms()
Definition: _killstreak_hacking.gsc:122
‪mpdialog_value
‪function mpdialog_value(mpdialogKey, defaultValue)
Definition: _battlechatter.gsc:253
‪is_ricochet_protected
‪function is_ricochet_protected(player)
Definition: _killstreaks.gsc:3185
‪should_override_entity_camera_in_demo
‪function should_override_entity_camera_in_demo(player, weapon)
Definition: _killstreaks.gsc:1409
‪WaitForTimeout
‪function WaitForTimeout(killstreak, duration, callback, endCondition1, endCondition2, endCondition3)
Definition: _killstreaks.gsc:2913
‪allow_assists
‪function allow_assists(killstreakType, allow)
Definition: _killstreaks.gsc:399
‪STATS_TABLE_COL_COUNT
‪#define STATS_TABLE_COL_COUNT
Definition: _statstable.gsh:7
‪register_dev_dvars
‪function register_dev_dvars(killstreakType)
Definition: _killstreaks.gsc:390
‪has_lockon
‪function has_lockon(target)
Definition: weapons_shared.gsc:207
‪defaultHackedHealthUpdateCallback
‪function defaultHackedHealthUpdateCallback(hacker)
Definition: _killstreaks.gsc:2652
‪get_killstreak_quantity
‪function get_killstreak_quantity(killstreakWeapon)
Definition: _killstreaks.gsc:1007
‪get_killstreak_inform_dialog
‪function get_killstreak_inform_dialog(killstreakType)
Definition: _killstreaks.gsc:2153
‪remove_oldest
‪function remove_oldest()
Definition: _killstreaks.gsc:592
‪get_killstreak_momentum_cost
‪function get_killstreak_momentum_cost(killstreak)
Definition: _killstreaks.gsc:1340
‪print_killstreak_start_text
‪function print_killstreak_start_text(killstreakType, owner, team, targetpos, dangerRadius)
Definition: _killstreaks.gsc:1803
‪get_weapon_damage
‪function get_weapon_damage(killstreakType, maxhealth, attacker, weapon, type, damage, flags, chargeShotLevel)
Definition: _killstreak_bundles.gsc:295
‪set_to_player
‪function set_to_player(str_field_name, n_value)
Definition: clientfield_shared.gsc:58
‪point_is_in_danger_area
‪function point_is_in_danger_area(point, targetpos, radius)
Definition: _killstreaks.gsc:1798
‪display_unavailable_time
‪function display_unavailable_time()
Definition: _killstreaks.gsc:1693
‪register_killstreak_bundle
‪function register_killstreak_bundle(killstreakType)
Definition: _killstreak_bundles.gsc:20
‪play_killstreak_firewall_hacked_dialog
‪function play_killstreak_firewall_hacked_dialog(killstreakType, killstreakId)
Definition: _killstreaks.gsc:1865
‪isHeldInventoryKillstreakWeapon
‪function isHeldInventoryKillstreakWeapon(killstreakWeapon)
Definition: killstreaks_shared.gsc:118
‪on_start_gametype
‪function on_start_gametype(func, obj)
Definition: callbacks_shared.csc:285
‪WatchTeamChange
‪function WatchTeamChange(teamChangeNotify)
Definition: _killstreaks.gsc:2895
‪play_killstreak_ready_sfx
‪function play_killstreak_ready_sfx(killstreaktype)
Definition: _killstreaks.gsc:1940
‪activate_next
‪function activate_next(do_not_update_death_count)
Definition: _killstreaks.gsc:951
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪play_killstreak_start_dialog
‪function play_killstreak_start_dialog(killstreakType, team, killstreakId)
Definition: _killstreaks.gsc:1905
‪play_killstreak_firewall_being_hacked_dialog
‪function play_killstreak_firewall_being_hacked_dialog(killstreakType, killstreakId)
Definition: _killstreaks.gsc:1855
‪play_killstreak_ready_dialog
‪function play_killstreak_ready_dialog(killstreakType, taacomWaitTime)
Definition: _killstreaks.gsc:1953
‪VAL
‪#define VAL(__var, __default)
Definition: shared.gsh:272
‪screen_fade_in
‪function screen_fade_in(fadeintime)
Definition: hud_shared.gsc:264
‪get_by_menu_name
‪function get_by_menu_name(killstreak)
Definition: _killstreaks.gsc:430
‪play_pilot_dialog_on_owner
‪function play_pilot_dialog_on_owner(dialogKey, killstreakType, killstreakId)
Definition: _killstreaks.gsc:2010
‪OnDamagePerWeapon
‪function OnDamagePerWeapon(killstreak_ref, attacker, damage, flags, type, weapon, max_health, destroyed_callback, low_health, low_health_callback, emp_damage, emp_callback, allow_bullet_damage, chargeLevel)
Definition: _killstreaks.gsc:2667
‪get_menu_name
‪function get_menu_name(killstreakType)
Definition: _killstreaks.gsc:435
‪remove_when_done
‪function remove_when_done(killstreak, hasKillstreakBeenUsed, isFromInventory)
Definition: _killstreaks.gsc:1094
‪play_taacom_dialog_response
‪function play_taacom_dialog_response(dialogKey, killstreakType, killstreakId, pilotIndex)
Definition: _killstreaks.gsc:2052
‪_setPlayerMomentum
‪function _setPlayerMomentum(player, momentum, updateScore=true)
Definition: _globallogic_score.gsc:584
‪init
‪function init()
Definition: _killstreaks.gsc:87
‪freeze_player_controls
‪function freeze_player_controls(b_frozen=true)
Definition: util_shared.gsc:2474
‪waittill_any_timeout
‪function waittill_any_timeout(n_timeout, string1, string2, string3, string4, string5)
Definition: util_shared.csc:423
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪SQR
‪#define SQR(__var)
Definition: shared.gsh:293
‪reset_killstreak_delay_killcam
‪function reset_killstreak_delay_killcam()
Definition: _killstreaks.gsc:2451
‪track_weapon_usage
‪function track_weapon_usage()
Definition: _killstreaks.gsc:1450
‪play_killstreak_threat
‪function play_killstreak_threat(killstreakType)
Definition: _battlechatter.gsc:892
‪delay
‪function delay(time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6)
Definition: util_shared.csc:784
‪useKillstreak
‪function useKillstreak(killstreak, isFromInventory)
Definition: _killstreaks.gsc:1209
‪get_xp_amount_for_killstreak
‪function get_xp_amount_for_killstreak(killstreakType)
Definition: _killstreaks.gsc:1652
‪getActiveKillstreaks
‪function getActiveKillstreaks()
Definition: _killstreaks.gsc:2834
‪get_low_health
‪function get_low_health(killstreakType)
Definition: _killstreak_bundles.gsc:195
‪add_to_notification_queue
‪function add_to_notification_queue(menuName, streakCount, hardpointType, noNotify)
Definition: _killstreaks.gsc:723
‪TAACOM_KILLSTREAK_READY_WAIT
‪#define TAACOM_KILLSTREAK_READY_WAIT
Definition: _killstreaks.gsc:67
‪change_killstreak_quantity
‪function change_killstreak_quantity(killstreakWeapon, delta)
Definition: _killstreaks.gsc:1012
‪take_weapon_after_use
‪function take_weapon_after_use(killstreakWeapon)
Definition: _killstreaks.gsc:1277
‪play_pilot_dialog
‪function play_pilot_dialog(dialogKey, killstreakType, killstreakId, pilotIndex)
Definition: _killstreaks.gsc:2024
‪MonitorDamage
‪function MonitorDamage(killstreak_ref, max_health, destroyed_callback, low_health, low_health_callback, emp_damage, emp_callback, allow_bullet_damage)
Definition: _killstreaks.gsc:2499
‪gadget_is_in_use
‪function gadget_is_in_use(slot)
Definition: _ability_player.gsc:321
‪__init__
‪function __init__()
Definition: _killstreaks.gsc:75
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪get_killstreak_for_weapon
‪function get_killstreak_for_weapon(weapon)
Definition: _killstreaks.gsc:1357
‪get_killstreak_weapon
‪function get_killstreak_weapon(killstreak)
Definition: killstreaks_shared.gsc:106
‪get_killstreak_for_weapon_for_stats
‪function get_killstreak_for_weapon_for_stats(weapon)
Definition: _killstreaks.gsc:1365
‪play_taacom_dialog_on_owner
‪function play_taacom_dialog_on_owner(dialogKey, killstreakType, killstreakId)
Definition: _killstreaks.gsc:1997
‪update_dog_threat
‪function update_dog_threat(dog)
Definition: _killstreaks.gsc:3083
‪killstreak_assist
‪function killstreak_assist(victim, assister, killstreak)
Definition: _killstreaks.gsc:3144
‪set_killstreak_delay_killcam
‪function set_killstreak_delay_killcam(killstreak_name)
Definition: _killstreaks.gsc:2446
‪is_killstreak_weapon_assist_allowed
‪function is_killstreak_weapon_assist_allowed(weapon)
Definition: _killstreaks.gsc:1380
‪is_delayable_killstreak
‪function is_delayable_killstreak(killstreakType)
Definition: _killstreaks.gsc:1642
‪switch_to_last_non_killstreak_weapon
‪function switch_to_last_non_killstreak_weapon(immediate, awayfromBall)
Definition: killstreaks_shared.gsc:36
‪update_non_player_threat
‪function update_non_player_threat(non_player)
Definition: _killstreaks.gsc:3039
‪killstreak_dialog_on_player
‪function killstreak_dialog_on_player(dialogKey, killstreakType, killstreakId, pilotIndex)
Definition: _globallogic_audio.gsc:279
‪get_top_killstreak_unique_id
‪function get_top_killstreak_unique_id()
Definition: _killstreaks.gsc:1316
‪DEFAULT
‪#define DEFAULT(__var, __default)
Definition: shared.gsh:270
‪trigger_killstreak
‪function trigger_killstreak(killstreakType, isFromInventory)
Definition: _killstreaks.gsc:1705
‪on_spawned
‪function on_spawned(func, obj)
Definition: callbacks_shared.csc:245
‪registerDvars
‪function registerDvars()
Definition: _globallogic.gsc:295
‪is_primary_weapon
‪function is_primary_weapon(weapon)
Definition: weapons_shared.gsc:15
‪getTimePassed
‪function getTimePassed()
Definition: _globallogic_utils.gsc:274
‪is_killstreak_weapon
‪function is_killstreak_weapon(weapon)
Definition: killstreaks_shared.gsc:16
‪play_destroyed_dialog_on_owner
‪function play_destroyed_dialog_on_owner(killstreakType, killstreakId)
Definition: _killstreaks.gsc:1982
‪isKillStreaksEnabled
‪function isKillStreaksEnabled()
Definition: _util.gsc:564
‪get_old_damage
‪function get_old_damage(attacker, weapon, type, damage, allow_bullet_damage)
Definition: _killstreaks.gsc:2757
‪set_team_kill_penalty_scale
‪function set_team_kill_penalty_scale(killstreakType, scale, isInventory)
Definition: _killstreaks.gsc:404
‪get_killstreak_team_kill_penalty_scale
‪function get_killstreak_team_kill_penalty_scale(weapon)
Definition: _killstreaks.gsc:1397
‪_setup_configure_team_callbacks
‪function private _setup_configure_team_callbacks(influencerType, configureTeamPreFunction, configureTeamPostFunction)
Definition: _killstreaks.gsc:2884
‪get_random_pilot_index
‪function get_random_pilot_index(killstreakType)
Definition: _killstreaks.gsc:2067
‪create_entity_enemy_influencer
‪function create_entity_enemy_influencer(name, team)
Definition: _spawning.gsc:310
‪flush_killstreak_dialog_on_player
‪function flush_killstreak_dialog_on_player(killstreakId)
Definition: _globallogic_audio.gsc:179
‪play_killstreak_hacked_dialog
‪function play_killstreak_hacked_dialog(killstreakType, killstreakId, hacker)
Definition: _killstreaks.gsc:1885
‪is_killstreak_start_blocked
‪function is_killstreak_start_blocked()
Definition: _killstreaks.gsc:3205
‪get_from_weapon
‪function get_from_weapon(weapon)
Definition: _killstreaks.gsc:806
‪isRoundBased
‪function isRoundBased()
Definition: util_shared.gsc:3742
‪register
‪function register(killstreakType, killstreakWeaponName, killstreakMenuName, killstreakUsageKey, killstreakUseFunction, killstreakDelayStreak, weaponHoldAllowed=false, killstreakStatsName=undefined, registerDvars=true, registerInventory=true)
Definition: _killstreaks.gsc:146
‪should_give_killstreak
‪function should_give_killstreak(weapon)
Definition: _killstreaks.gsc:1780
‪fade_to_black_for_x_sec
‪function fade_to_black_for_x_sec(startwait, blackscreenwait, fadeintime, fadeouttime, shaderName)
Definition: hud_shared.gsc:250
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪configure_team_internal
‪function configure_team_internal(owner, isHacked)
Definition: _killstreaks.gsc:2839
‪has_launcher
‪function has_launcher()
Definition: _bot.gsc:1295
‪SERVER_FRAME
‪#define SERVER_FRAME
Definition: shared.gsh:264
‪doDamageFeedback
‪function doDamageFeedback(weapon, eInflictor, iDamage, sMeansOfDeath)
Definition: damagefeedback_shared.gsc:423
‪add_to_killstreak_count
‪function add_to_killstreak_count(weapon)
Definition: _killstreaks.gsc:1751
‪get_max_health
‪function get_max_health(killstreakType)
Definition: _killstreak_bundles.gsc:188
‪remove_influencers
‪function remove_influencers()
Definition: _spawning.gsc:405
‪wait_till_hero_weapon_is_fully_on
‪function wait_till_hero_weapon_is_fully_on(weapon)
Definition: _killstreaks.gsc:1431
‪get_top_killstreak
‪function get_top_killstreak()
Definition: _killstreaks.gsc:1293
‪missile_valid_target_check
‪function missile_valid_target_check(missiletarget)
Definition: _killstreaks.gsc:3094
‪register_dialog
‪function register_dialog(killstreakType, informDialog, taacomDialogBundleKey, pilotDialogArrayKey, startDialogKey, enemyStartDialogKey, enemyStartMultipleDialogKey, hackedDialogKey, hackedStartDialogKey, requestDialogKey, threatDialogKey, isInventory)
Definition: _killstreaks.gsc:239
‪clear_ride_intro
‪function clear_ride_intro(delay)
Definition: _killstreaks.gsc:2373
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪unhide_compass
‪function unhide_compass()
Definition: _killstreaks.gsc:2461
‪RecordKillstreakEndDirect
‪function RecordKillstreakEndDirect(eventIndex, recordStreakIndex, totalKills)
Definition: _killstreakrules.gsc:255
‪STATS_TABLE_COL_MOMENTUM
‪#define STATS_TABLE_COL_MOMENTUM
Definition: _statstable.gsh:16
‪remove_used_killstreak
‪function remove_used_killstreak(killstreak, killstreakId, take_weapon_after_use=true)
Definition: _killstreaks.gsc:1222
‪is_weapon_associated_with_killstreak
‪function is_weapon_associated_with_killstreak(weapon)
Definition: killstreaks_shared.gsc:31
‪is_available
‪function is_available(killstreak)
Definition: _killstreaks.gsc:418
‪isFirstRound
‪function isFirstRound()
Definition: util_shared.gsc:3505
‪on_player_spawned
‪function on_player_spawned()
Definition: _killstreaks.gsc:2182
‪register_strings
‪function register_strings(killstreakType, receivedText, notUsableText, inboundText, inboundNearPlayerText, hackedText, utilizesAirspace=true, isInventory=false)
Definition: _killstreaks.gsc:223
‪setup_health
‪function setup_health(killstreak_ref, max_health, low_health)
Definition: _killstreaks.gsc:2466
‪killstreak_dialog_queued
‪function killstreak_dialog_queued(dialogKey, killstreakType, killstreakId)
Definition: _globallogic_audio.gsc:195
‪register_tos_dvar
‪function register_tos_dvar(dvar)
Definition: _killstreaks.gsc:394
‪get_hacked_health
‪function get_hacked_health(killstreakType)
Definition: _killstreak_bundles.gsc:202
‪has_killstreak_in_class
‪function has_killstreak_in_class(killstreakMenuName)
Definition: _killstreaks.gsc:1038
‪is_an_a_killstreak
‪function is_an_a_killstreak()
Definition: _killstreaks.gsc:520
‪STATS_TABLE_COL_REFERENCE
‪#define STATS_TABLE_COL_REFERENCE
Definition: _statstable.gsh:6
‪has_killstreak
‪function has_killstreak(killstreak)
Definition: _killstreaks.gsc:1050
‪init_ride_killstreak_internal
‪function init_ride_killstreak_internal(streak, always_allow)
Definition: _killstreaks.gsc:2261
‪get_killstreak_usage_by_killstreak
‪function get_killstreak_usage_by_killstreak(killstreakType)
Definition: _killstreaks.gsc:2165
‪STATS_TABLE_COL_IMAGE
‪#define STATS_TABLE_COL_IMAGE
Definition: _statstable.gsh:8
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪override_entity_camera_in_demo
‪function override_entity_camera_in_demo(killstreakType, value, isInventory)
Definition: _killstreaks.gsc:411
‪update_missile_dog_threat
‪function update_missile_dog_threat(dog)
Definition: _killstreaks.gsc:3139
‪give_for_streak
‪function give_for_streak()
Definition: _killstreaks.gsc:498
‪take
‪function take(killstreak)
Definition: _killstreaks.gsc:568
‪play_killstreak_being_hacked_dialog
‪function play_killstreak_being_hacked_dialog(killstreakType, killstreakId)
Definition: _killstreaks.gsc:1875
‪main
‪function main()
Definition: _global_fx.csc:17
‪leader_dialog
‪function leader_dialog(dialogKey, team, excludeList, objectiveKey, killstreakId, dialogBufferKey)
Definition: _globallogic_audio.gsc:435
‪trackAssists
‪function trackAssists(attacker, damage, isFlare)
Definition: challenges_shared.gsc:26
‪configure_team
‪function configure_team(killstreakType, killstreakId, owner, influencerType, configureTeamPreFunction, configureTeamPostFunction, isHacked=false)
Definition: _killstreaks.gsc:2806
‪remove_ricochet_protection
‪function remove_ricochet_protection(killstreak_id, owner)
Definition: _killstreaks.gsc:3177
‪update_player_threat
‪function update_player_threat(player)
Definition: _killstreaks.gsc:2997
‪play_taacom_dialog_response_on_owner
‪function play_taacom_dialog_response_on_owner(dialogKey, killstreakType, killstreakId)
Definition: _killstreaks.gsc:2036
‪_get_from_weapon
‪function _get_from_weapon(weapon)
Definition: _killstreaks.gsc:766
‪killstreak_waiter
‪function killstreak_waiter()
Definition: _killstreaks.gsc:1530
‪WaitForTimeoutBeep
‪function WaitForTimeoutBeep(killstreakBundle, duration)
Definition: _killstreaks.gsc:2945
‪get_level
‪function get_level(index, killstreak)
Definition: _killstreaks.gsc:441
‪set_player_uimodel
‪function set_player_uimodel(str_field_name, n_value)
Definition: clientfield_shared.gsc:75
‪CLIENT_FIELD_KILLSTREAK_HIDES_COMPASS
‪#define CLIENT_FIELD_KILLSTREAK_HIDES_COMPASS
Definition: clientfields.gsh:9
‪get_first_valid_killstreak_alt_weapon
‪function get_first_valid_killstreak_alt_weapon(killstreakType)
Definition: _killstreaks.gsc:1762
‪set_ricochet_protection_endtime
‪function set_ricochet_protection_endtime(killstreak_id, owner, endTime)
Definition: _killstreaks.gsc:3166
‪setWeaponAmmoOverall
‪function setWeaponAmmoOverall(weapon, amount)
Definition: _loadout.gsc:1173
‪register_alt_weapon
‪function register_alt_weapon(killstreakType, weaponName, isInventory)
Definition: _killstreaks.gsc:318
‪update_missile_player_threat
‪function update_missile_player_threat(player)
Definition: _killstreaks.gsc:3109
‪update
‪function update()
Definition: _serversettings.gsc:71
‪clear_using_remote
‪function clear_using_remote(immediate, skipNotify)
Definition: _killstreaks.gsc:2403
‪watch_for_remove_remote_weapon
‪function watch_for_remove_remote_weapon()
Definition: _killstreaks.gsc:2250
‪get_script_bundle
‪function get_script_bundle(str_type, str_name)
Definition: struct.csc:45
‪player_killstreak_threat_tracking
‪function player_killstreak_threat_tracking(killstreakType)
Definition: _killstreaks.gsc:2092
‪give_weapon
‪function give_weapon(weapon, isinventory, useStoredAmmo)
Definition: _killstreaks.gsc:821
‪play_taacom_dialog
‪function play_taacom_dialog(dialogKey, killstreakType, killstreakId)
Definition: _globallogic_audio.gsc:274
‪get_emp_grenade_damage
‪function get_emp_grenade_damage(killstreakType, maxhealth)
Definition: _killstreak_bundles.gsc:265
‪register_remote_override_weapon
‪function register_remote_override_weapon(killstreakType, weaponName, isInventory)
Definition: _killstreaks.gsc:349
‪killstreakDamageModifier
‪function killstreakDamageModifier(damage, attacker, direction, point, sMeansOfDeath, tagName, modelName, partname, weapon, flags, inflictor, chargeLevel)
Definition: _satellite.gsc:363
‪should_delay_killstreak
‪function should_delay_killstreak(killstreakType)
Definition: _killstreaks.gsc:1610
‪give
‪function give(killstreakType, streak, suppressNotification, noXP, toBottom)
Definition: _killstreaks.gsc:539
‪RecordKillstreakBeginDirect
‪function RecordKillstreakBeginDirect(recordStreakIndex)
Definition: _killstreaks.gsc:1065
‪get_killstreak_usage
‪function get_killstreak_usage(usageKey)
Definition: _killstreaks.gsc:2172
‪get_if_top_killstreak_has_been_used
‪function get_if_top_killstreak_has_been_used()
Definition: _killstreaks.gsc:1303
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪isHacked
‪function isHacked()
Definition: util_shared.gsc:2493
‪leader_dialog_on_player
‪function leader_dialog_on_player(dialogKey, objectiveKey, killstreakId, dialogBufferKey, introDialog)
Definition: _globallogic_audio.gsc:460
‪hide_tablet
‪function hide_tablet()
Definition: _killstreaks.gsc:2439
‪friendlyFireCheck
‪function friendlyFireCheck(owner, attacker, forcedFriendlyFireRule)
Definition: _weaponobjects.gsc:2733
‪has_hero_weapon
‪function has_hero_weapon()
Definition: weapons_shared.gsc:201
‪name
‪class GroundFx name
‪WaitForTimeoutHacked
‪function WaitForTimeoutHacked(killstreak, callback, endCondition1, endCondition2, endCondition3)
Definition: _killstreaks.gsc:2976
‪update_actor_threat
‪function update_actor_threat(actor)
Definition: _killstreaks.gsc:3053
‪MigrationAwareWait
‪function MigrationAwareWait(durationMs)
Definition: hostmigration_shared.gsc:333
‪getStatsTableName
‪function getStatsTableName()
Definition: util_shared.csc:1343
‪can_play_dialog
‪function can_play_dialog(teamOnly)
Definition: _battlechatter.gsc:1495
‪should_not_timeout
‪function should_not_timeout(killstreak)
Definition: _killstreaks.gsc:2908
‪is_registered
‪function is_registered(killstreakType)
Definition: _killstreaks.gsc:218
‪give_if_streak_count_matches
‪function give_if_streak_count_matches(index, killstreak, streakCount)
Definition: _killstreaks.gsc:458
‪has_lmg
‪function has_lmg()
Definition: weapons_shared.gsc:189
‪get_enemy_players
‪function get_enemy_players()
Definition: _battlechatter.gsc:1443
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265
‪has_equipped
‪function has_equipped()
Definition: _killstreaks.gsc:750