‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_zm_lightning_chain.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\clientfield_shared;
6 #using scripts\shared\demo_shared;
7 #using scripts\shared\laststand_shared;
8 #using scripts\shared\system_shared;
9 #using scripts\shared\util_shared;
10 
11 #using scripts\shared\ai\zombie_utility;
12 
13 #insert scripts\shared\shared.gsh;
14 #insert scripts\shared\version.gsh;
15 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
16 
17 #using scripts\zm\_util;
18 #using scripts\zm\_zm_audio;
19 #using scripts\zm\_zm_laststand;
20 #using scripts\zm\_zm_net;
21 #using scripts\zm\_zm_score;
22 #using scripts\zm\_zm_stats;
23 #using scripts\zm\_zm_spawner;
24 #using scripts\zm\_zm_utility;
25 #using scripts\zm\_zm_weapons;
26 
27 #insert scripts\zm\_zm_lightning_chain.gsh;
28 
29 #namespace lightning_chain;
30 
31 ‪REGISTER_SYSTEM( "lightning_chain", &‪init, undefined )
32 
33 
34 #define FX_LC_BOLT "zombie/fx_tesla_bolt_secondary_zmb"
35 #define FX_LC_SHOCK "zombie/fx_tesla_shock_zmb"
36 #define FX_LC_SHOCK_SECONDARY "zombie/fx_tesla_bolt_secondary_zmb"
37 #define FX_LC_SHOCK_EYES "zombie/fx_tesla_shock_eyes_zmb"
38 #define FX_LC_SHOCK_NONFATAL "zombie/fx_bmode_shock_os_zod_zmb"
39 
40 
41 #precache( "fx", FX_LC_BOLT );
42 #precache( "fx", FX_LC_SHOCK );
43 #precache( "fx", FX_LC_SHOCK_SECONDARY );
44 #precache( "fx", FX_LC_SHOCK_NONFATAL );
45 #precache( "fx", FX_LC_SHOCK_EYES );
46 
47 
48 function ‪init()
49 {
50  level._effect["tesla_bolt"] = ‪FX_LC_BOLT;
51  level._effect["tesla_shock"] = ‪FX_LC_SHOCK;
52  level._effect["tesla_shock_secondary"] = ‪FX_LC_SHOCK_SECONDARY;
53  level._effect["tesla_shock_nonfatal"] = ‪FX_LC_SHOCK_NONFATAL;
54 
55  level._effect["tesla_shock_eyes"] = ‪FX_LC_SHOCK_EYES;
56 
57  level.default_lightning_chain_params = ‪create_lightning_chain_params();
58 
59  ‪clientfield::register( "actor", "lc_fx", ‪VERSION_SHIP, 2, "int" );
60  ‪clientfield::register( "vehicle", "lc_fx", ‪VERSION_SHIP, 2, "int" );
61 
62  ‪clientfield::register( "actor", "lc_death_fx", ‪VERSION_SHIP, 2, "int" );
63  ‪clientfield::register( "vehicle", "lc_death_fx", ‪VERSION_TU10, 2, "int" ); // Leave at VERSION_TU10
64 
66 }
67 
69  max_arcs = 5,
70  max_enemies_killed = 10,
71  radius_start = 300,
72  radius_decay = 20,
73  head_gib_chance = 75,
74  arc_travel_time = 0.11,
75  kills_for_powerup = 10,
76  min_fx_distance = 128,
77  network_death_choke = 4,
78  should_kill_enemies = true,
79  clientside_fx = true,
80  arc_fx_sound = undefined,
81  no_fx = false,
82  prevent_weapon_kill_credit = false
83  )
84 {
85  lcp = SpawnStruct();
86  lcp.max_arcs = max_arcs;
87  lcp.max_enemies_killed = max_enemies_killed;
88  lcp.radius_start = radius_start;
89  lcp.radius_decay = radius_decay;
90  lcp.head_gib_chance = head_gib_chance;
91  lcp.arc_travel_time = arc_travel_time;
92  lcp.kills_for_powerup = kills_for_powerup;
93  lcp.min_fx_distance = min_fx_distance;
94  lcp.network_death_choke = network_death_choke;
95  lcp.should_kill_enemies = should_kill_enemies;
96  lcp.clientside_fx = clientside_fx;
97  lcp.arc_fx_sound = arc_fx_sound;
98  lcp.no_fx = no_fx;
99  lcp.prevent_weapon_kill_credit = prevent_weapon_kill_credit;
100 
101  return lcp;
102 }
103 
104 function private ‪on_player_connect()
105 {
106  self endon( "disconnect" );
107  self endon( "death" );
108  self waittill( "spawned_player" );
109 
110  self.tesla_network_death_choke = 0;
111 
112  for ( ;; )
113  {
115  self.tesla_network_death_choke = 0;
116  }
117 }
118 
119 // this enemy is in the range of the source_enemy's tesla effect
120 function ‪arc_damage( source_enemy, player, arc_num, params = level.default_lightning_chain_params )
121 {
122  // DO NOT ADD ENDONS HERE - any endon in this routine is likely to result in zombies that are immune to lightning damage
123  player endon( "disconnect" );
124 
125  ‪DEFAULT( player.tesla_network_death_choke, 0 );
126  ‪DEFAULT( player.tesla_enemies_hit, 0 );
127 
128  ‪zm_utility::debug_print( "TESLA: Evaulating arc damage for arc: " + arc_num + " Current enemies hit: " + player.tesla_enemies_hit );
129 
130  ‪lc_flag_hit( self, true );
131 
132  radius_decay = params.radius_decay * arc_num;
133  origin = self GetTagOrigin( "j_head" );
134  if ( !IsDefined( origin ) )
135  {
136  origin = self.origin;
137  }
138  enemies = ‪lc_get_enemies_in_area( origin, params.radius_start - radius_decay, player );
139 
141 
142  ‪lc_flag_hit( enemies, true );
143 
144  self thread ‪lc_do_damage( source_enemy, arc_num, player, params );
145 
146  ‪zm_utility::debug_print( "TESLA: " + enemies.size + " enemies hit during arc: " + arc_num );
147 
148  for( i = 0; i < enemies.size; i++ )
149  {
150  if( !isdefined(enemies[i]) || enemies[i] == self )
151  {
152  continue;
153  }
154 
155  if ( ‪lc_end_arc_damage( arc_num + 1, player.tesla_enemies_hit, params ) )
156  {
157  ‪lc_flag_hit( enemies[i], false );
158  continue;
159  }
160 
161  player.tesla_enemies_hit++;
162 
163  enemies[i] ‪arc_damage( self, player, arc_num + 1, params );
164  }
165 }
166 
167 // self = enemy ent
168 function ‪arc_damage_ent( player, arc_num, params = level.default_lightning_chain_params )
169 {
170  ‪lc_flag_hit( self, true );
171  self thread ‪lc_do_damage( self, arc_num, player, params );
172 }
173 
174 function private ‪lc_end_arc_damage( arc_num, enemies_hit_num, params )
175 {
176  if ( arc_num >= params.max_arcs )
177  {
178  ‪zm_utility::debug_print( "TESLA: Ending arcing. Max arcs hit" );
179  return true;
180  //TO DO Play Super Happy Tesla sound
181  }
182 
183  if ( enemies_hit_num >= params.max_enemies_killed )
184  {
185  ‪zm_utility::debug_print( "TESLA: Ending arcing. Max enemies killed" );
186  return true;
187  }
188 
189  radius_decay = params.radius_decay * arc_num;
190  if ( params.radius_start - radius_decay <= 0 )
191  {
192  ‪zm_utility::debug_print( "TESLA: Ending arcing. Radius is less or equal to zero" );
193  return true;
194  }
195 
196  return false;
197  //TO DO play Tesla Missed sound (sad)
198 }
199 
200 
201 function private ‪lc_get_enemies_in_area( origin, distance, player )
202 {
203  distance_squared = distance * distance;
204  enemies = [];
205 
206  if ( !IsDefined( player.tesla_enemies ) )
207  {
208  player.tesla_enemies = ‪zombie_utility::get_round_enemy_array();
209  if( player.tesla_enemies.size>0 )
210  {
211  player.tesla_enemies = array::get_all_closest( origin, player.tesla_enemies );
212  }
213  }
214 
215  zombies = player.tesla_enemies;
216 
217  if ( IsDefined( zombies ) )
218  {
219  for ( i = 0; i < zombies.size; i++ )
220  {
221  if ( !IsDefined( zombies[i] ) )
222  {
223  continue;
224  }
225 
226  if ( ‪IS_TRUE( zombies[i].lightning_chain_immune ) )
227  {
228  continue;
229  }
230 
231  test_origin = zombies[i] GetTagOrigin( "j_head" );
232  if ( !IsDefined( test_origin ) )
233  {
234  test_origin = zombies[i].origin;
235  }
236 
237  if ( IsDefined( zombies[i].zombie_tesla_hit ) && zombies[i].zombie_tesla_hit == true )
238  {
239  continue;
240  }
241 
243  {
244  continue;
245  }
246 
247  if ( DistanceSquared( origin, test_origin ) > distance_squared )
248  {
249  continue;
250  }
251 
252  if ( !BulletTracePassed( origin, test_origin, false, undefined ) )
253  {
254  continue;
255  }
256 
257  enemies[enemies.size] = zombies[i];
258  }
259  }
260 
261  return enemies;
262 }
263 
264 
265 function private ‪lc_flag_hit( enemy, hit )
266 {
267  if( IsDefined( enemy ) )
268  {
269  if( IsArray( enemy ) )
270  {
271  for( i = 0; i < enemy.size; i++ )
272  {
273  if ( IsDefined(enemy[i]) )
274  enemy[i].zombie_tesla_hit = hit;
275  }
276  }
277  else
278  {
279  if ( IsDefined(enemy) )
280  enemy.zombie_tesla_hit = hit;
281  }
282  }
283 }
284 
285 
286 function private ‪lc_do_damage( source_enemy, arc_num, player, params )
287 {
288  player endon( "disconnect" );
289 
290  if ( arc_num > 1 )
291  {
292  wait( randomfloatrange( 0.2, 0.6 ) * arc_num );
293  }
294 
295  if( !IsDefined( self ) || !IsAlive( self ) )
296  {
297  // guy died on us
298  return;
299  }
300 
301  if ( params.clientside_fx )
302  {
303  if ( arc_num > 1 )
304  ‪clientfield::set( "lc_fx", 2 );
305  else
306  ‪clientfield::set( "lc_fx", 1 );
307  }
308 
309  if( !IsDefined( self ) || !IsAlive( self ) )
310  {
311  // guy died on us
312  return;
313  }
314 
315  if( IsDefined( source_enemy ) && source_enemy != self )
316  {
317  if ( player.tesla_arc_count > 3 )
318  {
320  player.tesla_arc_count = 0;
321  }
322 
323  player.tesla_arc_count++;
324  source_enemy ‪lc_play_arc_fx( self, params );
325  }
326 
327  while ( player.tesla_network_death_choke > params.network_death_choke )
328  {
329  ‪zm_utility::debug_print( "TESLA: Choking Tesla Damage. Dead enemies this network frame: " + player.tesla_network_death_choke );
331  }
332 
333  if( !IsDefined( self ) || !IsAlive( self ) )
334  {
335  // guy died on us
336  return;
337  }
338 
339  player.tesla_network_death_choke++;
340 
341  self ‪lc_play_death_fx( arc_num, params );
342 
343  self.tesla_death = params.should_kill_enemies;
344 
345  // use the origin of the arc orginator so it pics the correct death direction anim
346  origin = player.origin;
347  if ( IsDefined( source_enemy ) && source_enemy != self )
348  {
349  origin = source_enemy.origin;
350  }
351 
352  if( !IsDefined( self ) || !IsAlive( self ) )
353  {
354  // guy died on us
355  return;
356  }
357  if( params.should_kill_enemies )
358  {
359  if ( IsDefined( self.tesla_damage_func ) )
360  {
361  self [[ self.tesla_damage_func ]]( origin, player );
362  return;
363  }
364  else if( ‪IS_TRUE( params.prevent_weapon_kill_credit ) )
365  {
366  self DoDamage( self.health + 666, origin, player, undefined, "none", "MOD_UNKNOWN", 0, level.weaponNone );
367  }
368  else
369  {
370  weapon = level.weaponNone;
371  if ( isdefined(params.weapon) )
372  {
373  weapon = params.weapon;
374  }
375  self DoDamage( self.health + 666, origin, player, undefined, "none", "MOD_UNKNOWN", 0, weapon );
376  }
377  if ( !‪IS_TRUE(self.deathpoints_already_given) && player ‪zm_spawner::player_can_score_from_zombies() )
378  {
379  self.deathpoints_already_given = true;
380  player ‪zm_score::player_add_points( "death", "", "" );
381  }
382 
383  if ( IsDefined( params.challenge_stat_name ) && IsDefined( player ) && IsPlayer( player ) )
384  {
385  player ‪zm_stats::increment_challenge_stat( params.challenge_stat_name );
386  }
387  }
388 // if ( !player.tesla_powerup_dropped && player.tesla_enemies_hit >= params.kills_for_powerup )
389 // {
390 // player.tesla_powerup_dropped = true;
391 // level.zombie_vars["zombie_drop_item"] = 1;
392 // level thread zm_powerups::powerup_drop( self.origin );
393 // }
394 }
395 
396 
397 function ‪lc_play_death_fx( arc_num, params )
398 {
399  tag = "J_SpineUpper";
400  fx = "tesla_shock";
402 
403  b_can_clientside = true;
404 
405  if ( ‪IS_TRUE(self.isdog) )
406  {
407  tag = "J_Spine1";
408  }
409 
410  if( isdefined(self.teslafxtag) )
411  {
412  b_can_clientside = false;
413  tag = self.teslafxtag;
414  }
415  else if ( !‪IS_EQUAL(self.archetype,‪ARCHETYPE_ZOMBIE) )
416  {
417  tag = "tag_origin";
418  }
419 
420  if ( arc_num > 1 )
421  {
422  fx = "tesla_shock_secondary";
424  }
425 
426  if ( !params.should_kill_enemies )
427  {
428  fx = "tesla_shock_nonfatal";
430  }
431 
432  if ( params.no_fx )
433  {
434  }
435  else if ( params.clientside_fx && b_can_clientside )
436  {
437  ‪clientfield::set( "lc_death_fx", n_fx );
438  }
439  else
440  {
441  ‪zm_net::network_safe_play_fx_on_tag( "tesla_death_fx", 2, level._effect[fx], self, tag );
442  }
443 
444  if ( IsDefined( self.tesla_head_gib_func ) && !self.head_gibbed && params.should_kill_enemies && !‪IS_TRUE(self.no_gib) )
445  {
446  [[ self.tesla_head_gib_func ]]();
447  }
448 }
449 
450 
451 function ‪lc_play_arc_fx( target, params )
452 {
453  if ( !IsDefined( self ) || !IsDefined( target ) )
454  {
455  // TODO: can happen on dog exploding death
456  wait( params.arc_travel_time );
457  return;
458  }
459 
460  tag = "J_SpineUpper";
461 
462  if ( ‪IS_TRUE(self.isdog) )
463  {
464  tag = "J_Spine1";
465  }
466  else if ( !‪IS_EQUAL( self.archetype, ‪ARCHETYPE_ZOMBIE ) )
467  {
468  tag = "tag_origin";
469  }
470 
471  target_tag = "J_SpineUpper";
472 
473  if ( ‪IS_TRUE(target.isdog) )
474  {
475  target_tag = "J_Spine1";
476  }
477  else if ( !‪IS_EQUAL( self.archetype, ‪ARCHETYPE_ZOMBIE ) )
478  {
479  tag = "tag_origin";
480  }
481 
482  origin = self GetTagOrigin( tag );
483  target_origin = target GetTagOrigin( target_tag );
484  distance_squared = params.min_fx_distance * params.min_fx_distance;
485 
486  if ( DistanceSquared( origin, target_origin ) < distance_squared )
487  {
488  ‪zm_utility::debug_print( "TESLA: Not playing arcing FX. Enemies too close." );
489  return;
490  }
491 
492  fxOrg = ‪util::spawn_model( "tag_origin", origin );
493 
494  fx = PlayFxOnTag( level._effect["tesla_bolt"], fxOrg, "tag_origin" );
495  if( isdefined( params.arc_fx_sound ) )
496  {
497  PlaySoundAtPosition( params.arc_fx_sound, fxOrg.origin );
498  }
499 
500  fxOrg MoveTo( target_origin, params.arc_travel_time );
501  fxOrg waittill( "movedone" );
502  fxOrg delete();
503 }
504 
505 function private ‪lc_debug_arc( origin, distance )
506 {
507 }
508 
‪FX_LC_SHOCK
‪#define FX_LC_SHOCK
Definition: _zm_lightning_chain.gsc:35
‪N_NONFATAL_SHOCK_EFFECT
‪#define N_NONFATAL_SHOCK_EFFECT
Definition: _zm_lightning_chain.gsh:4
‪arc_damage
‪function arc_damage(source_enemy, player, arc_num, params=level.default_lightning_chain_params)
Definition: _zm_lightning_chain.gsc:120
‪FX_LC_SHOCK_EYES
‪#define FX_LC_SHOCK_EYES
Definition: _zm_lightning_chain.gsc:37
‪player_add_points
‪function player_add_points(event, mod, hit_location, is_dog, zombie_team, damage_weapon)
Definition: _zm_score.gsc:129
‪VERSION_TU10
‪#define VERSION_TU10
Definition: version.gsh:59
‪init
‪function init()
Definition: _zm_lightning_chain.gsc:48
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪debug_print
‪function debug_print(str_line)
Definition: _zm_daily_challenges.gsc:402
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪get_round_enemy_array
‪function get_round_enemy_array()
Definition: zombie_utility.gsc:2024
‪spawn_model
‪function spawn_model(n_client, str_model, origin=(0, 0, 0), angles=(0, 0, 0))
Definition: util_shared.csc:92
‪N_DEFAULT_SHOCK_EFFECT
‪#define N_DEFAULT_SHOCK_EFFECT
Definition: _zm_lightning_chain.gsh:2
‪increment_challenge_stat
‪function increment_challenge_stat(stat_name, amount=1)
Definition: _zm_stats.gsc:478
‪lc_end_arc_damage
‪function private lc_end_arc_damage(arc_num, enemies_hit_num, params)
Definition: _zm_lightning_chain.gsc:174
‪DEFAULT
‪#define DEFAULT(__var, __default)
Definition: shared.gsh:270
‪lc_flag_hit
‪function private lc_flag_hit(enemy, hit)
Definition: _zm_lightning_chain.gsc:265
‪lc_play_arc_fx
‪function lc_play_arc_fx(target, params)
Definition: _zm_lightning_chain.gsc:451
‪wait_network_frame
‪function wait_network_frame(n_count=1)
Definition: util_shared.gsc:64
‪FX_LC_SHOCK_SECONDARY
‪#define FX_LC_SHOCK_SECONDARY
Definition: _zm_lightning_chain.gsc:36
‪lc_debug_arc
‪function private lc_debug_arc(origin, distance)
Definition: _zm_lightning_chain.gsc:505
‪player_can_score_from_zombies
‪function player_can_score_from_zombies()
Definition: _zm_spawner.gsc:1534
‪N_SECONDARY_SHOCK_EFFECT
‪#define N_SECONDARY_SHOCK_EFFECT
Definition: _zm_lightning_chain.gsh:3
‪lc_play_death_fx
‪function lc_play_death_fx(arc_num, params)
Definition: _zm_lightning_chain.gsc:397
‪create_lightning_chain_params
‪function create_lightning_chain_params(max_arcs=5, max_enemies_killed=10, radius_start=300, radius_decay=20, head_gib_chance=75, arc_travel_time=0.11, kills_for_powerup=10, min_fx_distance=128, network_death_choke=4, should_kill_enemies=true, clientside_fx=true, arc_fx_sound=undefined, no_fx=false, prevent_weapon_kill_credit=false)
Definition: _zm_lightning_chain.gsc:68
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪lc_get_enemies_in_area
‪function private lc_get_enemies_in_area(origin, distance, player)
Definition: _zm_lightning_chain.gsc:201
‪FX_LC_BOLT
‪#define FX_LC_BOLT
Definition: _zm_lightning_chain.gsc:34
‪network_safe_play_fx_on_tag
‪function network_safe_play_fx_on_tag(id, max, fx, entity, tag)
Definition: _zm_net.gsc:108
‪FX_LC_SHOCK_NONFATAL
‪#define FX_LC_SHOCK_NONFATAL
Definition: _zm_lightning_chain.gsc:38
‪ARCHETYPE_ZOMBIE
‪#define ARCHETYPE_ZOMBIE
Definition: archetype_shared.gsh:10
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪IS_EQUAL
‪#define IS_EQUAL(__a, __b)
Definition: shared.gsh:250
‪on_player_connect
‪function private on_player_connect()
Definition: _zm_lightning_chain.gsc:104
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪on_connect
‪function on_connect()
Definition: _arena.gsc:20
‪arc_damage_ent
‪function arc_damage_ent(player, arc_num, params=level.default_lightning_chain_params)
Definition: _zm_lightning_chain.gsc:168
‪lc_do_damage
‪function private lc_do_damage(source_enemy, arc_num, player, params)
Definition: _zm_lightning_chain.gsc:286
‪is_magic_bullet_shield_enabled
‪function is_magic_bullet_shield_enabled(ent)
Definition: _zm_utility.gsc:3474
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265