‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_zm_traps.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\exploder_shared;
6 #using scripts\shared\flag_shared;
7 #using scripts\shared\laststand_shared;
8 #using scripts\shared\system_shared;
9 #using scripts\shared\trigger_shared;
10 #using scripts\shared\util_shared;
11 #using scripts\shared\visionset_mgr_shared;
12 
13 #insert scripts\shared\shared.gsh;
14 #insert scripts\shared\version.gsh;
15 
16 #using scripts\shared\ai\zombie_death;
17 
18 #using scripts\zm\_util;
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_utility;
24 #using scripts\zm\_zm_audio;
25 
26 #insert scripts\zm\_zm_perks.gsh;
27 #insert scripts\zm\_zm_traps.gsh;
28 #insert scripts\zm\_zm_utility.gsh;
29 
30 #namespace zm_traps;
31 
32 #precache( "model", "zombie_zapper_cagelight_red");
33 #precache( "model", "zombie_zapper_cagelight_green");
34 #precache( "model", "zombie_zapper_cagelight" );
35 #precache( "model", "zombie_zapper_handle" );
36 
37 #precache( "triggerstring", "ZOMBIE_TRAP_ACTIVE" );
38 #precache( "triggerstring", "ZOMBIE_TRAP_COOLDOWN" );
39 
40 ‪REGISTER_SYSTEM_EX( "zm_traps", &‪__init__, &‪__main__, undefined )
41 //TODO T7 - break out trap types into their own files to support p&p
42 
43 //
44 // NOTES:
45 // See trap_init for trap trigger setup info.
46 // Make sure you precache the trap effects for your level.
47 // Also, start a trap monitor thread for each unique trap in your clientscripts
48 
49 //*****************************************************************************
50 // All traps are trigger_multiples that will be used to determine if the
51 // zombie is within the trap zone.
52 //*****************************************************************************
53 
54 function ‪__init__()
55 {
56  level.trap_kills = 0;
57 
58  level.burning_zombies = []; //JV max number of zombies that can be on fire
59 
61 }
62 
63 function ‪init()
64 {
65  traps = GetEntArray( "zombie_trap", "targetname" );
66 
67  array::thread_all( traps, &‪trap_init );
68  //DCS: needs to be properly setup.
69 }
70 
71 function ‪__main__()
72 {
73  traps = GetEntArray( "zombie_trap", "targetname" );
74 
75  array::thread_all( traps, &‪trap_main );
76 }
77 
78 //*****************************************************************************
79 // This gets information from the trap trigger and then loops through its targets
80 // to identify and sets up each component.
81 //
82 // TRAP KVPs:
83 // target
84 // Trap components including use_triggers, switches and lights
85 // script_noteworthy
86 // The type of trap it is, such as "fire" or "electric"
87 // script_string
88 // Two character unique ID (used for clientnotify messages, which should
89 // be max 3 characters long. The first character should not be a number.
90 // The extra character will have "1" for on and "0" for off
91 // Alternatively, this could be a number which will be used to fire off an exploder.
92 // script_flag_wait
93 // Set if you want it to wait for a flag like "power_on" before being usable
94 //*****************************************************************************
95 function ‪trap_init()
96 {
97  //Setup ent flag
98  self ‪flag::init( "flag_active" );
99  self ‪flag::init( "flag_cooldown" );
100 
101  self._trap_type = "";
102  // Figure out what kind of trap we are.
103  if ( isdefined(self.script_noteworthy) )
104  {
105  self._trap_type = self.script_noteworthy;
106 
107  // Note make sure you define your own _trap_activate_func!!
108  if( isdefined( level._custom_traps ) && isdefined( level._custom_traps[ self.script_noteworthy ] ) && isdefined( level._custom_traps[ self.script_noteworthy ].activate ) )
109  {
110  self._trap_activate_func = level._custom_traps[ self.script_noteworthy ].activate;
111  }
112  else
113  {
114  switch( self.script_noteworthy )
115  {
116  case "rotating":
117  self._trap_activate_func =&‪trap_activate_rotating;
118  break;
119  case "flipper":
120  self._trap_activate_func =&‪trap_activate_flipper;
121  break;
122  default:
123  self._trap_activate_func =&‪trap_activate_fire;
124  }
125  }
126 
127  // Note make sure you define your own _trap_use_func!!
128  if ( isdefined( level._zombiemode_trap_use_funcs ) &&
129  isdefined( level._zombiemode_trap_use_funcs[ self._trap_type ] ) )
130  {
131  self._trap_use_func = level._zombiemode_trap_use_funcs[ self._trap_type ];
132  }
133  else
134  {
135  self._trap_use_func =&‪trap_use_think;
136  }
137  }
138 
139  // WW: adding function to issue which models switch based on trigger script_parameters
141 
142  // Okay sort through the targets
143  self._trap_use_trigs = []; // What the player needs to use to activate the trap
144  self._trap_lights = []; // Indicates if the trap is available
145  self._trap_movers = []; // Physical part of the trap that moves
146  self._trap_switches = []; // Move when trap turned on/off
147 
148  components = GetEntArray( self.target, "targetname" );
149  for ( i=0; i<components.size; i++ )
150  {
151  if ( isdefined( components[i].script_noteworthy ) )
152  {
153  switch ( components[i].script_noteworthy )
154  {
155  case "counter_1s":
156  self.counter_1s = components[i];
157  continue;
158 
159  case "counter_10s":
160  self.counter_10s = components[i];
161  continue;
162 
163  case "counter_100s":
164  self.counter_100s = components[i];
165  continue;
166 
167  case "mover":
168  self._trap_movers[ self._trap_movers.size ] = components[i];
169  continue;
170  case "switch":
171  self._trap_switches[ self._trap_switches.size ] = components[i];
172  continue;
173  case "light":
174  self._trap_lights[ self._trap_lights.size ] = components[i];
175  continue;
176  }
177  }
178  if( isdefined( components[i].script_string ) ) // If a script noteworthy is defined
179  {
180  switch ( components[i].script_string )
181  {
182  case "flipper1":
183  self.flipper1 = components[i];
184  continue;
185  case "flipper2":
186  self.flipper2 = components[i];
187  continue;
188  case "flipper1_radius_check":
189  self.flipper1_radius_check = components[i];
190  continue;
191  case "flipper2_radius_check":
192  self.flipper2_radius_check = components[i];
193  continue;
194  case "target1":
195  self.target1 = components[i];
196  continue;
197  case "target2":
198  self.target2 = components[i];
199  continue;
200  case "target3":
201  self.target3 = components[i];
202  continue;
203  }
204  }
205 
206  switch ( components[i].classname )
207  {
208  case "trigger_use":
209  self._trap_use_trigs[ self._trap_use_trigs.size ] = components[i];
210  break;
211  case "script_model":
212  if ( components[i].model == self._trap_light_model_off )
213  {
214  self._trap_lights[ self._trap_lights.size ] = components[i];
215  }
216  else if ( components[i].model == self._trap_switch_model ) // "zombie_zapper_handle"
217  {
218  self._trap_switches[ self._trap_switches.size ] = components[i];
219  }
220  }
221  }
222 
223 // self.use_this_angle = struct::get ("use_this_angle", "script_string");
224 
225  self._trap_fx_structs = [];
226  components = ‪struct::get_array( self.target, "targetname" );
227 
228  for ( i=0; i<components.size; i++ )
229  {
230  if ( isdefined( components[i].script_string ) && components[i].script_string == "use_this_angle" )
231  {
232  self.use_this_angle = components[i];
233  }
234  else
235  {
236  self._trap_fx_structs[ self._trap_fx_structs.size ] = components[i];
237  }
238  }
239 
240  assert( self._trap_use_trigs.size > 0, "zm_traps::init no use triggers found for "+self.target );
241 
242  if ( !isdefined( self.zombie_cost ) )
243  {
244  self.zombie_cost = 1000;
245  }
246  self._trap_in_use = 0;
247  self._trap_cooling_down = 0;
248 
249  self thread ‪trap_dialog();
250 }
251 
252 function ‪trap_main()
253 {
254  level ‪flag::wait_till( "start_zombie_round_logic" );
255 
256  // Setup Use triggers
257  for ( i=0; i<self._trap_use_trigs.size; i++ )
258  {
259  self._trap_use_trigs[i] SetCursorHint( "HINT_NOICON" );
260  }
261 
262  // Wait for activation flag if necessary
263  if ( !isdefined( self.script_string ) || "disable_wait_for_power" != self.script_string )
264  {
265  self ‪trap_set_string( &"ZOMBIE_NEED_POWER" );
266 
267  if ( IsDefined( self.script_int ) )
268  {
269  level ‪flag::wait_till( "power_on" + self.script_int );
270  }
271  else
272  {
273  level ‪flag::wait_till( "power_on" );
274  }
275  }
276 
277  if ( IsDefined( self.‪script_flag_wait ) )
278  {
279  self ‪trap_set_string( "" );
280  self TriggerEnable( false );
281  self ‪trap_lights_red();
282 
283  if ( !isdefined( level.flag[ self.script_flag_wait ] ) )
284  {
285  level ‪flag::init( self.‪script_flag_wait );
286  }
288 
289  self TriggerEnable( true );
290  }
291 
292  // Set buy string
293  self ‪trap_set_string( &"ZOMBIE_BUTTON_BUY_TRAP", self.zombie_cost );
294 
295  // Open for business!
296  self ‪trap_lights_green();
297 
298  for ( i=0; i<self._trap_use_trigs.size; i++ )
299  {
300  self._trap_use_trigs[i] thread [[ self._trap_use_func ]]( self );
301  self._trap_use_trigs[i] thread ‪update_trigger_visibility();
302  }
303 }
304 
305 
306 //*****************************************************************************
307 // This controls the electric traps in the level
308 // self = use trigger associated with the trap
309 // trap = trap trigger entity
310 //*****************************************************************************
311 function ‪trap_use_think( trap )
312 {
313  while(1)
314  {
315  //wait until someone uses the valve
316  self waittill("trigger",who);
317 
319  {
320  continue;
321  }
322 
323  if( ‪IS_DRINKING(who.is_drinking) )
324  {
325  continue;
326  }
327 
328  if( ‪zm_utility::is_player_valid( who ) && !trap._trap_in_use )
329  {
330  // See if they can afford it
331  players = GetPlayers();
332  //if ( players.size == 1 && who.score >= trap.zombie_cost )
333  if ( who ‪zm_score::can_player_purchase( trap.zombie_cost ) )
334  {
335  // Solo buy
336  who ‪zm_score::minus_to_player_score( trap.zombie_cost );
337  }
338  /*
339  else if( level.team_pool[who.team_num].score >= trap.zombie_cost )
340  {
341  // Team buy
342  who zm_score::minus_to_team_score( trap.zombie_cost );
343  }
344  else if( level.team_pool[ who.team_num ].score + who.score >= trap.zombie_cost )
345  {
346  // team funds + player funds
347  team_points = level.team_pool[ who.team_num ].score;
348  who zm_score::minus_to_player_score( trap.zombie_cost - team_points );
349  who zm_score::minus_to_team_score( team_points );
350  }
351  */
352  else
353  {
354  self playsound("zmb_trap_deny");
355  who ‪zm_audio::create_and_play_dialog( "general", "outofmoney" );
356  continue;
357  }
358 
359  trap.activated_by_player = who;
360  trap._trap_in_use = 1;
361  trap ‪trap_set_string( &"ZOMBIE_TRAP_ACTIVE" );
362 
363  ‪zm_utility::play_sound_at_pos( "purchase", who.origin );
364 
365  if( !‪IS_TRUE( level.b_trap_start_custom_vo ))
366  {
367  who ‪zm_audio::create_and_play_dialog( "trap", "start" );
368  }
369 
370  if ( trap._trap_switches.size )
371  {
372  trap thread ‪trap_move_switches();
373  //need to play a 'woosh' sound here, like a gas furnace starting up
374  trap waittill("switch_activated");
375  }
376 
377  //this trigger detects zombies who need to be smacked
378  trap TriggerEnable( true );
379 
380  //start the movement
381  trap thread [[ trap._trap_activate_func ]]();
382  //wait until done and then clean up and cool down
383  trap waittill("trap_done");
384 
385  //turn the damage detection trigger off until the trap is used again
386  trap TriggerEnable( false );
387 
388  trap._trap_cooling_down = 1;
389  trap ‪trap_set_string( &"ZOMBIE_TRAP_COOLDOWN" );
390  wait( trap._trap_cooldown_time );
391  trap._trap_cooling_down = 0;
392 
393  //COLLIN: Play the 'alarm' sound to alert players that the traps are available again (playing on a temp ent in case the PA is already in use.
394  //speakerA = struct::get("loudspeaker", "targetname");
395  playsoundatposition("zmb_trap_ready", trap.origin);
396 
397  if ( isdefined( level.sndTrapFunc ) )
398  {
399  level thread [[ level.sndTrapFunc ]]( trap, 0 );
400  }
401 
402  trap notify("available");
403 
404  trap._trap_in_use = 0;
405  trap ‪trap_set_string( &"ZOMBIE_BUTTON_BUY_TRAP", trap.zombie_cost );
406  }
407  }
408 }
409 
410 //-------------------------------------------------------------------------------
411 // Trigger Visibility:
412 // Death machine powerup set .is_drinking on the player.
413 //-------------------------------------------------------------------------------
414 function private ‪update_trigger_visibility() //self = trigger
415 {
416  self endon( "death" );
417 
418  //similar to the logic in _zm_perks.gsc to update prompt visibility
419  const N_DIST_SQ = 16384; // 128 * 128
420 
421  while( true )
422  {
423  for( i = 0; i < level.players.size; i++ )
424  {
425  if( DistanceSquared( level.players[i].origin, self.origin ) < N_DIST_SQ )
426  {
427  if( ‪IS_DRINKING( level.players[i].is_drinking ) )
428  {
429  self SetInvisibleToPlayer( level.players[i], true );
430  }
431  else
432  {
433  self SetInvisibleToPlayer( level.players[i], false );
434  }
435  }
436  }
437  wait 0.25;
438  }
439 }
440 
441 //*****************************************************************************
442 // Swaps the cage light models to the red one.
443 // self is a trap damage trigger
444 //*****************************************************************************
446 {
447  for(i=0;i<self._trap_lights.size;i++)
448  {
449  light = self._trap_lights[i];
450 
451  str_light_red = light.targetname + "_red";
452  str_light_green = light.targetname + "_green";
453  ‪exploder::stop_exploder( str_light_green );
454  ‪exploder::exploder( str_light_red );
455  }
456 }
457 
458 
459 //*****************************************************************************
460 // Swaps the cage light models to the green one.
461 // self is a trap damage trigger
462 //*****************************************************************************
464 {
465  for(i=0;i<self._trap_lights.size;i++)
466  {
467  light = self._trap_lights[i];
468  if(isdefined(light._switch_disabled))
469  {
470  continue;
471  }
472 
473  str_light_red = light.targetname + "_red";
474  str_light_green = light.targetname + "_green";
475  ‪exploder::stop_exploder( str_light_red );
476  ‪exploder::exploder( str_light_green );
477  }
478 }
479 
480 
481 //*****************************************************************************
482 // Set the hintstrings for all associated use triggers
483 // self should be the trap entity
484 //*****************************************************************************
485 function ‪trap_set_string( string, param1, param2 )
486 {
487  // Set buy string
488  for ( i=0; i<self._trap_use_trigs.size; i++ )
489  {
490  if ( !isdefined(param1) )
491  {
492  self._trap_use_trigs[i] SetHintString( string );
493  }
494  else if ( !isdefined(param2) )
495  {
496  self._trap_use_trigs[i] SetHintString( string, param1 );
497  }
498  else
499  {
500  self._trap_use_trigs[i] SetHintString( string, param1, param2 );
501  }
502  }
503 }
504 
505 
506 //*****************************************************************************
507 // It's a throw switch
508 // self should be the trap entity
509 //*****************************************************************************
511 {
512  self ‪trap_lights_red();
513  for ( i=0; i<self._trap_switches.size; i++ )
514  {
515  // Rotate switch model "on"
516  self._trap_switches[i] rotatepitch( 180, .5 );
517  if(IsDefined (self._trap_type) && (self._trap_type == "fire"))
518  {
519  self._trap_switches[i] playsound( "evt_switch_flip_trap_fire" );
520  }
521  else
522  {
523  self._trap_switches[i] playsound( "evt_switch_flip_trap" );
524  }
525  }
526  self._trap_switches[0] waittill( "rotatedone" );
527 
528  // When "available" notify hit, bring back the level
529  self notify( "switch_activated" );
530 
531  self waittill( "available" );
532  for ( i=0; i<self._trap_switches.size; i++ )
533  {
534  // Rotate switch model "off"
535  self._trap_switches[i] rotatepitch( -180, .5 );
536  }
537  self._trap_switches[0] waittill( "rotatedone" );
538  self ‪trap_lights_green();
539 }
540 
541 //*****************************************************************************
542 //
543 //*****************************************************************************
544 
546 {
547  self._trap_duration = 40;
548  self._trap_cooldown_time = 60;
549 
550  // Kick off the client side FX structs
551 // util::clientNotify( self.script_string+"1" );
552 // util::clientNotify( self.script_parameters );
553 
554  // Kick off audio
555  fx_points = ‪struct::get_array( self.target,"targetname" );
556  for( i=0; i<fx_points.size; i++ )
557  {
559  fx_points[i] thread ‪trap_audio_fx(self);
560  }
561 
562  // Do the damage
563  self thread ‪trap_damage();
564  wait( self._trap_duration );
565 
566  // Shut down
567  self notify ("trap_done");
568 // util::clientNotify(self.script_string +"0"); // turn off FX
569 // util::clientNotify( self.script_parameters );
570 }
571 
572 
573 //*****************************************************************************
574 // Any traps that spin and cause damage from colliding
575 //*****************************************************************************
576 
578 {
579  self endon( "trap_done" ); // used to end the trap early
580 
581  self._trap_duration = 30;
582  self._trap_cooldown_time = 60;
583 
584  // Kick off audio
585 // fx_points = struct::get_array( self.target,"targetname" );
586 // for( i=0; i<fx_points.size; i++ )
587 // {
588 // util::wait_network_frame();
589 // fx_points[i] thread trap_audio_fx(self);
590 // }
591 
592  // Do the damage
593  self thread ‪trap_damage();
594  self thread ‪trig_update( self._trap_movers[0] );
595  old_angles = self._trap_movers[0].angles;
596 
597  //Shawn J Sound - power up sound for centrifuge
598 // self playsound ("evt_centrifuge_rise");
599 
600  for ( i=0; i<self._trap_movers.size; i++ )
601  {
602  self._trap_movers[i] RotateYaw( 360, 5.0, 4.5 );
603  }
604  wait( 5.0 );
605  step = 1.5;
606 
607  //Shawn J Sound - loop sound for centrifuge
608 // self playloopsound ("evt_centrifuge_loop", .6);
609 
610  for (t=0; t<self._trap_duration; t=t+step )
611  {
612  for ( i=0; i<self._trap_movers.size; i++ )
613  {
614  self._trap_movers[i] RotateYaw( 360, step );
615  }
616  wait( step );
617  }
618 
619  //Shawn J Sound - power down sound for centrifuge
620 // self stoploopsound (2);
621 // self playsound ("evt_centrifuge_fall");
622 
623  for ( i=0; i<self._trap_movers.size; i++ )
624  {
625  self._trap_movers[i] RotateYaw( 360, 5.0, 0.0, 4.5 );
626  }
627  wait( 5.0 );
628  for ( i=0; i<self._trap_movers.size; i++ )
629  {
630  self._trap_movers[i].angles = old_angles;
631  }
632 
633  // Shut down
634  self notify ("trap_done");
635 }
636 
637 //*****************************************************************************
638 // Any traps that spin and cause damage from colliding
639 //*****************************************************************************
640 
641 
642 //*****************************************************************************
643 // New zombapult or flipper traps
644 //*****************************************************************************
645 
647 { // basics of the trap are setup
648 // IPrintLnBold("trap is almost working...");
649 
650 // self endon( "trap_done" ); // Used to end the trap early
651 
652 
653 // wait( 4 );
654 // self._trap_duration = 3;
655 // self._trap_cooldown_time = 0;
656 
657 
658 // self notify ("trap_done");
659 
660  //I need to communicate from here to the actual funcion
661 }
662 
663 
664 //*****************************************************************************
665 //
666 //*****************************************************************************
667 
668 function ‪trap_audio_fx( trap )
669 {
670  if( isdefined( level._custom_traps ) && isdefined( level._custom_traps[ trap.script_noteworthy ] ) && isdefined( level._custom_traps[ trap.script_noteworthy ].audio ) )
671  {
672  self [[ level._custom_traps[ trap.script_noteworthy ].audio ]]( trap );
673  }
674  else
675  {
676  sound_origin = undefined;
677 
678  trap ‪util::waittill_any_timeout( trap._trap_duration, "trap_done");
679 
680  if(isdefined(sound_origin))
681  {
682  playsoundatposition( "wpn_zmb_electrap_stop", sound_origin.origin );
683 
684  sound_origin stoploopsound();
685  wait(.05);
686  sound_origin delete();
687  }
688  }
689 }
690 
691 //*****************************************************************************
692 //
693 //*****************************************************************************
694 
695 function ‪trap_damage()
696 {
697  self endon( "trap_done" );
698 
699  while(1)
700  {
701  self waittill( "trigger", ent );
702 
703  // Is player standing in the electricity?
704  if( isplayer(ent) )
705  {
706  if( isdefined( level._custom_traps ) && isdefined( level._custom_traps[ self._trap_type ] ) && isdefined( level._custom_traps[ self._trap_type ].player_damage ) )
707  {
708  ent thread [[ level._custom_traps[ self._trap_type ].player_damage ]]();
709  break;
710  }
711  else
712  {
713  switch ( self._trap_type )
714  {
715  case "rocket":
716  ent thread ‪player_fire_damage();
717  break;
718  case "rotating":
719  if ( ent GetStance() == "stand" )
720  {
721  ent dodamage( 50, ent.origin+(0,0,20) );
722  ent SetStance( "crouch" );
723  }
724  break;
725  }
726  }
727  }
728  else
729  {
730  if(!isdefined(ent.marked_for_death))
731  {
732  if( isdefined( level._custom_traps ) && isdefined( level._custom_traps[ self._trap_type ] ) && isdefined( level._custom_traps[ self._trap_type ].damage ) )
733  {
734  ent thread [[ level._custom_traps[ self._trap_type ].damage ]]( self );
735  break;
736  }
737  else
738  {
739  switch ( self._trap_type )
740  {
741  case "rocket":
742  ent thread ‪zombie_trap_death( self, 100 );
743  break;
744  case "rotating":
745  ent thread ‪zombie_trap_death( self, 200 );
746  break;
747 
748  default:
749  ent thread ‪zombie_trap_death( self, randomint(100) );
750  break;
751  }
752  }
753  }
754  }
755  }
756 }
757 
758 
759 //*****************************************************************************
760 // Updates the position of a trigger. MoveTo and RotateTo do not support triggers
761 //TODO This is unneeded. Should be able to Enable Linkto on the trigger.
762 //*****************************************************************************
763 function ‪trig_update( parent )
764 {
765  self endon( "trap_done" );
766 // start_origin = self.origin;
767  start_angles = self.angles;
768 
769  while (1)
770  {
771  self.angles = parent.angles;
772 
773 // segment = self.origin + VectorScale( AnglesToForward(self.angles), 300);
774 // draw_line_for_time( self.origin, segment, 1, 1, 1, 0.1 );
775 
777  }
778 }
779 
780 //*****************************************************************************
781 //
782 //*****************************************************************************
783 
785 {
786  self endon("death");
787  self endon("disconnect");
788 
789  if( !isdefined(level.elec_loop) )
790  {
791  level.elec_loop = 0;
792  }
793 
794  if( !‪IS_TRUE( self.is_burning ) && ‪zm_utility::is_player_valid( self ) )
795  {
796  self.is_burning = 1;
797 
798  if (‪IS_TRUE(level.trap_electric_visionset_registered))
799  {
800  ‪visionset_mgr::activate( "overlay", "zm_trap_electric", self, ‪ZM_TRAP_ELECTRIC_MAX, ‪ZM_TRAP_ELECTRIC_MAX );
801  }
802  else
803  {
804  self setelectrified(1.25);
805  }
806  shocktime = 2.5;
807  if ( isdefined( level.str_elec_damage_shellshock_override ) )
808  {
809  str_elec_shellshock = level.str_elec_damage_shellshock_override;
810  }
811  else
812  {
813  str_elec_shellshock = "electrocution";
814  }
815 
816  //Changed Shellshock to Electrocution so we can have different bus volumes.
817  self shellshock(str_elec_shellshock, shocktime);
818 
819  self PlayRumbleOnEntity( "damage_heavy" ); // PORTIZ 6/12/16: Adding rumble when damaged
820 
821  if(level.elec_loop == 0)
822  {
823  elec_loop = 1;
824  //self playloopsound ("electrocution");
825  self playsound("wpn_zmb_electrap_zap");
826  }
827  if(!self hasperk( ‪PERK_JUGGERNOG ) || self.health - 100 < 1)
828  {
829  self DoDamage( self.health + 100, self.origin );
830  self.is_burning = undefined;
831 
832  }
833  else
834  {
835  self DoDamage( 50, self.origin );
836  wait 0.1;
837  //self playsound("wpn_zmb_electrap_zap");
838  self.is_burning = undefined;
839  }
840  }
841 }
842 
844 {
845  self endon("death");
846  self endon("disconnect");
847 
848  if( !‪IS_TRUE(self.is_burning) && !self ‪laststand::player_is_in_laststand() )
849  {
850  self.is_burning = 1;
851  if (‪IS_TRUE(level.trap_fire_visionset_registered))
852  ‪visionset_mgr::activate( "overlay", "zm_trap_burn", self, ‪ZM_TRAP_BURN_MAX, ‪ZM_TRAP_BURN_MAX );
853  else
854  self setburn(1.25);
855 
856  self notify("burned");
857 
858  if(!self hasperk( ‪PERK_JUGGERNOG ) || self.health - 100 < 1)
859  {
860  radiusdamage(self.origin,10,self.health + 100,self.health + 100);
861  self.is_burning = undefined;
862  }
863  else
864  {
865  self dodamage(50, self.origin);
866  wait(.1);
867  //self playsound("wpn_zmb_electrap_zap");
868  self.is_burning = undefined;
869  }
870  }
871 }
872 
873 
874 //*****************************************************************************
875 // trap is the parent trap entity
876 // param is a multi-purpose paramater. The exact use is described by trap type
877 //*****************************************************************************
878 function ‪zombie_trap_death( trap, param )
879 {
880  self endon("death");
881 
882  self.marked_for_death = true;
883 
884  switch (trap._trap_type)
885  {
886  case "rocket":
887  // Param is used as a random chance number
888 
889  if ( isdefined( self.animname ) && self.animname != "zombie_dog" )
890  {
891  // 10% chance the zombie will burn, a max of 6 burning zombs can be going at once
892  // otherwise the zombie just gibs and dies
893  if( (param > 90) && (level.burning_zombies.size < 6) )
894  {
895  level.burning_zombies[level.burning_zombies.size] = self;
896  self thread ‪zombie_flame_watch();
897  self playsound("zmb_ignite");
898 
899  self thread ‪zombie_death::flame_death_fx();
900  PlayFxOnTag( level._effect["character_fire_death_torso"], self, "J_SpineLower" );
901 
902  wait( randomfloat(1.25) );
903  }
904  else
905  {
906  refs[0] = "guts";
907  refs[1] = "right_arm";
908  refs[2] = "left_arm";
909  refs[3] = "right_leg";
910  refs[4] = "left_leg";
911  refs[5] = "no_legs";
912  refs[6] = "head";
913  self.a.gib_ref = refs[randomint(refs.size)];
914 
915  playsoundatposition("wpn_zmb_electrap_zap", self.origin);
916 
917  wait(randomfloat(1.25));
918  self playsound("wpn_zmb_electrap_zap");
919  }
920  }
921 
922  // custom damage
923  if ( isdefined( self.fire_damage_func ) )
924  {
925  self [[ self.fire_damage_func ]]( trap );
926  }
927  else
928  {
929  level notify( "trap_kill", self, trap );
930  self dodamage(self.health + 666, self.origin, trap);
931  }
932 
933 // iprintlnbold("should be damaged");
934  break;
935 
936  case "rotating":
937  case "centrifuge":
938  // Param is used as a magnitude for the physics push
939 
940  // Get a vector for the force to be applied. It needs to be perpendicular to the
941  // bar
942  ang = VectorToAngles( trap.origin - self.origin );
943  // eliminate height difference factors
944  // calculate the right angle and increase intensity
945  direction_vec = VectorScale( AnglesToRight( ang ), param);
946 
947  // custom reaction
948  if ( isdefined( self.trap_reaction_func ) )
949  {
950  self [[ self.trap_reaction_func ]]( trap );
951  }
952 
953  level notify( "trap_kill", self, trap );
954  self StartRagdoll();
955  self launchragdoll(direction_vec);
957 
958  // Make sure they're dead...physics launch didn't kill them.
959  self.a.gib_ref = "head";
960  self dodamage(self.health, self.origin, trap);
961 
962  break;
963  }
964 
965  if ( IsDefined( trap.activated_by_player ) && IsPlayer( trap.activated_by_player ) )
966  {
967  trap.activated_by_player ‪zm_stats::increment_challenge_stat( "ZOMBIE_HUNTER_KILL_TRAP" );
968  }
969 }
970 
971 
972 //*****************************************************************************
973 //
974 //*****************************************************************************
975 
977 {
978  self waittill("death");
979  self stoploopsound();
980  ArrayRemoveValue(level.burning_zombies,self);
981 }
982 
983 
984 //*****************************************************************************
985 //
986 //*****************************************************************************
987 
989 {
990  if( isdefined (self) )
991  {
992  org = self.origin;
993  wait(0.15);
994  playsoundatposition("zmb_elec_vocals", org);
995  playsoundatposition("wpn_zmb_electrap_zap", org);
996  playsoundatposition("zmb_exp_jib_zombie", org);
997  }
998 }
999 
1000 
1001 //*****************************************************************************
1002 //
1003 //*****************************************************************************
1004 
1006 {
1007  self endon( "death" );
1008 
1009  if (isdefined(self.is_electrocuted) && self.is_electrocuted )
1010  {
1011  return;
1012  }
1013 
1014  self.is_electrocuted = true;
1015 
1016  self thread ‪electrocute_timeout();
1017 
1018  if ( ‪IS_ZOMBIETEAM( self ) )
1019  {
1020  level.bcOnFireTime = gettime();
1021  level.bcOnFireOrg = self.origin;
1022  }
1023 
1024  if (isdefined(level._effect["elec_torso"]))
1025  PlayFxOnTag( level._effect["elec_torso"], self, "J_SpineLower" );
1026  self playsound ("zmb_elec_jib_zombie");
1027  wait 1;
1028 
1029  tagArray = [];
1030  tagArray[0] = "J_Elbow_LE";
1031  tagArray[1] = "J_Elbow_RI";
1032  tagArray[2] = "J_Knee_RI";
1033  tagArray[3] = "J_Knee_LE";
1034  tagArray = array::randomize( tagArray );
1035 
1036  if (isdefined(level._effect["elec_md"]))
1037  PlayFxOnTag( level._effect["elec_md"], self, tagArray[0] );
1038  self playsound ("zmb_elec_jib_zombie");
1039 
1040  wait 1;
1041  self playsound ("zmb_elec_jib_zombie");
1042 
1043  tagArray[0] = "J_Wrist_RI";
1044  tagArray[1] = "J_Wrist_LE";
1045  if( !isdefined( self.‪a.gib_ref ) || self.a.gib_ref != "no_legs" )
1046  {
1047  tagArray[2] = "J_Ankle_RI";
1048  tagArray[3] = "J_Ankle_LE";
1049  }
1050  tagArray = array::randomize( tagArray );
1051 
1052  if (isdefined(level._effect["elec_sm"]))
1053  {
1054  PlayFxOnTag( level._effect["elec_sm"], self, tagArray[0] );
1055  PlayFxOnTag( level._effect["elec_sm"], self, tagArray[1] );
1056  }
1057 }
1058 
1059 
1060 //*****************************************************************************
1061 //
1062 //*****************************************************************************
1063 
1065 {
1066  self endon ("death");
1067  self playloopsound("amb_fire_manager_0");
1068  // about the length of the flame fx
1069  wait 12;
1070  self stoploopsound();
1071  if (isdefined(self) && isalive(self))
1072  {
1073  self.is_electrocuted = false;
1074  self notify ("stop_flame_damage");
1075  }
1076 
1077 }
1078 
1079 
1080 //*****************************************************************************
1081 //
1082 //*****************************************************************************
1083 
1084 function ‪trap_dialog()
1085 {
1086 
1087  self endon ("warning_dialog");
1088  level endon("switch_flipped");
1089  ‪timer =0;
1090  while(1)
1091  {
1092  wait(0.5);
1093  players = GetPlayers();
1094  for(i = 0; i < players.size; i++)
1095  {
1096  if (!IsDefined(players[i]))
1097  continue;
1098  dist = distancesquared(players[i].origin, self.origin );
1099  if(dist > 70*70)
1100  {
1101  ‪timer = 0;
1102  continue;
1103  }
1104  if(dist < 70*70 && ‪timer < 3)
1105  {
1106  wait(0.5);
1107  ‪timer ++;
1108  }
1109  if(dist < 70*70 && ‪timer == 3)
1110  {
1111 
1112  index = ‪zm_utility::get_player_index(players[i]);
1113  plr = "plr_" + index + "_";
1114  //players[i] zm_audio::create_and_play_dialog( plr, "vox_level_start", 0.25 );
1115  wait(3);
1116  self notify ("warning_dialog");
1117  //iprintlnbold("warning_given");
1118  }
1119  }
1120  }
1121 }
1122 
1123 
1124 //*****************************************************************************
1125 // Find Trap triggers
1126 //*****************************************************************************
1127 function ‪get_trap_array( trap_type )
1128 {
1129  ents = GetEntArray( "zombie_trap", "targetname" );
1130  traps = [];
1131  for ( i=0; i<ents.size; i++ )
1132  {
1133  if ( ents[i].script_noteworthy == trap_type )
1134  {
1135  traps[ traps.size ] = ents[i];
1136  }
1137  }
1138 
1139  return traps;
1140 }
1141 
1142 //*****************************************************************************
1143 //
1144 //*****************************************************************************
1146 {
1147  cooldown = self._trap_cooldown_time;
1148 
1149  if ( self._trap_in_use )
1150  {
1151  self notify( "trap_done" );
1152  self._trap_cooldown_time = 0.05;
1153  self waittill( "available" );
1154  }
1155 
1156  array::thread_all( self._trap_use_trigs,&TriggerEnable, false );
1157  self ‪trap_lights_red();
1158  self._trap_cooldown_time = cooldown;
1159 }
1160 
1161 //*****************************************************************************
1162 //
1163 //*****************************************************************************
1164 function ‪trap_enable()
1165 {
1166  array::thread_all( self._trap_use_trigs,&TriggerEnable, true );
1167  self ‪trap_lights_green();
1168 }
1169 
1170 //******************************************************************************
1171 // WWilliams: checks the trigger script parameters and then assigns which models
1172 // should be used for swapping
1173 //******************************************************************************
1175 {
1176  // this depends on the trap trigger to have the script_parameters
1177  // to chose which models to use
1178  if( !isdefined( self.script_parameters ) )
1179  {
1180  self.script_parameters = "default";
1181  }
1182 
1183  // new models should be added here for updated trap
1184  switch( self.script_parameters )
1185  {
1186  case "pentagon_electric": //WW: TODO - REMOVE THIS ONCE A NEW PENTAGON BSP HAS BEEN GENERATED
1187  self._trap_light_model_off = "zombie_trap_switch_light";
1188  self._trap_light_model_green = "zombie_trap_switch_light_on_green";
1189  self._trap_light_model_red = "zombie_trap_switch_light_on_red";
1190  self._trap_switch_model = "zombie_trap_switch_handle";
1191  break;
1192 
1193  case "default":
1194  default:
1195  self._trap_light_model_off = "zombie_zapper_cagelight";
1196  self._trap_light_model_green = "zombie_zapper_cagelight"; // TODO T7 "zombie_zapper_cagelight_green";
1197  self._trap_light_model_red = "zombie_zapper_cagelight"; // TODO T7 "zombie_zapper_cagelight_red";
1198  self._trap_switch_model = "zombie_zapper_handle";
1199  break;
1200  }
1201 
1202 }
1203 
1204 function ‪is_trap_registered( a_registered_traps )//self = struct
1205 {
1206  return isdefined( a_registered_traps[ self.script_noteworthy ] );
1207 }
1208 
1220 function ‪register_trap_basic_info( str_trap, func_activate, func_audio )
1221 {
1222  Assert( IsDefined( str_trap ), "str_trap is a required argument for register_trap_basic_info!" );
1223  Assert( IsDefined( func_activate ), "str_alias is a required argument for register_trap_basic_info!" );
1224  Assert( IsDefined( func_audio ), "n_perk_cost is a required argument for register_trap_basic_info!" );
1225 
1226  ‪_register_undefined_trap( str_trap );
1227 
1228  level._custom_traps[ str_trap ].activate = func_activate;
1229  level._custom_traps[ str_trap ].audio = func_audio;
1230 }
1231 
1232 // make sure trap exists before we actually try to set fields on it. Does nothing if it exists already
1233 function ‪_register_undefined_trap( str_trap )
1234 {
1235  if ( !IsDefined( level._custom_traps ) )
1236  {
1237  level._custom_traps = [];
1238  }
1239 
1240  if ( !IsDefined( level._custom_traps[ str_trap ] ) )
1241  {
1242  level._custom_traps[ str_trap ] = SpawnStruct();
1243  }
1244 }
1245 
1257 function ‪register_trap_damage( str_trap, func_player_damage, func_damage )
1258 {
1259  Assert( IsDefined( str_trap ), "str_trap is a required argument for register_trap_basic_info!" );
1260 
1261  ‪_register_undefined_trap( str_trap );
1262 
1263  level._custom_traps[ str_trap ].player_damage = func_player_damage;
1264  level._custom_traps[ str_trap ].damage = func_damage;
1265 }
‪trap_activate_rotating
‪function trap_activate_rotating()
Definition: _zm_traps.gsc:577
‪PERK_JUGGERNOG
‪#define PERK_JUGGERNOG
Definition: mechz.gsc:47
‪is_trap_registered
‪function is_trap_registered(a_registered_traps)
Definition: _zm_traps.gsc:1204
‪exploder
‪function exploder(exploder_id, n_localclientnumber)
Definition: exploder_shared.csc:297
‪activate
‪function activate()
Definition: traps_shared.gsc:655
‪stop_exploder
‪function stop_exploder(exploder_id, n_localclientnumber)
Definition: exploder_shared.csc:368
‪on_finalize_initialization
‪function on_finalize_initialization(func, obj)
Definition: callbacks_shared.csc:203
‪timer
‪function timer(n_time, str_endon, x, y, height)
Definition: lui_shared.gsc:163
‪play_sound_at_pos
‪function play_sound_at_pos(ref, pos, ent)
Definition: _zm_utility.gsc:3040
‪register_trap_basic_info
‪function register_trap_basic_info(str_trap, func_activate, func_audio)
Definition: _zm_traps.gsc:1220
‪trap_dialog
‪function trap_dialog()
Definition: _zm_traps.gsc:1084
‪__main__
‪function __main__()
Definition: _zm_traps.gsc:71
‪get_array
‪function get_array(kvp_value, kvp_key="targetname")
Definition: struct.csc:34
‪IS_ZOMBIETEAM
‪#define IS_ZOMBIETEAM(__self)
Definition: _zm_utility.gsh:2
‪waittill_any_timeout
‪function waittill_any_timeout(n_timeout, string1, string2, string3, string4, string5)
Definition: util_shared.csc:423
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪get_player_index
‪function get_player_index(player)
Definition: _zm_utility.gsc:5949
‪a
‪function add_remove_list a
Definition: util_shared.csc:906
‪init
‪function init()
Definition: _zm_traps.gsc:63
‪is_player_valid
‪function is_player_valid(player, checkIgnoreMeFlag, ignore_laststand_players)
Definition: skeleton.gsc:256
‪register_trap_damage
‪function register_trap_damage(str_trap, func_player_damage, func_damage)
Definition: _zm_traps.gsc:1257
‪player_elec_damage
‪function player_elec_damage()
Definition: _zm_traps.gsc:784
‪trap_move_switches
‪function trap_move_switches()
Definition: _zm_traps.gsc:510
‪trap_activate_flipper
‪function trap_activate_flipper()
Definition: _zm_traps.gsc:646
‪increment_challenge_stat
‪function increment_challenge_stat(stat_name, amount=1)
Definition: _zm_stats.gsc:478
‪electrocute_timeout
‪function electrocute_timeout()
Definition: _zm_traps.gsc:1064
‪player_fire_damage
‪function player_fire_damage()
Definition: _zm_traps.gsc:843
‪ZM_TRAP_BURN_MAX
‪#define ZM_TRAP_BURN_MAX
Definition: _zm_traps.gsh:3
‪minus_to_player_score
‪function minus_to_player_score(points)
Definition: _zm_score.gsc:551
‪can_player_purchase
‪function can_player_purchase(n_cost)
Definition: _zm_score.gsc:655
‪wait_network_frame
‪function wait_network_frame(n_count=1)
Definition: util_shared.gsc:64
‪script_flag_wait
‪function script_flag_wait()
Definition: flag_shared.gsc:394
‪trap_disable
‪function trap_disable()
Definition: _zm_traps.gsc:1145
‪REGISTER_SYSTEM_EX
‪#define REGISTER_SYSTEM_EX(__sys, __func_init_preload, __func_init_postload, __reqs)
Definition: shared.gsh:209
‪trap_damage
‪function trap_damage()
Definition: _zm_traps.gsc:695
‪trap_main
‪function trap_main()
Definition: _zm_traps.gsc:252
‪trap_lights_red
‪function trap_lights_red()
Definition: _zm_traps.gsc:445
‪electroctute_death_fx
‪function electroctute_death_fx()
Definition: _zm_traps.gsc:1005
‪wait_till
‪function wait_till(str_flag)
Definition: flag_shared.csc:189
‪trap_use_think
‪function trap_use_think(trap)
Definition: _zm_traps.gsc:311
‪trap_lights_green
‪function trap_lights_green()
Definition: _zm_traps.gsc:463
‪__init__
‪function __init__()
Definition: _zm_traps.gsc:54
‪flame_death_fx
‪function flame_death_fx(localClientNum)
Definition: zombie_death.csc:35
‪trap_activate_fire
‪function trap_activate_fire()
Definition: _zm_traps.gsc:545
‪trap_set_string
‪function trap_set_string(string, param1, param2)
Definition: _zm_traps.gsc:485
‪zombie_flame_watch
‪function zombie_flame_watch()
Definition: _zm_traps.gsc:976
‪update_trigger_visibility
‪function private update_trigger_visibility()
Definition: _zm_traps.gsc:414
‪zombie_trap_death
‪function zombie_trap_death(trap, param)
Definition: _zm_traps.gsc:878
‪_register_undefined_trap
‪function _register_undefined_trap(str_trap)
Definition: _zm_traps.gsc:1233
‪player_is_in_laststand
‪function player_is_in_laststand()
Definition: laststand_shared.gsc:18
‪trap_init
‪function trap_init()
Definition: _zm_traps.gsc:95
‪play_elec_vocals
‪function play_elec_vocals()
Definition: _zm_traps.gsc:988
‪trig_update
‪function trig_update(parent)
Definition: _zm_traps.gsc:763
‪get_trap_array
‪function get_trap_array(trap_type)
Definition: _zm_traps.gsc:1127
‪create_and_play_dialog
‪function create_and_play_dialog(category, subcategory, force_variant)
Definition: _zm_audio.gsc:603
‪in_revive_trigger
‪function in_revive_trigger()
Definition: _zm_utility.gsc:1684
‪ZM_TRAP_ELECTRIC_MAX
‪#define ZM_TRAP_ELECTRIC_MAX
Definition: _zm_traps.gsh:4
‪trap_model_type_init
‪function trap_model_type_init()
Definition: _zm_traps.gsc:1174
‪IS_DRINKING
‪#define IS_DRINKING(_is_drinking)
Definition: _zm_utility.gsh:1
‪trap_audio_fx
‪function trap_audio_fx(trap)
Definition: _zm_traps.gsc:668
‪trap_enable
‪function trap_enable()
Definition: _zm_traps.gsc:1164
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265