‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_destructible.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\challenges_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\system_shared;
6 
7 #insert scripts\shared\shared.gsh;
8 #insert scripts\shared\version.gsh;
9 #insert scripts\zm\_destructible.gsh;
10 
11 #using scripts\zm\gametypes\_globallogic_player;
12 
13 #using scripts\zm\_challenges;
14 
15 #insert scripts\shared\clientfields.gsh;
16 
17 #namespace destructible;
18 
19 #using_animtree ( "mp_vehicles" );
20 
21 #define EXPLODE_COMPLEX 300
22 #define CONCUSSIVE_DAMAGE_RADIUS_LG 280
23 #define CONCUSSIVE_DAMAGE_RADIUS_SM 220
24 #define ELECTRICAL_DAMAGE_RADIUS_LG 60
25 #define ELECTRICAL_DAMAGE_RADIUS_SM 210
26 #define INCENDIARY_DAMAGE_RADIUS_LG 250
27 #define INCENDIARY_DAMAGE_RADIUS_SM 200
28 
29 #define CONCUSSIVE_EXPLOSION_DMG_MIN 50
30 #define CONCUSSIVE_EXPLOSION_DMG_MAX 300
31 #define ELECTRICAL_EXPLOSION_DMG_MIN 80
32 #define ELECTRICAL_EXPLOSION_DMG_MAX 350
33 #define INCENDIARY_EXPLOSION_DMG_MIN 95
34 #define INCENDIARY_EXPLOSION_DMG_MAX 380
35 
36 ‪REGISTER_SYSTEM( "destructible", &‪__init__, undefined )
37 
38 function ‪__init__()
39 {
40  level.destructible_callbacks = [];
41  destructibles = GetEntArray( "destructible", "targetname" );
42 
44 
45  // since this is globally run, only continue if we have a destructible in the level
46  if( destructibles.size <= 0 )
47  {
48  return;
49  }
50 
51  for ( i = 0; i < destructibles.size; i++ )
52  {
53  if ( GetSubStr( destructibles[i].destructibledef, 0, 4 ) == "veh_" )
54  {
55  destructibles[i] thread ‪destructible_car_death_think();
56  destructibles[i] thread ‪destructible_car_grenade_stuck_think();
57  }
58  }
59 
61 }
62 
64 {
65  level.explosion_manager = SpawnStruct();
66  level.explosion_manager.count = 0;
67  level.explosion_manager.a_explosions = [];
68 
69  i = 0;
70  while( i < 32 )
71  {
72  sExplosion = ‪Spawn( "script_model", (0,0,0) );
73  ‪ARRAY_ADD( level.explosion_manager.a_explosions, sExplosion );
74  i++;
75  }
76 }
77 
79 {
80  foreach( explosion in level.explosion_manager.a_explosions )
81  {
82  if( !‪IS_TRUE( explosion.in_use ) )
83  {
84  return explosion;
85  }
86  }
87  return level.explosion_manager.a_explosions[0];
88 }
89 
90 function ‪physics_explosion_and_rumble( origin, radius, physics_explosion )
91 {
92  sExplosion = ‪get_unused_explosion();
93  sExplosion.in_use = true;
94  sExplosion.origin = origin;
95 
96  assert( radius <= ‪pow( 2, ‪DESTRUCTIBLE_CLIENTFIELD_NUM_BITS ) - 1 );
97 
98  if( ‪IS_TRUE( physics_explosion ) )
99  {
100  radius += ( 1 << ( ‪DESTRUCTIBLE_CLIENTFIELD_NUM_BITS - 1 ) );
101  }
102 
104 
105  sExplosion ‪clientfield::set( ‪DESTRUCTIBLE_CLIENTFIELD, radius );
106 
107  sExplosion.in_use = false;
108 }
109 
110 function ‪destructible_event_callback( destructible_event, attacker, weapon ) // self == the destructible object (like the car or barrel)
111 {
112  explosion_radius = 0;
113  if(IsSubStr(destructible_event, "explode") && destructible_event != "explode")
114  {
115  tokens = StrTok(destructible_event, "_");
116  explosion_radius = tokens[1];
117 
118  if(explosion_radius == "sm")
119  {
120  explosion_radius = 150;
121  }
122  else if(explosion_radius == "lg")
123  {
124  explosion_radius = 450;
125  }
126  else
127  {
128  explosion_radius = Int(explosion_radius);
129  }
130 
131  destructible_event = "explode_complex"; // use a different explosion function
132  }
133 
134  // Until these are moved into GDTs:
135  // Determine the type of explosive.
136  // Assign use the correct explosion radius.
137  if( IsSubStr( destructible_event, "explosive" ) )
138  {
139  // Grab damage type and radius
140  tokens = StrTok(destructible_event, "_");
141  damage_type = tokens[2];
142  explosion_radius_type = tokens[3];
143 
144  // Set a default radius in case this doesn't catch somewhere.
145  explosion_radius = 300;
146 
147  // Determine damage type
148  switch ( damage_type )
149  {
150  case "concussive":
151  if(explosion_radius_type == "large")
152  {
153  explosion_radius = ‪CONCUSSIVE_DAMAGE_RADIUS_LG;
154  }
155  else
156  {
157  explosion_radius = ‪CONCUSSIVE_DAMAGE_RADIUS_SM;
158  }
159 
160  break;
161 
162  case "electrical":
163 
164  if(explosion_radius_type == "large")
165  {
166  explosion_radius = ‪ELECTRICAL_DAMAGE_RADIUS_LG;
167  }
168  else
169  {
170  explosion_radius = ‪ELECTRICAL_DAMAGE_RADIUS_SM;
171  }
172  break;
173 
174  case "incendiary":
175  if(explosion_radius_type == "large")
176  {
177  explosion_radius = ‪INCENDIARY_DAMAGE_RADIUS_LG;
178  }
179  else
180  {
181  explosion_radius = ‪INCENDIARY_DAMAGE_RADIUS_SM;
182  }
183  break;
184  }
185  }
186 
187  if ( IsSubStr( destructible_event, "simple_timed_explosion" ) )
188  {
189  self thread ‪simple_timed_explosion( destructible_event, attacker );
190  return;
191  }
192 
193  switch ( destructible_event )
194  {
195  case "destructible_car_explosion":
196  self ‪destructible_car_explosion( attacker );
197  if ( isdefined( weapon ) )
198  {
199  self.destroyingWeapon = weapon;
200  }
201  break;
202 
203  case "destructible_car_fire":
204  self thread ‪destructible_car_fire_think(attacker);
205  if ( isdefined( weapon ) )
206  {
207  self.destroyingWeapon = weapon;
208  }
209  break;
210 
211  case "explode":
212  self thread ‪simple_explosion( attacker );
213  break;
214 
215  case "explode_complex":
216  self thread ‪complex_explosion( attacker, explosion_radius );
217  break;
218 
219  case "destructible_explosive_incendiary_small":
220  case "destructible_explosive_incendiary_large":
221  self ‪explosive_incendiary_explosion( attacker, explosion_radius, false );
222  if ( isdefined( weapon ) )
223  {
224  self.destroyingWeapon = weapon;
225  }
226  break;
227 
228  case "destructible_explosive_electrical_small":
229  case "destructible_explosive_electrical_large":
230  self ‪explosive_electrical_explosion( attacker, explosion_radius, false );
231  if ( isdefined( weapon ) )
232  {
233  self.destroyingWeapon = weapon;
234  }
235  break;
236 
237  case "destructible_explosive_concussive_small":
238  case "destructible_explosive_concussive_large":
239  self ‪explosive_concussive_explosion( attacker, explosion_radius, false );
240  if ( isdefined( weapon ) )
241  {
242  self.destroyingWeapon = weapon;
243  }
244  break;
245 
246  default:
247  //iprintln( "_destructible.gsc: unknown destructible event: '" + destructible_event + "'" );
248  break;
249  }
250 
251  if ( isdefined( level.destructible_callbacks[ destructible_event ] ) )
252  {
253  self thread [[level.destructible_callbacks[ destructible_event ]]]( destructible_event, attacker );
254  }
255 }
256 
257 function ‪simple_explosion( attacker )
258 {
259  offset = (0, 0, 5);
260  self RadiusDamage( self.origin + offset, 256, 300, 75, attacker, "MOD_EXPLOSIVE", GetWeapon( "explodable_barrel" ) );
261  ‪physics_explosion_and_rumble( self.origin, 255, true );
262  if ( isdefined( attacker ) )
263  {
264  self DoDamage( self.health + 10000, self.origin + offset, attacker );
265  }
266  else
267  {
268  self DoDamage( self.health + 10000, self.origin + offset );
269  }
270 }
271 
272 function ‪simple_timed_explosion( destructible_event, attacker )
273 {
274  self endon( "death" );
275 
276  wait_times = [];
277 
278  str = GetSubStr( destructible_event, 23 /* strlen( simple_timed_explosion ) */ );
279  tokens = StrTok( str, "_" );
280 
281  for ( i = 0; i < tokens.size; i++ )
282  {
283  wait_times[ wait_times.size ] = Int( tokens[i] );
284  }
285 
286  if ( wait_times.size <= 0 )
287  {
288  wait_times[ 0 ] = 5;
289  wait_times[ 1 ] = 10;
290  }
291 
292  wait( RandomIntRange( wait_times[0], wait_times[1] ) );
293  ‪simple_explosion( attacker );
294 }
295 
296 function ‪complex_explosion( attacker, max_radius )
297 {
298  offset = (0, 0, 5);
299 
300  if( isdefined( attacker ) )
301  {
302  self RadiusDamage( self.origin + offset, max_radius, 300, 100, attacker );
303  }
304  else
305  {
306  self RadiusDamage( self.origin + offset, max_radius, 300, 100 );
307  }
308 
309  ‪physics_explosion_and_rumble(self.origin, max_radius, true );
310 
311  if( isdefined( attacker ) )
312  {
313  self DoDamage( 20000, self.origin + offset, attacker );
314  }
315  else
316  {
317  self DoDamage( 20000, self.origin + offset );
318  }
319 }
320 
321 
322 function ‪destructible_car_explosion( attacker, physics_explosion )
323 {
324  if ( self.car_dead )
325  {
326  // prevents recursive entry caused by DoDamage call below
327  return;
328  }
329 
330  if ( !isdefined( physics_explosion ) )
331  {
332  physics_explosion = true;
333  }
334 
335  self notify( "car_dead" );
336  self.car_dead = true;
337 
338  if ( isdefined( attacker ))
339  {
340  self RadiusDamage( self.origin, 256, 300, 75, attacker, "MOD_EXPLOSIVE", GetWeapon( "destructible_car" ) );
341  }
342  else
343  {
344  self RadiusDamage( self.origin, 256, 300, 75 );
345  }
346  ‪physics_explosion_and_rumble(self.origin, 255, physics_explosion );
347 
348  level.globalCarsDestroyed++;
349  if ( isdefined ( attacker ) )
350  {
351  self DoDamage( self.health + 10000, self.origin + (0, 0, 1), attacker );
352  }
353  else
354  {
355  self DoDamage( self.health + 10000, self.origin + (0, 0, 1));
356  }
357 
358  self MarkDestructibleDestroyed();
359 }
360 
362 {
363  self endon( "car_dead" );
364  self.car_dead = false;
365 
366  self thread ‪destructible_car_death_notify();
367 
368  self waittill( "destructible_base_piece_death", attacker );
369 
370  if ( isdefined( self ) )
371  {
372  self thread ‪destructible_car_explosion( attacker, false );
373  }
374 }
375 
377 {
378  self endon( "destructible_base_piece_death" );
379  self endon( "car_dead" );
380  self endon( "death" );
381 
382  for ( ;; )
383  {
384  self waittill( "grenade_stuck", missile );
385 
386  if ( !isdefined( missile ) || !isdefined( missile.model ) )
387  {
388  continue;
389  }
390 
391  if ( missile.model == "t5_weapon_crossbow_bolt" || missile.model == "t6_wpn_grenade_semtex_projectile" || missile.model == "wpn_t7_c4_world" )
392  {
393  self thread ‪destructible_car_grenade_stuck_explode( missile );
394  }
395  }
396 }
397 
399 {
400  self endon( "destructible_base_piece_death" );
401  self endon( "car_dead" );
402  self endon( "death" );
403 
404  owner = GetMissileOwner( missile );
405 
406  if ( isdefined( owner ) && missile.model == "wpn_t7_c4_world" )
407  {
408  owner endon( "disconnect" );
409  owner endon( "weapon_object_destroyed" );
410  missile endon( "picked_up" );
411 
412  missile thread ‪destructible_car_hacked_c4( self );
413  }
414 
415  missile waittill( "explode" );
416 
417  if ( isdefined( owner ) )
418  {
419  self DoDamage( self.health + 10000, self.origin + (0, 0, 1), owner );
420  }
421  else
422  {
423  self DoDamage( self.health + 10000, self.origin + (0, 0, 1) );
424  }
425 }
426 
428 {
429  car endon( "destructible_base_piece_death" );
430  car endon( "car_dead" );
431  car endon( "death" );
432  self endon( "death" );
433 
434  self waittill( "hacked" );
435 
436  self notify( "picked_up" );
438 }
439 
441 {
442  self endon( "car_dead" );
443 
444  self waittill( "death", attacker );
445  self notify( "destructible_base_piece_death", attacker );
446 }
447 
449 {
450  self endon( "death" );
451 
452  wait( RandomIntRange( 7, 10 ) );
453 
454  self thread ‪destructible_car_explosion( attacker );
455 }
456 
457 function ‪CodeCallback_DestructibleEvent( event, param1, param2, param3, param4 )
458 {
459  if( event == "broken" )
460  {
461  notify_type = param1;
462  attacker = param2;
463  piece = param3;
464  weapon = param4;
465 
466  ‪destructible_event_callback( notify_type, attacker, weapon );
467 
468  self notify( event, notify_type, attacker );
469  }
470  else if( event == "breakafter" )
471  {
472  piece = param1;
473  time = param2;
474  ‪damage = param3;
475  self thread ‪breakAfter( time, ‪damage, piece );
476  }
477 }
478 
479 function ‪breakAfter( time, ‪damage, piece )
480 {
481  self notify( "breakafter" );
482  self endon( "breakafter" );
483 
484  wait time;
485 
486  // this does not work in mp. DoDamage does not take a piece for mp.
487  self dodamage( ‪damage, self.origin, undefined, /*piece*/undefined );
488 }
489 
490 function ‪explosive_incendiary_explosion( attacker, explosion_radius, physics_explosion )
491 {
492  if ( !IsVehicle( self ) )
493  {
494  offset = (0, 0, 5);
495  if ( isdefined( attacker ))
496  {
497  self RadiusDamage( self.origin + offset, explosion_radius, ‪INCENDIARY_EXPLOSION_DMG_MAX, ‪INCENDIARY_EXPLOSION_DMG_MIN, attacker, "MOD_BURNED", GetWeapon( "incendiary_fire" ) );
498  }
499  else
500  {
501  self RadiusDamage( self.origin + offset, explosion_radius, ‪INCENDIARY_EXPLOSION_DMG_MAX, ‪INCENDIARY_EXPLOSION_DMG_MIN );
502  }
503  ‪physics_explosion_and_rumble(self.origin, 255, physics_explosion );
504 
505  }
506 
507 
508  // delete the clip that is attached
509  if( isdefined( self.target ) )
510  {
511  dest_clip = GetEnt( self.target, "targetname" );
512  if( isDefined( dest_clip ) )
513  {
514  dest_clip delete();
515  }
516  }
517 
518  self MarkDestructibleDestroyed();
519 }
520 
521 function ‪explosive_electrical_explosion( attacker, explosion_radius, physics_explosion )
522 {
523  if ( !IsVehicle( self ) )
524  {
525  offset = (0, 0, 5);
526  if ( isdefined( attacker ))
527  {
528  self RadiusDamage( self.origin + offset, explosion_radius, ‪ELECTRICAL_EXPLOSION_DMG_MAX, ‪ELECTRICAL_EXPLOSION_DMG_MIN, attacker, "MOD_ELECTROCUTED" );
529  }
530  else
531  {
532  self RadiusDamage( self.origin + offset, explosion_radius, ‪ELECTRICAL_EXPLOSION_DMG_MAX, ‪ELECTRICAL_EXPLOSION_DMG_MIN );
533  }
534  ‪physics_explosion_and_rumble(self.origin, 255, physics_explosion );
535 
536  }
537 
538 
539  // delete the clip that is attached
540  if( isdefined( self.target ) )
541  {
542  dest_clip = GetEnt( self.target, "targetname" );
543  if( isDefined( dest_clip ) )
544  {
545  dest_clip delete();
546  }
547  }
548 
549  self MarkDestructibleDestroyed();
550 }
551 
552 function ‪explosive_concussive_explosion( attacker, explosion_radius, physics_explosion )
553 {
554  if ( !IsVehicle( self ) )
555  {
556  offset = (0, 0, 5);
557  if ( isdefined( attacker ))
558  {
559  self RadiusDamage( self.origin + offset, explosion_radius, ‪CONCUSSIVE_EXPLOSION_DMG_MAX, ‪CONCUSSIVE_EXPLOSION_DMG_MIN, attacker, "MOD_GRENADE" );
560  }
561  else
562  {
563  self RadiusDamage( self.origin + offset, explosion_radius, ‪CONCUSSIVE_EXPLOSION_DMG_MAX, ‪CONCUSSIVE_EXPLOSION_DMG_MIN );
564  }
565  ‪physics_explosion_and_rumble(self.origin, 255, physics_explosion );
566  }
567 
568 
569  // delete the clip that is attached
570  if( isdefined( self.target ) )
571  {
572  dest_clip = GetEnt( self.target, "targetname" );
573  if( isDefined( dest_clip ) )
574  {
575  dest_clip delete();
576  }
577  }
578 
579  self MarkDestructibleDestroyed();
580 }
‪__init__
‪function __init__()
Definition: _destructible.gsc:23
‪INCENDIARY_DAMAGE_RADIUS_SM
‪#define INCENDIARY_DAMAGE_RADIUS_SM
Definition: _destructible.gsc:27
‪simple_explosion
‪function simple_explosion(attacker)
Definition: _destructible.gsc:216
‪breakAfter
‪function breakAfter(time, damage, piece)
Definition: _destructible.gsc:510
‪CONCUSSIVE_EXPLOSION_DMG_MIN
‪#define CONCUSSIVE_EXPLOSION_DMG_MIN
Definition: _destructible.gsc:29
‪explosive_concussive_explosion
‪function explosive_concussive_explosion(attacker, explosion_radius, physics_explosion)
Definition: _destructible.gsc:582
‪destructible_car_grenade_stuck_explode
‪function destructible_car_grenade_stuck_explode(missile)
Definition: _destructible.gsc:398
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪DESTRUCTIBLE_CLIENTFIELD_NUM_BITS
‪#define DESTRUCTIBLE_CLIENTFIELD_NUM_BITS
Definition: _destructible.gsh:2
‪ELECTRICAL_EXPLOSION_DMG_MIN
‪#define ELECTRICAL_EXPLOSION_DMG_MIN
Definition: _destructible.gsc:31
‪INCENDIARY_EXPLOSION_DMG_MIN
‪#define INCENDIARY_EXPLOSION_DMG_MIN
Definition: _destructible.gsc:33
‪CONCUSSIVE_DAMAGE_RADIUS_LG
‪#define CONCUSSIVE_DAMAGE_RADIUS_LG
Definition: _destructible.gsc:22
‪destructible_car_grenade_stuck_think
‪function destructible_car_grenade_stuck_think()
Definition: _destructible.gsc:376
‪ELECTRICAL_EXPLOSION_DMG_MAX
‪#define ELECTRICAL_EXPLOSION_DMG_MAX
Definition: _destructible.gsc:32
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪get_unused_explosion
‪function get_unused_explosion()
Definition: _destructible.gsc:69
‪INCENDIARY_EXPLOSION_DMG_MAX
‪#define INCENDIARY_EXPLOSION_DMG_MAX
Definition: _destructible.gsc:34
‪damage
‪function damage(trap)
Definition: _zm_trap_electric.gsc:116
‪pow
‪function pow(base, exp)
Definition: math_shared.gsc:544
‪destructible_car_hacked_c4
‪function destructible_car_hacked_c4(car)
Definition: _destructible.gsc:427
‪explosive_incendiary_explosion
‪function explosive_incendiary_explosion(attacker, explosion_radius, physics_explosion)
Definition: _destructible.gsc:521
‪destructible_car_fire_think
‪function destructible_car_fire_think(attacker)
Definition: _destructible.gsc:448
‪complex_explosion
‪function complex_explosion(attacker, max_radius)
Definition: _destructible.gsc:263
‪ELECTRICAL_DAMAGE_RADIUS_SM
‪#define ELECTRICAL_DAMAGE_RADIUS_SM
Definition: _destructible.gsc:25
‪DESTRUCTIBLE_CLIENTFIELD
‪#define DESTRUCTIBLE_CLIENTFIELD
Definition: _destructible.gsh:1
‪ARRAY_ADD
‪#define ARRAY_ADD(__array, __item)
Definition: shared.gsh:304
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪destructible_event_callback
‪function destructible_event_callback(destructible_event, attacker, weapon)
Definition: _destructible.gsc:110
‪Spawn
‪function Spawn(parent, onDeathCallback)
Definition: _flak_drone.gsc:427
‪CONCUSSIVE_DAMAGE_RADIUS_SM
‪#define CONCUSSIVE_DAMAGE_RADIUS_SM
Definition: _destructible.gsc:23
‪physics_explosion_and_rumble
‪function physics_explosion_and_rumble(origin, radius, physics_explosion)
Definition: _destructible.gsc:82
‪INCENDIARY_DAMAGE_RADIUS_LG
‪#define INCENDIARY_DAMAGE_RADIUS_LG
Definition: _destructible.gsc:26
‪ELECTRICAL_DAMAGE_RADIUS_LG
‪#define ELECTRICAL_DAMAGE_RADIUS_LG
Definition: _destructible.gsc:24
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪explosive_electrical_explosion
‪function explosive_electrical_explosion(attacker, explosion_radius, physics_explosion)
Definition: _destructible.gsc:552
‪init_explosions
‪function init_explosions()
Definition: _destructible.gsc:54
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪CodeCallback_DestructibleEvent
‪function CodeCallback_DestructibleEvent(event, param1, param2, param3, param4)
Definition: _destructible.gsc:488
‪simple_timed_explosion
‪function simple_timed_explosion(destructible_event, attacker)
Definition: _destructible.gsc:239
‪destructible_car_death_notify
‪function destructible_car_death_notify()
Definition: _destructible.gsc:440
‪CONCUSSIVE_EXPLOSION_DMG_MAX
‪#define CONCUSSIVE_EXPLOSION_DMG_MAX
Definition: _destructible.gsc:30
‪destructible_car_explosion
‪function destructible_car_explosion(attacker, physics_explosion)
Definition: _destructible.gsc:322
‪destructible_car_death_think
‪function destructible_car_death_think()
Definition: _destructible.gsc:361
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265