‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_zm_blockers.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\array_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\demo_shared;
6 #using scripts\shared\flag_shared;
7 #using scripts\shared\laststand_shared;
8 #using scripts\shared\scoreevents_shared;
9 #using scripts\shared\system_shared;
10 #using scripts\shared\trigger_shared;
11 #using scripts\shared\util_shared;
12 
13 #insert scripts\shared\shared.gsh;
14 
15 #using scripts\zm\_util;
16 #using scripts\zm\_bb;
17 #using scripts\zm\_zm_audio;
18 #using scripts\zm\_zm_daily_challenges;
19 #using scripts\zm\_zm_laststand;
20 #using scripts\zm\_zm_pers_upgrades_functions;
21 #using scripts\zm\_zm_score;
22 #using scripts\zm\_zm_spawner;
23 #using scripts\zm\_zm_stats;
24 #using scripts\zm\_zm_unitrigger;
25 #using scripts\zm\_zm_utility;
26 #using scripts\zm\_zm_zonemgr;
27 
28 #insert scripts\zm\_zm_perks.gsh;
29 #insert scripts\zm\_zm_utility.gsh;
30 #insert scripts\zm\_zm.gsh;
31 
32 #namespace zm_blockers;
33 
34 ‪REGISTER_SYSTEM_EX( "zm_blockers", &‪__init__, &‪__main__, undefined )
35 
36 #define STR_NAV_VOLUME_TRAVERSAL "air_buy_gate" // script_noteworthy on a traversal node. Indicates it's used for nav volume
37 
38 function ‪__init__()
39 {
41  // Zombie Window and Blockers speaks between two main scripts _zombiemode_blockers
42  // and _zombiemode_spawner and _zombimode _utility
44 
45  // Debris
46  ‪zm_utility::add_zombie_hint( "default_buy_debris", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_COST" );
47 
48  // Doors
49  ‪zm_utility::add_zombie_hint( "default_buy_door", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_COST" );
50  ‪zm_utility::add_zombie_hint( "default_buy_door_close", &"ZOMBIE_BUTTON_BUY_CLOSE_DOOR" );
51 
53 
54 // level thread rebuild_barrier_think();
55 
57  //designed by prod
58  //zombie_utility::set_zombie_var( "rebuild_barrier_cap_per_round", 500 );
60 }
61 
62 function ‪__main__()
63 {
64  if ( isdefined( level.quantum_bomb_register_result_func ) )
65  {
66  [[level.quantum_bomb_register_result_func]]( "open_nearest_door", &‪quantum_bomb_open_nearest_door_result, 35, &‪quantum_bomb_open_nearest_door_validation );
67  }
68 }
69 
70 //
71 // BLOCKERS
72 //
73 function ‪init_blockers()
74 {
75  // EXTERIOR BLOCKERS ----------------------------------------------------------------- //
76  level.exterior_goals = ‪struct::get_array( "exterior_goal", "targetname" );
77  array::thread_all(level.exterior_goals, &‪blocker_init);
78 
79  // DOORS ----------------------------------------------------------------------------- //
80  zombie_doors = GetEntArray( "zombie_door", "targetname" );
81  if(isdefined(zombie_doors))
82  {
83  level ‪flag::init("door_can_close");
84  array::thread_all(zombie_doors, &‪door_init);
85  }
86  // DEBRIS ---------------------------------------------------------------------------- //
87  zombie_debris = GetEntArray( "zombie_debris", "targetname" );
88  array::thread_all(zombie_debris, &‪debris_init);
89 
90  // Flag Blockers ---------------------------------------------------------------------- //
91  flag_blockers = GetEntArray( "flag_blocker", "targetname" );
92  array::thread_all(flag_blockers, &‪flag_blocker);
93 }
94 
95 
96 //
97 // DOORS --------------------------------------------------------------------------------- //
98 //
99 function ‪door_init()
100 {
101  self.type = undefined;
102  self.purchaser = undefined;
103  self._door_open = false;
104 
105 
106  // Figure out what kind of door we are
107  ent_targets = GetEntArray( self.target, "targetname" );
108  node_targets = GetNodeArray( self.target, "targetname" );
109  targets = ArrayCombine( ent_targets, node_targets, false, true );
110 
111  //CHRIS_P - added script_flag support for doors as well
112  if( isDefined(self.script_flag) && !isdefined( level.flag[self.script_flag] ) )
113  {
114  // Initialize any flags called
115  if( isdefined( self.script_flag ) )
116  {
117  tokens = Strtok( self.script_flag, "," );
118  for ( i=0; i<tokens.size; i++ )
119  {
120  level ‪flag::init( self.script_flag );
121  }
122  }
123 
124  }
125 
126  // Door trigger types
127  if ( !isdefined( self.script_noteworthy ) )
128  {
129  self.script_noteworthy = "default";
130  }
131 
132  //MM Consolidate type codes for each door into script_string
133  self.doors = [];
134  for(i=0;i<targets.size;i++)
135  {
136  targets[i] ‪door_classify( self );
137 
138  if(!isDefined(targets[i].og_origin))
139  {
140  targets[i].og_origin = targets[i].origin;
141  targets[i].og_angles = targets[i].angles;
142  }
143  }
144 
145  //assert( isdefined( self.type ), "You must determine how this door opens. Specify script_angles, script_vector, or a script_noteworthy... Door at: " + self.origin );
146  cost = 1000;
147  if( isdefined( self.zombie_cost ) )
148  {
149  cost = self.zombie_cost;
150  }
151 
152  self SetCursorHint( "HINT_NOICON" );
153 
155 
156  // MM (03/09/10) - Allow activation at any time in order to make it easier to open bigger doors.
157 // self UseTriggerRequireLookAt();
158  self thread ‪door_think();
159 
160  // MM - Added support for electric doors. Don't have to add them to level scripts
161  if ( isdefined( self.script_noteworthy ) )
162  {
163  if ( self.script_noteworthy == "electric_door" || self.script_noteworthy == "electric_buyable_door" )
164  {
165  if ( GetDvarString( "ui_gametype" ) == "zgrief" )
166  {
167  self SetInvisibleToAll();
168  return;
169  }
170 
171  self sethintstring(&"ZOMBIE_NEED_POWER");
172 // self set_door_unusable();
173  if( isDefined( level.door_dialog_function ) )
174  {
175  self thread [[ level.door_dialog_function ]]();
176  }
177  return;
178  }
179  else if ( self.script_noteworthy == "local_electric_door" )
180  {
181  if ( GetDvarString( "ui_gametype" ) == "zgrief" )
182  {
183  self SetInvisibleToAll();
184  return;
185  }
186 
187  self sethintstring(&"ZOMBIE_NEED_LOCAL_POWER");
188 // self set_door_unusable();
189  if( isDefined( level.door_dialog_function ) )
190  {
191  self thread [[ level.door_dialog_function ]]();
192  }
193  return;
194  }
195  else if ( self.script_noteworthy == "kill_counter_door" )
196  {
197  self sethintstring(&"ZOMBIE_DOOR_ACTIVATE_COUNTER", cost);
198  return;
199  }
200  }
201 
202  self ‪zm_utility::set_hint_string( self, "default_buy_door", cost );
203 }
204 
205 
206 //
207 // Help fix-up doors not using script_string and also to reclassify non-door entities.
208 //
209 function ‪door_classify( parent_trig )
210 {
211  if( isdefined( self.script_noteworthy ) && self.script_noteworthy == ‪STR_NAV_VOLUME_TRAVERSAL )
212  {
213  //this is for navvolume traversals
214  UnlinkTraversal( self );
215  parent_trig.doors[parent_trig.doors.size] = self;
216  return;
217  }
218  if ( isdefined(self.script_noteworthy) && self.script_noteworthy == "clip" )
219  {
220  parent_trig.clip = self;
221  parent_trig.script_string = "clip";
222  }
223  else if( !isdefined( self.script_string ) )
224  {
225  if( isdefined( self.script_angles ) )
226  {
227  self.script_string = "rotate";
228  }
229  else if( isdefined( self.script_vector ) )
230  {
231  self.script_string = "move";
232  }
233  }
234  else
235  {
236  if ( !isdefined( self.script_string ) )
237  {
238  self.script_string = "";
239  }
240 
241  // Handle other script_strings here
242  switch( self.script_string )
243  {
244  case "anim":
245  assert( isdefined( self.script_animname ), "Blocker_init: You must specify a script_animname for "+self.targetname );
246  assert( isdefined( level.scr_anim[ self.script_animname ] ), "Blocker_init: You must define a level.scr_anim for script_anim -> "+self.script_animname );
247  assert( isdefined( level.blocker_anim_func ), "Blocker_init: You must define a level.blocker_anim_func" );
248  break;
249 
250  case "counter_1s":
251  parent_trig.counter_1s = self;
252  return; // this is not a door element
253 
254  case "counter_10s":
255  parent_trig.counter_10s = self;
256  return; // this is not a door element
257 
258  case "counter_100s":
259  parent_trig.counter_100s = self;
260  return; // this is not a door element
261 
262  case "explosives":
263  if ( !isdefined(parent_trig.explosives) )
264  {
265  parent_trig.explosives = [];
266  }
267  parent_trig.explosives[parent_trig.explosives.size] = self;
268  return; // this is not a door element
269  }
270  }
271 
272  if ( self.classname == "script_brushmodel" )
273  {
274  self DisconnectPaths();
275  }
276  parent_trig.doors[parent_trig.doors.size] = self;
277 }
278 
279 
280 //
281 // Someone just tried to buy the door
282 // return true if door was bought
283 // NOTE: This is currently intended to be used as a non-threaded call
284 // self is a door trigger
285 function ‪door_buy()
286 {
287  self waittill( "trigger", who, force );
288 
289  if ( isdefined( level.custom_door_buy_check ) )
290  {
291  if ( !who [[ level.custom_door_buy_check ]]( self ) )
292  {
293  return false;
294  }
295  }
296 
297  if(GetDvarInt( "zombie_unlock_all") > 0 || ‪IS_TRUE( force ) )
298  {
299  return true;
300  }
301 
302  if( !who UseButtonPressed() )
303  {
304  return false;
305  }
306 
308  {
309  return false;
310  }
311 
312  if( ‪IS_DRINKING(who.is_drinking) )
313  {
314  return false;
315  }
316  cost = 0;
317  upgraded = 0;
318  if( ‪zm_utility::is_player_valid( who ) )
319  {
320  players = GetPlayers();
321 
322  // Get the cost of the door
323  cost = self.zombie_cost;
324 
325  if( /*(isdefined(self.purchaser) && self.purchaser == who) &&*/ self._door_open == true)
326  {
327  self.purchaser = undefined;
328  }
329  else if( who ‪zm_score::can_player_purchase( cost ) )
330  {
332  ‪scoreevents::processScoreEvent( "open_door", who );
333  ‪demo::bookmark( "zm_player_door", gettime(), who );
334  who ‪zm_stats::increment_client_stat( "doors_purchased" );
335  who ‪zm_stats::increment_player_stat( "doors_purchased" );
336  who ‪zm_stats::increment_challenge_stat( "SURVIVALIST_BUY_DOOR" );
337  self.purchaser = who;
338  }
339  else // Not enough money
340  {
341  ‪zm_utility::play_sound_at_pos( "no_purchase", self.doors[0].origin );
342 
343  if(isDefined(level.custom_door_deny_vo_func))
344  {
345  who thread [[level.custom_door_deny_vo_func]]();
346  }
347  else if(isDefined(level.custom_generic_deny_vo_func))
348  {
349  who thread [[level.custom_generic_deny_vo_func]](true);
350  }
351  else
352  {
353  who ‪zm_audio::create_and_play_dialog( "general", "outofmoney" );
354  }
355  return false;
356  }
357 
358  }
359 
360  if(isdefined(level._door_open_rumble_func))
361  {
362  who thread [[ level._door_open_rumble_func ]]();
363  }
364  who RecordMapEvent(‪ZM_MAP_EVENT_PURCHASE_DOOR, GetTime(), who.origin, level.round_number, cost);
365  who ‪zm_stats::increment_challenge_stat( "ZM_DAILY_PURCHASE_DOORS" );
366  return true;
367 }
368 
370 {
371  self endon( "kill_door_think" );
372  self endon( "kill_debris_prompt_thread" );
373  self endon( "death" );
374 
375  //similar to the logic in _zm_perks.gsc to update prompt visibility
376  dist = 128 * 128;
377  while( true )
378  {
379  players = level.players;
380  if( isdefined( players ) )
381  {
382  for( i = 0; i < players.size; i++ )
383  {
384  if( DistanceSquared( players[i].origin, self.origin ) < dist )
385  {
386  if( ‪IS_DRINKING( players[i].is_drinking ) )
387  {
388  self SetInvisibleToPlayer( players[i], true );
389  }
390  else
391  {
392  self SetInvisibleToPlayer( players[i], false );
393  }
394  }
395  }
396  }
397  wait( 0.25 );
398  }
399 }
400 
401 //
402 // Open a delay door once the time has expired
403 // self is a door
404 function ‪door_delay()
405 {
406  // Show explosives
407  if ( isdefined( self.explosives ) )
408  {
409  for ( i=0; i<self.explosives.size; i++ )
410  {
411  self.explosives[i] Show();
412  }
413  }
414 
415  // Now wait
416  if (!isdefined(self.script_int) )
417  {
418  self.script_int = 5;
419  }
420 
421  // Turn off the triggers.
422  all_trigs = getentarray( self.target, "target" );
423  for( i = 0; i < all_trigs.size; i++ )
424  {
425  all_trigs[i] TriggerEnable( false );
426  }
427 
428  wait (self.script_int);
429  for ( i=0; i<self.script_int; i++ )
430  {
431  wait(1);
432  }
433 
434  // Time's Up!
435  // Show explosives
436  if ( isdefined( self.explosives ) )
437  {
438  for ( i=0; i<self.explosives.size; i++ )
439  {
440  PlayFX( level._effect["def_explosion"], self.explosives[i].origin, AnglesToForward(self.explosives[i].angles) );
441  self.explosives[i] Hide();
442  }
443  }
444 }
445 
446 
447 
448 
449 //
450 // Make the door do its thing
451 // self is a door
452 // open: true makes the door open, false makes it close (reverse operation). Defaults to TRUE
453 // NOTE: open is currently ONLY supported for "move" type doors
454 // time is a time override
455 function ‪door_activate( time, ‪open, quick, use_blocker_clip_for_pathing )
456 {
457  if ( !isdefined( ‪open ))
458  {
459  ‪open = true;
460  }
461 
462  if( isdefined( self.script_noteworthy ) && self.script_noteworthy == ‪STR_NAV_VOLUME_TRAVERSAL )
463  {
464  //this is for navvolume traversals
465  if( ‪open )
466  {
467  LinkTraversal( self );
468  }
469  else
470  {
471  UnlinkTraversal( self );
472  }
473  return;
474  }
475 
476  if ( !isdefined(time) )
477  {
478  time = 1;
479  if( isdefined( self.script_transition_time ) )
480  {
481  time = self.script_transition_time;
482  }
483  }
484 
485 
486  // Prevent multiple triggers from making doors move more than once
487  if ( isdefined(self.door_moving) )
488  {
489  if ( ( isdefined( self.script_noteworthy ) && self.script_noteworthy == "clip" ) ||
490  ( isdefined( self.script_string ) && self.script_string == "clip" ) )
491  {
492  if ( !‪IS_TRUE( use_blocker_clip_for_pathing ) )
493  {
494  if(!‪open)
495  return;
496  }
497  }
498  else
499  {
500  return;
501  }
502  }
503  self.door_moving = 1;
504  level notify( "sndDoorOpening" );
505 
506  if (‪open || !‪IS_TRUE(quick))
507  self NotSolid();
508  //else
509  // self Solid();
510 
511  if(self.classname == "script_brushmodel" || self.classname == "script_model")
512  {
513  if ( ‪open )
514  {
515  self ConnectPaths();
516  }
517  }
518 
519  if ( ( isdefined( self.script_noteworthy ) && self.script_noteworthy == "clip" ) ||
520  ( isdefined( self.script_string ) && self.script_string == "clip" ) )
521  {
522  if(!‪open)
523  {
524  self ‪util::delay( time, undefined, &‪self_disconnectpaths );
525  wait(.1);
526  self Solid();
527  }
528  return;
529  }
530 
531  if( isdefined( self.script_sound ) )
532  {
533  if( ‪open )
534  playsoundatposition( self.script_sound, self.origin );
535  else
536  playsoundatposition( self.script_sound + "_close", self.origin );
537  }
538  else
539  {
540  ‪zm_utility::play_sound_at_pos( "zmb_heavy_door_open", self.origin );
541  }
542 
543  // scale
544  scale = 1;
545  if ( !‪open )
546  {
547  scale = -1;
548  }
549 
550  // MM - each door can now have a different opening style instead of
551  // needing to be all the same
552  switch( self.script_string )
553  {
554  case "rotate":
555  if(isDefined(self.script_angles))
556  {
557  rot_angle = self.script_angles;
558  if(!‪open)
559  {
560  rot_angle = self.og_angles;
561  }
562  self RotateTo( rot_angle, time, 0, 0 );
563  //if (open || !IS_TRUE(quick))
564  self thread ‪door_solid_thread();
565  if ( !‪open )
566  {
567  self thread ‪disconnect_paths_when_done();
568  }
569  }
570  wait(randomfloat(.15));
571  break;
572  case "move":
573  case "slide_apart":
574  if(isDefined(self.script_vector))
575  {
576  vector = VectorScale( self.script_vector, scale );
577  if ( time >= 0.5 )
578  {
579  self MoveTo( self.origin + vector, time, time * 0.25, time * 0.25 );
580  }
581  else
582  {
583  self MoveTo( self.origin + vector, time );
584  }
585  //if (open || !IS_TRUE(quick))
586  self thread ‪door_solid_thread();
587  if ( !‪open )
588  {
589  self thread ‪disconnect_paths_when_done();
590  }
591  }
592  wait(randomfloat(.15));
593  break;
594 
595  case "anim":
596  // self animscripted( "door_anim", self.origin, self.angles, level.scr_anim[ self.script_animname ] );
597  self [[ level.blocker_anim_func ]]( self.script_animname );
598  self thread ‪door_solid_thread_anim();
599  wait(randomfloat(.15));
600  break;
601 
602  case "physics":
603  self thread ‪physics_launch_door( self );
604  wait(0.10);
605  break;
606  case "zbarrier":
607  self thread ‪door_zbarrier_move();
608  break;
609  }
610 
611  if( isdefined( self.script_firefx ) )
612  {
613  PlayFX( level._effect[self.script_firefx], self.origin );
614  }
615 }
616 
617 
618 function ‪kill_trapped_zombies(trigger)
619 {
620  zombies = GetAiTeamArray( level.zombie_team );
621  if ( !isDefined( zombies ) )
622  {
623  return;
624  }
625 
626  for (i=0; i<zombies.size; i++)
627  {
628  if ( !isdefined( zombies[i] ) )
629  {
630  continue;
631  }
632 
633  if ( zombies[i] istouching(trigger) )
634  {
635  zombies[i].marked_for_recycle = 1;
636  zombies[i] DoDamage( zombies[i].health + 666, trigger.origin, self );
637  wait RandomFloat(0.15);
638  }
639  else if(isdefined(level.custom_trapped_zombies))
640  {
641  zombies[i] thread [[level.custom_trapped_zombies]]();
642  wait RandomFloat(0.15);
643  }
644  }
645 }
646 
647 function ‪any_player_touching( trigger )
648 {
649  foreach( player in GetPlayers() )
650  {
651  if ( player IsTouching(trigger))
652  return true;
653  wait 0.01;
654  }
655  return false;
656 }
657 
658 function ‪any_player_touching_any( trigger, more_triggers )
659 {
660  foreach( player in GetPlayers() )
661  {
662  if( ‪zm_utility::is_player_valid(player, false, true) )
663  {
664  if (isdefined(trigger) && player IsTouching(trigger))
665  return true;
666  if (isdefined(more_triggers) && more_triggers.size>0)
667  foreach(trig in more_triggers)
668  if (isdefined(trig) && player IsTouching(trig))
669  return true;
670  }
671  }
672  return false;
673 }
674 
675 
676 function ‪any_zombie_touching_any( trigger, more_triggers )
677 {
678  zombies = GetAiTeamArray( level.zombie_team );
679  foreach ( zombie in zombies )
680  {
681  if (isdefined(trigger) && zombie IsTouching(trigger))
682  return true;
683  if (isdefined(more_triggers) && more_triggers.size>0)
684  foreach(trig in more_triggers)
685  if (isdefined(trig) && zombie IsTouching(trig))
686  return true;
687  }
688  return false;
689 }
690 
691 
692 function ‪wait_trigger_clear( trigger, more_triggers, end_on )
693 {
694  self endon( end_on );
695  while( ‪any_player_touching_any( trigger, more_triggers ) || ‪any_zombie_touching_any( trigger, more_triggers ) )
696  {
697  wait 1;
698  }
699  self notify("trigger_clear");
700 }
701 
702 
704 {
705  self endon("trigger_clear");
706  while(1)
707  {
708  if (‪IS_TRUE(self.local_power_on))
709  self waittill( "local_power_off" );
710  self ‪wait_trigger_clear( trigger, all_trigs, "local_power_on" );
711  }
712 }
713 
715 {
716  self endon("trigger_clear");
717  while(1)
718  {
719  if (‪IS_TRUE(self.power_on))
720  self waittill( "power_off" );
721  self ‪wait_trigger_clear( trigger, all_trigs, "power_on" );
722  }
723 }
724 
726 {
727  trigger = undefined;
728  if (isdefined(self.door_hold_trigger))
729  {
730  trigger = GetEnt(self.door_hold_trigger,"targetname");
731  }
732  all_trigs = getentarray( self.target, "target" );
733 
734  switch( self.script_noteworthy )
735  {
736  case "local_electric_door":
737  if (isdefined(trigger) || isdefined(all_trigs) )
738  {
739  self ‪waittill_door_trigger_clear_local_power_off(trigger, all_trigs);
740  self thread ‪kill_trapped_zombies(trigger);
741  }
742  else
743  {
744  if (‪IS_TRUE(self.local_power_on))
745  self waittill( "local_power_off" );
746  }
747  return;
748 
749  case "electric_door":
750  if (isdefined(trigger) || isdefined(all_trigs) )
751  {
752  self ‪waittill_door_trigger_clear_global_power_off(trigger, all_trigs);
753  if (isdefined(trigger))
754  self thread ‪kill_trapped_zombies(trigger);
755  }
756  else
757  {
758  if (‪IS_TRUE(self.power_on))
759  self waittill( "power_off" );
760  }
761  return;
762  }
763 }
764 
765 
766 //
767 // Wait to be opened!
768 // self is a door trigger
769 function ‪door_think()
770 {
771  self endon("kill_door_think");
772 
773  // maybe the door the should just bust open instead of slowly opening.
774  // maybe just destroy the door, could be two players from opposite sides..
775  // breaking into chunks seems best.
776  // or I cuold just give it no collision
777 
778  cost = 1000;
779  if( isdefined( self.zombie_cost ) )
780  {
781  cost = self.zombie_cost;
782  }
783 
784  self SetHintLowPriority( true );
785 
786  while( 1 )
787  {
788  switch( self.script_noteworthy )
789  {
790  case "local_electric_door":
791  if (!‪IS_TRUE(self.local_power_on))
792  self waittill( "local_power_on" );
793  if (!‪IS_TRUE(self._door_open))
794  {
795  self ‪door_opened(cost,true);
796  if (!isdefined(self.power_cost))
797  self.power_cost = 0;
798  self.power_cost += 200;
799  }
800  self setHintString("");
801 
802  if( ‪IS_TRUE( level.local_doors_stay_open ) )
803  {
804  return;
805  }
806 
807  //Else door can be closed
808  wait 3;
810  self ‪door_block();
811  if (‪IS_TRUE(self._door_open))
812  {
813  self ‪door_opened(cost,true);
814  }
815  self sethintstring(&"ZOMBIE_NEED_LOCAL_POWER");
816  wait 3;
817  continue;
818 
819  case "electric_door":
820  if (!‪IS_TRUE(self.power_on))
821  self waittill( "power_on" );
822  if (!‪IS_TRUE(self._door_open))
823  {
824  self ‪door_opened(cost,true);
825  if (!isdefined(self.power_cost))
826  self.power_cost = 0;
827  self.power_cost += 200;
828  }
829  self setHintString("");
830 
831  if( ‪IS_TRUE( level.local_doors_stay_open ) )
832  {
833  return;
834  }
835 
836  //Else door can be closed
837  wait 3;
839  self ‪door_block();
840  if (‪IS_TRUE(self._door_open))
841  {
842  self ‪door_opened(cost,true);
843  }
844  self sethintstring(&"ZOMBIE_NEED_POWER");
845  wait 3;
846  continue;
847  //self self_and_flag_wait( "power_on" );
848  //self door_opened(cost);
849  //return;
850 
851  case "electric_buyable_door":
852  if (!‪IS_TRUE(self.power_on))
853  self waittill( "power_on" );
854 
855  self ‪zm_utility::set_hint_string( self, "default_buy_door", cost );
856 // self UseTriggerRequireLookAt();
857 
858  if ( !self ‪door_buy() )
859  {
860  continue;
861  }
862  break;
863 
864  case "delay_door": // set timer and explode
865  if ( !self ‪door_buy() )
866  {
867  continue;
868  }
869 
870  self ‪door_delay();
871  break;
872 
873  default:
874  if(isDefined( level._default_door_custom_logic))
875  {
876  self [[level._default_door_custom_logic]]();
877  break;
878  }
879  if ( !self ‪door_buy() )
880  {
881  continue;
882  }
883  break;
884  }
885 
886  self ‪door_opened(cost);
887  if(!level ‪flag::get("door_can_close"))
888  {
889  break;
890  }
891  }
892 }
893 
894 function ‪self_and_flag_wait( msg )
895 {
896  self endon( msg );
897 
898  if ( ‪IS_TRUE( self.power_door_ignore_flag_wait ) )
899  {
900  level waittill( "forever" );
901  }
902  else
903  {
904  level ‪flag::wait_till( msg );
905  }
906 }
907 
908 function ‪door_block()
909 {
910  if(isdefined(self.doors)) //forces collision early
911  {
912  // block the door
913  for(i=0;i<self.doors.size;i++)
914  {
915  if ( ( isdefined( self.doors[i].script_noteworthy ) && self.doors[i].script_noteworthy == "clip" ) ||
916  ( isdefined( self.doors[i].script_string ) && self.doors[i].script_string == "clip" ) )
917  self.doors[i] Solid();
918  }
919  }
920 }
921 
922 
923 function ‪door_opened(cost,quick_close)
924 {
925  if ( ‪IS_TRUE( self.door_is_moving ) )
926  return;
927 
928  self.has_been_opened = true; //for tracking
929 
930  // get all trigs for the door, we might want a trigger on both sides
931  // of some junk sometimes
932  all_trigs = getentarray( self.target, "target" );
933 
934  self.door_is_moving = true; // just in case this doesn't target itself
935  foreach ( trig in all_trigs )
936  {
937  trig.door_is_moving = true;
938  trig TriggerEnable( false );
939 
940  trig.has_been_opened = true; //for achievement & stat tracking
941  if ( !isdefined( trig._door_open ) || (trig._door_open == false))
942  {
943  trig._door_open = true;
944  trig notify("door_opened");
945  }
946  else // close the door instead.
947  {
948  trig._door_open = false;
949  }
950 
951  // Set any flags called
952  if( isdefined( trig.script_flag ) && trig._door_open == true)
953  {
954  tokens = Strtok( trig.script_flag, "," );
955  for ( i=0; i<tokens.size; i++ )
956  {
957  level ‪flag::set( tokens[i] );
958  }
959  }
960  else if(isdefined( trig.script_flag ) && trig._door_open == false)
961  {
962  tokens = Strtok( trig.script_flag, "," );
963  for ( i=0; i<tokens.size; i++ )
964  {
965  level ‪flag::clear( tokens[i] );
966  }
967  }
968 
969  if ( ‪IS_TRUE(quick_close) )
970  {
971  trig ‪zm_utility::set_hint_string( trig, "" );
972  }
973  else if(trig._door_open == true && level ‪flag::get("door_can_close"))
974  {
975  trig ‪zm_utility::set_hint_string( trig, "default_buy_door_close" );
976  }
977  else if(trig._door_open == false)
978  {
979  trig ‪zm_utility::set_hint_string( trig, "default_buy_door", cost );
980  }
981  }
982 
983  level notify("door_opened"); //for achievement & stat tracking
984 
985  if(isdefined(self.doors))
986  {
987  is_script_model_door = false;
988  have_moving_clip_for_door = false;
989  use_blocker_clip_for_pathing = false;
990 
991  foreach ( door in self.doors )
992  {
993  if ( ‪IS_TRUE( door.ignore_use_blocker_clip_for_pathing_check ) )
994  {
995  continue;
996  }
997  if( isdefined( door.script_noteworthy ) && door.script_noteworthy == ‪STR_NAV_VOLUME_TRAVERSAL )
998  {
999  continue;
1000  }
1001  if ( door.classname == "script_model" )
1002  {
1003  is_script_model_door = true;
1004  continue;
1005  }
1006 
1007  if ( door.classname == "script_brushmodel" &&
1008  ( !isdefined( door.script_noteworthy ) || door.script_noteworthy != "clip" ) &&
1009  ( !isdefined( door.script_string ) || door.script_string != "clip" ) )
1010  {
1011  have_moving_clip_for_door = true;
1012  }
1013  }
1014 
1015  use_blocker_clip_for_pathing = is_script_model_door && !have_moving_clip_for_door;
1016 
1017  // Door has been activated, make it do its thing
1018  for(i=0;i<self.doors.size;i++)
1019  {
1020  // Don't thread this so the doors don't move at once
1021  // DCS 072812: was there a reason? this breaks if two triggers activated simultaneously otherwise.
1022  self.doors[i] thread Door_Activate(self.doors[i].script_transition_time, self._door_open, quick_close, use_blocker_clip_for_pathing);
1023  }
1024  // Just play purchase sound on the first door
1025  if( self.doors.size )
1026  {
1027  ‪zm_utility::play_sound_at_pos( "purchase", self.origin ); //self is the specific door being opened
1028  }
1029  }
1030 
1031  // Update the active zone names (so our unitriggers are responsive)
1032  // NOTE: THIS FUNCTION MAY BLOCK
1033  level.active_zone_names = ‪zm_zonemgr::get_active_zone_names();
1034 
1035  wait( 1 ); // wait a second to ensure a trigger at a multi-door on the same frame (accounting for lag) doesn't trigger a close
1036  self.door_is_moving = false; // just in case this doesn't target itself
1037  foreach ( trig in all_trigs )
1038  {
1039  trig.door_is_moving = false;
1040  }
1041 
1042  if ( ‪IS_TRUE(quick_close) )
1043  {
1044  for( i = 0; i < all_trigs.size; i++ )
1045  {
1046  all_trigs[i] TriggerEnable( true );
1047  }
1048  return;
1049  }
1050 
1051 
1052  // Check if doors can be closed.
1053  if(level ‪flag::get("door_can_close") )
1054  {
1055  wait(2.0);
1056 
1057  for( i = 0; i < all_trigs.size; i++ )
1058  {
1059  all_trigs[i] TriggerEnable( true );
1060  }
1061  }
1062 }
1063 
1064 
1065 //
1066 // Launch the door!
1067 // self = door entity
1068 // door_trig = door trigger
1069 function ‪physics_launch_door( door_trig )
1070 {
1071  vec = VectorScale( VectorNormalize( self.script_vector ), 10 );
1072  self RotateRoll( 5, 0.05 );
1074  self MoveTo( self.origin + vec, 0.1 );
1075  self waittill( "movedone" );
1076 
1077  self PhysicsLaunch( self.origin, self.script_vector *300 );
1078  //wait(0.1);
1079  //PhysicsExplosionSphere( VectorScale( vec, -1 ), 120, 1, 100 );
1080 
1081  wait(60);
1082 
1083  self delete();
1084 }
1085 
1086 
1087 //
1088 // Waits until it is finished moving and then returns to solid once no player is touching it
1089 // (So they don't get stuck). The door is made notSolid initially, otherwise, a player
1090 // could block its movement or cause a player to become stuck.
1091 // self is a door
1093 {
1094  // MM - added support for movedone.
1095  self ‪util::waittill_either( "rotatedone", "movedone" );
1096 
1097  self.door_moving = undefined;
1098  while( 1 )
1099  {
1100  players = GetPlayers();
1101  player_touching = false;
1102  for( i = 0; i < players.size; i++ )
1103  {
1104  if( players[i] IsTouching( self ) )
1105  {
1106  player_touching = true;
1107  break;
1108  }
1109  }
1110 
1111  if( !player_touching )
1112  {
1113  self Solid();
1114  return;
1115  }
1116 
1117  wait( 1 );
1118  }
1119 }
1120 
1121 
1122 //
1123 // Called on doors using anims. It needs a different waittill,
1124 // and expects the animname message to be the same as the one passed into scripted anim
1125 // self is a door
1127 {
1128  // MM - added support for movedone.
1129  self waittillmatch( "door_anim", "end" );
1130 
1131  self.door_moving = undefined;
1132  while( 1 )
1133  {
1134  players = GetPlayers();
1135  player_touching = false;
1136  for( i = 0; i < players.size; i++ )
1137  {
1138  if( players[i] IsTouching( self ) )
1139  {
1140  player_touching = true;
1141  break;
1142  }
1143  }
1144 
1145  if( !player_touching )
1146  {
1147  self Solid();
1148  return;
1149  }
1150 
1151  wait( 1 );
1152  }
1153 }
1154 
1155 
1156 //
1157 //
1158 //
1160 {
1161  self ‪util::waittill_either( "rotatedone", "movedone" );
1162 
1163  self DisconnectPaths();
1164 }
1165 
1166 
1167 //
1168 //
1169 //
1171 {
1172  self DisconnectPaths();
1173 }
1174 
1175 //
1176 // DEBRIS - these are "doors" that consist of various pieces of piled objects
1177 // they lift up and disappear when bought.
1178 //
1179 function ‪debris_init()
1180 {
1181  cost = 1000;
1182  if( isdefined( self.zombie_cost ) )
1183  {
1184  cost = self.zombie_cost;
1185  }
1186 
1187  self ‪zm_utility::set_hint_string( self, "default_buy_debris", cost );
1188  self setCursorHint( "HINT_NOICON" );
1189 
1190  if( isdefined (self.script_flag) && !isdefined( level.flag[self.script_flag] ) )
1191  {
1192  level ‪flag::init( self.script_flag );
1193  }
1194 
1195  // Look for zbarrier debris and initialize it.
1196  if ( isdefined( self.target ) )
1197  {
1198  targets = GetEntArray( self.target, "targetname" );
1199  foreach( target in targets )
1200  {
1201  if ( target IsZBarrier() )
1202  {
1203  for( i=0; i < target GetNumZBarrierPieces(); i++ )
1204  {
1205  target SetZBarrierPieceState( i, "closed" );
1206  }
1207  }
1208  }
1209 
1210  a_nd_targets = GetNodeArray( self.target, "targetname" );
1211  foreach( nd_target in a_nd_targets )
1212  {
1213  //this is for navvolume traversals
1214  if( isdefined( nd_target.script_noteworthy ) && nd_target.script_noteworthy == ‪STR_NAV_VOLUME_TRAVERSAL )
1215  {
1216  UnlinkTraversal( nd_target );
1217  }
1218  }
1219  }
1220 
1221 // self UseTriggerRequireLookAt();
1223  self thread ‪debris_think();
1224 }
1225 
1226 
1227 //
1228 // self is a debris trigger
1229 //
1231 {
1232  if( isDefined( level.custom_debris_function ) )
1233  {
1234  self [[ level.custom_debris_function ]]();
1235  }
1236 
1237  // cut the navmesh
1238  junk = getentarray( self.target, "targetname" );
1239  for( i = 0; i < junk.size; i++ )
1240  {
1241  if( isdefined( junk[i].script_noteworthy ) )
1242  {
1243  if( junk[i].script_noteworthy == "clip" )
1244  {
1245  junk[i] disconnectpaths();
1246  }
1247  }
1248  }
1249 
1250  while( 1 )
1251  {
1252  self waittill( "trigger", who, force );
1253 
1254  if(GetDvarInt( "zombie_unlock_all") > 0 || ‪IS_TRUE( force ) )
1255  {
1256  //bypass.
1257  }
1258  else
1259  {
1260  if( !who UseButtonPressed() )
1261  {
1262  continue;
1263  }
1264 
1265  if( ‪IS_DRINKING(who.is_drinking) )
1266  {
1267  continue;
1268  }
1269 
1271  {
1272  continue;
1273  }
1274  }
1275 
1276  if( ‪zm_utility::is_player_valid( who ) )
1277  {
1278  // Can we afford this door?
1279  players = GetPlayers();
1280  if(GetDvarInt( "zombie_unlock_all") > 0)
1281  {
1282  // bypass charge.
1283  }
1284  else if ( /*players.size == 1 &&*/ who ‪zm_score::can_player_purchase( self.zombie_cost ) )
1285  {
1286  // solo buy
1287  who ‪zm_score::minus_to_player_score( self.zombie_cost );
1288  ‪scoreevents::processScoreEvent( "open_door", who );
1289  ‪demo::bookmark( "zm_player_door", gettime(), who );
1290  who ‪zm_stats::increment_client_stat( "doors_purchased" );
1291  who ‪zm_stats::increment_player_stat( "doors_purchased" );
1292  who ‪zm_stats::increment_challenge_stat( "SURVIVALIST_BUY_DOOR" );
1293  }
1294 /*
1295  else if( level.team_pool[ who.team_num ].score >= self.zombie_cost )
1296  {
1297  // team buy
1298  who zm_score::minus_to_team_score( self.zombie_cost );
1299  }
1300  else if( level.team_pool[ who.team_num ].score + who.score >= self.zombie_cost )
1301  {
1302  // team funds + player funds
1303  team_points = level.team_pool[ who.team_num ].score;
1304  who zm_score::minus_to_player_score( self.zombie_cost - team_points );
1305  who zm_score::minus_to_team_score( team_points );
1306  }
1307 */
1308  else
1309  {
1310  ‪zm_utility::play_sound_at_pos( "no_purchase", self.origin );
1311  who ‪zm_audio::create_and_play_dialog( "general", "outofmoney" );
1312  continue;
1313  }
1314 
1315  self notify( "kill_debris_prompt_thread" );
1316 
1317  // Okay remove the debris
1318  // delete the stuff
1319  junk = getentarray( self.target, "targetname" );
1320 
1321  // Set any flags called
1322  if( isdefined( self.script_flag ) )
1323  {
1324  tokens = Strtok( self.script_flag, "," );
1325  for ( i=0; i<tokens.size; i++ )
1326  {
1327  level ‪flag::set( tokens[i] );
1328  }
1329  }
1330 
1331  ‪zm_utility::play_sound_at_pos( "purchase", self.origin );
1332  level notify ("junk purchased");
1333 
1334  move_ent = undefined;
1335  a_clip = [];
1336  for( i = 0; i < junk.size; i++ )
1337  {
1338  junk[i] connectpaths();
1339 
1340  if( isdefined( junk[i].script_noteworthy ) )
1341  {
1342  if( junk[i].script_noteworthy == "clip" )
1343  {
1344  a_clip[ a_clip.size ] = junk[i];
1345  continue;
1346  }
1347  }
1348 
1349  struct = undefined;
1350  if ( junk[i] IsZBarrier() )
1351  {
1352  move_ent = junk[i];
1353  junk[i] thread ‪debris_zbarrier_move();
1354  }
1355  else if( isdefined( junk[i].script_linkTo ) )
1356  {
1357  struct = ‪struct::get( junk[i].script_linkTo, "script_linkname" );
1358  if( isdefined( struct ) )
1359  {
1360  move_ent = junk[i];
1361  junk[i] thread ‪debris_move( struct );
1362  }
1363  else
1364  {
1365  junk[i] Delete();
1366  }
1367  }
1368  else if( isdefined( junk[i].target) )
1369  {
1370  struct = ‪struct::get( junk[i].target, "targetname" );
1371  if( isdefined( struct ) )
1372  {
1373  move_ent = junk[i];
1374  junk[i] thread ‪debris_move( struct );
1375  }
1376  else
1377  {
1378  junk[i] Delete();
1379  }
1380  }
1381  else
1382  {
1383  junk[i] Delete();
1384  }
1385  }
1386 
1387  // Connect NavVolume traversals
1388  a_nd_targets = GetNodeArray( self.target, "targetname" );
1389  foreach( nd_target in a_nd_targets )
1390  {
1391  //this is for navvolume traversals
1392  if( isdefined( nd_target.script_noteworthy ) && nd_target.script_noteworthy == ‪STR_NAV_VOLUME_TRAVERSAL )
1393  {
1394  LinkTraversal( nd_target );
1395  }
1396  }
1397 
1398  // get all trigs, we might want a trigger on both sides
1399  // of some junk sometimes
1400  all_trigs = getentarray( self.target, "target" );
1401  for( i = 0; i < all_trigs.size; i++ )
1402  {
1403  all_trigs[i] delete();
1404  }
1405 
1406  for( i=0; i<a_clip.size; i++ )
1407  {
1408  a_clip[i] Delete();
1409  }
1410 
1411  if( isdefined( move_ent ) )
1412  {
1413  move_ent waittill( "movedone" );
1414  }
1415 
1416  break;
1417  }
1418  }
1419 }
1420 
1422 {
1423  playsoundatposition ("zmb_lightning_l", self.origin);
1424  PlayFX( level._effect["poltergeist"], self.origin );
1425 
1426  for( i = 0; i < self GetNumZBarrierPieces(); i++ )
1427  {
1428  self thread ‪move_chunk( i, true );
1429  }
1430 }
1431 
1433 {
1434  //playsoundatposition ("zmb_lightning_l", self.origin);
1435 
1436  for( i = 0; i < self GetNumZBarrierPieces(); i++ )
1437  {
1438  self thread ‪move_chunk( i, false );
1439  }
1440 }
1441 
1442 function ‪move_chunk( index, b_hide )
1443 {
1444  self SetZBarrierPieceState(index, "opening");
1445  while(self GetZBarrierPieceState(index) == "opening")
1446  {
1447  wait (0.1);
1448  }
1449  self notify( "movedone" );
1450 
1451  if( b_hide )
1452  {
1453  self HideZBarrierPiece( index );
1454  }
1455 }
1456 
1457 
1458 //
1459 // Moves the debris out of place
1460 // self is a debris piece
1461 //
1462 function ‪debris_move( struct )
1463 {
1464  self ‪util::script_delay();
1465  //chrisp - prevent playerse from getting stuck on the stuff
1466  self notsolid();
1467 
1468  self ‪zm_utility::play_sound_on_ent( "debris_move" );
1469  playsoundatposition ("zmb_lightning_l", self.origin);
1470  if( isdefined( self.script_firefx ) )
1471  {
1472  PlayFX( level._effect[self.script_firefx], self.origin );
1473  }
1474 
1475  // Do a little jiggle, then move.
1476  if( isdefined( self.script_noteworthy ) )
1477  {
1478  if( self.script_noteworthy == "jiggle" )
1479  {
1480  num = RandomIntRange( 3, 5 );
1481  og_angles = self.angles;
1482  for( i = 0; i < num; i++ )
1483  {
1484  angles = og_angles + ( -5 + RandomFloat( 10 ), -5 + RandomFloat( 10 ), -5 + RandomFloat( 10 ) );
1485  time = RandomFloatRange( 0.1, 0.4 );
1486  self Rotateto( angles, time );
1487  wait( time - 0.05 );
1488  }
1489  }
1490  }
1491 
1492  time = 0.5;
1493  if( isdefined( self.script_transition_time ) )
1494  {
1495  time = self.script_transition_time;
1496  }
1497 
1498  self MoveTo( struct.origin, time, time * 0.5 );
1499  self RotateTo( struct.angles, time * 0.75 );
1500 
1501  self waittill( "movedone" );
1502 
1503  //Z2 commented out missing sound, wouldn't go past.
1504  //self play_sound_on_entity("couch_slam");
1505 
1506  if( isdefined( self.script_fxid ) )
1507  {
1508  PlayFX( level._effect[self.script_fxid], self.origin );
1509  playsoundatposition("zmb_zombie_spawn", self.origin); //just playing the zombie_spawn sound when it deletes the blocker because it matches the particle.
1510  }
1511 
1512  self Delete();
1513 
1514 }
1515 
1516 function ‪blocker_disconnect_paths(start_node, end_node, two_way)
1517 {
1518 /* if(!isdefined(two_way))
1519  two_way = false;
1520 
1521  if(isdefined(start_node) && isdefined(end_node))
1522  {
1523  if(NodesAreLinked(start_node, end_node))
1524  {
1525  zm_utility::unlink_nodes(start_node, end_node);
1526  }
1527 
1528  if(NodesAreLinked(end_node, start_node) && two_way == true)
1529  {
1530  zm_utility::unlink_nodes(end_node, start_node);
1531  }
1532  } */
1533 }
1534 
1535 function ‪blocker_connect_paths(start_node, end_node, two_way)
1536 {
1537 /* if(isdefined(start_node) && isdefined(end_node))
1538  {
1539  if(!isdefined(two_way))
1540  two_way = false;
1541 
1542  if(!NodesAreLinked(start_node, end_node))
1543  {
1544  zm_utility::link_nodes(start_node, end_node);
1545  }
1546 
1547  if(!NodesAreLinked(end_node, start_node) && two_way == true)
1548  {
1549  zm_utility::link_nodes(end_node, start_node);
1550  }
1551  } */
1552 }
1553 
1554 
1555 //
1556 // BLOCKER (aka window, bar, board)
1557 // Self = exterior_goal, it is the node that targets all of the boards and bars
1558 // This sets up every window in level,
1560 {
1561  if( !isdefined( self.target ) ) // If the exterior_goal entity has no targets defined then return
1562  {
1563  return;
1564  }
1565 
1566  pos = ‪zm_utility::groundpos( self.origin ) + ( 0, 0, 8 );
1567  if(isdefined(pos))
1568  {
1569  self.origin = pos;
1570  }
1571 
1572  targets = GetEntArray( self.target, "targetname" ); // Grab all the pieces that are targeted by the exterior_goal
1573 
1574  self.barrier_chunks = []; // self has a newly defined array of barrier_chunks
1575 
1576  for( j = 0; j < targets.size; j++ ) // count total targets of exterior_goal
1577  {
1578  if(targets[j] IsZBarrier())
1579  {
1580  if( isdefined( level.zbarrier_override ) )
1581  {
1582  self thread [[level.zbarrier_override]]( targets[j] );
1583  continue;
1584  }
1585 
1586  self.zbarrier = targets[j];
1587 
1588  self.zbarrier.chunk_health = [];
1589 
1590  for( i = 0; i < self.zbarrier GetNumZBarrierPieces(); i ++)
1591  {
1592  self.zbarrier.chunk_health[i] = 0;
1593  }
1594 
1595  continue;
1596  }
1597 
1598  // jl/ jan/15/10 add new setup for grates
1599  // I hide all the pieces you don't need to see right now.
1600  // This works
1601  // Now when they get pulled off, I just want them to swap out the model
1602 
1603  if( isdefined( targets[j].script_string ) && targets[j].script_string == "rock" )
1604  {
1605  targets[j].material = "rock";
1606  }
1607 
1608  if( isdefined( targets[j].script_parameters ) ) // If a script noteworthy is defined
1609  {
1610  if( targets[j].script_parameters == "grate" )
1611  {
1612  if( isdefined( targets[j].script_noteworthy ) ) // If a script noteworthy is defined
1613  {
1614  if( targets[j].script_noteworthy == "2" || targets[j].script_noteworthy == "3" || targets[j].script_noteworthy == "4" ||
1615  targets[j].script_noteworthy == "5" || targets[j].script_noteworthy == "6")
1616  {
1617  // this is an improper setup because each piece is still sitting there
1618  targets[j] Hide(); // this grabs all the pieces and hides it
1619  }
1620  }
1621  }
1622  //DCS: new pentagon system where barricade starts as new and is repaired with boards, etc.
1623  // start with repair boards hidden.
1624  else if( targets[j].script_parameters == "repair_board" )
1625  {
1626  targets[j].unbroken_section = GetEnt(targets[j].target,"targetname");
1627  if(isdefined(targets[j].unbroken_section))
1628  {
1629  targets[j].unbroken_section LinkTo(targets[j]);
1630  targets[j] Hide();
1631  targets[j] notSolid();
1632  targets[j].unbroken = true;
1633 
1634  // self is the goal (level.exterior_goals)
1635  if(isdefined(targets[j].unbroken_section.script_noteworthy) && targets[j].unbroken_section.script_noteworthy == "glass")
1636  {
1637  targets[j].material = "glass";
1638  targets[j] thread ‪destructible_glass_barricade(targets[j].unbroken_section, self);
1639  }
1640  else if(isdefined(targets[j].unbroken_section.script_noteworthy) && targets[j].unbroken_section.script_noteworthy == "metal")
1641  {
1642  targets[j].material = "metal";
1643  }
1644  }
1645  }
1646  else if( targets[j].script_parameters == "barricade_vents" )
1647  {
1648  targets[j].material = "metal_vent";
1649  }
1650  }
1651 
1652  if( isdefined ( targets[j].targetname ) )
1653  {
1654  if( targets[j].targetname == "auto2" )
1655  {
1656  // targets[j]
1657  }
1658  }
1659 
1660  targets[j] ‪update_states("repaired"); // Change state to repaired
1661  targets[j].destroyed = false;
1662  targets[j] show();
1663  targets[j].claimed = false;
1664  targets[j].anim_grate_index = 0; // check this index to know where each piece is
1665  // I can create another thing to track here if I need to
1666  targets[j].og_origin = targets[j].origin; // This one piece's origin is defined by grabbing the starting origin
1667  targets[j].og_angles = targets[j].angles; // The one piece's angles is defined by grabbing the starting angles
1668  self.barrier_chunks[self.barrier_chunks.size] = targets[j]; // barrier_chunks is the total size of the bars windows or boards used
1669 
1670  }
1671 
1672  target_nodes = GetNodeArray(self.target, "targetname" );
1673 
1674  for( j = 0; j < target_nodes.size; j++ ) // count total targets of exterior_goal
1675  {
1676  if(target_nodes[j].type == "Begin")
1677  {
1678  self.neg_start = target_nodes[j];
1679 
1680  if(isdefined(self.neg_start.target))
1681  {
1682  self.neg_end = getnode(self.neg_start.target, "targetname");
1683  }
1684 
1685  ‪blocker_disconnect_paths(self.neg_start, self.neg_end);
1686  }
1687  }
1688 
1689  if(isdefined(self.zbarrier))
1690  {
1691  if(isdefined(self.barrier_chunks))
1692  {
1693  for(i = 0; i < self.barrier_chunks.size; i ++)
1694  {
1695  self.barrier_chunks[i] delete();
1696  }
1697 
1698  self.barrier_chunks = [];
1699  }
1700  }
1701 
1702  if( isDefined(self.zbarrier) && ‪should_delete_zbarriers() )
1703  {
1704  self.zbarrier delete();
1705  self.zbarrier = undefined;
1706  return;
1707  }
1708 
1709  self ‪blocker_attack_spots(); // exterior_goal thread
1710 
1711  //assert( isdefined( self.clip ) );
1712  self.trigger_location = ‪struct::get( self.target, "targetname" ); // trigger_location is the new name for exterior_goal targets -- which is auto1 in all cases
1713 
1714  self thread ‪blocker_think(); // exterior_goal thread blocker_think
1715 }
1716 
1718 {
1719  gametype = GetDvarString( "ui_gametype" );
1720  if(!‪zm_utility::is_Classic() && !‪zm_utility::is_Standard() && gametype != "zgrief" )
1721  {
1722  return true;
1723  }
1724  return false;
1725 }
1726 
1727 //-------------------------------------------------------------------------------
1728 // DCS 090710: glass barricade. Player can damage.
1729 // self is chunk, aka. repair_board
1730 //-------------------------------------------------------------------------------
1731 function ‪destructible_glass_barricade(unbroken_section, node)
1732 {
1733  unbroken_section SetCanDamage( true );
1734  unbroken_section.health = 99999;
1735  unbroken_section waittill( "damage", amount, who);
1737  {
1738  self thread ‪zm_spawner::zombie_boardtear_offset_fx_horizontle( self, node );
1739  level thread ‪remove_chunk( self, node, true );
1740  self ‪update_states("destroyed");
1741  self notify("destroyed");
1742  self.unbroken = false;
1743 
1744  }
1745 }
1746 //-------------------------------------------------------------------------------
1747 
1748 // jl jan/05/10
1749 // Self = exterior_goal, it is the node that targets all of the boards and bars
1750 // Creates three spots that the AI can now choose from to attack the window
1752 {
1753 
1754  spots = [];
1755 
1756 
1757  numSlots = self.zbarrier GetZBarrierNumAttackSlots();
1758 
1759  numSlots = int(max(numSlots, 1));
1760 
1761  if(numSlots % 2)
1762  {
1763  spots[spots.size] = ‪zm_utility::groundpos_ignore_water_new( self.zbarrier.origin + ( 0, 0, 60 ) );
1764  }
1765 
1766  if(numSlots > 1)
1767  {
1768  reps = floor(numSlots / 2);
1769 
1770  slot = 1;
1771 
1772  for(i = 0; i < reps; i ++)
1773  {
1774  offset = self.zbarrier GetZBarrierAttackSlotHorzOffset() * (i + 1);
1775 
1776  spots[spots.size] = ‪zm_utility::groundpos_ignore_water_new( spots[0] + ( AnglesToRight( self.angles ) * offset ) + ( 0, 0, 60 ) );
1777 
1778  slot ++;
1779 
1780  if(slot < numSlots)
1781  {
1782  spots[spots.size] = ‪zm_utility::groundpos_ignore_water_new( spots[0] + ( AnglesToRight( self.angles ) * -offset ) + ( 0, 0, 60 ) );
1783 
1784  slot ++;
1785  }
1786  }
1787  }
1788 
1789  taken = []; // new array
1790  for( i = 0; i < spots.size; i++ ) // cycle through all spots and define as not taken
1791  {
1792  taken[i] = false;
1793  }
1794 
1795  self.attack_spots_taken = taken; // set attack_spots_taken to taken
1796  self.attack_spots = spots; // set attack_spots to spots
1797 }
1798 
1799 
1801 {
1802  level._blocker_choke = 0;
1803  level endon("stop_blocker_think");
1804  while(1)
1805  {
1807  level._blocker_choke = 0;
1808  }
1809 }
1810 
1811 
1812 // jl jan/05/10
1813 // Self = exterior_goal, it is the node that targets all of the boards and bars
1815 {
1816  level endon("stop_blocker_think");
1817  if(!isdefined(level._blocker_choke))
1818  {
1819  level thread ‪blocker_choke();
1820  }
1821 
1822  use_choke = false;
1823 
1824  if(isdefined(level._use_choke_blockers) && level._use_choke_blockers == 1)
1825  {
1826  use_choke = true;
1827  }
1828 
1829  while( 1 ) // exterior_goal is going to constantly loop
1830  {
1831  wait( 0.5 );
1832 
1833  if(use_choke)
1834  {
1835  if(level._blocker_choke > 3)
1836  {
1838  }
1839  }
1840 
1841  level._blocker_choke ++;
1842 
1843  if( ‪zm_utility::all_chunks_intact( self, self.barrier_chunks ) ) // speak to zm_utility and into all_chunks_intact function
1844  {
1845  // if any piece has the state of not repaired then return false
1846  // if the board has been repaired then return true
1847  continue;
1848  }
1849 
1850  if( ‪zm_utility::no_valid_repairable_boards( self, self.barrier_chunks ) )// speak to zm_utility and into no_valid_repairable_boards function
1851  {
1852  // if any piece has been destroyed return false
1853  // if any piece is not destroyed then return true
1854  continue;
1855  }
1856 
1857  self ‪blocker_trigger_think();
1858  }
1859 }
1860 
1861 function ‪player_fails_blocker_repair_trigger_preamble(player, players, trigger, hold_required)
1862 {
1863 
1864  if( !isdefined(trigger))
1865  {
1866  return true;
1867  }
1868 
1869 // if( !player IsTouching( trigger ) )
1870 // {
1871 // return true;
1872 // }
1873 
1874  if( !‪zm_utility::is_player_valid( player ) )
1875  {
1876  return true;
1877  }
1878 
1879  if( players.size == 1 && isdefined( players[0].‪intermission ) && players[0].‪intermission == 1)
1880  {
1881  return true;
1882  }
1883 
1884  //if( player zm_equipment::hacker_active() )
1885  //{
1886  // return true;
1887  //}
1888 
1889  if( hold_required && !player UseButtonPressed() )
1890  {
1891  return true;
1892  }
1893 
1894  if( !hold_required && !player ‪util::use_button_held() )
1895  {
1896  return true;
1897  }
1898 
1899  if( player ‪zm_utility::in_revive_trigger() )
1900  {
1901  return true;
1902  }
1903 
1904  if( ‪IS_DRINKING(player.is_drinking) )
1905  {
1906  return true;
1907  }
1908 
1909  return false;
1910 }
1911 
1913 {
1914  has_perk = undefined;
1915 
1916  if( self hasperk( ‪PERK_SLEIGHT_OF_HAND ) )
1917  {
1918  has_perk = ‪PERK_SLEIGHT_OF_HAND;
1919  }
1920 
1921  return has_perk;
1922 }
1923 
1925 {
1926  if( !self ‪util::script_delay() )
1927  {
1928  wait( 1 );
1929  }
1930 }
1931 
1932 function ‪handle_post_board_repair_rewards( cost, zbarrier )
1933 {
1934  self ‪zm_stats::increment_client_stat( "boards" );
1935  self ‪zm_stats::increment_player_stat( "boards" );
1936 
1937  // 5% chance every 5 boards, with a 60 sec minimum time between repeats
1938  if( isDefined(self.pers["boards"] ) && self.pers["boards"] %10 == 0 )
1939  {
1940  self ‪zm_audio::create_and_play_dialog( "general", "rebuild_boards" );
1941  }
1942 
1943  // set the score
1944  self.rebuild_barrier_reward += cost;
1945  if( self.rebuild_barrier_reward < level.zombie_vars["rebuild_barrier_cap_per_round"] )
1946  {
1947  self ‪zm_score::player_add_points( "rebuild_board", cost );
1948  self ‪zm_utility::play_sound_on_ent( "purchase" );
1949 
1950  }
1951  // general contractor achievement for dlc 2. keep track of how many board player repaired.
1952  if(isdefined(self.board_repair))
1953  {
1954  self.board_repair += 1;
1955  }
1956 }
1957 
1959 {
1960  self endon("kill_trigger");
1961 
1962  while ( 1 )
1963  {
1964  self waittill( "trigger", player );
1965  self.stub.trigger_target notify("trigger", player);
1966  }
1967 }
1968 
1969 // Self = exterior_goal, it is the node that targets all of the boards and bars
1970 // trigger_location
1971 // this function repairs the boards
1973 {
1974  self endon( "blocker_hacked" );
1975 
1976  if(‪IS_TRUE(level.no_board_repair)) // don't create the repair trigger if this is true
1977  {
1978  return;
1979  }
1980 
1981 
1982  level endon("stop_blocker_think");
1983 
1984  // They don't cost, they now award the player the cost...
1985  cost = 10;
1986  if( isdefined( self.zombie_cost ) )
1987  {
1988  cost = self.zombie_cost;
1989  }
1990 
1991  original_cost = cost;
1992 
1993 
1994  /*trigger = Spawn( "trigger_radius", trigger_pos, 0, radius, height ); // spawn in a trigger at the location of the exterior_goal
1995  trigger TriggerIgnoreTeam();*/
1996 
1997  if(!isdefined(self.unitrigger_stub))
1998  {
1999  radius = 94.21;
2000  height = 94.21;
2001 
2002 
2003  if( isdefined( self.trigger_location ) ) // this is defined in the blocker_init function
2004  {
2005  trigger_location = self.trigger_location; // trigger_location is the new name for exterior_goal targets -- which is auto1 in all cases
2006  }
2007  else
2008  {
2009  trigger_location = self; // if it is not defined then just use self as the trigger_location
2010  }
2011 
2012  if( isdefined( trigger_location.radius ) ) // he is asking if it is defined here, yet he never defines it anywhere
2013  {
2014  radius = trigger_location.radius;
2015  }
2016 
2017  if( isdefined( trigger_location.height ) ) // he is asking if it is defined here, yet he never defines it anywhere
2018  {
2019  height = trigger_location.height;
2020  }
2021 
2022  trigger_pos = ‪zm_utility::groundpos( trigger_location.origin ) + ( 0, 0, 4 ); // this is from trigger_location and is reset to trigger_pos
2023 
2024 
2025  self.unitrigger_stub = spawnstruct();
2026  self.unitrigger_stub.origin = trigger_pos;
2027  self.unitrigger_stub.radius = radius;
2028  self.unitrigger_stub.height = height;
2029  self.unitrigger_stub.script_unitrigger_type = "unitrigger_radius";
2030  self.unitrigger_stub.hint_string = ‪zm_utility::get_hint_string( self, "default_reward_barrier_piece" ); // this is the string to call when the player is the trigger
2031  self.unitrigger_stub.cursor_hint = "HINT_NOICON";
2032  self.unitrigger_stub.trigger_target = self;
2033  ‪zm_unitrigger::unitrigger_force_per_player_triggers( self.unitrigger_stub, true );
2034  self.unitrigger_stub.prompt_and_visibility_func = &‪blockertrigger_update_prompt;
2035 
2036  ‪zm_unitrigger::register_static_unitrigger(self.unitrigger_stub, &‪blocker_unitrigger_think); // Register to grab the zone we're in.
2037  ‪zm_unitrigger::unregister_unitrigger(self.unitrigger_stub); // Unregister straight away.
2038 
2039  if(!isdefined(trigger_location.angles))
2040  {
2041  trigger_location.angles = (0,0,0);
2042  }
2043 
2044  self.unitrigger_stub.origin = ‪zm_utility::groundpos( trigger_location.origin ) + ( 0, 0, 4 ) + (anglestoforward(trigger_location.angles) * - 11); // Move backwards for T5 parity.
2045  }
2046 
2047 
2048  self thread ‪trigger_delete_on_repair(); // This function waits till the boards/bars are repaired
2050 
2051 /* if(isdefined(level._zombiemode_blocker_trigger_extra_thread))
2052  {
2053  trigger thread [[level._zombiemode_blocker_trigger_extra_thread]]();
2054  }*/
2055 
2056  // Rebuilding no longer costs us money... It's rewarded
2057 
2059  //designed by prod; NO reward hint (See DT#36173)
2060  // trigger zm_utility::set_hint_string( self, "default_reward_barrier_piece" ); // this is the string to call when the player is the trigger
2061  //trigger thread blocker_doubler_hint( "default_reward_barrier_piece_", original_cost );
2063 
2064 // trigger SetCursorHint( "HINT_NOICON" );
2065 
2066  //***************************************************************************
2067  // The trigger constantly loops while the player interacts with it.
2068  // - The player is in position to board a window
2069  //***************************************************************************
2070 
2071  while( 1 )
2072  {
2073  self waittill( "trigger", player );
2074 
2075  has_perk = player ‪has_blocker_affecting_perk();
2076 
2077  if( ‪zm_utility::all_chunks_intact( self, self.barrier_chunks ) ) // barrier chunks are all the pieces targeted from the exterior_goal
2078  {
2079  // if any piece has the state of not repaired then return false
2080  // if the board has been repaired then return true
2081  self notify("all_boards_repaired");
2082  return;
2083  }
2084 
2085  if( ‪zm_utility::no_valid_repairable_boards( self, self.barrier_chunks ) ) // barrier chunks are all the pieces targeted from the exterior_goal
2086  {
2087  // if any piece has been destroyed return false
2088  // if any piece is not destroyed then return true
2089  self notify("no valid boards");
2090  return;
2091  }
2092 
2093  if( isdefined( level._zm_blocker_trigger_think_return_override ) )
2094  {
2095  if( self [[ level._zm_blocker_trigger_think_return_override ]]( player ) )
2096  {
2097  return;
2098  }
2099  }
2100 
2101  while( 1 )
2102  {
2103  players = GetPlayers();
2104 
2105  trigger = self.unitrigger_stub ‪zm_unitrigger::unitrigger_trigger( player );
2106  // Checks for the player to press the repair button
2107  if(‪player_fails_blocker_repair_trigger_preamble(player, players, trigger, false))
2108  {
2109  break;
2110  }
2111 
2112  // tracking when player boarding a window.
2113  player notify( "boarding_window", self );
2114 
2115  if(isdefined(self.zbarrier))
2116  {
2117  chunk = ‪zm_utility::get_random_destroyed_chunk(self, self.barrier_chunks);
2118 
2119  // sound played in handle_post_board_repair_rewards(cost,zbarrier)
2120  //playsoundatposition ("zmb_cha_ching", self.origin);
2121 
2122  self thread ‪replace_chunk( self, chunk, has_perk, ‪IS_TRUE( player.pers_upgrades_awarded["board"] ) ); // writing out
2123  }
2124  else
2125  {
2126  chunk = ‪zm_utility::get_random_destroyed_chunk( self, self.barrier_chunks ); // calls get_random_destroyed_chunk in zm_utility, continue if the chunk was destroyed
2127 
2128  if(isdefined(chunk.script_parameter) && chunk.script_parameters == "repair_board" || chunk.script_parameters == "barricade_vents")
2129  {
2130  if(isdefined(chunk.unbroken_section))
2131  {
2132  chunk Show();
2133  chunk Solid();
2134  chunk.unbroken_section ‪zm_utility::self_delete();
2135  }
2136  }
2137  else
2138  {
2139  chunk Show();
2140  }
2141 
2142  if ( !isDefined( chunk.script_parameters ) || chunk.script_parameters == "board" || chunk.script_parameters == "repair_board" || chunk.script_parameters == "barricade_vents")
2143  {
2144  //sounds now played on client
2145  if(!‪IS_TRUE(level.use_clientside_board_fx))
2146  {
2147 
2148  if( !isdefined( chunk.material ) || ( isdefined( chunk.material ) && chunk.material != "rock" ) )
2149  {
2150  chunk ‪zm_utility::play_sound_on_ent( "rebuild_barrier_piece" );
2151  }
2152  playsoundatposition ("zmb_cha_ching", (0,0,0));
2153  }
2154  }
2155  if ( chunk.script_parameters == "bar" )
2156  {
2157  chunk ‪zm_utility::play_sound_on_ent( "rebuild_barrier_piece" );
2158  playsoundatposition ("zmb_cha_ching", (0,0,0));
2159  }
2160 
2161  // I need to do this in a different place
2162  if(isdefined(chunk.script_parameters))
2163  {
2164  if( chunk.script_parameters == "bar" )
2165  {
2166  if(isdefined(chunk.script_noteworthy))
2167  {
2168  if(chunk.script_noteworthy == "5") // this is the far left , this bar now bends it does not leave
2169  {
2170  chunk hide();
2171  }
2172  else if(chunk.script_noteworthy == "3" )
2173  {
2174  chunk hide();
2175  }
2176  }
2177  }
2178  }
2179 
2180  self thread ‪replace_chunk( self, chunk, has_perk, ‪IS_TRUE( player.pers_upgrades_awarded["board"] ) ); // writing out
2181  }
2182 
2183  //assert( isdefined( self.clip ) );
2184  if(isdefined(self.clip))
2185  {
2186  self.clip TriggerEnable( true );
2187  self.clip DisconnectPaths(); // the boards disconnect paths everytime they are used here
2188  }
2189  else
2190  {
2191  ‪blocker_disconnect_paths(self.neg_start, self.neg_end);
2192  }
2193 
2194  //maps\_zombiemode_challenges::doMissionCallback( "zm_board_repair", player );
2195 
2196  self ‪do_post_chunk_repair_delay(has_perk);
2197 
2198  if( !‪zm_utility::is_player_valid( player ) )
2199  {
2200  break;
2201  }
2202 
2203  player ‪handle_post_board_repair_rewards(cost,self);
2204 
2205  if( ‪zm_utility::all_chunks_intact( self, self.barrier_chunks ) ) // This calls into zm_utility
2206  {
2207  // if any piece has the state of not repaired then return false
2208  // if the board has been repaired then return true
2209  self notify("all_boards_repaired");
2211  return;
2212  }
2213 
2214  if( ‪zm_utility::no_valid_repairable_boards( self, self.barrier_chunks ) ) // This calls into zm_utility
2215  {
2216  // if any piece has been destroyed return false
2217  // if any piece is not destroyed then return true
2218  self notify("no valid boards");
2219  player ‪increment_window_repaired( self );
2220  return;
2221  }
2222 
2223  }
2224  }
2225 }
2226 
2227 function ‪increment_window_repaired( s_barrier )//self = player
2228 {
2229  self ‪zm_stats::increment_challenge_stat( "SURVIVALIST_BOARD" );
2230  self incrementplayerstat("windowsBoarded", 1);
2231  self thread ‪zm_daily_challenges::increment_windows_repaired( s_barrier );
2232 }
2233 
2234 
2235 // self is a trigger
2237 {
2238  can_use = self.stub ‪blockerstub_update_prompt( player );
2239  self setInvisibleToPlayer( player, !can_use );
2240  self SetHintString( self.stub.hint_string );
2241  return can_use;
2242 }
2243 
2244 
2245 //
2246 // Update the unitrigger prompt
2247 // Returns false if the trigger should not be usable; true if usable
2248 // self is a unitrigger stub
2250 {
2251  if( !‪zm_utility::is_player_valid( player ) )
2252  {
2253  return false;
2254  }
2255 
2256  if( player ‪zm_utility::in_revive_trigger() )
2257  {
2258  return false;
2259  }
2260 
2261  if( ‪IS_DRINKING(player.is_drinking) )
2262  {
2263  return false;
2264  }
2265 
2266  return true;
2267 }
2268 
2269 
2270 
2271 
2272 //*****************************************************************************
2273 //*****************************************************************************
2274 
2276 {
2277  wait( 0.5 );
2278  self Show();
2279 }
2280 
2281 
2282 // jl this calls a rumble and zombie scream on the players if they are next to a door being opened.
2283 // call a distance check of the the last chunk replaced
2285 {
2286  players = GetPlayers();
2287  //players[0] PlayRumbleOnEntity("damage_heavy");
2288  // only do this if they are close enough
2289  // add distnace check
2290 
2291  for(i = 0; i < players.size; i++)
2292  {
2293 
2294  if (distance (players[i].origin, self.origin) < 150)
2295  {
2296 
2297  if(isalive(players[i]))
2298  //-- not usedif(isalive(players[i]) && (isdefined(players[i].pers["team"])) && (players[i].pers["team"] == team))
2299  {
2300 
2301  players[i] thread ‪board_completion();
2302 
2303  }
2304  }
2305  }
2306 }
2307 
2309 {
2310  self endon ("disconnect");
2311 
2312  // need to be place a delay if done within a certain time frame
2313  //wait(1.2);
2314  //self zm_utility::play_sound_on_ent( "purchase" );
2315  //players[i] iprintlnbold("Entrance 1 is fixed!!!");
2316  //wait(0.3);
2317  //self zm_utility::play_sound_on_ent( "purchase" );
2318  //wait(0.3);
2319  //self zm_utility::play_sound_on_ent( "purchase" );
2320 }
2321 
2322 
2323 // self is a trigger that is spawned off of the exterior_goal entity.
2325 {
2326  while( 1 )
2327  {
2328  self ‪util::waittill_either("all_boards_repaired", "no valid boards");
2329 // self thread door_repaired_rumble_n_sound(); // jl added cool repair sound
2330  //self delete(); // when the boards are totally repaired then delete your self
2331  ‪zm_unitrigger::unregister_unitrigger(self.unitrigger_stub);
2332  break;
2333  }
2334 
2335 }
2336 
2337 /*
2338 function blocker_doubler_hint( hint, original_cost )
2339 {
2340  self endon( "death" );
2341 
2342  doubler_status = level.zombie_vars["zombie_powerup_double_points_on"];
2343  while( 1 )
2344  {
2345  wait( 0.5 );
2346 
2347  if( doubler_status != level.zombie_vars["zombie_powerup_double_points_on"] )
2348  {
2349  doubler_status = level.zombie_vars["zombie_powerup_double_points_on"];
2350  cost = original_cost;
2351  if( level.zombie_vars["zombie_powerup_double_points_on"] )
2352  {
2353  cost = original_cost * 2;
2354  }
2355  self zm_utility::set_hint_string( self, hint + cost );
2356  }
2357  }
2358 }
2359 */
2360 
2362 {
2363  self.rebuild_barrier_reward = 0;
2364 }
2365 
2366 function ‪remove_chunk( chunk, node, destroy_immediately, zomb )
2367 {
2368  chunk ‪update_states("mid_tear");
2369 
2370  // jl dec 15 09
2371  // jl added check for differnt types of windows
2372  if(isdefined(chunk.script_parameters))
2373  {
2374  if( chunk.script_parameters == "board" || chunk.script_parameters == "repair_board" || chunk.script_parameters == "barricade_vents") // jl this is new check to see if it is a board then do board anims, this needs to hold the entire function
2375  {
2376  chunk thread ‪zombie_boardtear_audio_offset(chunk);
2377  }
2378  }
2379 
2380  if(isdefined(chunk.script_parameters))
2381  {
2382  if( chunk.script_parameters == "bar" ) // jl this is new check to see if it is a board then do board anims, this needs to hold the entire function
2383  {
2384  chunk thread ‪zombie_bartear_audio_offset(chunk);
2385  }
2386  }
2387 
2388 
2389  chunk NotSolid();
2390  // here I do a check for if it is a bar
2391 
2392  //if ( isdefined( destroy_immediately ) && destroy_immediately)
2393  //{
2394  // chunk.destroyed = true;
2395  //}
2396 
2397  fx = "wood_chunk_destory";
2398  if( isdefined( self.script_fxid ) )
2399  {
2400  fx = self.script_fxid;
2401  }
2402 
2403 
2404 
2405  if ( isdefined( chunk.script_moveoverride ) && chunk.script_moveoverride )
2406  {
2407  chunk Hide();
2408  }
2409 
2410 
2411  // an origin is created and the current chunk is linked to it. Then it flings the chunk and deletes the origin
2412  if ( isdefined( chunk.script_parameters ) && ( chunk.script_parameters == "bar" ) )
2413  {
2414 
2415  // added top bar check so it goes less higher
2416  if( isdefined ( chunk.script_noteworthy ) && ( chunk.script_noteworthy == "4" ) )
2417  {
2418  ent = ‪Spawn( "script_origin", chunk.origin );
2419  ent.angles = node.angles +( 0, 180, 0 );
2420 
2421  //DCS 030711: adding potential for having max distance movement
2422  //for boards in closets that aren't very deep.
2423  dist = 100; // base number.
2424  if(isdefined(chunk.script_move_dist))
2425  {
2426  dist_max = chunk.script_move_dist - 100;
2427  dist = 100 + RandomInt(dist_max);
2428  }
2429  else
2430  {
2431  dist = 100 + RandomInt( 100 );
2432  }
2433 
2434  dest = ent.origin + ( AnglesToForward( ent.angles ) * dist );
2435  ‪trace = BulletTrace( dest + ( 0, 0, 16 ), dest + ( 0, 0, -200 ), false, undefined );
2436 
2437  if( ‪trace["fraction"] == 1 )
2438  {
2439  dest = dest + ( 0, 0, -200 );
2440  }
2441  else
2442  {
2443  dest = ‪trace["position"];
2444  }
2445 
2446  // time = 1;
2447  chunk LinkTo( ent );
2448 
2449  //time = ent zm_utility::fake_physicslaunch( dest, 200 + RandomInt( 100 ) );
2450  time = ent ‪zm_utility::fake_physicslaunch( dest, 300 + RandomInt( 100 ) );
2451 
2452 
2453  if( RandomInt( 100 ) > 40 )
2454  {
2455  ent RotatePitch( 180, time * 0.5 );
2456  }
2457  else
2458  {
2459  ent RotatePitch( 90, time, time * 0.5 );
2460  }
2461  wait( time );
2462 
2463  chunk Hide();
2464 
2465  // try sending the notify now...
2466  wait( 0.1);
2467  //wait( 1 ); // the notify is sent out late... so I can't call it right away...
2468  // I need to keep track of what the last peice is...
2469  ent Delete();
2470  }
2471 
2472  else
2473  {
2474  ent = ‪Spawn( "script_origin", chunk.origin );
2475  ent.angles = node.angles +( 0, 180, 0 );
2476 
2477 
2478  //DCS 030711: adding potential for having max distance movement
2479  //for boards in closets that aren't very deep.
2480  dist = 100; // base number.
2481  if(isdefined(chunk.script_move_dist))
2482  {
2483  dist_max = chunk.script_move_dist - 100;
2484  dist = 100 + RandomInt(dist_max);
2485  }
2486  else
2487  {
2488  dist = 100 + RandomInt( 100 );
2489  }
2490 
2491  dest = ent.origin + ( AnglesToForward( ent.angles ) * dist );
2492  ‪trace = BulletTrace( dest + ( 0, 0, 16 ), dest + ( 0, 0, -200 ), false, undefined );
2493 
2494  if( ‪trace["fraction"] == 1 )
2495  {
2496  dest = dest + ( 0, 0, -200 );
2497  }
2498  else
2499  {
2500  dest = ‪trace["position"];
2501  }
2502 
2503  // time = 1;
2504  chunk LinkTo( ent );
2505 
2506  time = ent ‪zm_utility::fake_physicslaunch( dest, 260 + RandomInt( 100 ) );
2507 
2508  // here you will do a random damage... however it would be better if you made them fall over
2509  // call damage function out of here so the wait doesn't interrupt normal flow.
2510 
2511 
2512  //time = ent zm_utility::fake_physicslaunch( dest, 200 + RandomInt( 100 ) );
2513 
2514  //forward = AnglesToForward( ent.angles + ( -60, 0, 0 ) ) * power );
2515  //ent MoveGravity( forward, time );
2516 
2517  if( RandomInt( 100 ) > 40 )
2518  {
2519  ent RotatePitch( 180, time * 0.5 );
2520  }
2521  else
2522  {
2523  ent RotatePitch( 90, time, time * 0.5 );
2524  }
2525  wait( time );
2526 
2527  chunk Hide();
2528 
2529  // try sending the notify now...
2530  wait( 0.1);
2531  //wait( 1 ); // the notify is sent out late... so I can't call it right away...
2532  // I need to keep track of what the last peice is...
2533  ent Delete();
2534 
2535  }
2536  //if (isdefined( destroy_immediately ) && destroy_immediately)
2537  //{
2538  // return;
2539  //}
2540  chunk ‪update_states("destroyed");
2541  chunk notify( "destroyed" );
2542  }
2543 
2544  if ( isdefined ( chunk.script_parameters ) && chunk.script_parameters == "board" || chunk.script_parameters == "repair_board" || chunk.script_parameters == "barricade_vents" )
2545  {
2546 
2547  ent = ‪Spawn( "script_origin", chunk.origin );
2548  ent.angles = node.angles +( 0, 180, 0 );
2549 
2550  //DCS 030711: adding potential for having max distance movement
2551  //for boards in closets that aren't very deep.
2552  dist = 100; // base number.
2553  if(isdefined(chunk.script_move_dist))
2554  {
2555  dist_max = chunk.script_move_dist - 100;
2556  dist = 100 + RandomInt(dist_max);
2557  }
2558  else
2559  {
2560  dist = 100 + RandomInt( 100 );
2561  }
2562 
2563  dest = ent.origin + ( AnglesToForward( ent.angles ) * dist );
2564  ‪trace = BulletTrace( dest + ( 0, 0, 16 ), dest + ( 0, 0, -200 ), false, undefined );
2565 
2566  if( ‪trace["fraction"] == 1 )
2567  {
2568  dest = dest + ( 0, 0, -200 );
2569  }
2570  else
2571  {
2572  dest = ‪trace["position"];
2573  }
2574 
2575  // time = 1;
2576  chunk LinkTo( ent );
2577 
2578  time = ent ‪zm_utility::fake_physicslaunch( dest, 200 + RandomInt( 100 ) );
2579  //time = ent zm_utility::fake_physicslaunch( dest, 200 + RandomInt( 100 ) );
2580 
2581  // forward = AnglesToForward( ent.angles + ( -60, 0, 0 ) ) * power );
2582  // ent MoveGravity( forward, time );
2583 
2584  // DCS 090110: delete glass or wall piece before sending flying.
2585  //DCS 090910: but not metal.
2586  if(isdefined(chunk.unbroken_section))
2587  {
2588  if(!isdefined(chunk.material) || chunk.material != "metal")
2589  {
2590  chunk.unbroken_section ‪zm_utility::self_delete();
2591  }
2592  }
2593 
2594  if( RandomInt( 100 ) > 40 )
2595  {
2596  ent RotatePitch( 180, time * 0.5 );
2597  }
2598  else
2599  {
2600  ent RotatePitch( 90, time, time * 0.5 );
2601  }
2602  wait( time );
2603 
2604  // DCS 090910: let the metal vents go fly.
2605  if(isdefined(chunk.unbroken_section))
2606  {
2607  if(isdefined(chunk.material) && chunk.material == "metal")
2608  {
2609  chunk.unbroken_section ‪zm_utility::self_delete();
2610  }
2611  }
2612 
2613  chunk Hide();
2614 
2615  // try sending the notify now...
2616  wait( 0.1);
2617  //wait( 1 ); // the notify is sent out late... so I can't call it right away...
2618  // I need to keep track of what the last peice is...
2619  ent Delete();
2620 
2621 
2622  //if (isdefined( destroy_immediately ) && destroy_immediately)
2623  //{
2624  // return;
2625  //}
2626 
2627  chunk ‪update_states("destroyed");
2628  chunk notify( "destroyed" );
2629  }
2630 
2631 
2632  if ( isdefined ( chunk.script_parameters ) && ( chunk.script_parameters == "grate" ) )
2633  {
2634  // Only make the last piece of the grate get pulled off.
2635  if( isdefined ( chunk.script_noteworthy ) && ( chunk.script_noteworthy == "6" ) )
2636  {
2637  // angles = node.angles +( 0, 180, 0 );
2638  // force = AnglesToForward( angles + ( -60, 0, 0 ) ) * ( 200 + RandomInt( 100 ) );
2639  // chunk PhysicsLaunch( chunk.origin, force );
2640 
2641  ent = ‪Spawn( "script_origin", chunk.origin );
2642  ent.angles = node.angles +( 0, 180, 0 );
2643  dist = 100 + RandomInt( 100 );
2644  dest = ent.origin + ( AnglesToForward( ent.angles ) * dist );
2645  ‪trace = BulletTrace( dest + ( 0, 0, 16 ), dest + ( 0, 0, -200 ), false, undefined );
2646 
2647  if( ‪trace["fraction"] == 1 )
2648  {
2649  dest = dest + ( 0, 0, -200 );
2650  }
2651  else
2652  {
2653  dest = ‪trace["position"];
2654  }
2655 
2656  // time = 1;
2657  chunk LinkTo( ent );
2658 
2659  time = ent ‪zm_utility::fake_physicslaunch( dest, 200 + RandomInt( 100 ) );
2660  //time = ent zm_utility::fake_physicslaunch( dest, 200 + RandomInt( 100 ) );
2661 
2662  // forward = AnglesToForward( ent.angles + ( -60, 0, 0 ) ) * power );
2663  // ent MoveGravity( forward, time );
2664 
2665  if( RandomInt( 100 ) > 40 )
2666  {
2667  ent RotatePitch( 180, time * 0.5 );
2668  }
2669  else
2670  {
2671  ent RotatePitch( 90, time, time * 0.5 );
2672  }
2673  wait( time );
2674  chunk Hide();
2675  //wait( 1 ); // the notify is sent out late... so I can't call it right away...
2676  // I need to keep track of what the last peice is...
2677  ent Delete();
2678  chunk ‪update_states("destroyed");
2679  chunk notify( "destroyed" );
2680  }
2681 
2682  else
2683  {
2684  chunk Hide();
2685  //chunk moveto( chunk.origin + ( 0, 0, -1000 ), 0.3, 0.1, 0.1 );
2686  chunk ‪update_states("destroyed");
2687  chunk notify( "destroyed" );
2688  }
2689  //chunk Hide();
2690  }
2691 
2692  /*
2693  // this is kicking off but is to late to send the notify
2694  if( zm_utility::all_chunks_destroyed( node.barrier_chunks ) )
2695  {
2696 
2697  if( isdefined( node.clip ) )
2698  {
2699  node.clip ConnectPaths();
2700  WAIT_SERVER_FRAME;
2701  node.clip TriggerEnable( false );
2702  }
2703  else
2704  {
2705  for( i = 0; i < node.barrier_chunks.size; i++ )
2706  {
2707  node.barrier_chunks[i] ConnectPaths();
2708  }
2709  }
2710  }
2711  else
2712  {
2713  EarthQuake( RandomFloatRange( 1, 3 ), 0.9, chunk.origin, 500 );
2714  }
2715  */
2716 }
2717 
2718 
2719 // jl dec 15 09
2721 {
2722  // this is going to rotate all of them.. I need to some how do this off of the node pointing to it..
2723  //chunk_rotate_piece = GetEntArray( "grate", "script_parameters");
2724 
2725  //chunk_rotate_piece = GetEnt( "grate", "script_parameters");
2726  //chunk vibrate(( 0, 270, 0 ), 0.2, 0.4, 0.4);
2727 
2728 
2729  // how do I only effect the one for that window and not affect all of them
2730  // This is actually checked every time
2731 
2732  if( isdefined (chunk.script_parameters) && chunk.script_parameters == "grate" ) //&& chunk.script_parameters != "grate" )
2733  {
2734  chunk vibrate(( 0, 270, 0 ), 0.2, 0.4, 0.4);
2735  return;
2736  }
2737 }
2738 
2739 // jl just for now I added an audio offset to give more length and depth to the tearing off feeling
2740 // i should add these to the same area where the fx is called, which is zombie_boardtear_offset_fx_horizontle(chunk)
2741 // in zombiemode_spawner
2743 {
2744  if( isdefined(chunk.material) && !isdefined( chunk.already_broken ) )
2745  chunk.already_broken = false;
2746 
2747  if( isdefined(chunk.material) && chunk.material == "glass" && chunk.already_broken == false )
2748  {
2749  chunk PlaySound( "zmb_break_glass_barrier" );
2750  wait( randomfloatrange( 0.3, 0.6 ));
2751  chunk PlaySound( "zmb_break_glass_barrier" );
2752  chunk.already_broken = true;
2753  }
2754  else if( isdefined(chunk.material) && chunk.material == "metal" && chunk.already_broken == false )
2755  {
2756  chunk PlaySound( "grab_metal_bar" );
2757  wait( randomfloatrange( 0.3, 0.6 ));
2758  chunk PlaySound( "break_metal_bar" );
2759  chunk.already_broken = true;
2760  }
2761  else if( isdefined(chunk.material) && chunk.material == "rock" )
2762  {
2763  if(!‪IS_TRUE(level.use_clientside_rock_tearin_fx))
2764  {
2765  chunk PlaySound( "zmb_break_rock_barrier" );
2766  wait( randomfloatrange( 0.3, 0.6 ));
2767  chunk PlaySound( "zmb_break_rock_barrier" );
2768  }
2769  chunk.already_broken = true;
2770  }
2771  else if( isdefined(chunk.material) && chunk.material == "metal_vent")
2772  {
2773  if(!‪IS_TRUE(level.use_clientside_board_fx))
2774  {
2775  //chunk PlaySound( "evt_vent_slat_grab" );
2776  //wait( randomfloatrange( 0.3, 0.6 ));
2777  chunk PlaySound( "evt_vent_slat_remove" );
2778  }
2779  }
2780  else
2781  {
2782  if(!‪IS_TRUE(level.use_clientside_board_fx))
2783  {
2784  chunk ‪zm_utility::play_sound_on_ent( "break_barrier_piece" );
2785  wait( randomfloatrange( 0.3, 0.6 )); // 06 might be too much, a little seperation sounds great...
2786  chunk ‪zm_utility::play_sound_on_ent( "break_barrier_piece" );
2787  }
2788  chunk.already_broken = true;
2789  }
2790 }
2791 
2793 {
2794  chunk ‪zm_utility::play_sound_on_ent( "grab_metal_bar" );
2795  //iprintlnbold("RRIIIPPPPP!!!");
2796  wait( randomfloatrange( 0.3, 0.6 ));
2797  chunk ‪zm_utility::play_sound_on_ent( "break_metal_bar" );
2798  wait( randomfloatrange( 1.0, 1.3 ));
2799  chunk ‪zm_utility::play_sound_on_ent( "drop_metal_bar" );
2800 }
2801 
2803 {
2804  if ( chunk.origin != chunk.og_origin )
2805  {
2806  chunk notsolid();
2807  chunk waittill( "movedone" );
2808  }
2809 }
2810 
2811 function ‪replace_chunk( barrier, chunk, perk, upgrade, via_powerup )
2812 {
2813  if(!isdefined(barrier.zbarrier))
2814  {
2815  chunk ‪update_states("mid_repair");
2816  assert( isdefined( chunk.og_origin ) );
2817  assert( isdefined( chunk.og_angles ) );
2818 
2819  sound = "rebuild_barrier_hover";
2820  if( isdefined( chunk.script_presound ) )
2821  {
2822  sound = chunk.script_presound;
2823  }
2824 
2825  }
2826 
2827  has_perk = false;
2828 
2829  if( isDefined( perk ) )
2830  {
2831  has_perk = true;
2832  }
2833 
2834 
2835  if( !isdefined( via_powerup ) && isdefined(sound))
2836  {
2837  ‪zm_utility::play_sound_at_pos( sound, chunk.origin );
2838  }
2839 
2840 
2841  if(upgrade)
2842  {
2843  barrier.zbarrier ZBarrierPieceUseUpgradedModel(chunk);
2844  barrier.zbarrier.chunk_health[chunk] = barrier.zbarrier GetUpgradedPieceNumLives(chunk);
2845  }
2846  else
2847  {
2848  barrier.zbarrier ZBarrierPieceUseDefaultModel(chunk);
2849  barrier.zbarrier.chunk_health[chunk] = 0;
2850  }
2851 
2852  scalar = 1.0;
2853  if(has_perk)
2854  {
2855  if(‪PERK_SLEIGHT_OF_HAND == perk)
2856  {
2857  scalar = 0.31;
2858  }
2859  }
2860 
2861  barrier.zbarrier ShowZBarrierPiece(chunk);
2862 
2863  barrier.zbarrier SetZBarrierPieceState(chunk, "closing", scalar);
2864  waitDuration = barrier.zbarrier GetZBarrierPieceAnimLengthForState(chunk, "closing", scalar);
2865  wait(waitDuration);
2866 }
2867 
2869 {
2870  foreach ( barrier in level.exterior_goals )
2871  {
2872  if ( isdefined( barrier.zbarrier ) )
2873  {
2874  for ( x = 0; x < barrier.zbarrier GetNumZBarrierPieces(); x++ )
2875  {
2876  barrier.zbarrier SetZBarrierPieceState( x, "opening" );
2877  }
2878  }
2879 
2880  if ( isdefined( barrier.clip ) )
2881  {
2882  barrier.clip TriggerEnable( false );
2883  barrier.clip ConnectPaths();
2884  }
2885  else
2886  {
2887  ‪blocker_connect_paths( barrier.neg_start, barrier.neg_end );
2888  }
2889 
2890  }
2891 }
2892 
2893 // Jl we want different audio for each type of board or bar when they are repaired
2894 // Need tags so the off sets for the effects is less code.
2896 {
2897 
2898  if(isDefined(chunk.material) && chunk.material == "rock" )
2899  {
2900  if(‪IS_TRUE(level.use_clientside_rock_tearin_fx))
2901  {
2902  chunk ‪clientfield::set( "tearin_rock_fx", 0 );//PlayFX( level._effect["wall_break"], chunk.origin );
2903  }
2904  else
2905  {
2906  EarthQuake( RandomFloatRange( 0.3, 0.4 ), RandomFloatRange(0.2, 0.4), chunk.origin, 150 ); // do I want an increment if more are gone...
2907 // PlayFx( level._effect["wood_chunk_destory"], chunk.origin + (0, 0, 30));
2908  wait( randomfloatrange( 0.3, 0.6 )); // 06 might be too much, a little seperation sounds great...
2909  chunk ‪zm_utility::play_sound_on_ent( "break_barrier_piece" );
2910 // PlayFx( level._effect["wood_chunk_destory"], chunk.origin + (0, 0, -30));
2911  }
2912  }
2913  else
2914  {
2915  if(‪IS_TRUE(level.use_clientside_board_fx))
2916  {
2917  chunk ‪clientfield::set( "tearin_board_vertical_fx", 0 );
2918  }
2919  else
2920  {
2921  EarthQuake( RandomFloatRange( 0.3, 0.4 ), RandomFloatRange(0.2, 0.4), chunk.origin, 150 ); // do I want an increment if more are gone...
2922 // PlayFx( level._effect["wood_chunk_destory"], chunk.origin + (0, 0, 30));
2923  wait( randomfloatrange( 0.3, 0.6 )); // 06 might be too much, a little seperation sounds great...
2924  chunk ‪zm_utility::play_sound_on_ent( "break_barrier_piece" );
2925 // PlayFx( level._effect["wood_chunk_destory"], chunk.origin + (0, 0, -30));
2926  }
2927  }
2928 
2929 
2930 }
2931 
2933 {
2934  if(isDefined(chunk.material) && chunk.material == "rock")
2935  {
2936  if (‪IS_TRUE(level.use_clientside_rock_tearin_fx))
2937  {
2938  chunk ‪clientfield::set( "tearin_rock_fx", 0 );//PlayFX( level._effect["wall_break"], chunk.origin );
2939  }
2940  else
2941  {
2942 
2943  EarthQuake( RandomFloatRange( 0.3, 0.4 ), RandomFloatRange(0.2, 0.4), chunk.origin, 150 ); // do I want an increment if more are gone...
2944 // PlayFx( level._effect["wood_chunk_destory"], chunk.origin + (30, 0, 0));
2945  wait( randomfloatrange( 0.3, 0.6 )); // 06 might be too much, a little seperation sounds great...
2946  chunk ‪zm_utility::play_sound_on_ent( "break_barrier_piece" );
2947 // PlayFx( level._effect["wood_chunk_destory"], chunk.origin + (-30, 0, 0));
2948  }
2949  }
2950  else
2951  {
2952  if(‪IS_TRUE(level.use_clientside_board_fx))
2953  {
2954  chunk ‪clientfield::set( "tearin_board_horizontal_fx", 0 );
2955  }
2956  else
2957  {
2958  EarthQuake( RandomFloatRange( 0.3, 0.4 ), RandomFloatRange(0.2, 0.4), chunk.origin, 150 ); // do I want an increment if more are gone...
2959 // PlayFx( level._effect["wood_chunk_destory"], chunk.origin + (30, 0, 0));
2960  wait( randomfloatrange( 0.3, 0.6 )); // 06 might be too much, a little seperation sounds great...
2961  chunk ‪zm_utility::play_sound_on_ent( "break_barrier_piece" );
2962 // PlayFx( level._effect["wood_chunk_destory"], chunk.origin + (-30, 0, 0));
2963  }
2964  }
2965 
2966 
2967 }
2968 
2969 
2971 {
2972  EarthQuake( RandomFloatRange( 0.3, 0.4 ), RandomFloatRange(0.2, 0.4), chunk.origin, 150 ); // do I want an increment if more are gone...
2973  chunk ‪zm_utility::play_sound_on_ent( "bar_rebuild_slam" );
2974 
2975  switch( randomInt( 9 ) ) // This sets up random versions of the bars being pulled apart for variety
2976  {
2977  case 0:
2978  PlayFX( level._effect["fx_zombie_bar_break"], chunk.origin + (-30, 0, 0) );
2979  wait( randomfloatrange( 0.0, 0.3 ));
2980  PlayFX( level._effect["fx_zombie_bar_break_lite"], chunk.origin + (-30, 0, 0) );
2981  break;
2982 
2983  case 1:
2984  PlayFX( level._effect["fx_zombie_bar_break"], chunk.origin + (-30, 0, 0) );
2985  wait( randomfloatrange( 0.0, 0.3 ));
2986  PlayFX( level._effect["fx_zombie_bar_break"], chunk.origin + (-30, 0, 0) );
2987 
2988  break;
2989 
2990  case 2:
2991  PlayFX( level._effect["fx_zombie_bar_break_lite"], chunk.origin + (-30, 0, 0) );
2992  wait( randomfloatrange( 0.0, 0.3 ));
2993  PlayFX( level._effect["fx_zombie_bar_break"], chunk.origin + (-30, 0, 0) );
2994 
2995  break;
2996 
2997  case 3:
2998  PlayFX( level._effect["fx_zombie_bar_break"], chunk.origin + (-30, 0, 0) );
2999  wait( randomfloatrange( 0.0, 0.3 ));
3000  PlayFX( level._effect["fx_zombie_bar_break_lite"], chunk.origin + (-30, 0, 0) );
3001 
3002  break;
3003 
3004  case 4:
3005  PlayFX( level._effect["fx_zombie_bar_break_lite"], chunk.origin + (-30, 0, 0) );
3006  wait( randomfloatrange( 0.0, 0.3 ));
3007  PlayFX( level._effect["fx_zombie_bar_break_lite"], chunk.origin + (-30, 0, 0) );
3008  break;
3009 
3010  case 5:
3011  PlayFX( level._effect["fx_zombie_bar_break_lite"], chunk.origin + (-30, 0, 0) );
3012  break;
3013  case 6:
3014  PlayFX( level._effect["fx_zombie_bar_break_lite"], chunk.origin + (-30, 0, 0) );
3015  break;
3016  case 7:
3017  PlayFX( level._effect["fx_zombie_bar_break"], chunk.origin + (-30, 0, 0) );
3018  break;
3019  case 8:
3020  PlayFX( level._effect["fx_zombie_bar_break"], chunk.origin + (-30, 0, 0) );
3021  break;
3022  }
3023 
3024 }
3025 
3026 
3028 {
3029 
3030  EarthQuake( RandomFloatRange( 0.3, 0.4 ), RandomFloatRange(0.2, 0.4), chunk.origin, 150 ); // do I want an increment if more are gone...
3031  chunk ‪zm_utility::play_sound_on_ent( "bar_rebuild_slam" );
3032 
3033 
3034  switch( randomInt( 9 ) ) // This sets up random versions of the bars being pulled apart for variety
3035  {
3036  case 0:
3037  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_left" );
3038  wait( randomfloatrange( 0.0, 0.3 ));
3039  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_right" );
3040  break;
3041 
3042  case 1:
3043  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_left" );
3044  wait( randomfloatrange( 0.0, 0.3 ));
3045  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_right" );
3046  break;
3047 
3048  case 2:
3049  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_left" );
3050  wait( randomfloatrange( 0.0, 0.3 ));
3051  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_right" );
3052  break;
3053 
3054  case 3:
3055  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_left" );
3056  wait( randomfloatrange( 0.0, 0.3 ));
3057  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_right" );
3058  break;
3059 
3060  case 4:
3061  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_left" );
3062  wait( randomfloatrange( 0.0, 0.3 ));
3063  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_right" );
3064  break;
3065 
3066  case 5:
3067  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_left" );
3068  break;
3069  case 6:
3070  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_right" );
3071  break;
3072  case 7:
3073  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_left" );
3074  break;
3075  case 8:
3076  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_right" );
3077  break;
3078  }
3079 
3080 }
3081 
3083 {
3084  EarthQuake( RandomFloatRange( 0.3, 0.4 ), RandomFloatRange(0.2, 0.4), chunk.origin, 150 ); // do I want an increment if more are gone...
3085  chunk ‪zm_utility::play_sound_on_ent( "bar_rebuild_slam" );
3086 
3087 
3088  switch( randomInt( 9 ) ) // This sets up random versions of the bars being pulled apart for variety
3089  {
3090  case 0:
3091  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_top" );
3092  wait( randomfloatrange( 0.0, 0.3 ));
3093  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_bottom" );
3094  break;
3095 
3096  case 1:
3097  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_top" );
3098  wait( randomfloatrange( 0.0, 0.3 ));
3099  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_bottom" );
3100  break;
3101 
3102  case 2:
3103  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_top" );
3104  wait( randomfloatrange( 0.0, 0.3 ));
3105  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_bottom" );
3106  break;
3107 
3108  case 3:
3109  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_top" );
3110  wait( randomfloatrange( 0.0, 0.3 ));
3111  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_bottom" );
3112  break;
3113 
3114  case 4:
3115  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_top" );
3116  wait( randomfloatrange( 0.0, 0.3 ));
3117  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_bottom" );
3118  break;
3119 
3120  case 5:
3121  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_top" );
3122  break;
3123  case 6:
3124  PlayFXOnTag( level._effect["fx_zombie_bar_break_lite"], chunk, "Tag_fx_bottom" );
3125  break;
3126  case 7:
3127  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_top" );
3128  break;
3129  case 8:
3130  PlayFXOnTag( level._effect["fx_zombie_bar_break"], chunk, "Tag_fx_bottom" );
3131  break;
3132  }
3133 }
3134 
3135 
3136 //
3137 // Flag Blocker ----------------------------------------------------------------------------------- //
3138 //
3139 
3141 {
3142  if( !isdefined( self.‪script_flag_wait ) )
3143  {
3144  AssertMsg( "Flag Blocker at " + self.origin + " does not have a script_flag_wait key value pair" );
3145  return;
3146  }
3147 
3148  if( !isdefined( level.flag[self.script_flag_wait] ) )
3149  {
3150  level ‪flag::init( self.‪script_flag_wait );
3151  }
3152 
3153  type = "connectpaths";
3154  if( isdefined( self.script_noteworthy ) )
3155  {
3156  type = self.script_noteworthy;
3157  }
3158 
3160 
3161  self ‪util::script_delay();
3162 
3163  if( type == "connectpaths" )
3164  {
3165  self ConnectPaths();
3166  //FOCKER
3167  //iprintlnbold("BOARDS AREE ALL DOWN!!!");
3168  self TriggerEnable( false );
3169  return;
3170  }
3171 
3172  if( type == "disconnectpaths" )
3173  {
3174  self DisconnectPaths();
3175  //iprintlnbold("BOARDS ARE ALL UP!!!");
3176  self TriggerEnable( false );
3177  return;
3178  }
3179 
3180  AssertMsg( "flag blocker at " + self.origin + ", the type \"" + type + "\" is not recognized" );
3181 }
3182 
3183 function ‪update_states( states )
3184 {
3185  assert( isdefined( states ) );
3186 
3187  self.state = states;
3188 
3189 }
3190 
3191 
3193 {
3194  range_squared = 180 * 180; // 15 feet
3195 
3196  zombie_doors = GetEntArray( "zombie_door", "targetname" );
3197  for( i = 0; i < zombie_doors.size; i++ )
3198  {
3199  if ( DistanceSquared( zombie_doors[i].origin, position ) < range_squared )
3200  {
3201  return true;
3202  }
3203  }
3204 
3205  zombie_airlock_doors = GetEntArray( "zombie_airlock_buy", "targetname" );
3206  for( i = 0; i < zombie_airlock_doors.size; i++ )
3207  {
3208  if ( DistanceSquared( zombie_airlock_doors[i].origin, position ) < range_squared )
3209  {
3210  return true;
3211  }
3212  }
3213 
3214  zombie_debris = GetEntArray( "zombie_debris", "targetname" );
3215  for( i = 0; i < zombie_debris.size; i++ )
3216  {
3217  if ( DistanceSquared( zombie_debris[i].origin, position ) < range_squared )
3218  {
3219  return true;
3220  }
3221  }
3222 
3223  return false;
3224 }
3225 
3226 
3228 {
3229  range_squared = 180 * 180; // 15 feet
3230 
3231  zombie_doors = GetEntArray( "zombie_door", "targetname" );
3232  for( i = 0; i < zombie_doors.size; i++ )
3233  {
3234  if ( DistanceSquared( zombie_doors[i].origin, position ) < range_squared )
3235  {
3236  self thread ‪zm_audio::create_and_play_dialog( "kill", "quant_good" );
3237  zombie_doors[i] notify( "trigger", self, true );
3238  [[level.quantum_bomb_play_area_effect_func]]( position );
3239  return;
3240  }
3241  }
3242 
3243  zombie_airlock_doors = GetEntArray( "zombie_airlock_buy", "targetname" );
3244  for( i = 0; i < zombie_airlock_doors.size; i++ )
3245  {
3246  if ( DistanceSquared( zombie_airlock_doors[i].origin, position ) < range_squared )
3247  {
3248  self thread ‪zm_audio::create_and_play_dialog( "kill", "quant_good" );
3249  zombie_airlock_doors[i] notify( "trigger", self, true );
3250  [[level.quantum_bomb_play_area_effect_func]]( position );
3251  return;
3252  }
3253  }
3254 
3255  zombie_debris = GetEntArray( "zombie_debris", "targetname" );
3256  for( i = 0; i < zombie_debris.size; i++ )
3257  {
3258  if ( DistanceSquared( zombie_debris[i].origin, position ) < range_squared )
3259  {
3260  self thread ‪zm_audio::create_and_play_dialog( "kill", "quant_good" );
3261  zombie_debris[i] notify( "trigger", self, true );
3262  [[level.quantum_bomb_play_area_effect_func]]( position );
3263  return;
3264  }
3265  }
3266 }
3267 
‪door_activate
‪function door_activate(time, open, quick, use_blocker_clip_for_pathing)
Definition: _zm_blockers.gsc:455
‪open
‪function open(localClientNum, a_menu_items)
Definition: debug_menu_shared.csc:10
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪debris_think
‪function debris_think()
Definition: _zm_blockers.gsc:1230
‪script_delay
‪function script_delay()
Definition: util_shared.gsc:970
‪groundpos_ignore_water_new
‪function groundpos_ignore_water_new(origin)
Definition: _zm_utility.gsc:4590
‪blocker_attack_spots
‪function blocker_attack_spots()
Definition: _zm_blockers.gsc:1751
‪blocker_trigger_think
‪function blocker_trigger_think()
Definition: _zm_blockers.gsc:1972
‪all_chunks_intact
‪function all_chunks_intact(barrier, barrier_chunks)
Definition: _zm_utility.gsc:392
‪blocker_update_prompt_visibility
‪function blocker_update_prompt_visibility()
Definition: _zm_blockers.gsc:369
‪quantum_bomb_open_nearest_door_validation
‪function quantum_bomb_open_nearest_door_validation(position)
Definition: _zm_blockers.gsc:3192
‪blocker_think
‪function blocker_think()
Definition: _zm_blockers.gsc:1814
‪increment_client_stat
‪function increment_client_stat(stat_name, include_gametype)
Definition: _zm_stats.gsc:389
‪play_sound_at_pos
‪function play_sound_at_pos(ref, pos, ent)
Definition: _zm_utility.gsc:3040
‪play_sound_on_ent
‪function play_sound_on_ent(ref)
Definition: _zm_utility.gsc:3070
‪replace_chunk
‪function replace_chunk(barrier, chunk, perk, upgrade, via_powerup)
Definition: _zm_blockers.gsc:2811
‪flag_blocker
‪function flag_blocker()
Definition: _zm_blockers.gsc:3140
‪blockerstub_update_prompt
‪function blockerstub_update_prompt(player)
Definition: _zm_blockers.gsc:2249
‪intermission
‪function intermission()
Definition: _zm.gsc:6542
‪init_blockers
‪function init_blockers()
Definition: _zm_blockers.gsc:73
‪increment_player_stat
‪function increment_player_stat(stat_name)
Definition: _zm_stats.gsc:369
‪is_Standard
‪function is_Standard()
Definition: _zm_utility.gsc:47
‪player_add_points
‪function player_add_points(event, mod, hit_location, is_dog, zombie_team, damage_weapon)
Definition: _zm_score.gsc:129
‪door_repaired_rumble_n_sound
‪function door_repaired_rumble_n_sound()
Definition: _zm_blockers.gsc:2284
‪clear
‪function clear(str_flag)
Definition: flag_shared.csc:130
‪blockertrigger_update_prompt
‪function blockertrigger_update_prompt(player)
Definition: _zm_blockers.gsc:2236
‪door_classify
‪function door_classify(parent_trig)
Definition: _zm_blockers.gsc:209
‪__main__
‪function __main__()
Definition: _zm_blockers.gsc:62
‪blocker_init
‪function blocker_init()
Definition: _zm_blockers.gsc:1559
‪debris_init
‪function debris_init()
Definition: _zm_blockers.gsc:1179
‪waittill_either
‪function waittill_either(msg1, msg2)
Definition: util_shared.gsc:303
‪door_init
‪function door_init()
Definition: _zm_blockers.gsc:99
‪disconnect_paths_when_done
‪function disconnect_paths_when_done()
Definition: _zm_blockers.gsc:1159
‪do_post_chunk_repair_delay
‪function do_post_chunk_repair_delay(has_perk)
Definition: _zm_blockers.gsc:1924
‪zombie_gratetear_audio_plus_fx_offset_repair_horizontal
‪function zombie_gratetear_audio_plus_fx_offset_repair_horizontal(chunk)
Definition: _zm_blockers.gsc:2970
‪get_array
‪function get_array(kvp_value, kvp_key="targetname")
Definition: struct.csc:34
‪kill_trapped_zombies
‪function kill_trapped_zombies(trigger)
Definition: _zm_blockers.gsc:618
‪board_completion
‪function board_completion()
Definition: _zm_blockers.gsc:2308
‪unitrigger_trigger
‪function unitrigger_trigger(player)
Definition: _zm_unitrigger.gsc:65
‪debris_move
‪function debris_move(struct)
Definition: _zm_blockers.gsc:1462
‪debris_zbarrier_move
‪function debris_zbarrier_move()
Definition: _zm_blockers.gsc:1421
‪is_Classic
‪function is_Classic()
Definition: _zm_utility.gsc:42
‪trace
‪function trace(from, to, target)
Definition: grapple.gsc:369
‪self_delete
‪function self_delete()
Definition: _util.gsc:739
‪trigger_delete_on_repair
‪function trigger_delete_on_repair()
Definition: _zm_blockers.gsc:2324
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪get
‪function get(kvp_value, kvp_key="targetname")
Definition: struct.csc:13
‪blocker_choke
‪function blocker_choke()
Definition: _zm_blockers.gsc:1800
‪delay
‪function delay(time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6)
Definition: util_shared.csc:784
‪is_player_valid
‪function is_player_valid(player, checkIgnoreMeFlag, ignore_laststand_players)
Definition: skeleton.gsc:256
‪fake_physicslaunch
‪function fake_physicslaunch(target_pos, power)
Definition: _zm_utility.gsc:2896
‪zombie_bartear_audio_plus_fx_offset_repair_horizontal
‪function zombie_bartear_audio_plus_fx_offset_repair_horizontal(chunk)
Definition: _zm_blockers.gsc:3027
‪add_zombie_hint
‪function add_zombie_hint(ref, text)
Definition: _zm_utility.gsc:2923
‪unregister_unitrigger
‪function unregister_unitrigger(unitrigger_stub)
Definition: _zm_unitrigger.gsc:173
‪handle_post_board_repair_rewards
‪function handle_post_board_repair_rewards(cost, zbarrier)
Definition: _zm_blockers.gsc:1932
‪no_valid_repairable_boards
‪function no_valid_repairable_boards(barrier, barrier_chunks)
Definition: _zm_utility.gsc:419
‪increment_challenge_stat
‪function increment_challenge_stat(stat_name, amount=1)
Definition: _zm_stats.gsc:478
‪PERK_SLEIGHT_OF_HAND
‪#define PERK_SLEIGHT_OF_HAND
Definition: _zm_perks.gsh:25
‪ensure_chunk_is_back_to_origin
‪function ensure_chunk_is_back_to_origin(chunk)
Definition: _zm_blockers.gsc:2802
‪has_blocker_affecting_perk
‪function has_blocker_affecting_perk()
Definition: _zm_blockers.gsc:1912
‪door_block
‪function door_block()
Definition: _zm_blockers.gsc:908
‪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
‪zombie_bartear_audio_offset
‪function zombie_bartear_audio_offset(chunk)
Definition: _zm_blockers.gsc:2792
‪door_delay
‪function door_delay()
Definition: _zm_blockers.gsc:404
‪script_flag_wait
‪function script_flag_wait()
Definition: flag_shared.gsc:394
‪zombie_boardtear_audio_plus_fx_offset_repair_horizontal
‪function zombie_boardtear_audio_plus_fx_offset_repair_horizontal(chunk)
Definition: _zm_blockers.gsc:2895
‪REGISTER_SYSTEM_EX
‪#define REGISTER_SYSTEM_EX(__sys, __func_init_preload, __func_init_postload, __reqs)
Definition: shared.gsh:209
‪zombie_boardtear_offset_fx_horizontle
‪function zombie_boardtear_offset_fx_horizontle(chunk, node)
Definition: _zm_spawner.gsc:1235
‪any_player_touching
‪function any_player_touching(trigger)
Definition: _zm_blockers.gsc:647
‪use_button_held
‪function use_button_held()
Definition: util_shared.gsc:2253
‪random_destroyed_chunk_show
‪function random_destroyed_chunk_show()
Definition: _zm_blockers.gsc:2275
‪any_zombie_touching_any
‪function any_zombie_touching_any(trigger, more_triggers)
Definition: _zm_blockers.gsc:676
‪open_all_zbarriers
‪function open_all_zbarriers()
Definition: _zm_blockers.gsc:2868
‪blocker_unitrigger_think
‪function blocker_unitrigger_think()
Definition: _zm_blockers.gsc:1958
‪wait_till
‪function wait_till(str_flag)
Definition: flag_shared.csc:189
‪blocker_disconnect_paths
‪function blocker_disconnect_paths(start_node, end_node, two_way)
Definition: _zm_blockers.gsc:1516
‪remove_chunk_rotate_grate
‪function remove_chunk_rotate_grate(chunk)
Definition: _zm_blockers.gsc:2720
‪door_solid_thread
‪function door_solid_thread()
Definition: _zm_blockers.gsc:1092
‪increment_windows_repaired
‪function increment_windows_repaired(s_barrier)
Definition: _zm_daily_challenges.gsc:323
‪bookmark
‪function bookmark(type, time, mainClientEnt, otherClientEnt, eventPriority, inflictorEnt, overrideEntityCamera, actorEnt)
Definition: demo_shared.gsc:25
‪self_disconnectpaths
‪function self_disconnectpaths()
Definition: _zm_blockers.gsc:1170
‪Spawn
‪function Spawn(parent, onDeathCallback)
Definition: _flak_drone.gsc:427
‪wait_trigger_clear
‪function wait_trigger_clear(trigger, more_triggers, end_on)
Definition: _zm_blockers.gsc:692
‪waittill_door_trigger_clear_local_power_off
‪function waittill_door_trigger_clear_local_power_off(trigger, all_trigs)
Definition: _zm_blockers.gsc:703
‪increment_window_repaired
‪function increment_window_repaired(s_barrier)
Definition: _zm_blockers.gsc:2227
‪waittill_door_can_close
‪function waittill_door_can_close()
Definition: _zm_blockers.gsc:725
‪init
‪function init()
Definition: struct.csc:1
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪should_delete_zbarriers
‪function should_delete_zbarriers()
Definition: _zm_blockers.gsc:1717
‪groundpos
‪function groundpos(origin)
Definition: _zm_utility.gsc:4580
‪zombie_boardtear_audio_offset
‪function zombie_boardtear_audio_offset(chunk)
Definition: _zm_blockers.gsc:2742
‪get_active_zone_names
‪function get_active_zone_names()
Definition: _zm_zonemgr.gsc:1205
‪player_is_in_laststand
‪function player_is_in_laststand()
Definition: laststand_shared.gsc:18
‪blocker_connect_paths
‪function blocker_connect_paths(start_node, end_node, two_way)
Definition: _zm_blockers.gsc:1535
‪__init__
‪function __init__()
Definition: _zm_blockers.gsc:38
‪self_and_flag_wait
‪function self_and_flag_wait(msg)
Definition: _zm_blockers.gsc:894
‪set_hint_string
‪function set_hint_string(ent, default_ref, cost)
Definition: _zm_utility.gsc:2948
‪update_states
‪function update_states(states)
Definition: _zm_blockers.gsc:3183
‪destructible_glass_barricade
‪function destructible_glass_barricade(unbroken_section, node)
Definition: _zm_blockers.gsc:1731
‪remove_chunk
‪function remove_chunk(chunk, node, destroy_immediately, zomb)
Definition: _zm_blockers.gsc:2366
‪quantum_bomb_open_nearest_door_result
‪function quantum_bomb_open_nearest_door_result(position)
Definition: _zm_blockers.gsc:3227
‪create_and_play_dialog
‪function create_and_play_dialog(category, subcategory, force_variant)
Definition: _zm_audio.gsc:603
‪zombie_boardtear_audio_plus_fx_offset_repair_verticle
‪function zombie_boardtear_audio_plus_fx_offset_repair_verticle(chunk)
Definition: _zm_blockers.gsc:2932
‪unitrigger_force_per_player_triggers
‪function unitrigger_force_per_player_triggers(unitrigger_stub, opt_on_off)
Definition: _zm_unitrigger.gsc:58
‪in_revive_trigger
‪function in_revive_trigger()
Definition: _zm_utility.gsc:1684
‪door_solid_thread_anim
‪function door_solid_thread_anim()
Definition: _zm_blockers.gsc:1126
‪door_think
‪function door_think()
Definition: _zm_blockers.gsc:769
‪IS_DRINKING
‪#define IS_DRINKING(_is_drinking)
Definition: _zm_utility.gsh:1
‪player_fails_blocker_repair_trigger_preamble
‪function player_fails_blocker_repair_trigger_preamble(player, players, trigger, hold_required)
Definition: _zm_blockers.gsc:1861
‪register_static_unitrigger
‪function register_static_unitrigger(unitrigger_stub, trigger_func, recalculate_zone)
Definition: _zm_unitrigger.gsc:236
‪STR_NAV_VOLUME_TRAVERSAL
‪#define STR_NAV_VOLUME_TRAVERSAL
Definition: _zm_blockers.gsc:36
‪get_hint_string
‪function get_hint_string(ent, default_ref, cost)
Definition: _zm_utility.gsc:2974
‪move_chunk
‪function move_chunk(index, b_hide)
Definition: _zm_blockers.gsc:1442
‪waittill_door_trigger_clear_global_power_off
‪function waittill_door_trigger_clear_global_power_off(trigger, all_trigs)
Definition: _zm_blockers.gsc:714
‪door_zbarrier_move
‪function door_zbarrier_move()
Definition: _zm_blockers.gsc:1432
‪door_buy
‪function door_buy()
Definition: _zm_blockers.gsc:285
‪any_player_touching_any
‪function any_player_touching_any(trigger, more_triggers)
Definition: _zm_blockers.gsc:658
‪ZM_MAP_EVENT_PURCHASE_DOOR
‪#define ZM_MAP_EVENT_PURCHASE_DOOR
Definition: _zm_utility.gsh:38
‪zombie_bartear_audio_plus_fx_offset_repair_verticle
‪function zombie_bartear_audio_plus_fx_offset_repair_verticle(chunk)
Definition: _zm_blockers.gsc:3082
‪physics_launch_door
‪function physics_launch_door(door_trig)
Definition: _zm_blockers.gsc:1069
‪rebuild_barrier_reward_reset
‪function rebuild_barrier_reward_reset()
Definition: _zm_blockers.gsc:2361
‪get_random_destroyed_chunk
‪function get_random_destroyed_chunk(barrier, barrier_chunks)
Definition: _zm_utility.gsc:2438
‪door_opened
‪function door_opened(cost, quick_close)
Definition: _zm_blockers.gsc:923
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265