‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_weaponobjects.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\array_shared;
4 #using scripts\shared\callbacks_shared;
5 #using scripts\shared\challenges_shared;
6 #using scripts\shared\clientfield_shared;
7 #using scripts\shared\dev_shared;
8 #using scripts\shared\damagefeedback_shared;
9 #using scripts\shared\entityheadicons_shared;
10 #using scripts\shared\flagsys_shared;
11 #using scripts\shared\hud_util_shared;
12 #using scripts\shared\player_shared;
13 #using scripts\shared\scoreevents_shared;
14 #using scripts\shared\system_shared;
15 #using scripts\shared\util_shared;
16 #using scripts\shared\vehicle_shared;
17 #using scripts\shared\weapons_shared;
18 #using scripts\shared\weapons\_hive_gun;
19 #using scripts\shared\weapons\_satchel_charge;
20 #using scripts\shared\weapons\_trophy_system;
21 #using scripts\shared\weapons\_weaponobjects;
22 
23 #insert scripts\shared\shared.gsh;
24 #insert scripts\shared\version.gsh;
25 #insert scripts\shared\weapons\_weaponobjects.gsh;
26 
27 #define MAX_PROJECTILE_WEAPONOBJECTS 4
28 
29 #precache( "lui_menu_data", "spikeLauncherCounter.spikesReady" );
30 #precache( "lui_menu_data", "spikeLauncherCounter.blasting" );
31 
32 #precache( "string", "MP_DEFUSING_EXPLOSIVE" );
33 #precache( "string", "PLATFORM_SATCHEL_CHARGE_DOUBLE_TAP" );
34 
35 #precache( "fx", "_t6/weapon/claymore/fx_claymore_laser" );
36 #precache( "fx", "explosions/fx_exp_equipment_lg" );
37 #precache( "fx", "killstreaks/fx_emp_explosion_equip" );
38 #precache( "fx", "_t6/explosions/fx_exp_equipment" );
39 #precache( "fx", "explosions/fx_exp_equipment_lg" );
40 #precache( "fx", "weapon/fx_equip_light_os" );
41 
42 #precache( "triggerstring", "MP_BOUNCINGBETTY_HACKING" );
43 #precache( "triggerstring", "MP_BOUNCINGBETTY_PICKUP" );
44 #precache( "triggerstring", "MP_HATCHET_PICKUP");
45 #precache( "triggerstring", "MP_CLAYMORE_PICKUP");
46 #precache( "triggerstring", "MP_BOUNCINGBETTY_PICKUP");
47 #precache( "triggerstring", "MP_TROPHY_SYSTEM_PICKUP");
48 #precache( "triggerstring", "MP_ACOUSTIC_SENSOR_PICKUP");
49 #precache( "triggerstring", "MP_CAMERA_SPIKE_PICKUP");
50 #precache( "triggerstring", "MP_SATCHEL_CHARGE_PICKUP");
51 #precache( "triggerstring", "MP_SCRAMBLER_PICKUP");
52 #precache( "triggerstring", "MP_SHOCK_CHARGE_PICKUP");
53 #precache( "triggerstring", "MP_TROPHY_SYSTEM_DESTROY");
54 #precache( "triggerstring", "MP_SENSOR_GRENADE_DESTROY");
55 #precache( "triggerstring", "MP_CLAYMORE_HACKING");
56 #precache( "triggerstring", "MP_BOUNCINGBETTY_HACKING");
57 #precache( "triggerstring", "MP_TROPHY_SYSTEM_HACKING");
58 #precache( "triggerstring", "MP_ACOUSTIC_SENSOR_HACKING");
59 #precache( "triggerstring", "MP_CAMERA_SPIKE_HACKING");
60 #precache( "triggerstring", "MP_SATCHEL_CHARGE_HACKING");
61 #precache( "triggerstring", "MP_SCRAMBLER_HACKING");
62 
63 #namespace weaponobjects;
64 
65 function ‪init_shared()
66 {
68 
69  ‪clientfield::register( "toplayer", "proximity_alarm", ‪VERSION_SHIP, 2, "int" );
70  ‪clientfield::register( "clientuimodel", "hudItems.proximityAlarm", ‪VERSION_SHIP, 2, "int" ); // registered client-side in raw/ui/uieditor/clientfieldmodels.lua
71  ‪clientfield::register( "missile", "retrievable", ‪VERSION_SHIP, 1, "int" );
72  ‪clientfield::register( "scriptmover", "retrievable", ‪VERSION_SHIP, 1, "int" );
73  ‪clientfield::register( "missile", "enemyequip", ‪VERSION_SHIP, 2, "int" );
74  ‪clientfield::register( "scriptmover", "enemyequip", ‪VERSION_SHIP, 2, "int" );
75  ‪clientfield::register( "missile", "teamequip", ‪VERSION_SHIP, 1, "int" );
76 
77  level.weaponObjectDebug = GetDvarInt( "scr_weaponobject_debug", 0 );
78 
79  level.supplementalWatcherObjects = [];
80 
81  /#
82  level thread ‪updateDvars();
83  #/
84 }
85 
86 function ‪updateDvars()
87 {
88  while(1)
89  {
90  level.weaponObjectDebug = GetDvarInt( "scr_weaponobject_debug", 0 );
91 
92  wait(1.0);
93  }
94 }
95 
97 {
98  coneangle = GetDvarInt( "scr_weaponobject_coneangle", 70 );
99  mindist = GetDvarInt( "scr_weaponobject_mindist", 20 );
100  graceperiod = GetDvarFloat( "scr_weaponobject_graceperiod", 0.6 );
101  radius = GetDvarInt( "scr_weaponobject_radius", 192 );
102 
105 
106  level.watcherWeapons = [];
107  level.watcherWeapons = getWatcherWeapons();
108 
109  level.retrievableWeapons = [];
110  level.retrievableWeapons = getRetrievableWeapons();
111 
112  level.weaponobjectexplodethisframe = false;
113 
114  if ( GetDvarString( "scr_deleteexplosivesonspawn") == "" )
115  {
116  SetDvar("scr_deleteexplosivesonspawn", 1);
117  }
118 
119  level.deleteExplosivesOnSpawn = GetDvarInt( "scr_deleteexplosivesonspawn");
120 
121  level.claymoreFXid = "_t6/weapon/claymore/fx_claymore_laser";
122  level._equipment_spark_fx = "explosions/fx_exp_equipment_lg";
123  level._equipment_fizzleout_fx = "explosions/fx_exp_equipment_lg";
124  level._equipment_emp_destroy_fx = "killstreaks/fx_emp_explosion_equip";
125  level._equipment_explode_fx = "_t6/explosions/fx_exp_equipment";
126  level._equipment_explode_fx_lg = "explosions/fx_exp_equipment_lg";
127  level._effect[ "powerLight" ] = "weapon/fx_equip_light_os";
128 
130 
131  level.weaponobjects_hacker_trigger_width = 32;
132  level.weaponobjects_hacker_trigger_height = 32;
133 }
134 
136 {
137  ‪createRetrievableHint("hatchet", &"MP_HATCHET_PICKUP");
138  ‪createRetrievableHint("claymore", &"MP_CLAYMORE_PICKUP");
139  ‪createRetrievableHint("bouncingbetty", &"MP_BOUNCINGBETTY_PICKUP");
140  ‪createRetrievableHint("trophy_system", &"MP_TROPHY_SYSTEM_PICKUP");
141  ‪createRetrievableHint("acoustic_sensor", &"MP_ACOUSTIC_SENSOR_PICKUP");
142  //createRetrievableHint("sensor_grenade", &"MP_SENSOR_GRENADE_PICKUP");
143  ‪createRetrievableHint("camera_spike", &"MP_CAMERA_SPIKE_PICKUP");
144  ‪createRetrievableHint("satchel_charge", &"MP_SATCHEL_CHARGE_PICKUP");
145  ‪createRetrievableHint("scrambler", &"MP_SCRAMBLER_PICKUP");
146  ‪createRetrievableHint("proximity_grenade", &"MP_SHOCK_CHARGE_PICKUP");
147 
148  ‪createDestroyHint( "trophy_system", &"MP_TROPHY_SYSTEM_DESTROY");
149  ‪createDestroyHint( "sensor_grenade", &"MP_SENSOR_GRENADE_DESTROY");
150 
151  ‪createHackerHint("claymore", &"MP_CLAYMORE_HACKING");
152  ‪createHackerHint("bouncingbetty", &"MP_BOUNCINGBETTY_HACKING");
153  ‪createHackerHint("trophy_system", &"MP_TROPHY_SYSTEM_HACKING");
154  ‪createHackerHint("acoustic_sensor", &"MP_ACOUSTIC_SENSOR_HACKING");
155  //createHackerHint("sensor_grenade", &"MP_SENSOR_GRENADE_HACKING");
156  ‪createHackerHint("camera_spike", &"MP_CAMERA_SPIKE_HACKING");
157  ‪createHackerHint("satchel_charge", &"MP_SATCHEL_CHARGE_HACKING");
158  ‪createHackerHint("scrambler", &"MP_SCRAMBLER_HACKING");
159 }
160 
162 {
163  if ( isdefined( level._weaponobjects_on_player_connect_override ) )
164  {
165  level thread [[level._weaponobjects_on_player_connect_override]]();
166  return;
167  }
168 
169  self.usedWeapons = false;
170  self.hits = 0;
171 }
172 
173 function ‪on_player_spawned() // self == player
174 {
175  self endon("disconnect");
176 
177  pixbeginevent("onPlayerSpawned");
178 
179  if ( !isdefined( self.watchersInitialized ) )
180  {
181  self ‪createBaseWatchers();
182 
184 
185  //Ensure that the watcher name is the weapon name minus _mp if you want to add weapon specific functionality.
187  self ‪createRCBombWatcher();
190  //self createKniferangWatcher();
195 
196  //set up retrievable specific fields
198 
199  self thread ‪watchWeaponObjectUsage();
200 
201  self.watchersInitialized = true;
202  }
203 
204  self ‪resetWatchers();
205 
207 
208  pixendevent();
209 }
210 
212 {
213  if ( !isdefined(self.weaponObjectWatcherArray) )
214  {
215  return undefined;
216  }
217 
218  team = self.team;
219 
220  foreach( watcher in self.weaponObjectWatcherArray )
221  {
222  ‪resetWeaponObjectWatcher( watcher, team );
223  }
224 }
225 
227 {
228  //Check for die on respawn weapons
229  foreach( index, weapon in level.watcherWeapons )
230  {
231  self ‪createWeaponObjectWatcher( weapon.name, self.team );
232  }
233 
234  //Check for retrievable weapons
235  foreach( index, weapon in level.retrievableWeapons )
236  {
237  self ‪createWeaponObjectWatcher( weapon.name, self.team );
238  }
239 }
240 
242 {
243  //Check for retrievable weapons
244  for( i = 0; i < level.retrievableWeapons.size; i++ )
245  {
246  watcher = ‪getWeaponObjectWatcherByWeapon( level.retrievableWeapons[i] );
247  if( isdefined( watcher ) )
248  {
249  if( !isdefined( watcher.onSpawnRetrieveTriggers ) )
250  watcher.onSpawnRetrieveTriggers =&‪onSpawnRetrievableWeaponObject;
251 
252  if ( !isdefined( watcher.onDestroyed ))
253  watcher.onDestroyed =&‪onDestroyed;
254 
255  if( !isdefined( watcher.pickUp ) )
256  watcher.pickUp =&‪pickUp;
257  }
258  }
259 }
260 
262 {
263  watcher = self ‪createUseWeaponObjectWatcher( weaponName, self.team );
264  watcher.onDetonateCallback = &‪deleteEnt;
265  watcher.onDamage =&‪voidOnDamage;
266 
267  if ( ‪IS_TRUE( level.b_crossbow_bolt_destroy_on_impact ) ) // PORTIZ 7/5/16: override crossbow bolt lingering/retrieval, since behavior is set up here in script instead of through GDT
268  {
269  watcher.onSpawn = &‪onSpawnCrossbowBoltImpact;
270  watcher.onSpawnRetrieveTriggers = &‪voidOnSpawnRetrieveTriggers;
271  watcher.pickUp = &‪voidPickUp;
272  }
273  else
274  {
275  watcher.onSpawn = &‪onSpawnCrossbowBolt;
276  watcher.onSpawnRetrieveTriggers =&‪onSpawnSpecialCrossbowTrigger;
277  watcher.pickUp = &‪pickUpCrossbowBolt;
278  }
279 }
280 
281 function ‪createSpecialCrossbowWatcher() // self == player
282 {
283  ‪createSpecialCrossbowWatcherTypes( "special_crossbow" );
284  ‪createSpecialCrossbowWatcherTypes( "special_crossbowlh" );
285  ‪createSpecialCrossbowWatcherTypes( "special_crossbow_dw" );
286 
287  if ( ‪IS_TRUE( level.b_create_upgraded_crossbow_watchers ) ) // PORTIZ 7/5/16: ZM maps can set to true to include upgraded crossbows
288  {
289  ‪createSpecialCrossbowWatcherTypes( "special_crossbowlh_upgraded" );
290  ‪createSpecialCrossbowWatcherTypes( "special_crossbow_dw_upgraded" );
291  }
292 }
293 
294 function ‪createHatchetWatcher() // self == player
295 {
296  watcher = self ‪createUseWeaponObjectWatcher( "hatchet", self.team );
297  watcher.onDetonateCallback = &‪deleteEnt;
298  watcher.onSpawn =&‪onSpawnHatchet;
299  watcher.onDamage =&‪voidOnDamage;
300  watcher.onSpawnRetrieveTriggers =&‪onSpawnHatchetTrigger;
301 }
302 
303 function ‪createTactInsertWatcher() // self == player
304 {
305  watcher = self ‪createUseWeaponObjectWatcher( "tactical_insertion", self.team );
306  watcher.playDestroyedDialog = false;
307 }
308 
309 function ‪createRCBombWatcher() // self == player
310 {
311  watcher = self ‪createUseWeaponObjectWatcher( "rcbomb", self.team );
312 
313  watcher.altDetonate = false;
314  watcher.headIcon = false;
315  watcher.isMovable = true;
316  watcher.ownerGetsAssist = true;
317  watcher.playDestroyedDialog = false;
318  watcher.deleteOnKillbrush = false;
319 
320  watcher.onDetonateCallback = level.rcbombOnBlowUp;
321  watcher.stunTime = 1;
322  watcher.notEquipment = true;
323 }
324 
325 function ‪createQRDroneWatcher() // self == player
326 {
327  watcher = self ‪createUseWeaponObjectWatcher( "qrdrone", self.team );
328 
329  watcher.altDetonate = false;
330  watcher.headIcon = false;
331  watcher.isMovable = true;
332  watcher.ownerGetsAssist = true;
333  watcher.playDestroyedDialog = false;
334  watcher.deleteOnKillbrush = false;
335 
336  watcher.onDetonateCallback = level.qrdroneOnBlowUp;
337  watcher.onDamage = level.qrdroneOnDamage;
338  watcher.stunTime = 5;
339  watcher.notEquipment = true;
340 }
341 
343 {
344  // the spike launcher generates a new weapon when fired to handle detonation so make sure we're only counting the bolts
345  currentItemCount = 0;
346  foreach ( obj in watcher.objectArray )
347  {
348  if ( IsDefined(obj) && obj.item !== watcher.weapon )
349  {
350  currentItemCount++;
351  }
352  }
353  return currentItemCount;
354 }
355 
356 function ‪watchSpikeLauncherItemCountChanged( watcher ) // self == player
357 {
358  self endon( "death" );
359  lastItemCount = undefined;
360  while ( 1 )
361  {
362  self waittill( "weapon_change", weapon );
363 
364  while ( weapon.name == "spike_launcher" )
365  {
366  // the spike launcher generates a new weapon when fired to handle detonation so make sure we're only counting the bolts
367  currentItemCount = ‪getSpikeLauncherActiveSpikeCount( watcher );
368 
369  if ( currentItemCount !== lastItemCount )
370  {
371  self SetControllerUIModelValue( "spikeLauncherCounter.spikesReady", currentItemCount );
372  lastItemCount = currentItemCount;
373  }
374 
375  wait 0.1;
376  weapon = self GetCurrentWeapon();
377  }
378  }
379 }
380 
381 function ‪spikesDetonating( watcher ) // self == player
382 {
383  spikeCount = ‪getSpikeLauncherActiveSpikeCount( watcher );
384 
385  if ( spikeCount > 0 )
386  {
387  self SetControllerUIModelValue( "spikeLauncherCounter.blasting", 1 );
388  wait 2;
389  self SetControllerUIModelValue( "spikeLauncherCounter.blasting", 0 );
390  }
391 }
392 
393 function ‪createSpikeLauncherWatcher(weapon) // self == player
394 {
395  watcher = self ‪weaponobjects::createUseWeaponObjectWatcher( weapon, self.team );
396  watcher.altName = "spike_charge";
397  watcher.altWeapon = GetWeapon( "spike_charge" );
398  watcher.altDetonate = false;
399  watcher.watchForFire = true;
400  watcher.hackable = true;
401  watcher.hackerToolRadius = level.equipmentHackerToolRadius;
402  watcher.hackerToolTimeMs = level.equipmentHackerToolTimeMs;
403  watcher.headIcon = false;
404  watcher.onDetonateCallback = &‪spikeDetonate;
405  watcher.onStun = &‪weaponobjects::weaponStun;
406  watcher.stunTime = 1;
407  watcher.ownerGetsAssist = true;
408  watcher.detonateStationary = false;
409  watcher.detonationDelay = 0.0;
410  watcher.detonationSound = "wpn_claymore_alert";
411  watcher.onDetonationHandle = &‪spikesDetonating;
412  self thread ‪watchSpikeLauncherItemCountChanged( watcher );
413 }
414 
415 function ‪createPlayerHelicopterWatcher() // self == player
416 {
417  watcher = self ‪createUseWeaponObjectWatcher( "helicopter_player", self.team );
418 
419  watcher.altDetonate = true;
420  watcher.headIcon = false;
421 
422  watcher.notEquipment = true;
423 }
424 
425 function ‪createClaymoreWatcher() // self == player
426 {
427  watcher = self ‪createProximityWeaponObjectWatcher( "claymore", self.team );
428  watcher.watchForFire = true;
429  watcher.onDetonateCallback = &‪claymoreDetonate;
430  watcher.activateSound = "wpn_claymore_alert";
431  watcher.hackable = true;
432  watcher.hackerToolRadius = level.equipmentHackerToolRadius;
433  watcher.hackerToolTimeMs = level.equipmentHackerToolTimeMs;
434  watcher.ownerGetsAssist = true;
435 
436  detectionConeAngle = GetDvarInt( "scr_weaponobject_coneangle" );
437  watcher.detectionDot = cos( detectionConeAngle );
438  watcher.detectionMinDist = GetDvarInt( "scr_weaponobject_mindist" );
439  watcher.detectionGracePeriod = GetDvarFloat( "scr_weaponobject_graceperiod" );
440  watcher.detonateRadius = GetDvarInt( "scr_weaponobject_radius" );
441  watcher.onStun =&‪weaponStun;
442  watcher.stunTime = 1;
443 }
444 
445 function ‪voidOnSpawn( unused0, unused1 )
446 {
447 }
448 
449 function ‪voidOnDamage( unused0 )
450 {
451 }
452 
453 function ‪voidOnSpawnRetrieveTriggers( unused0, unused1 )
454 {
455 }
456 
457 function ‪voidPickUp( unused0, unused1 )
458 {
459 }
460 
461 function ‪deleteEnt( attacker, emp, target )
462 {
463  self delete();
464 }
465 
466 function ‪clearFXOnDeath( fx )
467 {
468  fx endon("death");
469  self ‪util::waittill_any( "death", "hacked" );
470  fx delete();
471 }
472 
473 //
474 // generic watcher code
475 //
476 
478 {
479  if ( !isdefined( self ) )
480  return;
481 
482  if ( isdefined( self.mineMover ) )
483  {
484  if ( isdefined( self.mineMover.killCamEnt ) )
485  {
486  self.mineMover.killCamEnt delete();
487  }
488 
489  self.mineMover delete();
490  }
491 
492  self delete();
493 }
494 
496 {
497  if ( isdefined( self.objectArray ) )
498  {
499  foreach( weaponObject in self.objectArray )
500  {
501  weaponObject ‪deleteWeaponObjectInstance();
502  }
503  }
504 
505  self.objectArray = [];
506 }
507 
508 function ‪delayedSpikeDetonation( attacker, weapon )
509 {
510 // wait 0.05;//flip the execute order back - previous wait will have flipped the thread order coming into this function - we want the charges to go off in the order they were placed
511  if (!IsDefined(self.owner.spikeDelay))
512  {
513  self.owner.spikeDelay = 0;
514  }
515  const delayTimeIncrement = 0.3;
516  delayTime = self.owner.spikeDelay;
517  owner = self.owner;
518  self.owner.spikeDelay += delayTimeIncrement;//delay between successive blasts
519  waittillframeend;//make sure any other thread that wants to fire this frame uses an incrementing time value, if it's zero it won't wait and everyone will get zero time delay
520  wait delayTime;
521  owner.spikeDelay -= delayTimeIncrement;
522  if (IsDefined(self))
523  {
524  self ‪weaponobjects::weaponDetonate( attacker, weapon );
525  }
526 }
527 
528 function ‪spikeDetonate( attacker, weapon, target )
529 {
530  if ( IsDefined( weapon ) && weapon.isValid )
531  {
532  if ( isdefined( attacker ) )
533  {
534  if ( self.owner ‪util::IsEnemyPlayer( attacker ) )
535  {
536 // attacker challenges::destroyedExplosive( weapon );
537 // scoreevents::processScoreEvent( "destroyed_c4", attacker, self.owner, weapon );
538  }
539 
540  }
541  }
542 
543  thread ‪delayedSpikeDetonation(attacker, weapon);
544 }
545 
546 function ‪claymoreDetonate( attacker, weapon, target )
547 {
548  if ( !isdefined( weapon ) || !weapon.isEmp )
549  {
550  //PlayFX( level._equipment_explode_fx_lg, self.origin );
551  }
552 
553  if ( isdefined(attacker) && self.owner ‪util::IsEnemyPlayer( attacker ) )
554  {
555  attacker ‪challenges::destroyedExplosive( weapon );
556  ‪scoreevents::processScoreEvent( "destroyed_claymore", attacker, self.owner, weapon );
557  }
558 
559  ‪weaponobjects::weaponDetonate( attacker, weapon );
560 }
561 
562 
563 function ‪weaponDetonate( attacker, weapon )
564 {
565  if ( IsDefined( weapon ) && weapon.isEmp )
566  {
567  self delete();
568  return;
569  }
570 
571  if ( isdefined( attacker ) )
572  {
573  if ( isdefined( self.owner ) && ( attacker != self.owner ) )
574  {
575  self.playDialog = true;
576  }
577 
578  if ( IsPlayer( attacker ) )
579  {
580  self Detonate( attacker );
581  }
582  else
583  {
584  self Detonate();
585  }
586  }
587  else if ( isdefined( self.owner ) && isplayer( self.owner ) )
588  {
589  self.playDialog = false;
590  self Detonate( self.owner );
591  }
592  else
593  {
594  self Detonate();
595  }
596 }
597 
598 function ‪detonateWhenStationary( object, ‪delay, attacker, weapon )
599 {
600  level endon( "game_ended" );
601 
602  object endon( "death" );
603  object endon( "hacked" );
604  object endon( "detonating" );
605 
606 
607  if ( object isOnGround() == false )
608  {
609  object waittill( "stationary" );
610  }
611 
612  self thread ‪waitAndDetonate( object, ‪delay, attacker, weapon );
613 }
614 
615 function ‪waitAndDetonate( object, ‪delay, attacker, weapon )
616 {
617  object endon("death");
618  object endon("hacked");
619 
620  if ( !isdefined( attacker ) && !isdefined( weapon ) && object.weapon.proximityalarmactivationdelay > 0 )
621  {
622  // no double armed_detonation_wait detonations
623  if ( ‪IS_TRUE( object.armed_detonation_wait ) )
624  {
625  return;
626  }
627 
628  object.armed_detonation_wait = true;
629 
630  while ( !‪IS_TRUE( object.proximity_deployed ) )
631  {
633  }
634  }
635 
636  // no double detonations
637  if ( ‪IS_TRUE( object.detonated ) )
638  {
639  return;
640  }
641 
642  object.detonated = true;
643 
644  object notify( "detonating" );
645 
646  isEmpDetonated = IsDefined( weapon ) && weapon.isemp;
647 
648  if ( isEmpDetonated && object.weapon.doEmpDestroyFx )
649  {
650  object.stun_fx = true;
651 
652  PlayFX( level._equipment_emp_destroy_fx, object.origin + ( 0, 0, 5 ) , ( 0, RandomFloat( 360 ), 0 ) );
653  empFxDelay = 1.1;
654  }
655 
656  if ( !isdefined( self.onDetonateCallback ) )
657  {
658  return;
659  }
660 
661  if ( !isEmpDetonated && !isdefined( weapon ) )
662  {
663  if ( isdefined( self.detonationDelay ) && self.detonationDelay > 0.0 )
664  {
665  if ( isdefined( self.detonationSound ) )
666  {
667  object playsound ( self.detonationSound );
668  }
669 
670  ‪delay = self.detonationDelay;
671  }
672  }
673  else if ( isdefined( empFxDelay ) )
674  {
675  ‪delay = empFxDelay;
676  }
677 
678  if ( ‪delay > 0 )
679  {
680  wait ( ‪delay );
681  }
682 
683  // "destroyed_explosive" notify, for challenges
684  if ( isdefined( attacker ) && IsPlayer( attacker ) && isdefined( attacker.pers["team"] ) && isdefined( object.owner ) && isdefined( object.owner.pers["team"] ) )
685  {
686  if ( level.teambased )
687  {
688  if ( attacker.pers["team"] != object.owner.pers["team"] )
689  {
690  attacker notify("destroyed_explosive");
691  //attacker _properks::destroyedEquipment();
692  }
693  }
694  else
695  {
696  if ( attacker != object.owner )
697  {
698  attacker notify("destroyed_explosive");
699  //attacker _properks::destroyedEquipment();
700  }
701  }
702  }
703 
704  object [[self.onDetonateCallback]]( attacker, weapon, undefined );
705 }
706 
707 function ‪waitAndFizzleOut( object, ‪delay )
708 {
709  object endon("death");
710  object endon("hacked");
711 
712  // no double detonations
713  if ( isdefined( object.detonated ) && object.detonated == true )
714  {
715  return;
716  }
717 
718  object.detonated = true;
719 
720  object notify( "fizzleout" );
721 
722  if ( ‪delay > 0 )
723  {
724  wait ( ‪delay );
725  }
726 
727  if ( !isdefined( self.onFizzleOut ) )
728  {
729  self ‪deleteEnt();
730  return;
731  }
732 
733  object [[self.onFizzleOut]]();
734 }
735 
736 function ‪detonateWeaponObjectArray( forceDetonation, weapon )
737 {
738  undetonated = [];
739  if ( isdefined(self.objectArray) )
740  {
741  for ( i = 0; i < self.objectArray.size; i++ )
742  {
743  if ( isdefined( self.objectArray[i] ) )
744  {
745  // weapon is stunned, but can be detonated later
746  if ( self.objectArray[i] isstunned() && forceDetonation == false )
747  {
748  undetonated[undetonated.size] = self.objectArray[i];
749  continue;
750  }
751 
752  if ( isdefined( weapon ) )
753  {
754  // hacked weapon, don't destroy other weapons not of the same
755  if ( weapon ‪util::isHacked() && weapon.name != self.objectArray[i].weapon.name )
756  {
757  undetonated[undetonated.size] = self.objectArray[i];
758  continue;
759  }
760  // planted weapon, don't destroy hacked weapons not of the same
761  else if ( self.objectArray[i] ‪util::isHacked() && weapon.name != self.objectArray[i].weapon.name )
762  {
763  undetonated[undetonated.size] = self.objectArray[i];
764  continue;
765  }
766  }
767 
768  // detonateStationary watcher, don't destroy until stationary
769  if ( isdefined( self.detonateStationary ) && self.detonateStationary && forceDetonation == false )
770  {
771  self thread ‪detonateWhenStationary( self.objectArray[i], 0.0, undefined, weapon );
772  }
773  else
774  {
775  self thread ‪waitAndDetonate( self.objectArray[i], 0.0, undefined, weapon );
776  }
777  }
778  }
779  }
780 
781  self.objectArray = undetonated;
782 }
783 
784 function ‪addWeaponObjectToWatcher( watcherName, weapon_instance )
785 {
786  watcher = ‪getWeaponObjectWatcher( watcherName );
787  assert( isdefined( watcher ), "Weapon object watcher " + watcherName + " does not exist" );
788 
789  self ‪addWeaponObject( watcher, weapon_instance );
790 }
791 
792 function ‪addWeaponObject( watcher, weapon_instance, weapon )
793 {
794  if( !isdefined( watcher.storeDifferentObject ) )
795  watcher.objectArray[watcher.objectArray.size] = weapon_instance;
796 
797  if ( !IsDefined( weapon ) )
798  {
799  weapon = watcher.weapon;
800  }
801 
802  weapon_instance.owner = self;
803  weapon_instance.detonated = false;
804  weapon_instance.weapon = weapon;
805 
806  if( isdefined( watcher.onDamage ) )
807  {
808  weapon_instance thread [[watcher.onDamage]]( watcher );
809  }
810  else
811  {
812  weapon_instance thread ‪weaponObjectDamage( watcher );
813  }
814 
815  weapon_instance.ownerGetsAssist = watcher.ownerGetsAssist;
816  weapon_instance.destroyedByEmp = watcher.destroyedByEmp;
817 
818  if ( isdefined( watcher.onSpawn ) )
819  weapon_instance thread [[watcher.onSpawn]]( watcher, self );
820 
821  if ( isdefined( watcher.onSpawnFX ) )
822  weapon_instance thread [[watcher.onSpawnFX]]();
823 
824  weapon_instance thread ‪setupReconEffect();
825 
826  if( isdefined( watcher.onSpawnRetrieveTriggers ) )
827  weapon_instance thread [[watcher.onSpawnRetrieveTriggers]](watcher, self);
828 
829  if ( watcher.hackable )
830  weapon_instance thread ‪hackerInit( watcher );
831 
832  if( watcher.playDestroyedDialog )
833  {
834  weapon_instance thread ‪playDialogOnDeath( self );
835  weapon_instance thread ‪watchObjectDamage( self );
836  }
837 
838  if( watcher.deleteOnKillbrush )
839  {
840  if ( isdefined ( level.deleteOnKillbrushOverride ) )
841  {
842  weapon_instance thread [[level.deleteOnKillbrushOverride]]( self, watcher );
843  }
844  else
845  {
846  weapon_instance thread ‪deleteOnKillbrush( self );
847  }
848  }
849 
850  if ( weapon_instance ‪useTeamEquipmentClientField( watcher ) )
851  {
852  weapon_instance ‪clientfield::set( "teamequip", 1 );
853  }
854 
855  if ( watcher.timeOut )
856  {
857  weapon_instance thread ‪weapon_object_timeout( watcher );
858  }
859 
860  weapon_instance thread ‪delete_on_notify( self );
861 
862  weapon_instance thread ‪cleanupWatcherOnDeath( watcher );
863 }
864 
865 function ‪cleanupWatcherOnDeath( watcher ) // call on weapon entity
866 {
867  self waittill( "death" );
868 
869  if ( isdefined( watcher ) && isdefined( watcher.objectarray ) )
870  {
871  ‪removeWeaponObject( watcher, self );
872  }
873 
874  if ( isdefined( self ) && ( self.‪delete_on_death === true ) )
875  {
877  }
878 }
879 
880 function ‪weapon_object_timeout( watcher )
881 {
882  self endon( "death" );
883 
884  wait ( watcher.timeOut );
885 
886  self ‪deleteEnt();
887 }
888 
889 function ‪delete_on_notify( e_player )
890 {
891  e_player endon( "disconnect" );
892  self endon( "death" );
893 
894  e_player waittill( "delete_weapon_objects" );
895 
896  self Delete();
897 }
898 
899 // call on player
900 function ‪deleteWeaponObjectHelper( weapon_ent )
901 {
902  watcher = self ‪getWeaponObjectWatcherByWeapon( weapon_ent.weapon );
903  if ( !isdefined( watcher ) )
904  {
905  return;
906  }
907 
908  ‪removeWeaponObject( watcher, weapon_ent );
909 }
910 
911 function ‪removeWeaponObject( watcher, weapon_ent )
912 {
913  watcher.objectArray = ‪array::remove_undefined( watcher.objectArray );
914  ArrayRemoveValue( watcher.objectArray, weapon_ent );
915 }
916 
917 function ‪cleanWeaponObjectArray( watcher )
918 {
919  watcher.objectArray = ‪array::remove_undefined( watcher.objectArray );
920 }
921 
922 function ‪weapon_object_do_DamageFeedBack( weapon, attacker )
923 {
924  if ( isdefined( weapon ) && isdefined( attacker ) )
925  {
926  if ( weapon.doDamageFeedback )
927  {
928  // if we're not on the same team then show damage feedback
929  if ( level.teambased && self.owner.team != attacker.team )
930  {
931  if ( ‪damagefeedback::doDamageFeedback( weapon, attacker ) )
932  attacker ‪damagefeedback::update();
933  }
934  // for ffa just make sure the owner isn't the same
935  else if ( !level.teambased && self.owner != attacker )
936  {
937  if ( ‪damagefeedback::doDamageFeedback( weapon, attacker ) )
938  attacker ‪damagefeedback::update();
939  }
940  }
941  }
942 }
943 
944 function ‪weaponObjectDamage( watcher ) // self == weapon object
945 {
946  self endon( "death" );
947  self endon( "hacked" );
948  self endon( "detonating" );
949 
950  self setcandamage(true);
951  self.maxhealth = 100000;
952  self.health = self.maxhealth;
953  self.damageTaken = 0;
954 
955  attacker = undefined;
956 
957  while ( 1 )
958  {
959  self waittill ( "damage", ‪damage, attacker, direction_vec, point, type, modelName, tagName, partName, weapon, iDFlags );
960 
961  self.damageTaken += ‪damage;
962 
963  if ( !isPlayer( attacker ) && isdefined( attacker.owner ) )
964  {
965  attacker = attacker.owner;
966  }
967 
968  if ( isdefined( weapon ) )
969  {
970  // do damage feedback
971  self ‪weapon_object_do_DamageFeedBack( weapon, attacker );
972 
973  // most equipment should be flash/concussion-able, so it'll disable for a short period of time
974  // check to see if the equipment has been flashed/concussed and disable it
975  if ( watcher.stunTime > 0 && weapon.doStun )
976  {
977  self thread ‪stunStart( watcher, watcher.stunTime );
978  continue;
979  }
980  }
981 
982  // we're currently allowing the owner/teammate to flash their own
983  if ( level.teambased && IsPlayer( attacker ) && isdefined( self.owner ) )
984  {
985  // if we're not hardcore and the team is the same, do not destroy
986  if( !level.hardcoreMode && self.owner.team == attacker.pers["team"] && self.owner != attacker )
987  {
988  continue;
989  }
990  }
991 
992  if ( IsDefined( watcher.shouldDamage ) && !(self [[watcher.shouldDamage]]( watcher, attacker, weapon, ‪damage )) )
993  {
994  continue;
995  }
996 
997  // TODO: figure out if this is needed anymore
998  // don't allow people to destroy satchel on their team if FF is off
999  // don't bother with the FF check on vehicles as it will already have been done in
1000  // the vehicle damage callback
1001  if ( !isvehicle( self ) && !‪friendlyFireCheck( self.owner, attacker ) )
1002  continue;
1003 
1004  break;
1005  }
1006 
1007  if ( level.weaponobjectexplodethisframe )
1008  wait .1 + randomfloat(.4);
1009  else
1010  wait .05;
1011 
1012  if (!isdefined(self))
1013  return;
1014 
1015  level.weaponobjectexplodethisframe = true;
1016 
1018 
1020 
1021  if ( isdefined( type ) && (isSubStr( type, "MOD_GRENADE_SPLASH" ) || isSubStr( type, "MOD_GRENADE" ) || isSubStr( type, "MOD_EXPLOSIVE" )) )
1022  self.wasChained = true;
1023 
1024  if ( isdefined( iDFlags ) && (iDFlags & ‪IDFLAGS_PENETRATION) )
1025  {
1026  self.wasDamagedFromBulletPenetration = true;
1027  //attacker _properks::shotEquipment( self.owner, iDFlags );
1028  }
1029 
1030  self.wasDamaged = true;
1031 
1032  watcher thread ‪waitAndDetonate( self, 0.0, attacker, weapon );
1033 
1034  // won't get here; got death notify.
1035 }
1036 
1037 //Notify player that their equipment was destroyed
1038 function ‪playDialogOnDeath( owner )
1039 {
1040  owner endon("death");
1041  owner endon("disconnect");
1042  self endon( "hacked" );
1043 
1044  self waittill( "death" );
1045 
1046  if( isdefined(self.playDialog) && self.playDialog )
1047  {
1048  if( isdefined( level.playEquipmentDestroyedOnPlayer ) )
1049  {
1050  owner [[level.playEquipmentDestroyedOnPlayer]]( );
1051  }
1052  }
1053 }
1054 
1055 function ‪watchObjectDamage( owner )
1056 {
1057  owner endon("death");
1058  owner endon("disconnect");
1059  self endon( "hacked" );
1060  self endon( "death" );
1061 
1062  while(1)
1063  {
1064  self waittill( "damage", ‪damage, attacker );
1065 
1066  if( isdefined(attacker) && isPlayer(attacker) && attacker != owner )
1067  {
1068  self.playDialog = true;
1069  }
1070  else
1071  {
1072  self.playDialog = false;
1073  }
1074  }
1075 }
1076 
1077 function ‪stunStart( watcher, time )
1078 {
1079  self endon ( "death" );
1080 
1081  if ( self ‪isStunned() )
1082  {
1083  return;
1084  }
1085 
1086  if ( isdefined( self.cameraHead ) )
1087  {
1088  //self.cameraHead clientfield::set( "cf_m_stun", 1 );
1089  }
1090  //self clientfield::set( "cf_m_stun", 1 );
1091 
1092  // allow specific effects
1093  if ( isdefined( watcher.onStun ) )
1094  self thread [[watcher.onStun]]();
1095 
1096  if ( watcher.name == "rcbomb" )
1097  {
1098  self.owner ‪util::freeze_player_controls( true );
1099  }
1100 
1101  if ( isdefined( time ) )
1102  {
1103  wait ( time );
1104  }
1105  else
1106  {
1107  return;
1108  }
1109 
1110  if ( watcher.name == "rcbomb" )
1111  {
1112  self.owner ‪util::freeze_player_controls( false );
1113  }
1114 
1115  self ‪stunStop();
1116 }
1117 
1118 function ‪stunStop()
1119 {
1120  self notify ( "not_stunned" );
1121  if ( isdefined( self.cameraHead ) )
1122  {
1123  //self.cameraHead clientfield::set( "cf_m_stun", 0 );
1124  }
1125  //self clientfield::set( "cf_m_stun", 0 );
1126 }
1127 
1128 function ‪weaponStun() // self == weapon object
1129 {
1130  self endon( "death" );
1131  self endon( "not_stunned" );
1132 
1133  origin = self GetTagOrigin( "tag_fx" );
1134 
1135  if ( !isdefined( origin ) )
1136  {
1137  origin = self.origin + ( 0, 0, 10 );
1138  }
1139 
1140  self.stun_fx = ‪spawn( "script_model", origin );
1141  self.stun_fx SetModel( "tag_origin" );
1142  self thread ‪stunFxThink( self.stun_fx );
1143  wait ( 0.1 );
1144 
1145  PlayFXOnTag( level._equipment_spark_fx, self.stun_fx, "tag_origin" );
1146 
1147 }
1148 
1149 function ‪stunFxThink( fx )
1150 {
1151  fx endon("death");
1152  self ‪util::waittill_any( "death", "not_stunned" );
1153  fx delete();
1154 }
1155 
1156 function ‪isStunned()
1157 {
1158  return ( isdefined( self.stun_fx ) );
1159 }
1160 
1162 {
1163  self endon( "death" );
1164 
1165  PlayFX( level._equipment_fizzleout_fx, self.origin );
1166 
1167  ‪deleteEnt();
1168 }
1169 
1171 {
1172  wait .05;
1173  level.weaponobjectexplodethisframe = false;
1174 }
1175 
1177 {
1178  if ( !isdefined(self.weaponObjectWatcherArray) )
1179  {
1180  return undefined;
1181  }
1182 
1183  for ( watcher = 0; watcher < self.weaponObjectWatcherArray.size; watcher++ )
1184  {
1185  if ( self.weaponObjectWatcherArray[watcher].‪name == ‪name || (isdefined(self.weaponObjectWatcherArray[watcher].altName) && self.weaponObjectWatcherArray[watcher].altName == ‪name) )
1186  {
1187  return self.weaponObjectWatcherArray[watcher];
1188  }
1189  }
1190 
1191  return undefined;
1192 }
1193 
1194 function ‪getWeaponObjectWatcherByWeapon( weapon ) // self == player
1195 {
1196  if ( !isdefined(self.weaponObjectWatcherArray) )
1197  {
1198  return undefined;
1199  }
1200 
1201  if ( !isdefined( weapon ) )
1202  {
1203  return undefined;
1204  }
1205 
1206  for ( watcher = 0; watcher < self.weaponObjectWatcherArray.size; watcher++ )
1207  {
1208  if ( isdefined(self.weaponObjectWatcherArray[watcher].weapon) && ( self.weaponObjectWatcherArray[watcher].weapon == weapon || self.weaponObjectWatcherArray[watcher].weapon == weapon.rootWeapon ) )
1209  {
1210  return self.weaponObjectWatcherArray[watcher];
1211  }
1212  if ( isdefined(self.weaponObjectWatcherArray[watcher].weapon) && isdefined(self.weaponObjectWatcherArray[watcher].altWeapon) && self.weaponObjectWatcherArray[watcher].altWeapon == weapon )
1213  {
1214  return self.weaponObjectWatcherArray[watcher];
1215  }
1216  }
1217 
1218  return undefined;
1219 }
1220 
1221 function ‪resetWeaponObjectWatcher( watcher, ownerTeam )
1222 {
1223  if ( watcher.deleteOnPlayerSpawn == 1 || ( isdefined( watcher.ownerTeam ) && watcher.ownerTeam != ownerTeam ) )
1224  {
1225  self notify( "weapon_object_destroyed" );
1226  watcher ‪deleteWeaponObjectArray();
1227  }
1228 
1229  // player may have switched teams
1230  watcher.ownerTeam = ownerTeam;
1231 }
1232 
1233 function ‪createWeaponObjectWatcher( weaponname, ownerTeam )
1234 {
1235  if ( !isdefined(self.weaponObjectWatcherArray) )
1236  {
1237  self.weaponObjectWatcherArray = [];
1238  }
1239 
1240  weaponObjectWatcher = ‪getWeaponObjectWatcher( weaponname );
1241 
1242  if ( !isdefined( weaponObjectWatcher ) )
1243  {
1244  weaponObjectWatcher = SpawnStruct();
1245  self.weaponObjectWatcherArray[self.weaponObjectWatcherArray.size] = weaponObjectWatcher;
1246 
1247  weaponObjectWatcher.name = weaponname;
1248  weaponObjectWatcher.type = "use";
1249  weaponObjectWatcher.weapon = GetWeapon( weaponname );
1250  weaponObjectWatcher.watchForFire = false;
1251  weaponObjectWatcher.hackable = false;
1252  weaponObjectWatcher.altDetonate = false;
1253  weaponObjectWatcher.detectable = true;
1254  weaponObjectWatcher.headIcon = false;
1255  weaponObjectWatcher.stunTime = 0;
1256  weaponObjectWatcher.timeOut = 0;
1257  weaponObjectWatcher.destroyedByEmp = true;
1258  weaponObjectWatcher.activateSound = undefined;
1259  weaponObjectWatcher.ignoreDirection = undefined;
1260  weaponObjectWatcher.immediateDetonation = undefined;
1261  weaponObjectWatcher.deploySound = weaponObjectWatcher.weapon.firesound;
1262  weaponObjectWatcher.deploySoundPlayer = weaponObjectWatcher.weapon.firesoundplayer;
1263  weaponObjectWatcher.pickUpSound = weaponObjectWatcher.weapon.pickupsound;
1264  weaponObjectWatcher.pickUpSoundPlayer = weaponObjectWatcher.weapon.pickupsoundplayer;
1265  weaponObjectWatcher.altWeapon = weaponObjectWatcher.weapon.altweapon;
1266  weaponObjectWatcher.ownerGetsAssist = false;
1267  weaponObjectWatcher.playDestroyedDialog = true;
1268  weaponObjectWatcher.deleteOnKillbrush = true;
1269  weaponObjectWatcher.deleteOnDifferentObjectSpawn = true;
1270  weaponObjectWatcher.enemyDestroy = false;
1271  weaponObjectWatcher.deleteOnPlayerSpawn = level.deleteExplosivesOnSpawn;
1272  weaponObjectWatcher.ignoreVehicles = false;
1273  weaponObjectWatcher.ignoreAI = false;
1274  weaponObjectWatcher.activationDelay = 0;
1275 
1276  // callbacks
1277  weaponObjectWatcher.onSpawn = undefined;
1278  weaponObjectWatcher.onSpawnFX = undefined;
1279  weaponObjectWatcher.onSpawnRetrieveTriggers = undefined;
1280  weaponObjectWatcher.onDetonateCallback = undefined;
1281  weaponObjectWatcher.onStun = undefined;
1282  weaponObjectWatcher.onStunFinished = undefined;
1283  weaponObjectWatcher.onDestroyed = undefined;
1284  weaponObjectWatcher.onFizzleOut = &‪weaponobjects::weaponObjectFizzleOut;
1285  weaponObjectWatcher.shouldDamage = undefined;
1286  weaponObjectWatcher.onSupplementalDetonateCallback = undefined;
1287 
1288  if ( !isdefined( weaponObjectWatcher.objectArray ) )
1289  weaponObjectWatcher.objectArray = [];
1290  }
1291 
1292  ‪resetWeaponObjectWatcher( weaponObjectWatcher, ownerTeam );
1293 
1294  return weaponObjectWatcher;
1295 }
1296 
1297 function ‪createUseWeaponObjectWatcher( weaponname, ownerTeam )
1298 {
1299  weaponObjectWatcher = ‪createWeaponObjectWatcher( weaponname, ownerTeam );
1300 
1301  weaponObjectWatcher.type = "use";
1302  weaponObjectWatcher.onSpawn =&‪onSpawnUseWeaponObject;
1303 
1304  return weaponObjectWatcher;
1305 }
1306 
1307 function ‪createProximityWeaponObjectWatcher( weaponname, ownerTeam )
1308 {
1309  weaponObjectWatcher = ‪createWeaponObjectWatcher( weaponname, ownerTeam );
1310 
1311  weaponObjectWatcher.type = "proximity";
1312  weaponObjectWatcher.onSpawn =&‪onSpawnProximityWeaponObject;
1313 
1314  detectionConeAngle = GetDvarInt( "scr_weaponobject_coneangle" );
1315  weaponObjectWatcher.detectionDot = cos( detectionConeAngle );
1316  weaponObjectWatcher.detectionMinDist = GetDvarInt( "scr_weaponobject_mindist" );
1317  weaponObjectWatcher.detectionGracePeriod = GetDvarFloat( "scr_weaponobject_graceperiod" );
1318  weaponObjectWatcher.detonateRadius = GetDvarInt( "scr_weaponobject_radius" );
1319 
1320  return weaponObjectWatcher;
1321 }
1322 
1323 function ‪commonOnSpawnUseWeaponObject( watcher, owner ) // self == weapon (for example: the claymore)
1324 {
1325  level endon ( "game_ended" );
1326  self endon ( "death" );
1327  self endon ( "hacked" );
1328 
1329  if ( watcher.detectable )
1330  {
1331 // if ( isdefined(watcher.isMovable) && watcher.isMovable )
1332 // self thread weaponObjectDetectionMovable( owner.pers["team"] );
1333 // else
1334 // self thread weaponObjectDetectionTrigger_wait( owner.pers["team"] );
1335 
1336  if ( watcher.headIcon && level.teamBased )
1337  {
1339 
1340  if ( isdefined( self ) )
1341  {
1342  offset = self.weapon.weaponHeadObjectiveHeight;
1343 
1344  v_up = AnglesToUp( self.angles );
1345  x_offset = abs( v_up[0] );
1346  y_offset = abs( v_up[1] );
1347  z_offset = abs( v_up[2] );
1348 
1349  if( x_offset > y_offset && x_offset > z_offset )
1350  {
1351  //v_up = v_up * ( 1, 0, 0 );
1352  }
1353  else if( y_offset > x_offset && y_offset > z_offset )
1354  {
1355  //v_up = v_up * ( 0, 1, 0 );
1356  }
1357  else if( z_offset > x_offset && z_offset > y_offset )
1358  {
1359  v_up = v_up * ( 0, 0, 1 );
1360  }
1361 
1362  up_offset_modified = v_up * offset;
1363  up_offset = AnglesToUp( self.angles ) * offset;
1364 
1365  objective = GetEquipmentHeadObjective( self.weapon );
1366  self ‪entityheadicons::setEntityHeadIcon( owner.pers["team"], owner, up_offset, objective );
1367  }
1368  }
1369  }
1370 }
1371 
1373 {
1374  return isdefined( self.owner.ProximityAmlarmEnt ) && self.owner.ProximityAmlarmEnt == self;
1375 }
1376 
1377 function ‪ProximityAlarmActivate( active, watcher )
1378 {
1379  if ( !IsDefined( self.owner ) || !IsPlayer( self.owner ) )
1380  {
1381  return;
1382  }
1383 
1384  if ( active && !isdefined( self.owner.ProximityAmlarmEnt ) )
1385  {
1386  self.owner.ProximityAmlarmEnt = self;
1387  self.owner ‪clientfield::set_to_player( "proximity_alarm", ‪PROXIMITY_ALARM_ON );
1388  self.owner ‪clientfield::set_player_uimodel( "hudItems.proximityAlarm", ‪PROXIMITY_ALARM_ON );
1389  }
1390  else
1391  {
1392  if ( !isdefined( self ) || self ‪WasProximityAlarmActivatedBySelf() || self.owner ‪clientfield::get_to_player( "proximity_alarm" ) == ‪PROXIMITY_ALARM_DEPLOYED )
1393  {
1394  self.owner.ProximityAmlarmEnt = undefined;
1395  self.owner ‪clientfield::set_to_player( "proximity_alarm", ‪PROXIMITY_ALARM_OFF );
1396  self.owner ‪clientfield::set_player_uimodel( "hudItems.proximityAlarm", ‪PROXIMITY_ALARM_OFF );
1397  }
1398  }
1399 
1400 }
1401 
1402 function ‪ProximityAlarmLoop( watcher, owner ) // self == weapon entity (for example: the claymore)
1403 {
1404  level endon ( "game_ended" );
1405  self endon ( "death" );
1406  self endon ( "hacked" );
1407  self endon( "detonating" );
1408 
1409  if ( self.weapon.proximityalarminnerradius <= 0 )
1410  {
1411  return;
1412  }
1413 
1415 
1416  delayTimeSec = self.weapon.proximityalarmactivationdelay / 1000;
1417 
1418  if ( delayTimeSec > 0 )
1419  {
1420  wait delayTimeSec;
1421 
1422  if ( !IsDefined( self ) )
1423  {
1424  return;
1425  }
1426  }
1427 
1428  if( !‪IS_TRUE( self.owner._disable_proximity_alarms ) )
1429  {
1430  self.owner ‪clientfield::set_to_player( "proximity_alarm", ‪PROXIMITY_ALARM_DEPLOYED );
1431  self.owner ‪clientfield::set_player_uimodel( "hudItems.proximityAlarm", ‪PROXIMITY_ALARM_DEPLOYED );
1432  }
1433 
1434  self.proximity_deployed = true;
1435 
1436  alarmStatusOld = "notify";
1437  alarmStatus = "off";
1438 
1439  // this is executing for each equipment with proximity alarm
1440  // the loop will turn on/off the alarm
1441  // the loop will play proximityAlarmActivateSound when going from 'off' to 'on'
1442  while ( 1 )
1443  {
1444  wait( .05 );
1445 
1446  if ( !IsDefined( self.owner ) || !IsPlayer( self.owner ) )
1447  {
1448  return;
1449  }
1450 
1451  if ( IsAlive( self.owner ) == false && self.owner ‪util::isUsingRemote() == false )
1452  {
1453  self ‪ProximityAlarmActivate( false, watcher );
1454  return;
1455  }
1456 
1457  if( ‪IS_TRUE( self.owner._disable_proximity_alarms ) )
1458  {
1459  self ‪ProximityAlarmActivate( false, watcher );
1460  }
1461  else if ( (alarmStatus != alarmStatusOld) || (alarmStatus == "on" && !isdefined( self.owner.ProximityAmlarmEnt )) ) // check if there is a change in the alarm status
1462  {
1463  if ( alarmStatus == "on" )
1464  {
1465  // the alarm turns on if it was not already on
1466  if ( alarmStatusOld == "off" && isdefined( watcher ) && isdefined( watcher.proximityAlarmActivateSound ) )
1467  {
1468  // play alarm activated sound, plays only once even if more players come within range
1469  //self playsound( watcher.proximityAlarmActivateSound );
1470  //changed this playsound to the line below because the sound origin was slightly below ground and occluding the sound.
1471  playsoundatposition( watcher.proximityAlarmActivateSound , (self.origin + (0,0,32)) );
1472  }
1473 
1474  // turn on the alarm
1475  self ‪ProximityAlarmActivate( true, watcher );
1476  }
1477  else
1478  {
1479  // turn off the alarm
1480  self ‪ProximityAlarmActivate( false, watcher );
1481  }
1482 
1483  alarmStatusOld = alarmStatus;
1484  }
1485 
1486  alarmStatus = "off";
1487 
1488  actors = GetActorArray();
1489  players = Getplayers();
1490  detectEntities = arraycombine( players, actors, false, false );
1491 
1492  foreach ( entity in detectEntities )
1493  {
1494  wait( .05 ); // only handle 1 player per frame
1495 
1496  if ( !isdefined( entity ) )
1497  {
1498  continue;
1499  }
1500 
1501  owner = entity;
1502  if( IsActor( entity ) && ( !isDefined( entity.isAiClone ) || !entity.isAiClone ) )
1503  {
1504  continue;
1505  }
1506  else if( isActor( entity ) )
1507  {
1508  owner = entity.owner;
1509  }
1510 
1511  if ( entity.team == "spectator" )
1512  {
1513  continue;
1514  }
1515 
1516  if ( level.weaponObjectDebug != 1 )
1517  {
1518  if( owner HasPerk( "specialty_detectexplosive" ) )
1519  {
1520  continue;
1521  }
1522  if ( isdefined( self.owner ) && owner == self.owner )
1523  {
1524  continue;
1525  }
1526  if ( !‪friendlyFireCheck( self.owner, owner, 0 ) )
1527  {
1528  continue;
1529  }
1530  }
1531 
1532  if ( self isstunned() )
1533  continue;
1534 
1535  if( !IsAlive( entity ) )
1536  continue;
1537 
1538  if ( isdefined( watcher.immunespecialty ) && owner hasPerk( watcher.immunespecialty ) )
1539  continue;
1540 
1541  radius = self.weapon.proximityalarmouterradius;
1542  distanceSqr = DistanceSquared( self.origin, entity.origin );
1543 
1544  if ( radius * radius < distanceSqr )
1545  {
1546  // this player is outside outer radius
1547  continue;
1548  }
1549 
1550  if ( entity damageConeTrace( self.origin, self ) == 0 )
1551  {
1552  // this player cannot be damaged
1553  continue;
1554  }
1555 
1556  if ( alarmStatusOld == "on" )
1557  {
1558  // this player is inside outer radius and the alarm was already on
1559  alarmStatus = "on";
1560  break;
1561  }
1562 
1563  radius = self.weapon.proximityalarminnerradius;
1564 
1565  if ( radius * radius < distanceSqr )
1566  {
1567  // this player is not triggering the alarm
1568  continue;
1569  }
1570 
1571  // this player is inside the inner radius
1572  alarmStatus = "on";
1573  break;
1574  }
1575  }
1576 }
1577 
1578 // self is the entity with proximity alarm
1579 function ‪commonOnSpawnUseWeaponObjectProximityAlarm( watcher, owner ) // self == weapon entity (for example: the claymore)
1580 {
1581  /#
1582  if ( level.weaponObjectDebug == 1 )
1583  {
1584  self thread ‪proximityAlarmWeaponObjectDebug( watcher );
1585  }
1586  #/
1587 
1588  // waits until self is dead
1589  self ‪ProximityAlarmLoop( watcher, owner );
1590 
1591  // cleans up after self death
1592  self ‪ProximityAlarmActivate( false, watcher );
1593 
1594 
1595 }
1596 
1597 function ‪onSpawnUseWeaponObject( watcher, owner ) // self == weapon (for example: the claymore)
1598 {
1599  self thread ‪commonOnSpawnUseWeaponObject(watcher, owner);
1600  self thread ‪commonOnSpawnUseWeaponObjectProximityAlarm(watcher, owner);
1601 }
1602 
1603 function ‪onSpawnProximityWeaponObject( watcher, owner ) // self == weapon (for example: the claymore)
1604 {
1605  self.protected_entities = [];
1606 
1607  self thread ‪commonOnSpawnUseWeaponObject(watcher, owner);
1608 
1609  if ( isdefined( level._proximityWeaponObjectDetonation_override ) )
1610  {
1611  self thread [[level._proximityWeaponObjectDetonation_override]]( watcher );
1612  }
1613  else
1614  {
1615  self thread ‪proximityWeaponObjectDetonation( watcher );
1616  }
1617 
1618  /#
1619  if ( level.weaponObjectDebug == 1 )
1620  {
1621  self thread ‪proximityWeaponObjectDebug( watcher );
1622  }
1623  #/
1624 }
1625 
1626 function ‪watchWeaponObjectUsage() // self == player
1627 {
1628  self endon( "disconnect" );
1629 
1630  if ( !isdefined(self.weaponObjectWatcherArray) )
1631  {
1632  self.weaponObjectWatcherArray = [];
1633  }
1634 
1635  self thread ‪watchWeaponObjectSpawn( "grenade_fire" );
1636  self thread ‪watchWeaponObjectSpawn( "grenade_launcher_fire" );
1637  self thread ‪watchWeaponObjectSpawn( "missile_fire" );
1638  self thread ‪watchWeaponObjectDetonation();
1639  self thread ‪watchWeaponObjectAltDetonation();
1640  self thread ‪watchWeaponObjectAltDetonate();
1641  self thread ‪deleteWeaponObjectsOn();
1642 }
1643 
1644 // check for projectile type weapon objects spawning
1645 function ‪watchWeaponObjectSpawn( notify_type ) // self == player
1646 {
1647  self notify( "watchWeaponObjectSpawn_" + notify_type );
1648  self endon( "watchWeaponObjectSpawn_" + notify_type );
1649  self endon( "disconnect" );
1650 
1651  while(1)
1652  {
1653  self waittill( notify_type, weapon_instance, weapon );
1654 
1655  if( ( ‪IS_BONUSZM || ‪IS_TRUE( level.projectiles_should_ignore_world_pause ) ) && IsDefined( weapon_instance ) )
1656  {
1657  weapon_instance SetIgnorePauseWorld( true );
1658  }
1659 
1660  // need to increment the used stat for claymore and c4
1661  if ( weapon.setUsedStat && !self ‪util::isHacked() )
1662  {
1663  self AddWeaponStat( weapon, "used", 1 );
1664  }
1665 
1666  watcher = ‪getWeaponObjectWatcherByWeapon( weapon );
1667  if ( isdefined( watcher ) )
1668  {
1669  // remove any empty objects
1670  ‪cleanWeaponObjectArray( watcher );
1671 
1672  if ( weapon.maxinstancesallowed )
1673  {
1674  // This allows you to have only a certain number of this weapon object type in the world
1675  // Once you reach the max the first will "fizzle out".
1676  if( watcher.objectarray.size > (weapon.maxinstancesallowed - 1))
1677  {
1678  watcher thread ‪waitAndFizzleOut( watcher.objectarray[0], 0.1 );
1679  watcher.objectarray[0] = undefined;
1680 
1681  ‪cleanWeaponObjectArray( watcher );
1682  }
1683  }
1684 
1685  self ‪addWeaponObject( watcher, weapon_instance );
1686  }
1687  }
1688 }
1689 
1690 function ‪anyObjectsInWorld( weapon )
1691 {
1692  objectsInWorld = false;
1693  for( i = 0; i < self.weaponObjectWatcherArray.size; i++)
1694  {
1695  if( self.weaponObjectWatcherArray[i].weapon != weapon )
1696  continue;
1697 
1698  if( isdefined( self.weaponObjectWatcherArray[i].onDetonateCallback ) && self.weaponObjectWatcherArray[i].objectarray.size > 0 )
1699  {
1700  objectsInWorld = true;
1701  break;
1702  }
1703  }
1704  return objectsInWorld;
1705 }
1706 
1707 /#
1708 function ‪proximitySphere( origin, innerRadius, inColor, outerRadius, outColor )
1709 {
1710  self endon("death");
1711 
1712  while(1)
1713  {
1714  if ( isdefined( innerRadius ) )
1715  {
1716  ‪util::debug_sphere( origin, innerRadius, inColor, 0.25, 1 ); // inner
1717  }
1718 
1719  if ( isdefined( outerRadius ) )
1720  {
1721  ‪util::debug_sphere( origin, outerRadius, outColor, 0.25, 1 ); // outer
1722  }
1723 
1724  wait .05;
1725  }
1726 }
1727 
1729 {
1730  self endon("death");
1731 
1733 
1734  if ( !isdefined( self ) )
1735  {
1736  return;
1737  }
1738 
1739  self thread ‪proximitySphere( self.origin, self.weapon.proximityalarminnerradius, (0,0.75,0), self.weapon.proximityalarmouterradius, (0,0.75,0) );
1740 }
1741 
1743 {
1744  self endon("death");
1745 
1747 
1748  if ( !isdefined( self ) )
1749  {
1750  return;
1751  }
1752 
1753  if( isdefined( watcher.ignoreDirection ) )
1754  {
1755  self thread ‪proximitySphere( self.origin, watcher.detonateRadius, (1,.85,0), self.weapon.explosionRadius, (1,0,0) );
1756  }
1757  else
1758  {
1759  self thread ‪showCone( acos( watcher.detectionDot ), watcher.detonateRadius, (1,.85,0) );
1760  self thread ‪showCone( 60, 256, (1,0,0) );
1761  }
1762 }
1763 
1764 function ‪showCone( angle, range, color )
1765 {
1766  self endon("death");
1767 
1768  start = self.origin;
1769  forward = anglestoforward(self.angles);
1770  right = vectorcross( forward, (0,0,1) );
1771  up = vectorcross( forward, right );
1772 
1773  fullforward = forward * range * cos( angle );
1774  sideamnt = range * sin( angle );
1775 
1776  while(1)
1777  {
1778  prevpoint = (0,0,0);
1779  for ( i = 0; i <= 20; i++ )
1780  {
1781  coneangle = i/20.0 * 360;
1782  point = start + fullforward + sideamnt * (right * cos(coneangle) + up * sin(coneangle));
1783  if ( i > 0 )
1784  {
1785  line( start, point, color );
1786  line( prevpoint, point, color );
1787  }
1788  prevpoint = point;
1789  }
1790  wait .05;
1791  }
1792 }
1793 #/
1794 
1795 function ‪weaponObjectDetectionMovable( ownerTeam ) // self == weapon (for example: the claymore)
1796 {
1797  self endon ( "end_detection" );
1798  level endon ( "game_ended" );
1799  self endon ( "death" );
1800  self endon ( "hacked" );
1801 
1802  if ( !level.teambased )
1803  return;
1804 
1805  self.detectId = "rcBomb" + getTime() + randomInt( 1000000 );
1806 }
1807 
1808 
1809 function ‪setIconPos( item, icon, heightIncrease )
1810 {
1811  icon.x = item.origin[0];
1812  icon.y = item.origin[1];
1813  icon.z = item.origin[2]+heightIncrease;
1814 }
1815 
1816 function ‪weaponObjectDetectionTrigger_wait( ownerTeam ) // self == weapon (for example: the claymore)
1817 {
1818  self endon ( "death" );
1819  self endon ( "hacked" );
1820  self endon( "detonating" );
1821 
1823 
1824  self thread ‪weaponObjectDetectionTrigger( ownerTeam );
1825 }
1826 
1827 function ‪weaponObjectDetectionTrigger( ownerTeam ) // self == weapon (for example: the claymore)
1828 {
1829  trigger = ‪spawn( "trigger_radius", self.origin-(0,0,128), 0, 512, 256 );
1830  trigger.detectId = "trigger" + getTime() + randomInt( 1000000 );
1831 
1832  trigger SetHintLowPriority( true );
1833 
1834  self ‪util::waittill_any( "death", "hacked", "detonating" );
1835  trigger notify ( "end_detection" );
1836 
1837  if ( isdefined( trigger.bombSquadIcon ) )
1838  trigger.bombSquadIcon ‪destroy();
1839 
1840  trigger delete();
1841 }
1842 
1844 {
1845  self endon( "death" );
1846 
1847  assert( IsPlayer( owner ) );
1848 
1849  ownerTeam = owner.pers["team"];
1850 
1851  for ( ;; )
1852  {
1853  if ( level.teamBased && isdefined( ownerTeam ) )
1854  {
1855  self SetVisibleToAllExceptTeam( ownerTeam );
1856  self SetExcludeTeamForTrigger( ownerTeam );
1857  }
1858  else
1859  {
1860  self SetVisibleToAll();
1861  self SetTeamForTrigger( "none" );
1862  }
1863 
1864  if ( isdefined( owner ) )
1865  {
1866  self SetInvisibleToPlayer( owner );
1867  }
1868 
1869  level ‪util::waittill_any( "player_spawned", "joined_team" );
1870  }
1871 }
1872 
1874 {
1875  self endon( "death" );
1877  self notify( "landed" );
1878 }
1879 
1880 function ‪hackerInit( watcher )
1881 {
1882  self thread ‪hackerNotMoving();
1883 
1884  event = self ‪util::waittill_any_return( "death", "landed" );
1885 
1886  if ( event == "death" )
1887  {
1888  return;
1889  }
1890 
1891  triggerOrigin = self.origin;
1892  if ( "" != self.weapon.hackerTriggerOriginTag )
1893  {
1894  triggerOrigin = self GetTagOrigin( self.weapon.hackerTriggerOriginTag );
1895  }
1896 
1897  // set up a trigger for a hacker
1898  self.hackerTrigger = ‪spawn( "trigger_radius_use", triggerOrigin, level.weaponobjects_hacker_trigger_width, level.weaponobjects_hacker_trigger_height );
1899 
1900  /#
1901  //_teargrenades::drawcylinder( self.hackerTrigger.origin, level.weaponobjects_hacker_trigger_width, level.weaponobjects_hacker_trigger_height, 0, "hacker_debug" );
1902  #/
1903 
1904  self.hackerTrigger SetHintLowPriority( true );
1905  self.hackerTrigger SetCursorHint( "HINT_NOICON", self );
1906  self.hackerTrigger SetIgnoreEntForTrigger( self );
1907 
1908  self.hackerTrigger EnableLinkTo();
1909  self.hackerTrigger LinkTo( self );
1910 
1911  if( isdefined( level.hackerHints[self.weapon.name] ) )
1912  {
1913  self.hackerTrigger SetHintString( level.hackerHints[self.weapon.name].hint );
1914  }
1915  else
1916  {
1917  self.hackerTrigger SetHintString( &"MP_GENERIC_HACKING" );
1918  }
1919 
1920 
1921  self.hackerTrigger SetPerkForTrigger( "specialty_disarmexplosive" );
1922  self.hackerTrigger thread ‪hackerTriggerSetVisibility( self.owner );
1923 
1924  self thread ‪hackerThink( self.hackerTrigger, watcher );
1925 }
1926 
1927 function ‪hackerThink( trigger, watcher ) // self == weapon_instance
1928 {
1929  self endon( "death" );
1930 
1931  for ( ;; )
1932  {
1933  trigger waittill( "trigger", player, instant );
1934 
1935  if ( !isdefined( instant ) && !trigger ‪hackerResult( player, self.owner ) )
1936  {
1937  continue;
1938  }
1939 
1940  self ‪ItemHacked( watcher, player );
1941 
1942  // the hacker thread will be respawned with the new owner, this thread can be killed
1943  return;
1944  }
1945 }
1946 
1947 function ‪ItemHacked( watcher, player )
1948 {
1949  self ‪ProximityAlarmActivate( false, watcher );
1950 
1951  self.owner ‪hackerRemoveWeapon( self );
1952 
1953  if( isdefined( level.playEquipmentHackedOnPlayer ) )
1954  {
1955  self.owner [[level.playEquipmentHackedOnPlayer]]( );
1956  }
1957 
1958  if ( self.weapon.ammoCountEquipment > 0 && isdefined( self.ammo ) )
1959  {
1960  ammoLeftEquipment = self.ammo;
1961 
1962  if ( self.weapon.rootWeapon == GetWeapon( "trophy_system" ) )
1963  {
1964  player ‪trophy_system::ammo_weapon_hacked( ammoLeftEquipment );
1965  }
1966  }
1967 
1968  self.hacked = true;
1969  self SetMissileOwner( player );
1970  self SetTeam( player.pers["team"] );
1971  self.owner = player;
1972  self ‪clientfield::set( "retrievable", 0 );
1973 
1974  if ( self.weapon.doHackedStats )
1975  {
1976  ‪scoreevents::processScoreEvent( "hacked", player );
1977  player AddWeaponStat( GetWeapon( "pda_hack" ), "CombatRecordStat", 1 );
1978 
1980  }
1981 
1982  // detonation info for the C4
1983  if ( self.weapon.rootWeapon == level.weaponSatchelCharge && isdefined( player.lowerMessage ) )
1984  {
1985  player.lowerMessage SetText( &"PLATFORM_SATCHEL_CHARGE_DOUBLE_TAP" );
1986  player.lowerMessage.alpha = 1;
1987  player.lowerMessage FadeOverTime( 2.0 );
1988  player.lowerMessage.alpha = 0;
1989  }
1990 
1991  // kill the previous owner's threads
1992  self notify( "hacked", player );
1993  level notify( "hacked", self, player );
1994 
1995  if ( isdefined( self.cameraHead ) )
1996  {
1997  self.cameraHead notify( "hacked", player );
1998  }
1999 
2000  /#
2001  //level notify ( "hacker_debug" );
2002  #/
2003 
2004  ‪WAIT_SERVER_FRAME; // let current threads clean up from the 'hacked' notify
2005 
2006  if ( isdefined( player ) && player.sessionstate == "playing" )
2007  {
2008  // this will re-initialize the watcher system for this equipment
2009  player notify( "grenade_fire", self, self.weapon, true );
2010  }
2011  else
2012  {
2013  watcher thread ‪waitAndDetonate( self, 0.0, undefined, self.weapon );
2014  }
2015 }
2016 
2017 function ‪hackerUnfreezePlayer( player )
2018 {
2019  self endon( "hack_done" );
2020  self waittill( "death" );
2021 
2022  if ( isdefined( player ) )
2023  {
2024  player ‪util::freeze_player_controls( false );
2025  player EnableWeapons();
2026  }
2027 }
2028 
2029 function ‪hackerResult( player, owner ) // self == trigger_radius
2030 {
2031  success = true;
2032  time = GetTime();
2033  hackTime = GetDvarfloat( "perk_disarmExplosiveTime" );
2034 
2035  if ( !‪canHack( player, owner, true ) )
2036  {
2037  return false;
2038  }
2039 
2040  self thread ‪hackerUnfreezePlayer( player );
2041 
2042  while ( time + ( hackTime * 1000 ) > GetTime() )
2043  {
2044  if ( !‪canHack( player, owner, false ) )
2045  {
2046  success = false;
2047  break;
2048  }
2049 
2050  if ( !player UseButtonPressed() )
2051  {
2052  success = false;
2053  break;
2054  }
2055 
2056  if ( !isdefined( self ) )
2057  {
2058  success = false;
2059  break;
2060  }
2061 
2062  /*
2063  if ( !player IsTouching( self ) )
2064  {
2065  success = false;
2066  break;
2067  }
2068  */
2069 
2070  player ‪util::freeze_player_controls( true );
2071  player DisableWeapons();
2072 
2073  if ( !isdefined( self.progressBar ) )
2074  {
2075  self.progressBar = player ‪hud::createPrimaryProgressBar();
2076  self.progressBar.lastUseRate = -1;
2077  self.progressBar ‪hud::showElem();
2078  self.progressBar ‪hud::updateBar( 0.01, 1 / hackTime );
2079 
2080  self.progressText = player ‪hud::createPrimaryProgressBarText();
2081  self.progressText setText( &"MP_HACKING" );
2082  self.progressText ‪hud::showElem();
2083  player PlayLocalSound ( "evt_hacker_hacking" );
2084  }
2085 
2087  }
2088 
2089  if ( isdefined( player ) )
2090  {
2091  player ‪util::freeze_player_controls( false );
2092  player EnableWeapons();
2093  }
2094 
2095  if ( isdefined( self.progressBar ) )
2096  {
2097  self.progressBar ‪hud::destroyElem();
2098  self.progressText ‪hud::destroyElem();
2099  }
2100 
2101  if ( isdefined( self ) )
2102  {
2103  self notify( "hack_done" );
2104  }
2105 
2106  return success;
2107 }
2108 
2109 function ‪canHack( player, owner, weapon_check )
2110 {
2111  if ( !isdefined( player ) )
2112  return false;
2113 
2114  if ( !IsPlayer( player ) )
2115  return false;
2116 
2117  if ( !IsAlive( player ) )
2118  return false;
2119 
2120  if ( !isdefined( owner ) )
2121  return false;
2122 
2123  if ( owner == player )
2124  return false;
2125 
2126  if ( level.teambased && player.team == owner.team )
2127  return false;
2128 
2129  if ( ( isdefined( player.isDefusing ) && player.isDefusing ) )
2130  return false;
2131 
2132  if ( ( isdefined( player.isPlanting ) && player.isPlanting ) )
2133  return false;
2134 
2135  if ( isdefined( player.proxBar ) && !player.proxBar.hidden )
2136  return false;
2137 
2138  if ( isdefined( player.revivingTeammate ) && player.revivingTeammate == true )
2139  return false;
2140 
2141  if ( !player IsOnGround() )
2142  return false;
2143 
2144  if ( player IsInVehicle() )
2145  return false;
2146 
2147  if ( player IsWeaponViewOnlyLinked() )
2148  return false;
2149 
2150  if ( !player HasPerk( "specialty_disarmexplosive" ) )
2151  return false;
2152 
2153  if ( player IsEMPJammed() )
2154  return false;
2155 
2156  if ( isdefined( player.laststand ) && player.laststand )
2157  return false;
2158 
2159  if ( weapon_check )
2160  {
2161  if ( player IsThrowingGrenade() )
2162  return false;
2163 
2164  if ( player IsSwitchingWeapons() )
2165  return false;
2166 
2167  if ( player IsMeleeing() )
2168  return false;
2169 
2170  weapon = player GetCurrentWeapon();
2171 
2172  if ( !isdefined( weapon ) )
2173  return false;
2174 
2175  if ( weapon == level.weaponNone )
2176  return false;
2177 
2178  if ( weapon.isEquipment && player IsFiring() )
2179  return false;
2180 
2181  if ( weapon.isSpecificUse )
2182  return false;
2183  }
2184 
2185  return true;
2186 }
2187 
2188 function ‪hackerRemoveWeapon( weapon_instance )
2189 {
2190  for( i = 0; i < self.weaponObjectWatcherArray.size; i++)
2191  {
2192  if( self.weaponObjectWatcherArray[i].weapon != weapon_instance.weapon.rootWeapon )
2193  {
2194  continue;
2195  }
2196 
2197  // remove any empty objects and the hacked object
2198  ‪removeWeaponObject( self.weaponObjectWatcherArray[i], weapon_instance );
2199 
2200  return;
2201  }
2202 }
2203 
2205 {
2206  damagearea = ‪spawn("trigger_radius", self.origin + (0,0,0-watcher.detonateRadius), level.aiTriggerSpawnFlags | level.vehicleTriggerSpawnFlags, watcher.detonateRadius, watcher.detonateRadius*2);
2207  damagearea EnableLinkTo();
2208  damagearea LinkTo( self );
2209 
2210  self thread ‪deleteOnDeath( damagearea );
2211 
2212  return damagearea;
2213 }
2214 
2216 {
2217  if ( level.weaponObjectDebug != 1 )
2218  {
2219  if ( isdefined( self.owner ) && ent == self.owner )
2220  return false;
2221  if ( IsVehicle( ent ) )
2222  {
2223  if ( watcher.ignoreVehicles )
2224  return false;
2225 
2226  if ( self.owner === ent.owner ) // owner's own vehicle
2227  return false;
2228  }
2229 
2230  if ( !‪friendlyFireCheck( self.owner, ent, 0 ) )
2231  return false;
2232 
2233  if ( watcher.ignoreVehicles && IsAI( ent ) && !‪IS_TRUE( ent.isAiClone ) )
2234  return false;
2235  }
2236  if ( ( lengthsquared( ent getVelocity() ) < 10 ) && !isdefined( watcher.immediateDetonation ) )
2237  return false;
2238 
2239  if ( !ent ‪shouldAffectWeaponObject( self, watcher ) )
2240  return false;
2241 
2242  if ( self isstunned() )
2243  return false;
2244 
2245  if( IsPlayer( ent ) )
2246  {
2247  if ( !IsAlive(ent) ) //Make sure player watching their killcam won't set it off
2248  return false;
2249 
2250  if ( isdefined( watcher.immunespecialty ) && ent hasPerk( watcher.immunespecialty ) )
2251  return false;
2252  }
2253 
2254  return true;
2255 }
2256 
2258 {
2259  self endon("death");
2260 
2261  ent ‪util::waittill_any("death", "disconnected");
2262 
2263  ArrayRemoveValue( self.protected_entities, ent );
2264 }
2265 
2267 {
2268  self endon("death");
2269  ent endon("death");
2270  ent endon("disconnect");
2271 
2272  self.protected_entities[self.protected_entities.size] = ent;
2273 
2274  // this function will not get cleaned up until either ent dies which should not cause problems
2276 
2277  radius_sqr = watcher.detonateRadius * watcher.detonateRadius;
2278 
2279  while ( 1 )
2280  {
2281  if ( DistanceSquared( ent.origin, self.origin ) > radius_sqr )
2282  {
2283  ArrayRemoveValue( self.protected_entities, ent );
2284  return;
2285  }
2286 
2287  wait( 0.5 );
2288  }
2289 }
2290 
2292 {
2293  if( !IsPlayer( ent ) )
2294  return false;
2295 
2296  foreach( protected_ent in self.protected_entities )
2297  {
2298  if ( protected_ent == ent )
2299  return true;
2300  }
2301 
2302  linked_to = self GetLinkedEnt();
2303  if (linked_to === ent )
2304  return false;
2305 
2306  if ( ent ‪player::is_spawn_protected() )
2307  {
2308  self thread ‪proximityWeaponObject_SpawnProtect( watcher, ent );
2309  return true;
2310  }
2311 
2312  return false;
2313 }
2314 
2315 function ‪proximityWeaponObject_DoDetonation( watcher, ent, traceOrigin )
2316 {
2317  self endon( "death" );
2318  self endon( "hacked" );
2319 
2320  self notify( "kill_target_detection" );
2321 
2322  if ( isdefined(watcher.activateSound) )
2323  {
2324  self playsound (watcher.activateSound);
2325  }
2326 
2327  wait watcher.detectionGracePeriod;
2328 
2329  if ( IsPlayer( ent ) && ent HasPerk( "specialty_delayexplosive" ) )
2330  {
2331  wait( GetDvarfloat( "perk_delayExplosiveTime" ) );
2332  }
2333 
2335 
2336  // move up one unit
2337  self.origin = traceOrigin;
2338 
2339  if ( isdefined( self.owner ) && isplayer( self.owner ) )
2340  {
2341  self [[watcher.onDetonateCallback]]( self.owner, undefined, ent );
2342  }
2343  else
2344  {
2345  self [[watcher.onDetonateCallback]]( undefined, undefined, ent );
2346  }
2347 }
2348 
2350 {
2352 
2353  if ( watcher.activationDelay )
2354  {
2355  wait( watcher.activationDelay );
2356  }
2357 }
2358 
2360 {
2361  self endon( "death" );
2362 
2363  dist = Distance( ent.origin, self.origin );
2364 
2365  if ( isdefined( self.activated_entity_distance ) )
2366  {
2367  if ( dist < self.activated_entity_distance )
2368  {
2369  // this is a closer target
2370  self notify( "better_target" );
2371  }
2372  else
2373  {
2374  // the other target was better
2375  return;
2376  }
2377  }
2378 
2379  self endon( "better_target" );
2380  self.activated_entity_distance = dist;
2381 
2382  // this allows anything that is in the trigger to have a chance to be the target
2383  // so we can pick the closest instead of just picking the first numerically
2384  wait(0.05);
2385 
2386  ‪proximityWeaponObject_DoDetonation( watcher, ent, traceOrigin );
2387 }
2388 
2390 {
2391  self endon( "death" );
2392  self endon( "hacked" );
2393  self endon( "kill_target_detection" );
2394 
2396 
2397  damagearea = ‪proximityWeaponObject_CreateDamageArea( watcher );
2398 
2399  up = AnglesToUp( self.angles );
2400  traceOrigin = self.origin + up;
2401 
2402  while(1)
2403  {
2404  damagearea waittill("trigger", ent);
2405 
2406  if ( !‪proximityWeaponObject_ValidTriggerEntity( watcher, ent ) )
2407  continue;
2408 
2409  if ( ‪proximityWeaponObject_IsSpawnProtected( watcher, ent ) )
2410  continue;
2411 
2412  if ( ent damageConeTrace( traceOrigin, self ) > 0 )
2413  {
2414  thread ‪proximityWeaponObject_WaitTillFrameEndAndDoDetonation( watcher, ent, traceOrigin );
2415  }
2416  }
2417 }
2418 
2419 function ‪shouldAffectWeaponObject( object, watcher )
2420 {
2421  radius = object.weapon.explosionRadius;
2422  distanceSqr = DistanceSquared( self.origin, object.origin );
2423 
2424  // this fixes an issue where if the object is above head height
2425  // the players head can set it off but the radius damage check
2426  // looks at the origin of the player
2427  if ( radius * radius < distanceSqr )
2428  return false;
2429 
2430  pos = self.origin + (0,0,32);
2431 
2432  if( isdefined( watcher.ignoreDirection ) )
2433  {
2434  return true;
2435  }
2436 
2437  dirToPos = pos - object.origin;
2438  objectForward = anglesToForward( object.angles );
2439 
2440  dist = vectorDot( dirToPos, objectForward );
2441  if ( dist < watcher.detectionMinDist )
2442  return false;
2443 
2444  dirToPos = vectornormalize( dirToPos );
2445 
2446  dot = vectorDot( dirToPos, objectForward );
2447  return ( dot > watcher.detectionDot );
2448 }
2449 
2450 function ‪deleteOnDeath(ent)
2451 {
2452  self ‪util::waittill_any("death", "hacked");
2453  wait .05;
2454  if ( isdefined(ent) )
2455  ent delete();
2456 }
2457 
2458 function ‪testKillbrushOnStationary( a_killbrushes, player ) // self == weaponobject
2459 {
2460  player endon( "disconnect" );
2461  self endon( "death" );
2462 
2463  self waittill( "stationary" );
2464 
2465  foreach ( trig in a_killbrushes )
2466  {
2467  if ( isdefined( trig ) && self IsTouching( trig ) )
2468  {
2469  if ( !trig IsTriggerEnabled() )
2470  {
2471  continue;
2472  }
2473 
2475  {
2476  continue;
2477  }
2478 
2479  if ( self.origin[ 2 ] > player.origin[ 2 ] )
2480  {
2481  break;
2482  }
2483 
2484  if ( isdefined( self ) )
2485  {
2486  self delete();
2487  }
2488 
2489  return;
2490  }
2491  }
2492 }
2493 
2494 function ‪deleteOnKillbrush(player)
2495 {
2496  player endon( "disconnect" );
2497  self endon( "death" );
2498  self endon( "stationary" );
2499 
2500  a_killbrushes = GetEntArray( "trigger_hurt","classname" );
2501 
2502  self thread ‪testKillbrushOnStationary( a_killbrushes, player );
2503 
2504  while( 1 )
2505  {
2506  a_killbrushes = GetEntArray( "trigger_hurt","classname" );
2507 
2508  for ( i = 0; i < a_killbrushes.size; i++)
2509  {
2510  if ( self IsTouching( a_killbrushes[ i ] ) )
2511  {
2512  if ( !a_killbrushes[ i ] IsTriggerEnabled() )
2513  {
2514  continue;
2515  }
2516 
2518  {
2519  continue;
2520  }
2521 
2522  if( self.origin[ 2 ] > player.origin[ 2 ] )
2523  {
2524  break;
2525  }
2526 
2527  if ( isdefined( self ) )
2528  {
2529  self delete();
2530  }
2531 
2532  return;
2533  }
2534  }
2535 
2536  wait 0.1;
2537  }
2538 }
2539 
2540 
2541 function ‪watchWeaponObjectAltDetonation() // self == player
2542 {
2543  self endon("disconnect");
2544 
2545  while( 1 )
2546  {
2547  self waittill( "alt_detonate" );
2548 
2549  if ( !IsAlive( self ) || ( self ‪util::isUsingRemote() ) )
2550  {
2551  continue;
2552  }
2553 
2554  for ( watcher = 0; watcher < self.weaponObjectWatcherArray.size; watcher++ )
2555  {
2556  if ( self.weaponObjectWatcherArray[watcher].altDetonate )
2557  {
2558  self.weaponObjectWatcherArray[watcher] ‪detonateWeaponObjectArray( false );
2559  }
2560  }
2561  }
2562 }
2563 
2564 
2565 function ‪watchWeaponObjectAltDetonate() // self == player
2566 {
2567  self endon( "disconnect" );
2568  level endon( "game_ended" );
2569 
2570  buttonTime = 0;
2571  for( ;; )
2572  {
2573  self waittill( "doubletap_detonate" );
2574 
2575  if ( !IsAlive( self ) && !( self ‪util::isUsingRemote() ) )
2576  {
2577  continue;
2578  }
2579 
2580  self notify ( "alt_detonate" );
2581 
2583  }
2584 }
2585 
2586 function ‪watchWeaponObjectDetonation() // self == player
2587 {
2588  self endon( "disconnect" );
2589 
2590  while( 1 )
2591  {
2592  self waittill( "detonate" );
2593 
2594  if ( self isUsingOffhand() )
2595  {
2596  weap = self getCurrentOffhand();
2597  }
2598  else
2599  {
2600  weap = self getCurrentWeapon();
2601  }
2602 
2603  watcher = ‪getWeaponObjectWatcherByWeapon( weap );
2604 
2605  if ( isdefined( watcher ) )
2606  {
2607  if ( isdefined( watcher.onDetonationHandle ) )
2608  {
2609  self thread [[watcher.onDetonationHandle]]( watcher );
2610  }
2611 
2612  watcher ‪detonateWeaponObjectArray( false );
2613  }
2614  }
2615 }
2616 
2618 {
2619  if ( !isdefined(self.weaponObjectWatcherArray) )
2620  {
2621  assert( "Can't clean Up watechers" );
2622  return;
2623  }
2624 
2625  watchers = [];
2626 
2627  // make a psudo copy of the watchers out of the player
2628  // so that when the player ent gets cleaned we still have
2629  // the object arrays to clean up
2630  for ( watcher = 0; watcher < self.weaponObjectWatcherArray.size; watcher++ )
2631  {
2632  weaponObjectWatcher = SpawnStruct();
2633  watchers[watchers.size] = weaponObjectWatcher;
2634  weaponObjectWatcher.objectArray = [];
2635 
2636  if ( isdefined( self.weaponObjectWatcherArray[watcher].objectArray ) )
2637  {
2638  weaponObjectWatcher.objectArray = self.weaponObjectWatcherArray[watcher].objectArray;
2639  }
2640  }
2641 
2642  wait .05;
2643 
2644  for ( watcher = 0; watcher < watchers.size; watcher++ )
2645  {
2646  watchers[watcher] ‪deleteWeaponObjectArray();
2647  }
2648 }
2649 
2650 
2652 {
2653  self waittill( "disconnect" );
2654 
2656 }
2657 
2658 function ‪deleteWeaponObjectsOn() // self == player
2659 {
2660  self thread ‪watchForDisconnectCleanUp();
2661 
2662  self endon( "disconnect" );
2663 
2664  if( !isPlayer( self ))
2665  {
2666  return;
2667  }
2668 
2669  while(1)
2670  {
2671  msg = self ‪util::waittill_any_return( "joined_team", "joined_spectators", "death", "disconnect" );
2672 
2673  // only need this because util::waittill_any_return will endon death if we dont pass it in
2674  if ( msg == "death" )
2675  continue;
2676 
2678  }
2679 }
2680 
2681 function ‪saydamaged(orig, amount)
2682 {
2683  /#
2684  for (i = 0; i < 60; i++)
2685  {
2686  print3d(orig, "damaged! " + amount);
2687  wait .05;
2688  }
2689  #/
2690 }
2691 
2692 function ‪showHeadIcon( trigger )
2693 {
2694  triggerDetectId = trigger.detectId;
2695  useId = -1;
2696  for ( index = 0; index < 4; index++ )
2697  {
2698  detectId = self.bombSquadIcons[index].detectId;
2699 
2700  if ( detectId == triggerDetectId )
2701  return;
2702 
2703  if ( detectId == "" )
2704  useId = index;
2705  }
2706 
2707  if ( useId < 0 )
2708  return;
2709 
2710  self.bombSquadIds[triggerDetectId] = true;
2711 
2712  self.bombSquadIcons[useId].x = trigger.origin[0];
2713  self.bombSquadIcons[useId].y = trigger.origin[1];
2714  self.bombSquadIcons[useId].z = trigger.origin[2]+24+128;
2715 
2716  self.bombSquadIcons[useId] fadeOverTime( 0.25 );
2717  self.bombSquadIcons[useId].alpha = 1;
2718  self.bombSquadIcons[useId].detectId = trigger.detectId;
2719 
2720  while ( isAlive( self ) && isdefined( trigger ) && self isTouching( trigger ) )
2722 
2723  if ( !isdefined( self ) )
2724  return;
2725 
2726  self.bombSquadIcons[useId].detectId = "";
2727  self.bombSquadIcons[useId] fadeOverTime( 0.25 );
2728  self.bombSquadIcons[useId].alpha = 0;
2729  self.bombSquadIds[triggerDetectId] = undefined;
2730 }
2731 
2732 // returns true if damage should be done to the item given its owner and the attacker
2733 function ‪friendlyFireCheck( owner, attacker, forcedFriendlyFireRule )
2734 {
2735  if ( !isdefined(owner) ) // owner has disconnected? allow it
2736  return true;
2737 
2738  if ( !level.teamBased ) // not a team based mode? allow it
2739  return true;
2740 
2741  friendlyFireRule = [[ level.figure_out_friendly_fire ]]( undefined ); // there is no victim here
2742  if ( isdefined( forcedFriendlyFireRule ) )
2743  friendlyFireRule = forcedFriendlyFireRule;
2744 
2745  if ( friendlyFireRule != 0 ) // friendly fire is on? allow it
2746  return true;
2747 
2748  if ( attacker == owner ) // owner may attack his own items
2749  return true;
2750 
2751  if ( isplayer( attacker ) )
2752  {
2753  if ( !isdefined(attacker.pers["team"])) // attacker not on a team? allow it
2754  return true;
2755 
2756  if ( attacker.pers["team"] != owner.pers["team"] ) // attacker not on the same team as the owner? allow it
2757  return true;
2758  }
2759  else if ( IsActor(attacker) )
2760  {
2761  if ( attacker.team != owner.pers["team"] ) // attacker not on the same team as the owner? allow it
2762  return true;
2763  }
2764  else if ( isvehicle( attacker ) )
2765  {
2766  if ( isdefined(attacker.owner) && IsPlayer(attacker.owner) )
2767  {
2768  if ( attacker.owner.pers["team"] != owner.pers["team"] )
2769  return true;
2770  }
2771  else
2772  {
2773  occupant_team = attacker vehicle::vehicle_get_occupant_team();
2774  if ( occupant_team != owner.pers["team"] && occupant_team != "spectator" ) // attacker not on the same team as the owner? allow it
2775  return true;
2776  }
2777  }
2778 
2779  return false; // disallow it
2780 }
2781 
2782 function ‪onSpawnHatchet( watcher, player )
2783 {
2784  if ( isdefined( level.playThrowHatchet ) )
2785  {
2786  player [[level.playThrowHatchet]]();
2787  }
2788 }
2789 
2790 function ‪onSpawnCrossbowBolt( watcher, player )
2791 {
2792  self.delete_on_death = true;
2793  self thread ‪onSpawnCrossbowBolt_internal( watcher, player );
2794 }
2795 
2796 function ‪onSpawnCrossbowBolt_internal( watcher, player )
2797 {
2798  player endon( "disconnect" );
2799  self endon( "death" );
2800 
2801  wait 0.25; // wait before setting takedamage
2802 
2803  linkedEnt = self GetLinkedEnt();
2804  if ( !isdefined( linkedEnt ) || !IsVehicle( linkedEnt ) )
2805  {
2806  self.takedamage = false;
2807  }
2808  else
2809  {
2810  self.takedamage = true;
2811 
2812  if ( IsVehicle( linkedEnt ) )
2813  {
2814  self thread ‪dieOnEntityDeath( linkedEnt, player );
2815  }
2816  }
2817 }
2818 
2819 function ‪dieOnEntityDeath( entity, player )
2820 {
2821  player endon( "disconnect" );
2822  self endon( "death" );
2823 
2824  alreadyDead = ( ( entity.dead === true ) || ( isdefined( entity.health ) && entity.health < 0 ) );
2825 
2826  if ( !alreadyDead )
2827  {
2828  entity waittill( "death" );
2829  }
2830 
2831  self notify( "death" );
2832 }
2833 
2834 function ‪onSpawnCrossbowBoltImpact( s_watcher, e_player )
2835 {
2836  self.delete_on_death = true;
2837  self thread ‪onSpawnCrossbowBoltImpact_internal( s_watcher, e_player );
2838 }
2839 
2840 // PORTIZ 7/5/16: crossbow bolt will be deleted when it impacts
2841 function ‪onSpawnCrossbowBoltImpact_internal( s_watcher, e_player )
2842 {
2843  self endon( "death" );
2844  e_player endon( "disconnect" );
2845 
2846  self waittill( "stationary" );
2847 
2848  s_watcher thread ‪waitAndFizzleOut( self, 0 ); // use fizzle out to make use of existing FX and logic
2849 
2850  foreach ( n_index, e_object in s_watcher.objectarray )
2851  {
2852  if ( self == e_object )
2853  {
2854  s_watcher.objectarray[ n_index ] = undefined;
2855  }
2856  }
2857 
2858  ‪cleanWeaponObjectArray( s_watcher );
2859 }
2860 
2861 function ‪onSpawnSpecialCrossbowTrigger( watcher, player ) // self == weapon_instance (for example: the claymore)
2862 {
2863  self endon( "death" );
2864 
2865  self SetOwner( player );
2866  self SetTeam( player.pers["team"] );
2867  self.owner = player;
2868  self.oldAngles = self.angles;
2869 
2871  waittillframeend;
2872 
2873  if( player.pers["team"] == "spectator" )
2874  {
2875  return;
2876  }
2877 
2878  triggerOrigin = self.origin;
2879  triggerParentEnt = undefined;
2880 
2881  if ( isdefined( self.stuckToPlayer ) )
2882  {
2883  if ( IsAlive( self.stuckToPlayer ) || !isdefined( self.stuckToPlayer.body ) )
2884  {
2885  if ( IsAlive( self.stuckToPlayer ) )
2886  {
2887  // Drop the arrow to the ground if it doesn't kill the player.
2888  triggerParentEnt = self;
2889  self Unlink();
2890  self.angles = self.oldAngles;
2891  self ‪launch( (5,5,5) );
2893  waittillframeend;
2894  }
2895  else
2896  {
2897  triggerParentEnt = self.stuckToPlayer;
2898  }
2899  }
2900  else
2901  {
2902  triggerParentEnt = self.stuckToPlayer.body;
2903  }
2904  }
2905 
2906  if ( isdefined( triggerParentEnt ) )
2907  triggerOrigin = triggerParentEnt.origin + ( 0, 0, 10 );
2908 
2909  if ( self.weapon.ShownRetrievable )
2910  {
2911  self ‪clientfield::set( "retrievable", 1 );
2912  }
2913 
2914  self.hatchetPickUpTrigger = ‪spawn( "trigger_radius", triggerOrigin, 0, 50, 50 );
2915 
2916  self.hatchetPickUpTrigger EnableLinkTo();
2917  self.hatchetPickUpTrigger LinkTo( self );
2918 
2919  if ( isdefined( triggerParentEnt ) )
2920  {
2921  self.hatchetPickUpTrigger linkto( triggerParentEnt );
2922  }
2923 
2924  self thread ‪watchSpecialCrossbowTrigger( self.hatchetPickUpTrigger, watcher.pickUp, watcher.pickUpSoundPlayer, watcher.pickUpSound );
2925 
2926  /#
2927  thread ‪switch_team( self, watcher, player );
2928  #/
2929 
2930  self thread ‪watchShutdown( player );
2931 }
2932 
2933 function ‪watchSpecialCrossbowTrigger( trigger, ‪callback, playerSoundOnUse, npcSoundOnUse ) // self == weapon (for example: the claymore)
2934 {
2935  self endon( "delete" );
2936  self endon( "hacked" );
2937 
2938  while ( true )
2939  {
2940  trigger waittill( "trigger", player );
2941 
2942  if ( !isAlive( player ) )
2943  continue;
2944 
2945  if ( isdefined( trigger.claimedBy ) && ( player != trigger.claimedBy ) )
2946  continue;
2947 
2948  crossbow_weapon = player ‪get_player_crossbow_weapon();
2949  if ( !isdefined( crossbow_weapon ) )
2950  continue;
2951 
2952  stock_ammo = player GetWeaponAmmoStock( crossbow_weapon );
2953  if( stock_ammo >= crossbow_weapon.maxammo )
2954  continue;
2955 
2956  if ( isdefined( playerSoundOnUse ) )
2957  player playLocalSound( playerSoundOnUse );
2958  if ( isdefined( npcSoundOnUse ) )
2959  player playSound( npcSoundOnUse );
2960 
2961  self thread [[‪callback]]( player, crossbow_weapon );
2962  }
2963 }
2964 
2965 function ‪onSpawnHatchetTrigger( watcher, player ) // self == weapon_instance (for example: the claymore)
2966 {
2967  self endon( "death" );
2968 
2969  self SetOwner( player );
2970  self SetTeam( player.pers["team"] );
2971  self.owner = player;
2972  self.oldAngles = self.angles;
2973 
2975  waittillframeend;
2976 
2977  if( player.pers["team"] == "spectator" )
2978  {
2979  return;
2980  }
2981 
2982  triggerOrigin = self.origin;
2983  triggerParentEnt = undefined;
2984 
2985  if ( isdefined( self.stuckToPlayer ) )
2986  {
2987  if ( IsAlive( self.stuckToPlayer ) || !isdefined( self.stuckToPlayer.body ) )
2988  {
2989  if ( IsAlive( self.stuckToPlayer ) )
2990  {
2991  // Drop the hatchet to the ground if it doesn't kill the player.
2992  triggerParentEnt = self;
2993  self Unlink();
2994  self.angles = self.oldAngles;
2995  self ‪launch( (5,5,5) );
2997  waittillframeend;
2998  }
2999  else
3000  {
3001  triggerParentEnt = self.stuckToPlayer;
3002  }
3003  }
3004  else
3005  {
3006  triggerParentEnt = self.stuckToPlayer.body;
3007  }
3008  }
3009 
3010  if ( isdefined( triggerParentEnt ) )
3011  triggerOrigin = triggerParentEnt.origin + ( 0, 0, 10 );
3012 
3013  if ( self.weapon.ShownRetrievable )
3014  {
3015  self ‪clientfield::set( "retrievable", 1 );
3016  }
3017 
3018  self.hatchetPickUpTrigger = ‪spawn( "trigger_radius", triggerOrigin, 0, 50, 50 );
3019 
3020  self.hatchetPickUpTrigger EnableLinkTo();
3021  self.hatchetPickUpTrigger LinkTo( self );
3022 
3023  if ( isdefined( triggerParentEnt ) )
3024  {
3025  self.hatchetPickUpTrigger linkto( triggerParentEnt );
3026  }
3027 
3028  self thread ‪watchHatchetTrigger( self.hatchetPickUpTrigger, watcher.pickUp, watcher.pickUpSoundPlayer, watcher.pickUpSound );
3029 
3030  /#
3031  thread ‪switch_team( self, watcher, player );
3032  #/
3033 
3034  self thread ‪watchShutdown( player );
3035 }
3036 
3037 function ‪watchHatchetTrigger( trigger, ‪callback, playerSoundOnUse, npcSoundOnUse ) // self == weapon (for example: the claymore)
3038 {
3039  self endon( "delete" );
3040  self endon( "hacked" );
3041 
3042  while ( true )
3043  {
3044  trigger waittill( "trigger", player );
3045 
3046  if ( !isAlive( player ) )
3047  continue;
3048 
3049  if ( !player isOnGround() && !player IsPlayerSwimming() )
3050  continue;
3051 
3052  if ( isdefined( trigger.claimedBy ) && ( player != trigger.claimedBy ) )
3053  continue;
3054 
3055  heldWeapon = player ‪get_held_weapon_match_or_root_match( self.weapon );
3056  if ( !IsDefined( heldWeapon ) )
3057  {
3058  continue;
3059  }
3060 
3061  maxAmmo = 0;
3062 
3063  if ( heldWeapon == player.grenadeTypePrimary && isdefined( player.grenadeTypePrimaryCount ) && player.grenadeTypePrimaryCount > 0 )
3064  {
3065  maxAmmo = player.grenadeTypePrimaryCount;
3066  }
3067  else if ( heldWeapon == player.grenadeTypeSecondary && isdefined( player.grenadeTypeSecondaryCount ) && player.grenadeTypeSecondaryCount > 0 )
3068  {
3069  maxAmmo = player.grenadeTypeSecondaryCount;
3070  }
3071 
3072  if ( maxAmmo == 0 )
3073  {
3074  continue;
3075  }
3076 
3077  clip_ammo = player GetWeaponAmmoClip( heldWeapon );
3078 
3079  if( clip_ammo >= maxAmmo )
3080  {
3081  continue;
3082  }
3083 
3084  if ( isdefined( playerSoundOnUse ) )
3085  player playLocalSound( playerSoundOnUse );
3086  if ( isdefined( npcSoundOnUse ) )
3087  player playSound( npcSoundOnUse );
3088 
3089  self thread [[‪callback]]( player );
3090  }
3091 }
3092 
3094 {
3095  pweapons = self GetWeaponsList( true );
3096 
3097  foreach( pweapon in pweapons )
3098  {
3099  if ( pweapon == weapon )
3100  {
3101  return pweapon;
3102  }
3103  }
3104 
3105  foreach( pweapon in pweapons )
3106  {
3107  if ( pweapon.rootweapon == weapon.rootweapon )
3108  {
3109  return pweapon;
3110  }
3111  }
3112 
3113  return undefined;
3114 }
3115 
3117 {
3118  pweapons = self GetWeaponsList( true );
3119 
3120  crossbow = GetWeapon( "special_crossbow" );
3121  crossbow_dw = GetWeapon( "special_crossbow_dw" );
3122  // crossbowlh = GetWeapon( "special_crossbowlh" ); // doesn't seem to be needed
3123 
3124  foreach( pweapon in pweapons )
3125  {
3126  if ( pweapon.rootweapon == crossbow || pweapon.rootweapon == crossbow_dw )
3127  {
3128  return pweapon;
3129  }
3130  }
3131 
3132  return undefined;
3133 }
3134 
3135 function ‪onSpawnRetrievableWeaponObject( watcher, player ) // self == weapon (for example: the claymore)
3136 {
3137  self endon( "death" );
3138  self endon( "hacked" );
3139 
3140  self SetOwner( player );
3141  self SetTeam( player.pers["team"] );
3142  self.owner = player;
3143  self.oldAngles = self.angles;
3144 
3146 
3147  if ( watcher.activationDelay )
3148  {
3149  wait( watcher.activationDelay );
3150  }
3151 
3152  waittillframeend;
3153 
3154  if(player.pers["team"] == "spectator")
3155  {
3156  return;
3157  }
3158 
3159  triggerOrigin = self.origin;
3160  triggerParentEnt = undefined;
3161  if ( isdefined( self.stuckToPlayer ) )
3162  {
3163  if ( IsAlive( self.stuckToPlayer ) || !isdefined( self.stuckToPlayer.body ) )
3164  {
3165  triggerParentEnt = self.stuckToPlayer;
3166  }
3167  else
3168  {
3169  triggerParentEnt = self.stuckToPlayer.body;
3170  }
3171  }
3172 
3173  if ( isdefined( triggerParentEnt ) )
3174  {
3175  triggerOrigin = triggerParentEnt.origin + ( 0, 0, 10 );
3176  }
3177  else
3178  {
3179  // move the trigger 1 unit along the up axis to prevent the it
3180  // from failing the sight trace in player_use
3181  up = AnglesToUp( self.angles );
3182  triggerOrigin = self.origin + up;
3183  }
3184 
3185  if ( !self ‪util::isHacked() )
3186  {
3187  if ( self.weapon.ShownRetrievable )
3188  {
3189  self ‪clientfield::set( "retrievable", 1 );
3190  }
3191 
3192  self.pickUpTrigger = ‪spawn( "trigger_radius_use", triggerOrigin );
3193  self.pickUpTrigger SetHintLowPriority( true );
3194  self.pickUpTrigger SetCursorHint( "HINT_NOICON", self );
3195  self.pickUpTrigger EnableLinkTo();
3196  self.pickUpTrigger LinkTo( self );
3197  self.pickUpTrigger SetInvisibleToAll();
3198  self.pickUpTrigger SetVisibleToPlayer( player );
3199 
3200  if( isdefined(level.retrieveHints[watcher.name]) )
3201  {
3202  self.pickUpTrigger SetHintString( level.retrieveHints[watcher.name].hint );
3203  }
3204  else
3205  {
3206  self.pickUpTrigger SetHintString( &"MP_GENERIC_PICKUP" );
3207  }
3208 
3209  self.pickUpTrigger SetTeamForTrigger( player.pers["team"] );
3210 
3211  if ( isdefined( triggerParentEnt ) )
3212  {
3213  self.pickUpTrigger linkto( triggerParentEnt );
3214  }
3215 
3216  self thread ‪watchUseTrigger( self.pickUpTrigger, watcher.pickUp, watcher.pickUpSoundPlayer, watcher.pickUpSound );
3217 
3218  if ( isdefined( watcher.pickup_trigger_listener ) )
3219  {
3220  self thread [[watcher.pickup_trigger_listener]]( self.pickUpTrigger, player );
3221  }
3222  }
3223 
3224  if ( watcher.enemyDestroy )
3225  {
3226  self.enemyTrigger = ‪spawn( "trigger_radius_use", triggerOrigin );
3227  self.enemyTrigger SetCursorHint( "HINT_NOICON", self );
3228  self.enemyTrigger EnableLinkTo();
3229  self.enemyTrigger LinkTo( self );
3230  self.enemyTrigger SetInvisibleToPlayer( player );
3231 
3232  if ( level.teamBased )
3233  {
3234  self.enemyTrigger SetExcludeTeamForTrigger( player.team );
3235  self.enemyTrigger.triggerTeamIgnore = self.team;
3236  }
3237 
3238  if( isdefined(level.destroyHints[watcher.name]) )
3239  {
3240  self.enemyTrigger SetHintString( level.destroyHints[watcher.name].hint );
3241  }
3242  else
3243  {
3244  self.enemyTrigger SetHintString( &"MP_GENERIC_DESTROY" );
3245  }
3246 
3247  self thread ‪watchUseTrigger( self.enemyTrigger, watcher.onDestroyed );
3248  }
3249 
3250  /#
3251  thread ‪switch_team( self, watcher, player );
3252  #/
3253 
3254  self thread ‪watchShutdown( player );
3255 }
3256 
3257 function ‪destroyEnt()
3258 {
3259  self delete();
3260 }
3261 
3262 function ‪pickUp( player ) // self == weapon_instance (for example: the claymore)
3263 {
3264  if ( !self.weapon.anyPlayerCanRetrieve && isdefined( self.owner ) && self.owner != player )
3265  {
3266  return;
3267  }
3268 
3269  pikedWeapon = self.weapon;
3270 
3271  if ( self.weapon.ammoCountEquipment > 0 && isdefined( self.ammo ) )
3272  {
3273  ammoLeftEquipment = self.ammo;
3274  }
3275 
3276  self notify( "picked_up" );
3277  self.playDialog = false;
3278  self ‪destroyEnt();
3279 
3280  heldWeapon = player ‪get_held_weapon_match_or_root_match( self.weapon );
3281  if ( !IsDefined( heldWeapon ) )
3282  {
3283  return;
3284  }
3285 
3286  maxAmmo = 0;
3287 
3288  if ( heldWeapon == player.grenadeTypePrimary && isdefined( player.grenadeTypePrimaryCount ) && player.grenadeTypePrimaryCount > 0 )
3289  {
3290  maxAmmo = player.grenadeTypePrimaryCount;
3291  }
3292  else if ( heldWeapon == player.grenadeTypeSecondary && isdefined( player.grenadeTypeSecondaryCount ) && player.grenadeTypeSecondaryCount > 0 )
3293  {
3294  maxAmmo = player.grenadeTypeSecondaryCount;
3295  }
3296 
3297  if ( maxAmmo == 0 )
3298  {
3299  return;
3300  }
3301 
3302  clip_ammo = player GetWeaponAmmoClip( heldWeapon );
3303 
3304  if( clip_ammo < maxAmmo )
3305  {
3306  clip_ammo++;
3307  }
3308 
3309  if ( isdefined ( ammoLeftEquipment ) )
3310  {
3311  if ( pikedWeapon.rootWeapon == GetWeapon( "trophy_system" ) )
3312  {
3313  player ‪trophy_system::ammo_weapon_pickup( ammoLeftEquipment );
3314  }
3315  }
3316 
3317  player setWeaponAmmoClip( heldWeapon, clip_ammo );
3318 }
3319 
3320 function ‪pickUpCrossbowBolt( player, heldWeapon ) // self == weapon_instance (for example: the crossbow bolt)
3321 {
3322  self notify( "picked_up" );
3323  self.playDialog = false;
3324  self ‪destroyEnt();
3325 
3326  // note: ammo limits should be regulated in watchSpecialCrossbowTrigger
3327  stock_ammo = player GetWeaponAmmoStock( heldWeapon );
3328  stock_ammo++;
3329  player SetWeaponAmmoStock( heldWeapon, stock_ammo );
3330 }
3331 
3332 function ‪onDestroyed( attacker ) // self == weapon object
3333 {
3334  PlayFX( level._effect["tacticalInsertionFizzle"], self.origin );
3335  self playsound ("dst_tac_insert_break");
3336 
3337  if( isdefined( level.playEquipmentDestroyedOnPlayer ) )
3338  {
3339  self.owner [[level.playEquipmentDestroyedOnPlayer]]();
3340  }
3341 
3342  self delete(); // will call watchShutdow() to clean up the trigger ents
3343 }
3344 
3345 function ‪watchShutdown( player ) // self == weapon (for example: the claymore)
3346 {
3347  self ‪util::waittill_any( "death", "hacked", "detonating" );
3348 
3349  pickUpTrigger = self.pickUpTrigger;
3350  hackerTrigger = self.hackerTrigger;
3351  hatchetPickUpTrigger = self.hatchetPickUpTrigger;
3352  enemyTrigger = self.enemyTrigger;
3353 
3354  if( isdefined( pickUpTrigger ) )
3355  pickUpTrigger delete();
3356 
3357  if( isdefined( hackerTrigger ) )
3358  {
3359  if ( isdefined( hackerTrigger.progressBar ) )
3360  {
3361  hackerTrigger.progressBar ‪hud::destroyElem();
3362  hackerTrigger.progressText ‪hud::destroyElem();
3363  }
3364  hackerTrigger delete();
3365  }
3366 
3367  if( isdefined( hatchetPickUpTrigger ) )
3368  hatchetPickUpTrigger delete();
3369 
3370  if ( isdefined( enemyTrigger ))
3371  {
3372  enemyTrigger delete();
3373  }
3374 }
3375 
3376 function ‪watchUseTrigger( trigger, ‪callback, playerSoundOnUse, npcSoundOnUse ) // self == weapon (for example: the claymore)
3377 {
3378  self endon( "delete" );
3379  self endon( "hacked" );
3380 
3381  while ( true )
3382  {
3383  trigger waittill( "trigger", player );
3384 
3385  if ( isdefined( self.detonated ) && self.detonated == true )
3386  {
3387  if ( isdefined( trigger ) )
3388  {
3389  trigger delete();
3390  }
3391  return;
3392  }
3393 
3394  if ( !isAlive( player ) )
3395  continue;
3396 
3397  if ( isdefined( trigger.triggerTeam ) && ( player.pers["team"] != trigger.triggerTeam ) )
3398  continue;
3399 
3400  if ( isdefined( trigger.triggerTeamIgnore ) && ( player.team == trigger.triggerTeamIgnore ) )
3401  continue;
3402 
3403  if ( isdefined( trigger.claimedBy ) && ( player != trigger.claimedBy ) )
3404  continue;
3405 
3406  grenade = player.throwingGrenade;
3407  weapon = player GetCurrentWeapon();
3408 
3409  if ( weapon.isEquipment )
3410  {
3411  grenade = false;
3412  }
3413 
3414  if ( player useButtonPressed() && !grenade && !player meleeButtonPressed() )
3415  {
3416  if ( isdefined( playerSoundOnUse ) )
3417  player playLocalSound( playerSoundOnUse );
3418  if ( isdefined( npcSoundOnUse ) )
3419  player playSound( npcSoundOnUse );
3420  self thread [[‪callback]]( player );
3421  }
3422  }
3423 }
3424 
3426 {
3427  retrieveHint = spawnStruct();
3428 
3429  retrieveHint.name = ‪name;
3430  retrieveHint.hint = hint;
3431 
3432  level.retrieveHints[‪name] = retrieveHint;
3433 }
3434 
3436 {
3437  hackerHint = spawnStruct();
3438 
3439  hackerHint.name = ‪name;
3440  hackerHint.hint = hint;
3441 
3442  level.hackerHints[‪name] = hackerHint;
3443 }
3444 
3446 {
3447  destroyHint = spawnStruct();
3448 
3449  destroyHint.name = ‪name;
3450  destroyHint.hint = hint;
3451 
3452  level.destroyHints[‪name] = destroyHint;
3453 }
3454 
3456 {
3457  if ( !isdefined( self ) )
3458  return;
3459 
3460  if ( self.weapon.ShownEnemyExplo || self.weapon.ShownEnemyEquip )
3461  {
3462  if( ‪IS_TRUE( self.hacked ) )
3463  {
3464  self ‪clientfield::set( "enemyequip", ENEMY_EQUIPMENT_SHADER_HACKED );
3465  }
3466  else
3467  {
3469  }
3470  }
3471 }
3472 
3474 {
3475  if ( isdefined( watcher ) )
3476  {
3477  if ( !isdefined( watcher.notEquipment ) )
3478  {
3479  if ( isdefined( self ) )
3480  {
3481  //if ( self.type == "missile" )
3482  {
3483  return true;
3484  }
3485  }
3486  }
3487  }
3488 
3489  return false;
3490 }
3491 
3492 function ‪GetWatcherForWeapon( weapon )
3493 {
3494  if ( !isdefined( self ) )
3495  {
3496  return undefined;
3497  }
3498 
3499  if ( !IsPlayer( self ) )
3500  {
3501  return undefined;
3502  }
3503 
3504  for ( i = 0; i < self.weaponObjectWatcherArray.size; i++ )
3505  {
3506  if ( self.weaponObjectWatcherArray[i].weapon != weapon )
3507  {
3508  continue;
3509  }
3510 
3511  return ( self.weaponObjectWatcherArray[i] );
3512  }
3513 
3514  return undefined;
3515 }
3516 
3517 // secondary items which need to be cleaned up during an emp
3518 // most primary watcher items are in the level.missileEntities list
3520 {
3521  if( level.teamBased )
3522  {
3523  foreach( team in level.teams )
3524  {
3525  if( team == attacker.team )
3526  {
3527  continue;
3528  }
3529 
3530  ‪destroy_supplemental_watcher_objects( attacker, team, weapon );
3531  }
3532  }
3533 
3534  ‪destroy_supplemental_watcher_objects( attacker, "free", weapon );
3535 }
3536 
3537 function ‪destroy_supplemental_watcher_objects( attacker, team, weapon )
3538 {
3539  foreach ( item in level.supplementalWatcherObjects )
3540  {
3541  if ( !isdefined( item.weapon ) )
3542  {
3543  continue;
3544  }
3545 
3546  if ( !isdefined( item.owner ) )
3547  {
3548  continue;
3549  }
3550 
3551  if ( isdefined( team ) && item.owner.team != team )
3552  {
3553  continue;
3554  }
3555  else if ( item.owner == attacker )
3556  {
3557  continue;
3558  }
3559 
3560  watcher = item.owner getWatcherForWeapon( item.weapon );
3561 
3562  if ( !isdefined( watcher ) || !IsDefined( watcher.onSupplementalDetonateCallback ) )
3563  {
3564  continue;
3565  }
3566 
3567  item thread [[watcher.onSupplementalDetonateCallback]]();
3568  }
3569 }
3570 
3571 function ‪add_supplemental_object( object )
3572 {
3573  level.supplementalWatcherObjects[ level.supplementalWatcherObjects.size ] = object;
3574  object thread ‪watch_supplemental_object_death();
3575 }
3576 
3577 function ‪watch_supplemental_object_death() // self == object
3578 {
3579  self waittill( "death" );
3580  ArrayRemoveValue( level.supplementalWatcherObjects, self );
3581 }
3582 
3583 /#
3584 function ‪switch_team( entity, watcher, owner ) // self == ??
3585 {
3586  self notify( "stop_disarmthink" );
3587  self endon( "stop_disarmthink" );
3588  self endon( "death" );
3589 
3590  //Init my dvar
3591  SetDvar("scr_switch_team", "");
3592 
3593  while( true )
3594  {
3595  wait(0.5);
3596 
3597  //Grab my dvar every .5 seconds in the form of an int
3598  devgui_int = GetDvarint( "scr_switch_team");
3599 
3600  //"" returns as zero with GetDvarInt
3601  if(devgui_int != 0)
3602  {
3603  // spawn a larry to be the opposing team
3604  team = "autoassign";
3605 
3606  if( isdefined( level.getEnemyTeam ) && isdefined( owner ) && isdefined( owner.team ) )
3607  {
3608  team = [[level.getEnemyTeam]]( owner.team );
3609  }
3610 
3611  if ( isdefined( level.devOnGetOrMakeBot ) )
3612  {
3613  player = [[level.devOnGetOrMakeBot]]( team );
3614  }
3615 
3616  if( !isdefined( player ) )
3617  {
3618  println("Could not add test client");
3619  wait 1;
3620  continue;
3621  }
3622 
3623  entity ‪ItemHacked( watcher, player );
3624 
3625  SetDvar("scr_switch_team", "0");
3626  }
3627  }
3628 }
3629 
3630 #/
‪weaponObjectDetectionTrigger_wait
‪function weaponObjectDetectionTrigger_wait(ownerTeam)
Definition: _weaponobjects.gsc:1816
‪cleanUpWatchers
‪function cleanUpWatchers()
Definition: _weaponobjects.gsc:2617
‪createBaseWatchers
‪function createBaseWatchers()
Definition: _weaponobjects.gsc:226
‪createSpikeLauncherWatcher
‪function createSpikeLauncherWatcher(weapon)
Definition: _weaponobjects.gsc:393
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪onSpawnUseWeaponObject
‪function onSpawnUseWeaponObject(watcher, owner)
Definition: _weaponobjects.gsc:1597
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪createPrimaryProgressBarText
‪function createPrimaryProgressBarText()
Definition: hud_util_shared.gsc:612
‪showCone
‪function showCone(angle, range, color)
Definition: _weaponobjects.gsc:1764
‪createHatchetWatcher
‪function createHatchetWatcher()
Definition: _weaponobjects.gsc:294
‪weaponStun
‪function weaponStun()
Definition: _weaponobjects.gsc:1128
‪getSpikeLauncherActiveSpikeCount
‪function getSpikeLauncherActiveSpikeCount(watcher)
Definition: _weaponobjects.gsc:342
‪delayedSpikeDetonation
‪function delayedSpikeDetonation(attacker, weapon)
Definition: _weaponobjects.gsc:508
‪onSpawnHatchetTrigger
‪function onSpawnHatchetTrigger(watcher, player)
Definition: _weaponobjects.gsc:2965
‪proximityWeaponObjectDebug
‪function proximityWeaponObjectDebug(watcher)
Definition: _weaponobjects.gsc:1742
‪setUpRetrievableHintStrings
‪function setUpRetrievableHintStrings()
Definition: _weaponobjects.gsc:135
‪watchSpikeLauncherItemCountChanged
‪function watchSpikeLauncherItemCountChanged(watcher)
Definition: _weaponobjects.gsc:356
‪get_to_player
‪function get_to_player(field_name)
Definition: clientfield_shared.csc:38
‪hackerInit
‪function hackerInit(watcher)
Definition: _weaponobjects.gsc:1880
‪hackerUnfreezePlayer
‪function hackerUnfreezePlayer(player)
Definition: _weaponobjects.gsc:2017
‪setIconPos
‪function setIconPos(item, icon, heightIncrease)
Definition: _weaponobjects.gsc:1809
‪deleteEnt
‪function deleteEnt(attacker, emp, target)
Definition: _weaponobjects.gsc:461
‪voidOnSpawn
‪function voidOnSpawn(unused0, unused1)
Definition: _weaponobjects.gsc:445
‪hackerRemoveWeapon
‪function hackerRemoveWeapon(weapon_instance)
Definition: _weaponobjects.gsc:2188
‪voidOnSpawnRetrieveTriggers
‪function voidOnSpawnRetrieveTriggers(unused0, unused1)
Definition: _weaponobjects.gsc:453
‪weaponObjectDetectionTrigger
‪function weaponObjectDetectionTrigger(ownerTeam)
Definition: _weaponobjects.gsc:1827
‪pickUp
‪function pickUp(player)
Definition: _weaponobjects.gsc:3262
‪hackerResult
‪function hackerResult(player, owner)
Definition: _weaponobjects.gsc:2029
‪set_to_player
‪function set_to_player(str_field_name, n_value)
Definition: clientfield_shared.gsc:58
‪PROXIMITY_ALARM_ON
‪#define PROXIMITY_ALARM_ON
Definition: _weaponobjects.gsh:3
‪claymoreDetonate
‪function claymoreDetonate(attacker, weapon, target)
Definition: _weaponobjects.gsc:546
‪debug_sphere
‪function debug_sphere(origin, radius, color, alpha, time)
Definition: _airsupport.gsc:1153
‪launch
‪function launch(ent_1, str_tag1, ent_2, str_tag2, str_beam_type)
Definition: beam_shared.csc:11
‪playDialogOnDeath
‪function playDialogOnDeath(owner)
Definition: _weaponobjects.gsc:1038
‪on_start_gametype
‪function on_start_gametype(func, obj)
Definition: callbacks_shared.csc:285
‪addWeaponObjectToWatcher
‪function addWeaponObjectToWatcher(watcherName, weapon_instance)
Definition: _weaponobjects.gsc:784
‪destroyedExplosive
‪function destroyedExplosive(weapon)
Definition: challenges_shared.gsc:951
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪updateDvars
‪function updateDvars()
Definition: _weaponobjects.gsc:86
‪waittill_any_return
‪function waittill_any_return(string1, string2, string3, string4, string5, string6, string7)
Definition: util_shared.csc:212
‪isStunned
‪function isStunned()
Definition: _weaponobjects.gsc:1156
‪createSpecialCrossbowWatcherTypes
‪function createSpecialCrossbowWatcherTypes(weaponName)
Definition: _weaponobjects.gsc:261
‪WasProximityAlarmActivatedBySelf
‪function WasProximityAlarmActivatedBySelf()
Definition: _weaponobjects.gsc:1372
‪createWeaponObjectWatcher
‪function createWeaponObjectWatcher(weaponname, ownerTeam)
Definition: _weaponobjects.gsc:1233
‪deleteOnDeath
‪function deleteOnDeath(ent)
Definition: _weaponobjects.gsc:2450
‪proximityWeaponObject_ActivationDelay
‪function proximityWeaponObject_ActivationDelay(watcher)
Definition: _weaponobjects.gsc:2349
‪onSpawnCrossbowBolt
‪function onSpawnCrossbowBolt(watcher, player)
Definition: _weaponobjects.gsc:2790
‪destroyElem
‪function destroyElem()
Definition: hud_util_shared.gsc:755
‪destroyEnt
‪function destroyEnt()
Definition: _weaponobjects.gsc:3257
‪proximityAlarmWeaponObjectDebug
‪function proximityAlarmWeaponObjectDebug(watcher)
Definition: _weaponobjects.gsc:1728
‪watchWeaponObjectDetonation
‪function watchWeaponObjectDetonation()
Definition: _weaponobjects.gsc:2586
‪freeze_player_controls
‪function freeze_player_controls(b_frozen=true)
Definition: util_shared.gsc:2474
‪ProximityAlarmActivate
‪function ProximityAlarmActivate(active, watcher)
Definition: _weaponobjects.gsc:1377
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪createFireflyPodWatcher
‪function createFireflyPodWatcher()
Definition: _hive_gun.gsc:81
‪createRCBombWatcher
‪function createRCBombWatcher()
Definition: _weaponobjects.gsc:309
‪proximityWeaponObject_DoDetonation
‪function proximityWeaponObject_DoDetonation(watcher, ent, traceOrigin)
Definition: _weaponobjects.gsc:2315
‪get_player_crossbow_weapon
‪function get_player_crossbow_weapon()
Definition: _weaponobjects.gsc:3116
‪showHeadIcon
‪function showHeadIcon(trigger)
Definition: _weaponobjects.gsc:2692
‪delay
‪function delay(time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6)
Definition: util_shared.csc:784
‪deleteWeaponObjectsOn
‪function deleteWeaponObjectsOn()
Definition: _weaponobjects.gsc:2658
‪cleanupWatcherOnDeath
‪function cleanupWatcherOnDeath(watcher)
Definition: _weaponobjects.gsc:865
‪waitAndDetonate
‪function waitAndDetonate(object, delay, attacker, weapon)
Definition: _weaponobjects.gsc:615
‪proximityWeaponObject_ValidTriggerEntity
‪function proximityWeaponObject_ValidTriggerEntity(watcher, ent)
Definition: _weaponobjects.gsc:2215
‪PROXIMITY_ALARM_DEPLOYED
‪#define PROXIMITY_ALARM_DEPLOYED
Definition: _weaponobjects.gsh:2
‪createDestroyHint
‪function createDestroyHint(name, hint)
Definition: _weaponobjects.gsc:3445
‪isUsingRemote
‪function isUsingRemote()
Definition: util_shared.gsc:2705
‪IsEnemyPlayer
‪function IsEnemyPlayer(player)
Definition: util_shared.csc:1220
‪watchForDisconnectCleanUp
‪function watchForDisconnectCleanUp()
Definition: _weaponobjects.gsc:2651
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪on_player_spawned
‪function on_player_spawned()
Definition: _weaponobjects.gsc:34
‪weaponObjectDamage
‪function weaponObjectDamage(watcher)
Definition: _weaponobjects.gsc:944
‪getWeaponObjectWatcher
‪function getWeaponObjectWatcher(name)
Definition: _weaponobjects.gsc:1176
‪createSpecialCrossbowWatcher
‪function createSpecialCrossbowWatcher()
Definition: _weaponobjects.gsc:281
‪IDFLAGS_PENETRATION
‪#define IDFLAGS_PENETRATION
Definition: shared.gsh:414
‪proximityWeaponObject_SpawnProtect
‪function proximityWeaponObject_SpawnProtect(watcher, ent)
Definition: _weaponobjects.gsc:2266
‪deleteWeaponObjectInstance
‪function deleteWeaponObjectInstance()
Definition: _weaponobjects.gsc:477
‪createPrimaryProgressBar
‪function createPrimaryProgressBar()
Definition: hud_util_shared.gsc:602
‪ItemHacked
‪function ItemHacked(watcher, player)
Definition: _weaponobjects.gsc:1947
‪proximityWeaponObject_RemoveSpawnProtectOnDeath
‪function proximityWeaponObject_RemoveSpawnProtectOnDeath(ent)
Definition: _weaponobjects.gsc:2257
‪watchSpecialCrossbowTrigger
‪function watchSpecialCrossbowTrigger(trigger, callback, playerSoundOnUse, npcSoundOnUse)
Definition: _weaponobjects.gsc:2933
‪on_spawned
‪function on_spawned(func, obj)
Definition: callbacks_shared.csc:245
‪ammo_weapon_hacked
‪function ammo_weapon_hacked(ammo)
Definition: _trophy_system.gsc:490
‪ProximityAlarmLoop
‪function ProximityAlarmLoop(watcher, owner)
Definition: _weaponobjects.gsc:1402
‪watchWeaponObjectAltDetonation
‪function watchWeaponObjectAltDetonation()
Definition: _weaponobjects.gsc:2541
‪createPlayerHelicopterWatcher
‪function createPlayerHelicopterWatcher()
Definition: _weaponobjects.gsc:415
‪proximityWeaponObject_CreateDamageArea
‪function proximityWeaponObject_CreateDamageArea(watcher)
Definition: _weaponobjects.gsc:2204
‪updateBar
‪function updateBar(barFrac, rateOfChange)
Definition: hud_util_shared.gsc:294
‪watchObjectDamage
‪function watchObjectDamage(owner)
Definition: _weaponobjects.gsc:1055
‪watch_supplemental_object_death
‪function watch_supplemental_object_death()
Definition: _weaponobjects.gsc:3577
‪deleteWeaponObjectArray
‪function deleteWeaponObjectArray()
Definition: _weaponobjects.gsc:495
‪onSpawnCrossbowBolt_internal
‪function onSpawnCrossbowBolt_internal(watcher, player)
Definition: _weaponobjects.gsc:2796
‪saydamaged
‪function saydamaged(orig, amount)
Definition: _weaponobjects.gsc:2681
‪useTeamEquipmentClientField
‪function useTeamEquipmentClientField(watcher)
Definition: _weaponobjects.gsc:3473
‪get_held_weapon_match_or_root_match
‪function get_held_weapon_match_or_root_match(weapon)
Definition: _weaponobjects.gsc:3093
‪resetWeaponObjectExplodeThisFrame
‪function resetWeaponObjectExplodeThisFrame()
Definition: _weaponobjects.gsc:1170
‪commonOnSpawnUseWeaponObjectProximityAlarm
‪function commonOnSpawnUseWeaponObjectProximityAlarm(watcher, owner)
Definition: _weaponobjects.gsc:1579
‪deleteOnKillbrush
‪function deleteOnKillbrush(player)
Definition: _weaponobjects.gsc:2494
‪add_supplemental_object
‪function add_supplemental_object(object)
Definition: _weaponobjects.gsc:3571
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪deleteWeaponObjectHelper
‪function deleteWeaponObjectHelper(weapon_ent)
Definition: _weaponobjects.gsc:900
‪watchWeaponObjectUsage
‪function watchWeaponObjectUsage()
Definition: _weaponobjects.gsc:1626
‪showElem
‪function showElem()
Definition: hud_util_shared.gsc:695
‪doDamageFeedback
‪function doDamageFeedback(weapon, eInflictor, iDamage, sMeansOfDeath)
Definition: damagefeedback_shared.gsc:423
‪watchHatchetTrigger
‪function watchHatchetTrigger(trigger, callback, playerSoundOnUse, npcSoundOnUse)
Definition: _weaponobjects.gsc:3037
‪is_spawn_protected
‪function is_spawn_protected()
Definition: player_shared.gsc:364
‪watchWeaponObjectAltDetonate
‪function watchWeaponObjectAltDetonate()
Definition: _weaponobjects.gsc:2565
‪createTactInsertWatcher
‪function createTactInsertWatcher()
Definition: _weaponobjects.gsc:303
‪dieOnEntityDeath
‪function dieOnEntityDeath(entity, player)
Definition: _weaponobjects.gsc:2819
‪watchShutdown
‪function watchShutdown(player)
Definition: _weaponobjects.gsc:3345
‪spikesDetonating
‪function spikesDetonating(watcher)
Definition: _weaponobjects.gsc:381
‪watchWeaponObjectSpawn
‪function watchWeaponObjectSpawn(notify_type)
Definition: _weaponobjects.gsc:1645
‪remove_undefined
‪function remove_undefined(array, b_keep_keys)
Definition: array_shared.csc:56
‪SPAWNFLAG
‪#define SPAWNFLAG(__e, __f)
Definition: shared.gsh:95
‪detonateWhenStationary
‪function detonateWhenStationary(object, delay, attacker, weapon)
Definition: _weaponobjects.gsc:598
‪proximityWeaponObjectDetonation
‪function proximityWeaponObjectDetonation(watcher)
Definition: _weaponobjects.gsc:2389
‪detonateWeaponObjectArray
‪function detonateWeaponObjectArray(forceDetonation, weapon)
Definition: _weaponobjects.gsc:736
‪createClaymoreWatcher
‪function createClaymoreWatcher()
Definition: _weaponobjects.gsc:425
‪voidOnDamage
‪function voidOnDamage(unused0)
Definition: _weaponobjects.gsc:449
‪ammo_reset
‪function ammo_reset()
Definition: _trophy_system.gsc:449
‪watchUseTrigger
‪function watchUseTrigger(trigger, callback, playerSoundOnUse, npcSoundOnUse)
Definition: _weaponobjects.gsc:3376
‪createRetrievableHint
‪function createRetrievableHint(name, hint)
Definition: _weaponobjects.gsc:3425
‪waitAndFizzleOut
‪function waitAndFizzleOut(object, delay)
Definition: _weaponobjects.gsc:707
‪onSpawnHatchet
‪function onSpawnHatchet(watcher, player)
Definition: _weaponobjects.gsc:2782
‪stunFxThink
‪function stunFxThink(fx)
Definition: _weaponobjects.gsc:1149
‪GetWatcherForWeapon
‪function GetWatcherForWeapon(weapon)
Definition: _weaponobjects.gsc:3492
‪onSpawnSpecialCrossbowTrigger
‪function onSpawnSpecialCrossbowTrigger(watcher, player)
Definition: _weaponobjects.gsc:2861
‪hackedOrDestroyedEquipment
‪function hackedOrDestroyedEquipment()
Definition: challenges_shared.gsc:929
‪resetWeaponObjectWatcher
‪function resetWeaponObjectWatcher(watcher, ownerTeam)
Definition: _weaponobjects.gsc:1221
‪stunStop
‪function stunStop()
Definition: _weaponobjects.gsc:1118
‪createProximityWeaponObjectWatcher
‪function createProximityWeaponObjectWatcher(weaponname, ownerTeam)
Definition: _weaponobjects.gsc:1307
‪setEntityHeadIcon
‪function setEntityHeadIcon(team, owner, offset, objective, constant_size)
Definition: entityheadicons_shared.gsc:43
‪weapon_object_timeout
‪function weapon_object_timeout(watcher)
Definition: _weaponobjects.gsc:880
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪proximityWeaponObject_IsSpawnProtected
‪function proximityWeaponObject_IsSpawnProtected(watcher, ent)
Definition: _weaponobjects.gsc:2291
‪setupRetrievableWatcher
‪function setupRetrievableWatcher()
Definition: _weaponobjects.gsc:241
‪hackerTriggerSetVisibility
‪function hackerTriggerSetVisibility(owner)
Definition: _weaponobjects.gsc:1843
‪SPAWNFLAG_TRIGGER_HURT_PLAYER_ONLY
‪#define SPAWNFLAG_TRIGGER_HURT_PLAYER_ONLY
Definition: shared.gsh:41
‪waitTillNotMoving
‪function waitTillNotMoving()
Definition: util_shared.gsc:2621
‪voidPickUp
‪function voidPickUp(unused0, unused1)
Definition: _weaponobjects.gsc:457
‪createUseWeaponObjectWatcher
‪function createUseWeaponObjectWatcher(weaponname, ownerTeam)
Definition: _weaponobjects.gsc:1297
‪clearFXOnDeath
‪function clearFXOnDeath(fx)
Definition: _weaponobjects.gsc:466
‪weaponObjectDetectionMovable
‪function weaponObjectDetectionMovable(ownerTeam)
Definition: _weaponobjects.gsc:1795
‪weaponObjectFizzleOut
‪function weaponObjectFizzleOut()
Definition: _weaponobjects.gsc:1161
‪weapon_object_do_DamageFeedBack
‪function weapon_object_do_DamageFeedBack(weapon, attacker)
Definition: _weaponobjects.gsc:922
‪onSpawnRetrievableWeaponObject
‪function onSpawnRetrievableWeaponObject(watcher, player)
Definition: _weaponobjects.gsc:3135
‪ENEMY_EQUIPMENT_SHADER_ACTIVE
‪#define ENEMY_EQUIPMENT_SHADER_ACTIVE
Definition: _weaponobjects.gsh:6
‪onSpawnProximityWeaponObject
‪function onSpawnProximityWeaponObject(watcher, owner)
Definition: _weaponobjects.gsc:1603
‪resetWatchers
‪function resetWatchers()
Definition: _weaponobjects.gsc:211
‪cleanWeaponObjectArray
‪function cleanWeaponObjectArray(watcher)
Definition: _weaponobjects.gsc:917
‪set_player_uimodel
‪function set_player_uimodel(str_field_name, n_value)
Definition: clientfield_shared.gsc:75
‪canHack
‪function canHack(player, owner, weapon_check)
Definition: _weaponobjects.gsc:2109
‪callback_weapon_watcher
‪function callback_weapon_watcher()
Definition: callbacks_shared.gsc:619
‪update
‪function update()
Definition: _serversettings.gsc:71
‪testKillbrushOnStationary
‪function testKillbrushOnStationary(a_killbrushes, player)
Definition: _weaponobjects.gsc:2458
‪destroy
‪function destroy(watcher, owner)
Definition: _decoy.gsc:108
‪stunStart
‪function stunStart(watcher, time)
Definition: _weaponobjects.gsc:1077
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪destroy_supplemental_watcher_objects
‪function destroy_supplemental_watcher_objects(attacker, team, weapon)
Definition: _weaponobjects.gsc:3537
‪proximityWeaponObject_WaitTillFrameEndAndDoDetonation
‪function proximityWeaponObject_WaitTillFrameEndAndDoDetonation(watcher, ent, traceOrigin)
Definition: _weaponobjects.gsc:2359
‪onDestroyed
‪function onDestroyed(attacker)
Definition: _weaponobjects.gsc:3332
‪spikeDetonate
‪function spikeDetonate(attacker, weapon, target)
Definition: _weaponobjects.gsc:528
‪delete_on_notify
‪function delete_on_notify(e_player)
Definition: _weaponobjects.gsc:889
‪createQRDroneWatcher
‪function createQRDroneWatcher()
Definition: _weaponobjects.gsc:325
‪switch_team
‪function switch_team(entity, watcher, owner)
Definition: _weaponobjects.gsc:3584
‪init_shared
‪function init_shared()
Definition: _weaponobjects.gsc:65
‪onSpawnCrossbowBoltImpact_internal
‪function onSpawnCrossbowBoltImpact_internal(s_watcher, e_player)
Definition: _weaponobjects.gsc:2841
‪on_connect
‪function on_connect()
Definition: _arena.gsc:20
‪weaponDetonate
‪function weaponDetonate(attacker, weapon)
Definition: _weaponobjects.gsc:563
‪commonOnSpawnUseWeaponObject
‪function commonOnSpawnUseWeaponObject(watcher, owner)
Definition: _weaponobjects.gsc:1323
‪isHacked
‪function isHacked()
Definition: util_shared.gsc:2493
‪PROXIMITY_ALARM_OFF
‪#define PROXIMITY_ALARM_OFF
Definition: _weaponobjects.gsh:1
‪delete_on_death
‪function delete_on_death(ent)
Definition: util_shared.gsc:1796
‪addWeaponObject
‪function addWeaponObject(watcher, weapon_instance, weapon)
Definition: _weaponobjects.gsc:792
‪IS_BONUSZM
‪#define IS_BONUSZM
Definition: shared.gsh:532
‪removeWeaponObject
‪function removeWeaponObject(watcher, weapon_ent)
Definition: _weaponobjects.gsc:911
‪friendlyFireCheck
‪function friendlyFireCheck(owner, attacker, forcedFriendlyFireRule)
Definition: _weaponobjects.gsc:2733
‪on_player_connect
‪function on_player_connect()
Definition: _weaponobjects.gsc:161
‪ammo_weapon_pickup
‪function ammo_weapon_pickup(ammo)
Definition: _trophy_system.gsc:474
‪anyObjectsInWorld
‪function anyObjectsInWorld(weapon)
Definition: _weaponobjects.gsc:1690
‪createHackerHint
‪function createHackerHint(name, hint)
Definition: _weaponobjects.gsc:3435
‪name
‪class GroundFx name
‪pickUpCrossbowBolt
‪function pickUpCrossbowBolt(player, heldWeapon)
Definition: _weaponobjects.gsc:3320
‪hackerThink
‪function hackerThink(trigger, watcher)
Definition: _weaponobjects.gsc:1927
‪setupReconEffect
‪function setupReconEffect()
Definition: _weaponobjects.gsc:3455
‪getWeaponObjectWatcherByWeapon
‪function getWeaponObjectWatcherByWeapon(weapon)
Definition: _weaponobjects.gsc:1194
‪onSpawnCrossbowBoltImpact
‪function onSpawnCrossbowBoltImpact(s_watcher, e_player)
Definition: _weaponobjects.gsc:2834
‪shouldAffectWeaponObject
‪function shouldAffectWeaponObject(object, watcher)
Definition: _weaponobjects.gsc:2419
‪proximitySphere
‪function proximitySphere(origin, innerRadius, inColor, outerRadius, outColor)
Definition: _weaponobjects.gsc:1708
‪start_gametype
‪function start_gametype()
Definition: _weaponobjects.gsc:28
‪destroy_other_teams_supplemental_watcher_objects
‪function destroy_other_teams_supplemental_watcher_objects(attacker, weapon)
Definition: _weaponobjects.gsc:3519
‪hackerNotMoving
‪function hackerNotMoving()
Definition: _weaponobjects.gsc:1873
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265