‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_riotshield.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\killstreaks_shared;
6 #using scripts\shared\scoreevents_shared;
7 #using scripts\shared\system_shared;
8 #using scripts\shared\util_shared;
9 
10 #insert scripts\shared\shared.gsh;
11 #insert scripts\shared\version.gsh;
12 
13 #precache( "fx", "_t6/weapon/riotshield/fx_riotshield_depoly_lights" );
14 #precache( "fx", "_t6/weapon/riotshield/fx_riotshield_depoly_dust" );
15 
16 #using_animtree ( "mp_riotshield" );
17 
18 #namespace riotshield;
19 
20 function ‪init_shared()
21 {
22  if ( !isdefined( level.weaponRiotshield ) )
23  {
24  level.weaponRiotshield = GetWeapon( "riotshield" );
25  }
26 
27  level.deployedShieldModel = "t6_wpn_shield_carry_world";
28  level.stowedShieldModel = "t6_wpn_shield_stow_world";
29  level.carriedShieldModel = "t6_wpn_shield_carry_world";
30  level.detectShieldModel = "t6_wpn_shield_carry_world_detect";
31 
32  level.riotshieldDestroyAnim = %o_riot_stand_destroyed;
33  level.riotshieldDeployAnim = %o_riot_stand_deploy;
34 
35  level.riotshieldShotAnimFront = %o_riot_stand_shot;
36  level.riotshieldShotAnimBack = %o_riot_stand_shot_back;
37 
38  level.riotshieldMeleeAnimFront = %o_riot_stand_melee_front;
39  level.riotshieldMeleeAnimBack = %o_riot_stand_melee_back;
40 
41  level.riotshield_placement_zoffset = 26;
42 
43  thread register();
44 
46 }
47 
48 //******************************************************************
49 // *
50 // *
51 //******************************************************************
52 function register()
53 {
54  ‪clientfield::register( "scriptmover", "riotshield_state", ‪VERSION_SHIP, 2, "int" );
55 }
56 
57 //******************************************************************
58 // *
59 // *
60 //******************************************************************
62 {
63  self endon ( "death" );
64  self endon ( "disconnect" );
65  self endon ( "track_riot_shield" );
66 
67  self waittill( "changed_class" );
68 
69  if (( level.inGracePeriod && !self.hasDoneCombat ))
70  {
71  self ClearStowedWeapon();
72  self RefreshShieldAttachment();
73  self thread ‪trackRiotShield();
74  }
75 }
76 
77 //******************************************************************
78 // *
79 // *
80 //******************************************************************
81 function ‪watchRiotshieldPickup() // self == player
82 {
83  self endon ( "death" );
84  self endon ( "disconnect" );
85  self endon ( "track_riot_shield" );
86 
87  self notify( "watch_riotshield_pickup" );
88  self endon( "watch_riotshield_pickup" );
89 
90  // tagTMR<NOTE>: fix for rare case when riotshield is given by the server
91  // but the client fails to equip because of prone
92 
93  self waittill( "pickup_riotshield" );
94  self endon( "weapon_change" );
95 
96  /#println( "Picked up riotshield, expecting weapon_change notify..." );#/
97 
98  wait 0.5;
99 
100  /#println( "picked up shield but didn't change weapons, attach it!" );#/
101 
102  currentWeapon = self getCurrentWeapon();
103  self.hasRiotShield = self HasRiotShield();
104  self.hasRiotShieldEquipped = ( currentWeapon.isRiotshield );
105 
106  self RefreshShieldAttachment();
107 }
108 
109 function ‪trackRiotShield() // self == player
110 {
111  self endon( "death" );
112  self endon( "disconnect" );
113 
114  self notify ( "track_riot_shield" );
115  self endon ( "track_riot_shield" );
116 
117  self thread ‪watchPregameClassChange();
118 
119  self waittill( "weapon_change", newWeapon );
120 
121  self RefreshShieldAttachment();
122 
123  currentWeapon = self getCurrentWeapon();
124  self.hasRiotShield = self HasRiotShield();
125  self.hasRiotShieldEquipped = ( currentWeapon.isRiotshield );
126  self.lastNonShieldWeapon = level.weaponNone;
127 
128  while( true )
129  {
130  self thread ‪watchRiotshieldPickup();
131  currentWeapon = self getCurrentWeapon();
132 
133  currentWeapon = self getCurrentWeapon();
134  self.hasRiotShield = self HasRiotShield();
135  self.hasRiotShieldEquipped = ( currentWeapon.isRiotshield );
136 
137  refresh_attach = false;
138 
139  self waittill( "weapon_change", newWeapon );
140 
141  if ( newWeapon.isRiotShield )
142  {
143  refresh_attach = true;
144 
145  // if we have a deployed riotshield in the world, delete if we pickup another
146  if ( isdefined( self.riotshieldEntity ))
147  {
148  self notify( "destroy_riotshield" );
149  }
150 
151  if ( self.hasRiotShield )
152  {
153  if ( isdefined( self.riotshieldTakeWeapon ))
154  {
155  self TakeWeapon( self.riotshieldTakeWeapon );
156  self.riotshieldTakeWeapon = undefined;
157  }
158  }
159 
160  if( ‪isValidNonShieldWeapon( currentWeapon ))
161  {
162  self.lastNonShieldWeapon = currentWeapon;
163  }
164  }
165 
166  if ( self.hasRiotShield || ( refresh_attach == true ))
167  {
168  self RefreshShieldAttachment();
169  }
170  }
171 }
172 
173 function ‪isValidNonShieldWeapon( weapon )
174 {
176  return false;
177 
178  if( weapon.isCarriedKillstreak )
179  return false;
180 
181  if( weapon.isGameplayWeapon )
182  return false;
183 
184  if( weapon == level.weaponNone )
185  return false;
186 
187  if ( weapon.isEquipment )
188  return false;
189 
190  return true;
191 
192 }
193 //******************************************************************
194 // *
195 // *
196 //******************************************************************
197 function ‪startRiotshieldDeploy() // self == player
198 {
199  self notify( "start_riotshield_deploy" );
200  self thread ‪watchRiotshieldDeploy();
201 }
202 
203 //******************************************************************
204 // *
205 // *
206 //******************************************************************
207 function ‪resetReconModelVisibility( owner ) // self == recon model
208 {
209  if ( !isdefined( self ) )
210  return;
211 
212  self SetInvisibleToAll();
213  self SetForceNoCull();
214 
215  if ( !isdefined( owner ) )
216  return;
217 
218  for ( i = 0 ; i < level.players.size ; i++ )
219  {
220  if( level.players[i] HasPerk( "specialty_showenemyequipment" ) )
221  {
222  if ( level.players[i].team == "spectator" )
223  continue;
224 
225  isEnemy = true;
226 
227  if ( level.teamBased )
228  {
229  if ( level.players[i].team == owner.team )
230  isEnemy = false;
231  }
232  else
233  {
234  if ( level.players[i] == owner )
235  isEnemy = false;
236  }
237 
238  if ( isEnemy )
239  {
240  self SetVisibleToPlayer( level.players[i] );
241  }
242  }
243  }
244 }
245 
246 //******************************************************************
247 // *
248 // *
249 //******************************************************************
250 function ‪resetReconModelOnEvent( eventName, owner ) // self == reconModel
251 {
252  self endon( "death" );
253 
254  for ( ;; )
255  {
256  level waittill( eventName, newOwner );
257  if( isdefined( newOwner ) )
258  {
259  owner = newOwner;
260  }
261  self ‪resetReconModelVisibility( owner );
262  }
263 }
264 
265 //******************************************************************
266 // *
267 // *
268 //******************************************************************
269 function ‪attachReconModel( modelName, owner ) // self == shield model
270 {
271  if ( !isdefined( self ) )
272  return;
273 
274  reconModel = ‪spawn( "script_model", self.origin );
275  reconModel.angles = self.angles;
276  reconModel SetModel( modelName );
277  reconModel.model_name = modelName;
278  reconModel linkto( self );
279  reconModel SetContents( 0 );
280  reconModel ‪resetReconModelVisibility( owner );
281 
282  reconModel thread ‪resetReconModelOnEvent( "joined_team", owner );
283  reconModel thread ‪resetReconModelOnEvent( "player_spawned", owner );
284 
285  self.reconModel = reconModel;
286 }
287 
288 //******************************************************************
289 // *
290 // *
291 //******************************************************************
292 function ‪spawnRiotshieldCover( origin, angles ) // self == player
293 {
294  shield_ent = ‪spawn( "script_model", origin, 1 ); // third param is spawn flag for dynamic pathing
295  shield_ent.targetname = "riotshield_mp";
296  shield_ent.angles = angles;
297  shield_ent SetModel( level.deployedShieldModel );
298  shield_ent SetOwner( self );
299  shield_ent.owner = self;
300  shield_ent.team = self.team;
301  shield_ent SetTeam( self.team );
302 
303  shield_ent ‪attachReconModel( level.detectShieldModel, self );
304 
305  shield_ent UseAnimTree( #animtree );
306  shield_ent SetScriptMoverFlag( 0 ); // SCRIPTMOVER_FLAG_RIOTSHIELD
307 
308  shield_ent DisconnectPaths();
309 
310  return shield_ent;
311 }
312 
313 //******************************************************************
314 // *
315 // *
316 //******************************************************************
317 function ‪watchRiotshieldDeploy() // self == player
318 {
319  self endon( "death" );
320  self endon( "disconnect" );
321  self endon( "start_riotshield_deploy" );
322 
323  self waittill( "deploy_riotshield", deploy_attempt, weapon );
324  self SetPlacementHint( 1 );
325 
326  placement_hint = false;
327 
328  if ( deploy_attempt )
329  {
330  placement = self CanPlaceRiotshield( "deploy_riotshield" );
331 
332  if ( placement["result"] /*&& riotshieldDistanceTest( placement["origin"] )*/)
333  {
334  self.hasDoneCombat = true;
335 
336  zoffset = level.riotshield_placement_zoffset;
337 
338  shield_ent = self ‪spawnRiotshieldCover( placement["origin"] + (0,0,zoffset), placement["angles"] );
339  item_ent = DeployRiotShield( self, shield_ent );
340 
341  primaries = self GetWeaponsListPrimaries();
342 
343  /#
344  assert( isdefined( item_ent ));
345  assert( !isdefined( self.riotshieldRetrieveTrigger ));
346  assert( !isdefined( self.riotshieldEntity ));
347  if ( level.gameType != "shrp" )
348  {
349  assert( primaries.size > 0 );
350  }
351  #/
352 
353  shield_ent ‪clientfield::set( "riotshield_state", ‪RIOTSHIELD_STATE_DEPLOYED );
354  shield_ent.reconModel ‪clientfield::set( "riotshield_state", ‪RIOTSHIELD_STATE_DEPLOYED );
355 
356  if ( level.gameType != "shrp" )
357  {
358  if( self.lastNonShieldWeapon != level.weaponNone && self hasWeapon( self.lastNonShieldWeapon ) )
359  self SwitchToWeapon( self.lastNonShieldWeapon );
360  else
361  self SwitchToWeapon( primaries[0] );
362  }
363 
364  if ( !self HasWeapon( level.weaponBaseMeleeHeld ))
365  {
366  self GiveWeapon( level.weaponBaseMeleeHeld );
367  self.riotshieldTakeWeapon = level.weaponBaseMeleeHeld;
368  }
369 
370  self.riotshieldRetrieveTrigger = item_ent;
371  self.riotshieldEntity = shield_ent;
372 
373  self thread ‪watchDeployedRiotshieldEnts();
374 
375  self thread ‪deleteShieldOnTriggerDeath( self.riotshieldRetrieveTrigger );
376  self thread ‪deleteShieldOnPlayerDeathOrDisconnect( shield_ent );
377 
378  self.riotshieldEntity thread ‪watchDeployedRiotshieldDamage();
379  level notify( "riotshield_planted", self );
380  }
381  else
382  {
383  placement_hint = true;
384 
385  clip_max_ammo = weapon.clipSize;
386  self setWeaponAmmoClip( weapon, clip_max_ammo );
387  }
388  }
389  else
390  {
391  // tagTMR<NOTE>: just lowering the shield not trying to deploy
392  placement_hint = true;
393  }
394 
395  if ( placement_hint )
396  {
397  self SetRiotshieldFailHint();
398  }
399 
400 }
401 
402 //******************************************************************
403 // *
404 // *
405 //******************************************************************
406 // tagTMR<NOTE>: distance check to keep riotshields from deploying too near each other
407 function ‪riotshieldDistanceTest( origin )
408 {
409  /#
410  assert ( isdefined( origin ));
411  #/
412 
413  min_dist_squared = GetDvarFloat( "riotshield_deploy_limit_radius" );
414  min_dist_squared *= min_dist_squared;
415 
416  for ( i = 0; i < level.players.size; i++ )
417  {
418  if ( isdefined( level.players[i].riotshieldEntity ))
419  {
420  dist_squared = DistanceSquared( level.players[i].riotshieldEntity.origin, origin );
421  if ( min_dist_squared > dist_squared )
422  {
423  /#
424  println( "Shield placement denied! Failed distance check to other riotshields." );
425  #/
426  return false;
427  }
428  }
429  }
430 
431  return true;
432 }
433 
434 //******************************************************************
435 // *
436 // *
437 //******************************************************************
438 function ‪watchDeployedRiotshieldEnts() // self == player
439 {
440  /#
441  assert( isdefined( self.riotshieldRetrieveTrigger ));
442  assert( isdefined( self.riotshieldEntity ));
443  #/
444 
445  self waittill( "destroy_riotshield" );
446 
447  if ( isdefined( self.riotshieldRetrieveTrigger ))
448  {
449  self.riotshieldRetrieveTrigger delete();
450  }
451 
452  if ( isdefined( self.riotshieldEntity ))
453  {
454  if ( isdefined( self.riotshieldEntity.reconModel ))
455  {
456  self.riotshieldEntity.reconModel delete();
457  }
458 
459  self.riotshieldEntity ConnectPaths();
460  self.riotshieldEntity delete();
461  }
462 }
463 
464 //******************************************************************
465 // *
466 // *
467 //******************************************************************
468 function ‪watchDeployedRiotshieldDamage() // self == riotshield script_model ent
469 {
470  self endon("death");
471 
472  damageMax = GetDvarInt("riotshield_deployed_health");
473  self.damageTaken = 0;
474 
475  while( true )
476  {
477  self.maxhealth = 100000;
478  self.health = self.maxhealth;
479 
480  self waittill( "damage", ‪damage, attacker, direction, point, type, tagName, modelName, partname, weapon, iDFlags );
481 
482  if( !isdefined( attacker ) )
483  {
484  continue;
485  }
486 
487  /#
488  assert( isdefined( self.owner ) && isdefined( self.owner.team ));
489  #/
490 
491  if ( isplayer( attacker ) )
492  {
493  if ( (level.teamBased) && ( attacker.team == self.owner.team ) && ( attacker != self.owner))
494  {
495  continue;
496  }
497  }
498 
499  if ( type == "MOD_MELEE" || type == "MOD_MELEE_ASSASSINATE" )
500  {
501  ‪damage *= GetDvarfloat( "riotshield_melee_damage_scale" );
502  }
503  else if ( type == "MOD_PISTOL_BULLET" || type == "MOD_RIFLE_BULLET" )
504  {
505  ‪damage *= GetDvarfloat( "riotshield_bullet_damage_scale" );
506  }
507  else if ( type == "MOD_GRENADE" || type == "MOD_GRENADE_SPLASH" || type == "MOD_EXPLOSIVE" || type == "MOD_EXPLOSIVE_SPLASH" || type == "MOD_PROJECTILE" || type == "MOD_PROJECTILE_SPLASH")
508  {
509  ‪damage *= GetDvarfloat( "riotshield_explosive_damage_scale" );
510  }
511  else if ( type == "MOD_IMPACT" )
512  {
513  ‪damage *= GetDvarFloat( "riotshield_projectile_damage_scale" );
514  }
515  else if ( type == "MOD_CRUSH" )
516  {
517  ‪damage = damageMax;
518  }
519 
520  self.damageTaken += ‪damage;
521 
522  if( self.damageTaken >= damageMax )
523  {
524  self thread ‪damageThenDestroyRiotshield( attacker, weapon );
525  break;
526  }
527  }
528 }
529 
530 //******************************************************************
531 // *
532 // *
533 //******************************************************************
534 function ‪damageThenDestroyRiotshield( attacker, weapon ) // self == riotshield script_model ent
535 {
536  self notify( "damageThenDestroyRiotshield" );
537  self endon("death");
538 
539  if ( isdefined( self.owner.riotshieldRetrieveTrigger ))
540  {
541  self.owner.riotshieldRetrieveTrigger delete();
542  }
543 
544  if ( isdefined( self.reconModel ))
545  {
546  self.reconModel delete();
547  }
548 
549  self ConnectPaths();
550  self.owner.riotshieldEntity = undefined;
551 
552  self NotSolid();
553  self ‪clientfield::set( "riotshield_state", ‪RIOTSHIELD_STATE_DESTROYED );
554 
555  if (isdefined (attacker) && attacker != self.owner && isplayer( attacker ) )
556  {
557  ‪scoreevents::processScoreEvent( "destroyed_shield", attacker, self.owner, weapon );
558  }
559 
560  wait( GetDvarFloat( "riotshield_destroyed_cleanup_time" ));
561 
562  self delete();
563 }
564 
565 //******************************************************************
566 // *
567 // *
568 //******************************************************************
569 function ‪deleteShieldOnTriggerDeath( shield_trigger ) // self == player
570 {
571  shield_trigger ‪util::waittill_any( "trigger", "death" );
572  self notify( "destroy_riotshield" );
573 }
574 
575 //******************************************************************
576 // *
577 // *
578 //******************************************************************
579 function ‪deleteShieldOnPlayerDeathOrDisconnect( shield_ent ) // self == player
580 {
581  shield_ent endon( "death" );
582  shield_ent endon( "damageThenDestroyRiotshield" );
583 
584  self ‪util::waittill_any( "death", "disconnect", "remove_planted_weapons" );
585 
586  shield_ent thread ‪damageThenDestroyRiotshield();
587 }
588 
589 //******************************************************************
590 // *
591 // *
592 //******************************************************************
593 function ‪watchRiotshieldStuckEntityDeath( grenade, owner ) // self == entity stuck with nade
594 {
595  grenade endon( "death" );
596 
597  self ‪util::waittill_any( "damageThenDestroyRiotshield", "death", "disconnect", "weapon_change", "deploy_riotshield" );
598 
599  grenade Detonate( owner );
600 }
601 
603 {
604  self thread ‪watch_riot_shield_use();
605  self thread ‪begin_other_grenade_tracking();
606 }
607 
608 function ‪watch_riot_shield_use() // self == player
609 {
610  self endon( "death" );
611  self endon( "disconnect" );
612 
613  // watcher for attaching the model to correct player bones
614  self thread ‪trackRiotShield();
615 
616  for ( ;; )
617  {
618  self waittill( "raise_riotshield" );
619  self thread ‪startRiotshieldDeploy();
620  }
621 }
622 
624 {
625  self endon( "death" );
626  self endon( "disconnect" );
627 
628  self notify( "riotshieldTrackingStart" );
629  self endon( "riotshieldTrackingStart" );
630 
631  for (;;)
632  {
633  self waittill ( "grenade_fire", grenade, weapon, cookTime );
634 
635  if ( grenade ‪util::isHacked() )
636  {
637  continue;
638  }
639 
640  switch ( weapon.name )
641  {
642  case "sticky_grenade":
643  case "proximity_grenade":
644  case "explosive_bolt":
645  grenade thread ‪check_stuck_to_shield();
646  break;
647  }
648 
649  }
650 }
651 
652 function ‪check_stuck_to_shield() // self == grenade
653 {
654  self endon( "death" );
655 
656  self waittill( "stuck_to_shield", other, owner );
657 
658  other ‪watchRiotshieldStuckEntityDeath( self, owner );
659 }
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪RIOTSHIELD_STATE_DEPLOYED
‪#define RIOTSHIELD_STATE_DEPLOYED
Definition: shared.gsh:316
‪watch_riot_shield_use
‪function watch_riot_shield_use()
Definition: _riotshield.gsc:608
‪resetReconModelVisibility
‪function resetReconModelVisibility(owner)
Definition: _riotshield.gsc:207
‪riotshieldDistanceTest
‪function riotshieldDistanceTest(origin)
Definition: _riotshield.gsc:407
‪startRiotshieldDeploy
‪function startRiotshieldDeploy()
Definition: _riotshield.gsc:197
‪trackRiotShield
‪function trackRiotShield()
Definition: _riotshield.gsc:109
‪isValidNonShieldWeapon
‪function isValidNonShieldWeapon(weapon)
Definition: _riotshield.gsc:173
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪spawnRiotshieldCover
‪function spawnRiotshieldCover(origin, angles)
Definition: _riotshield.gsc:292
‪RIOTSHIELD_STATE_DESTROYED
‪#define RIOTSHIELD_STATE_DESTROYED
Definition: shared.gsh:317
‪resetReconModelOnEvent
‪function resetReconModelOnEvent(eventName, owner)
Definition: _riotshield.gsc:250
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪watchRiotshieldDeploy
‪function watchRiotshieldDeploy()
Definition: _riotshield.gsc:317
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪watchRiotshieldStuckEntityDeath
‪function watchRiotshieldStuckEntityDeath(grenade, owner)
Definition: _riotshield.gsc:593
‪register
‪function register()
Definition: _riotshield.gsc:52
‪attachReconModel
‪function attachReconModel(modelName, owner)
Definition: _riotshield.gsc:269
‪on_player_spawned
‪function on_player_spawned()
Definition: _riotshield.gsc:602
‪watchPregameClassChange
‪function watchPregameClassChange()
Definition: _riotshield.gsc:61
‪on_spawned
‪function on_spawned(func, obj)
Definition: callbacks_shared.csc:245
‪is_killstreak_weapon
‪function is_killstreak_weapon(weapon)
Definition: killstreaks_shared.gsc:16
‪check_stuck_to_shield
‪function check_stuck_to_shield()
Definition: _riotshield.gsc:652
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪begin_other_grenade_tracking
‪function begin_other_grenade_tracking()
Definition: _riotshield.gsc:623
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪watchDeployedRiotshieldEnts
‪function watchDeployedRiotshieldEnts()
Definition: _riotshield.gsc:438
‪deleteShieldOnTriggerDeath
‪function deleteShieldOnTriggerDeath(shield_trigger)
Definition: _riotshield.gsc:569
‪damageThenDestroyRiotshield
‪function damageThenDestroyRiotshield(attacker, weapon)
Definition: _riotshield.gsc:534
‪deleteShieldOnPlayerDeathOrDisconnect
‪function deleteShieldOnPlayerDeathOrDisconnect(shield_ent)
Definition: _riotshield.gsc:579
‪isHacked
‪function isHacked()
Definition: util_shared.gsc:2493
‪init_shared
‪function init_shared()
Definition: _riotshield.gsc:20
‪watchDeployedRiotshieldDamage
‪function watchDeployedRiotshieldDamage()
Definition: _riotshield.gsc:468
‪watchRiotshieldPickup
‪function watchRiotshieldPickup()
Definition: _riotshield.gsc:81