‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_tacticalinsertion.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\challenges_shared;
5 #using scripts\shared\clientfield_shared;
6 #using scripts\shared\damagefeedback_shared;
7 #using scripts\shared\scoreevents_shared;
8 #using scripts\shared\system_shared;
9 #using scripts\shared\util_shared;
10 #using scripts\shared\weapons\_hacker_tool;
11 #using scripts\shared\weapons\_weaponobjects;
12 
13 #insert scripts\shared\shared.gsh;
14 #insert scripts\shared\version.gsh;
15 
16 #precache( "fx", "_t6/misc/fx_equip_tac_insert_light_grn" );
17 #precache( "fx", "_t6/misc/fx_equip_tac_insert_light_red" );
18 #precache( "fx", "_t6/misc/fx_equip_tac_insert_exp" );
19 
20 #namespace tacticalinsertion;
21 
22 function ‪init_shared()
23 {
24  level.weaponTacticalInsertion = GetWeapon( "tactical_insertion" );
25 
26  level._effect["tacticalInsertionFizzle"] = "_t6/misc/fx_equip_tac_insert_exp";
27 
28  ‪clientfield::register( "scriptmover", "tacticalinsertion", ‪VERSION_SHIP, 1, "int" );
29 
31 }
32 
34 {
35  self thread ‪begin_other_grenade_tracking();
36 }
37 
38 function ‪isTacSpawnTouchingCrates( origin, angles )
39 {
40  crate_ents = GetEntArray( "care_package", "script_noteworthy" );
41  mins = ( -17, -17, -40 );
42  maxs = ( 17, 17, 40 );
43  for ( i = 0 ; i < crate_ents.size ; i++ )
44  {
45  if ( crate_ents[i] IsTouchingVolume( origin + (0,0,40), mins, maxs ) )
46  {
47  return true;
48  }
49  }
50 
51  return false;
52 }
53 
54 function ‪overrideSpawn(isPredictedSpawn)
55 {
56  if ( !isdefined( self.tacticalInsertion ) )
57  return false;
58 
59  origin = self.tacticalInsertion.origin;
60  angles = self.tacticalInsertion.angles;
61  team = self.tacticalInsertion.team;
62 
63  if (!isPredictedSpawn)
64  self.tacticalInsertion ‪destroy_tactical_insertion();
65 
66  if ( team != self.team )
67  return false;
68 
69  if ( ‪isTacSpawnTouchingCrates( origin ) )
70  return false;
71 
72  if (!isPredictedSpawn)
73  {
74  self.tacticalInsertionTime = getTime();
75  self ‪spawn( origin, angles, "tactical insertion" );
76  self SetSpawnClientFlag( "SCDFL_DISABLE_LOGGING" );
77  self AddWeaponStat( level.weaponTacticalInsertion, "used", 1 );
78  }
79  return true;
80 }
81 
82 function ‪waitAndDelete( time )
83 {
84  self endon( "death" );
85 
86  // Wait a server frame to let missile fully enter the world
88 
89  // Delete grenade entity
90  self delete();
91 }
92 
93 function ‪watch( player )
94 {
95  // Remove existing tactical insertion, if it exists
96  if ( isdefined( player.tacticalInsertion ) )
97  {
98  player.tacticalInsertion ‪destroy_tactical_insertion();
99  }
100 
101  // Spawn tactical insertion
102  player thread ‪spawnTacticalInsertion();
103 
104  // Delete grenade entity
105  self ‪waitAndDelete( 0.05 );
106 }
107 
108 function ‪watchUseTrigger( trigger, ‪callback, playerSoundOnUse, npcSoundOnUse )
109 {
110  self endon( "delete" );
111 
112  while ( true )
113  {
114  trigger waittill( "trigger", player );
115 
116  if ( !isAlive( player ) )
117  continue;
118 
119  if ( !player isOnGround() )
120  continue;
121 
122  if ( isdefined( trigger.triggerTeam ) && ( player.team != trigger.triggerTeam ) )
123  continue;
124 
125  if ( isdefined( trigger.triggerTeamIgnore ) && ( player.team == trigger.triggerTeamIgnore ) )
126  continue;
127 
128  if ( isdefined( trigger.claimedBy ) && ( player != trigger.claimedBy ) )
129  continue;
130 
131  if ( player useButtonPressed() && !player.throwingGrenade && !player meleeButtonPressed() )
132  {
133  if ( isdefined( playerSoundOnUse ) )
134  player playLocalSound( playerSoundOnUse );
135  if ( isdefined( npcSoundOnUse ) )
136  player playSound( npcSoundOnUse );
137 
138  self thread [[‪callback]]( player );
139  }
140  }
141 }
142 
144 {
145  self.tacticalInsertion endon( "delete" );
146 
147  self waittill( "disconnect" );
148  self.tacticalInsertion thread ‪destroy_tactical_insertion();
149 }
150 
152 {
153  self.owner.tacticalInsertion = undefined;
154  self notify( "delete" );
155  self.owner notify( "tactical_insertion_destroyed" );
156 
157  self.friendlyTrigger delete();
158  self.enemyTrigger delete();
159  // "destroyed_explosive" notify, for challenges
160  if ( isdefined( attacker ) && isdefined( attacker.pers["team"] ) && isdefined( self.owner ) && isdefined( self.owner.pers["team"] ) )
161  {
162  if ( level.teambased )
163  {
164  if ( attacker.pers["team"] != self.owner.pers["team"] )
165  {
166  attacker notify("destroyed_explosive");
169  ‪scoreevents::processScoreEvent( "destroyed_tac_insert", attacker );
170  }
171  }
172  else
173  {
174  if ( attacker!= self.owner )
175  {
176  attacker notify("destroyed_explosive");
179  ‪scoreevents::processScoreEvent( "destroyed_tac_insert", attacker );
180  }
181  }
182  }
183 
184  self delete();
185 }
186 
187 function ‪fizzle( attacker )
188 {
189  if ( isdefined( self.‪fizzle ) && self.‪fizzle )
190  return;
191  self.fizzle = true;
192  PlayFX( level._effect["tacticalInsertionFizzle"], self.origin );
193  self playsound ("dst_tac_insert_break");
194  //Notify player that their tact insert was destroyed
195  if ( isdefined( attacker ) && attacker != self.owner )
196  {
197  if( isdefined( level.globallogic_audio_dialog_on_player_override ) )//TODO T7 - remove once globallogic_audio is shared
198  {
199  self.owner [[level.globallogic_audio_dialog_on_player_override]]( "tact_destroyed", "item_destroyed" );
200  }
201  }
202 
203  self ‪destroy_tactical_insertion( attacker );
204 }
205 
206 function ‪pickUp( attacker )
207 {
208  player = self.owner;
210  player GiveWeapon( level.weaponTacticalInsertion );
211  player setWeaponAmmoClip( level.weaponTacticalInsertion, 1 );
212 }
213 
214 function ‪spawnTacticalInsertion() // self == player
215 {
216  self endon( "disconnect" );
217 
218  // Setup model
219  self.tacticalInsertion = ‪spawn( "script_model", self.origin + ( 0, 0, 1 ) );
220  self.tacticalInsertion setModel( "t6_wpn_tac_insert_world" );
221  self.tacticalInsertion.origin = self.origin + ( 0, 0, 1 );
222  self.tacticalInsertion.angles = self.angles;
223  self.tacticalInsertion.team = self.team;
224  self.tacticalInsertion setTeam( self.team );
225  self.tacticalInsertion.owner = self;
226  self.tacticalInsertion setOwner( self );
227  self.tacticalInsertion setWeapon( level.weaponTacticalInsertion );
228 
229  // setup recon model
230  self.tacticalInsertion thread ‪weaponobjects::setupReconEffect();
231 
232  self.tacticalInsertion endon( "delete" );
233 
234  self.tacticalInsertion ‪hacker_tool::registerWithHackerTool( level.equipmentHackerToolRadius, level.equipmentHackerToolTimeMs );
235 
236  // Make usable
237  triggerHeight = 64;
238  triggerRadius = 128;
239 
240  self.tacticalInsertion.friendlyTrigger = ‪spawn( "trigger_radius_use", self.tacticalInsertion.origin + ( 0, 0, 3 ) );
241  self.tacticalInsertion.friendlyTrigger SetCursorHint( "HINT_NOICON", self.tacticalInsertion );
242  self.tacticalInsertion.friendlyTrigger SetHintString( &"MP_TACTICAL_INSERTION_PICKUP" );
243  if ( level.teamBased )
244  {
245  self.tacticalInsertion.friendlyTrigger SetTeamForTrigger( self.team );
246  self.tacticalInsertion.friendlyTrigger.triggerTeam = self.team;
247  }
248  self ClientClaimTrigger( self.tacticalInsertion.friendlyTrigger );
249  self.tacticalInsertion.friendlyTrigger.claimedBy = self;
250 
251  self.tacticalInsertion.enemyTrigger = ‪spawn( "trigger_radius_use", self.tacticalInsertion.origin + ( 0, 0, 3 ) );
252  self.tacticalInsertion.enemyTrigger SetCursorHint( "HINT_NOICON", self.tacticalInsertion );
253  self.tacticalInsertion.enemyTrigger SetHintString( &"MP_TACTICAL_INSERTION_DESTROY" );
254  self.tacticalInsertion.enemyTrigger SetInvisibleToPlayer( self );
255  if ( level.teamBased )
256  {
257  self.tacticalInsertion.enemyTrigger SetExcludeTeamForTrigger( self.team );
258  self.tacticalInsertion.enemyTrigger.triggerTeamIgnore = self.team;
259  }
260 
261  self.tacticalInsertion ‪clientfield::set( "tacticalinsertion", 1 );
262 
263  self thread ‪watchDisconnect();
264  watcher = ‪weaponobjects::getWeaponObjectWatcherByWeapon( level.weaponTacticalInsertion );
265  self.tacticalInsertion thread ‪watchUseTrigger( self.tacticalInsertion.friendlyTrigger,&‪pickUp, watcher.pickUpSoundPlayer, watcher.pickUpSound );
266  self.tacticalInsertion thread ‪watchUseTrigger( self.tacticalInsertion.enemyTrigger,&‪fizzle );
267 
268  if ( isdefined( self.tacticalInsertionCount ) )
269  self.tacticalInsertionCount++;
270  else
271  self.tacticalInsertionCount = 1;
272 
273  self.tacticalInsertion SetCanDamage( true );
274  self.tacticalInsertion.health = 1;
275 
276  while ( true )
277  {
278  self.tacticalInsertion waittill( "damage", ‪damage, attacker, direction, point, type, tagName, modelName, partname, weapon, iDFlags );
279 
280  if ( level.teamBased && ( !isdefined( attacker ) || !isPlayer( attacker ) || attacker.team == self.team ) && attacker != self )
281  continue;
282 
283  if( attacker != self )
284  {
285  attacker ‪challenges::destroyedEquipment( weapon );
287  ‪scoreevents::processScoreEvent( "destroyed_tac_insert", attacker );
288  }
289 
290  // most equipment should be flash/concussion-able, so it'll disable for a short period of time
291  // check to see if the equipment has been flashed/concussed and disable it (checking damage < 5 is a bad idea, so check the weapon name)
292  // we're currently allowing the owner/teammate to flash their own
293  // do damage feedback
294  if ( watcher.stunTime > 0 && weapon.doStun )
295  {
296  self thread ‪weaponobjects::stunStart( watcher, watcher.stunTime );
297  }
298 
299  if ( weapon.doDamageFeedback )
300  {
301  // if we're not on the same team then show damage feedback
302  if ( level.teambased && self.tacticalInsertion.owner.team != attacker.team )
303  {
304  if ( ‪damagefeedback::doDamageFeedback( weapon, attacker ) )
305  attacker ‪damagefeedback::update();
306  }
307  // for ffa just make sure the owner isn't the same
308  else if ( !level.teambased && self.tacticalInsertion.owner != attacker )
309  {
310  if ( ‪damagefeedback::doDamageFeedback( weapon, attacker ) )
311  attacker ‪damagefeedback::update();
312  }
313  }
314 
315  //Notify player that their tact insert was destroyed
316  if ( isdefined( attacker ) && attacker != self )
317  {
318  if( isdefined( level.globallogic_audio_dialog_on_player_override ) )//TODO T7 - remove once globallogic_audio is shared
319  {
320  self [[level.globallogic_audio_dialog_on_player_override]]( "tact_destroyed", "item_destroyed" );
321  }
322  }
323 
324  self.tacticalInsertion thread ‪fizzle();
325  }
326 }
327 
329 {
330  if ( !isdefined( self.tacticalInsertion ) )
331  {
332  return;
333  }
334 
335  text = ‪cancel_text_create();
336 
337  self thread ‪cancel_button_press();
338 
339  event = self ‪util::waittill_any_return( "tactical_insertion_destroyed", "disconnect", "end_killcam", "abort_killcam", "tactical_insertion_canceled", "spawned" );
340 
341  if ( event == "tactical_insertion_canceled" )
342  {
343  self.tacticalInsertion ‪destroy_tactical_insertion();
344  }
345 
346  if ( isdefined( text ) )
347  {
348  text Destroy();
349  }
350 }
351 
353 {
354  if( level.console )
355  return self changeSeatButtonPressed();
356  else
357  return self jumpButtonPressed();
358 }
359 
361 {
362  self endon( "disconnect" );
363  self endon( "end_killcam" );
364  self endon( "abort_killcam" );
365 
366  while( true )
367  {
368  wait( .05 );
369  if ( self ‪cancelTackInsertionButton() )
370  break;
371  }
372 
373  self notify( "tactical_insertion_canceled" );
374 }
375 
377 {
378  text = NewClientHudElem( self );
379  text.archived = false;
380  text.y = -100;
381  text.alignX = "center";
382  text.alignY = "middle";
383  text.horzAlign = "center";
384  text.vertAlign = "bottom";
385  text.sort = 10; // force to draw after the bars
386  text.font = "small";
387  text.foreground = true;
388  text.hideWhenInMenu = true;
389 
390  if ( self IsSplitscreen() )
391  {
392  text.y = -80;
393  text.fontscale = 1.2;
394  }
395  else
396  {
397  text.fontscale = 1.6;
398  }
399 
400  text setText( &"PLATFORM_PRESS_TO_CANCEL_TACTICAL_INSERTION" );
401  text.alpha = 1;
402 
403  return text;
404 }
405 
407 {
408  tac_inserts = [];
409 
410  foreach( player in level.players )
411  {
412  if ( isdefined( player.tacticalInsertion ))
413  {
414  tac_inserts[ tac_inserts.size ] = player.tacticalInsertion;
415  }
416  }
417 
418  return tac_inserts;
419 }
420 
421 function ‪tacticalInsertionDestroyedByTrophySystem( attacker, trophySystem ) // self == tac insert
422 {
423  owner = self.owner;
424 
425  if ( isdefined( attacker ))
426  {
427  attacker ‪challenges::destroyedEquipment( trophySystem.name );
429  }
430 
431  self thread ‪fizzle();
432 
433  if( isdefined( owner ))
434  {
435  owner endon( "death" );
436  owner endon( "disconnect" );
437 
438  wait (.05); // prevents clash with the player killed/lead change leader dialog(s)
439 
440  if( isdefined( level.globallogic_audio_dialog_on_player_override ) )//TODO T7 - remove once globallogic_audio is shared
441  {
442  owner [[level.globallogic_audio_dialog_on_player_override]]( "tact_destroyed", "item_destroyed" );
443  }
444  }
445 }
446 
448 {
449  self endon( "death" );
450  self endon( "disconnect" );
451 
452  self notify( "insertionTrackingStart" );
453  self endon( "insertionTrackingStart" );
454 
455  for (;;)
456  {
457  self waittill ( "grenade_fire", grenade, weapon, cookTime );
458 
459  if ( grenade ‪util::isHacked() )
460  {
461  continue;
462  }
463 
464  if ( weapon == level.weaponTacticalInsertion )
465  {
466  grenade thread ‪watch( self );
467  }
468  }
469 }
‪registerWithHackerTool
‪function registerWithHackerTool(radius, hackTimeMs)
Definition: _hacker_tool.gsc:944
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪overrideSpawn
‪function overrideSpawn(isPredictedSpawn)
Definition: _tacticalinsertion.gsc:54
‪isTacSpawnTouchingCrates
‪function isTacSpawnTouchingCrates(origin, angles)
Definition: _tacticalinsertion.gsc:38
‪cancel_text_create
‪function cancel_text_create()
Definition: _tacticalinsertion.gsc:376
‪tacticalInsertionDestroyedByTrophySystem
‪function tacticalInsertionDestroyedByTrophySystem(attacker, trophySystem)
Definition: _tacticalinsertion.gsc:421
‪destroyedEquipment
‪function destroyedEquipment(weapon)
Definition: challenges_shared.gsc:43
‪getTacticalInsertions
‪function getTacticalInsertions()
Definition: _tacticalinsertion.gsc:406
‪destroyedTacticalInsert
‪function destroyedTacticalInsert()
Definition: challenges_shared.gsc:72
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪watch
‪function watch(player)
Definition: _tacticalinsertion.gsc:93
‪waittill_any_return
‪function waittill_any_return(string1, string2, string3, string4, string5, string6, string7)
Definition: util_shared.csc:212
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪fizzle
‪function fizzle(attacker)
Definition: _tacticalinsertion.gsc:187
‪cancelTackInsertionButton
‪function cancelTackInsertionButton()
Definition: _tacticalinsertion.gsc:352
‪cancel_button_think
‪function cancel_button_think()
Definition: _tacticalinsertion.gsc:328
‪on_player_spawned
‪function on_player_spawned()
Definition: _tacticalinsertion.gsc:33
‪cancel_button_press
‪function cancel_button_press()
Definition: _tacticalinsertion.gsc:360
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪begin_other_grenade_tracking
‪function begin_other_grenade_tracking()
Definition: _tacticalinsertion.gsc:447
‪on_spawned
‪function on_spawned(func, obj)
Definition: callbacks_shared.csc:245
‪doDamageFeedback
‪function doDamageFeedback(weapon, eInflictor, iDamage, sMeansOfDeath)
Definition: damagefeedback_shared.gsc:423
‪watchUseTrigger
‪function watchUseTrigger(trigger, callback, playerSoundOnUse, npcSoundOnUse)
Definition: _tacticalinsertion.gsc:108
‪spawnTacticalInsertion
‪function spawnTacticalInsertion()
Definition: _tacticalinsertion.gsc:214
‪watchDisconnect
‪function watchDisconnect()
Definition: _tacticalinsertion.gsc:143
‪waitAndDelete
‪function waitAndDelete(time)
Definition: _tacticalinsertion.gsc:82
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪pickUp
‪function pickUp(attacker)
Definition: _tacticalinsertion.gsc:206
‪destroy_tactical_insertion
‪function destroy_tactical_insertion(attacker)
Definition: _tacticalinsertion.gsc:151
‪init_shared
‪function init_shared()
Definition: _tacticalinsertion.gsc:22
‪update
‪function update()
Definition: _serversettings.gsc:71
‪stunStart
‪function stunStart(watcher, time)
Definition: _weaponobjects.gsc:1077
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪isHacked
‪function isHacked()
Definition: util_shared.gsc:2493
‪setupReconEffect
‪function setupReconEffect()
Definition: _weaponobjects.gsc:3455
‪getWeaponObjectWatcherByWeapon
‪function getWeaponObjectWatcherByWeapon(weapon)
Definition: _weaponobjects.gsc:1194
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265