‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_zm_ai_faller.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\laststand_shared;
4 #using scripts\shared\math_shared;
5 #using scripts\shared\util_shared;
6 
7 #insert scripts\shared\shared.gsh;
8 
9 #using scripts\shared\ai\systems\animation_state_machine_mocomp;
10 #using scripts\shared\ai\systems\animation_state_machine_notetracks;
11 #using scripts\shared\ai\systems\animation_state_machine_utility;
12 #using scripts\shared\ai\systems\behavior_tree_utility;
13 #using scripts\shared\ai\zombie_shared;
14 #using scripts\shared\ai\zombie_utility;
15 
16 #using scripts\zm\_zm_laststand;
17 #using scripts\zm\_zm_spawner;
18 #using scripts\zm\_zm_utility;
19 
20 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
21 #insert scripts\shared\ai\systems\behavior.gsh;
22 #insert scripts\shared\ai\systems\behavior_tree.gsh;
23 
24 #define DEFAULT_DIST_SQ_VISIBLE ( 1000 * 1000 )
25 #define FALLER_DIST_SQ_VISIBLE ( 1500 * 1500 )
26 
27 #define ASM_FALLER_MELEE_NOTETRACK "faller_melee"
28 #define ASM_FALLER_DEATHOUT_NOTETRACK "deathout"
29 
30 #namespace zm_ai_faller;
31 
32 function autoexec ‪init()
33 {
34  // INIT BEHAVIORS
36 
39 }
40 
41 function private ‪InitFallerBehaviorsAndASM()
42 {
44 
45  ‪BT_REGISTER_API( "shouldFallerDrop", &‪shouldFallerDrop );
46 
47  ‪BT_REGISTER_API( "isFallerInCeiling", &‪isFallerInCeiling );
48  ‪BT_REGISTER_API( "fallerCeilingDeath", &‪fallerCeilingDeath );
49 
50  ‪ASM_REGISTER_MOCOMP( "mocomp_drop@faller", &‪mocompFallerDrop, undefined, undefined );
51  ‪ASM_REGISTER_MOCOMP( "mocomp_ceiling_death@faller", &‪mocompCeilingDeath, undefined, undefined );
52 }
53 
54 //*****************************************************************************
55 //*****************************************************************************
56 
57 function ‪fallerDropAction( entity, asmStateName )
58 {
59  ‪AnimationStateNetworkUtility::RequestState( entity, asmStateName );
60 
61  return ‪BHTN_RUNNING;
62 }
63 
64 function ‪fallerDropActionUpdate( entity, asmStateName )
65 {
66  ground_pos = ‪zm_utility::groundpos_ignore_water_new( entity.origin );
67  if( entity.origin[2] - ground_pos[2] < 20)
68  {
69  return ‪BHTN_SUCCESS;
70  }
71 
72  return ‪BHTN_RUNNING;
73 }
74 
75 function ‪fallerDropActionTerminate( entity, asmStateName )
76 {
77  entity.faller_drop = false;
78 
79  return ‪BHTN_SUCCESS;
80 }
81 
82 function ‪shouldFallerDrop( entity )
83 {
84  if ( ‪IS_TRUE( entity.faller_drop ) )
85  {
86  return true;
87  }
88 
89  return false;
90 }
91 
92 function ‪isFallerInCeiling( entity )
93 {
94  if ( ‪IS_TRUE( entity.in_the_ceiling ) && !‪IS_TRUE( entity.normal_death ) )
95  {
96  return true;
97  }
98 
99  return false;
100 }
101 
102 function ‪fallerCeilingDeath( entity )
103 {
104 
105 }
106 
107 function private ‪mocompFallerDrop( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
108 {
109  entity AnimMode( ‪AI_ANIM_USE_BOTH_DELTAS_NOGRAVITY, false );
110 }
111 
112 function private ‪mocompCeilingDeath( entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration )
113 {
114  entity AnimMode( ‪AI_ANIM_USE_BOTH_DELTAS_NOCLIP, false );
115 }
116 
117 //*****************************************************************************
118 //*****************************************************************************
119 
121 {
122  level.zombie_total++;
124  if ( isdefined( self.zombie_faller_location ) )
125  {
126  self.zombie_faller_location.is_enabled = true;
127  self.zombie_faller_location = undefined;
128  }
129  self Delete();
130 }
131 
133 {
134  if ( isdefined( self.script_parameters ) )
135  {
136  parms = strtok( self.script_parameters, ";" );
137  if ( isdefined( parms ) && parms.size > 0 )
138  {
139  for ( i = 0; i < parms.size; i++ )
140  {
141  if ( parms[i] == "drop_now" )
142  {
143  self.drop_now = true;
144  }
145  //Drop if zone is not occupied
146  if ( parms[i] == "drop_not_occupied" )
147  {
148  self.drop_not_occupied = true;
149  }
150 
151  if(parms[i] == "emerge_top" ) //faller variant that comes through the wall rather than from the ceiling
152  {
153  self.emerge_top = true;
154  }
155  if(parms[i] == "emerge_bottom" ) //faller variant that comes through the wall rather than from the ceiling
156  {
157  self.emerge_bottom = true;
158  }
159  }
160  }
161  }
162 }
163 
164 function ‪setup_deathfunc(func_name)
165 {
166  self endon( "death" );
167 
168  while ( !‪IS_TRUE( self.zombie_init_done ) )
169  {
171  }
172 
173  if(isDefined(func_name))
174  {
175  self.deathFunction = func_name;
176  }
177  else if(IsDefined(level.custom_faller_death))
178  {
179  self.deathFunction = level.custom_faller_death;
180  }
181  else
182  {
183  // rsh040711 - fixed faller deaths
184  self.deathFunction =&‪zombie_fall_death_func;
185  }
186 }
187 
188 function ‪do_zombie_fall(spot)
189 {
190  self endon("death");
191 
192  if ( !‪IS_TRUE( level.faller_init ) )
193  {
194  level.faller_init = true;
195 
196  faller_anim = self AnimMappingSearch( IString( "anim_faller_emerge" ) );
197  level.faller_emerge_time = GetAnimLength( faller_anim );
198 
199  faller_anim = self AnimMappingSearch( IString( "anim_faller_attack_01" ) );
200  level.faller_attack_01_time = GetAnimLength( faller_anim );
201 
202  faller_anim = self AnimMappingSearch( IString( "anim_faller_attack_02" ) );
203  level.faller_attack_02_time = GetAnimLength( faller_anim );
204 
205  faller_anim = self AnimMappingSearch( IString( "anim_faller_fall" ) );
206  level.faller_fall_time = GetAnimLength( faller_anim );
207  }
208 
209  self.zombie_faller_location = spot;
210  //NOTE: multiple zombie fallers could be waiting in the same spot now, need to have spawners detect this
211  // and not use the spot again until the previous zombie has died or dropped down
212  self.zombie_faller_location.is_enabled = false;
213  self.zombie_faller_location ‪faller_script_parameters();
214 
215  if(‪IS_TRUE(self.zombie_faller_location.emerge_bottom) || ‪IS_TRUE(self.zombie_faller_location.emerge_top ) )
216  {
217  self ‪do_zombie_emerge(spot);
218  return;
219  }
220 
221  self thread ‪setup_deathfunc();
222 
223  self.no_powerups = true;
224  self.in_the_ceiling = true;
225 
226  self.anchor = ‪spawn("script_origin", self.origin);
227  self.anchor.angles = self.angles;
228  self linkto(self.anchor);
229 
230  if( !isdefined( spot.angles ) )
231  {
232  spot.angles = (0, 0, 0);
233  }
234 
235  anim_org = spot.origin;
236  anim_ang = spot.angles;
237 
238  self Ghost();
239  self.anchor moveto(anim_org, .05);
240  self.anchor waittill("movedone");
241 
242  // face goal
244  if (isdefined(target_org))
245  {
246  anim_ang = VectorToAngles(target_org - self.origin);
247  self.anchor RotateTo((0, anim_ang[1], 0), .05);
248  self.anchor waittill("rotatedone");
249  }
250 
251  self unlink();
252  if(isdefined(self.anchor))
253  {
254  self.anchor delete();
255  }
256  self thread ‪zombie_utility::hide_pop();
257 
258  self thread ‪zombie_fall_death(spot);
259  self thread ‪zombie_fall_fx(spot);
260 
261  self thread ‪zombie_faller_death_wait();
262 
263  self thread ‪zombie_faller_do_fall();
264 
265  self.no_powerups = false;
266  self notify("risen", spot.script_string );
267 }
268 
270 {
271  self endon("death");
272 
273  // first play the emerge, then the fall anim
274  self AnimScripted( "fall_anim", self.origin, self.zombie_faller_location.angles, "ai_zm_dlc5_zombie_ceiling_emerge_01" );
275  wait( level.faller_emerge_time );
276 
277  //NOTE: now we don't fall until we've attacked at least once from the ceiling
278  self.zombie_faller_wait_start = GetTime();
279  self.zombie_faller_should_drop = false;
280  self thread ‪zombie_fall_wait();
282  while ( !self.zombie_faller_should_drop )
283  {
284  if ( self ‪zombie_fall_should_attack(self.zombie_faller_location) )
285  {
286  if ( ‪math::cointoss() )
287  {
288  self AnimScripted( "fall_anim", self.origin, self.zombie_faller_location.angles, "ai_zm_dlc5_zombie_ceiling_attack_01" );
289  wait( level.faller_attack_01_time );
290  }
291  else
292  {
293  self AnimScripted( "fall_anim", self.origin, self.zombie_faller_location.angles, "ai_zm_dlc5_zombie_ceiling_attack_02" );
294  wait( level.faller_attack_02_time );
295  }
296 
297  //50/50 chance that we'll stay up here and attack again or drop down
298  if ( !(self ‪zombie_faller_always_drop()) && randomfloat(1) > 0.5 )
299  {
300  //NOTE: if we *can* attack, should we actually stay up here until we can't anymore?
301  self.zombie_faller_should_drop = true;
302  }
303  }
304  else
305  {
306  if ( (self ‪zombie_faller_always_drop()) )
307  {
308  //drop as soon as we have nobody to attack!
309  self.zombie_faller_should_drop = true;
310  break;
311  }
312  //otherwise, wait to attack
313  else if ( GetTime() >= self.zombie_faller_wait_start + 20000 )
314  {
315  //we've been hanging here for 20 seconds, go ahead and drop
316  //IPrintLnBold("zombie faller waited too long, dropping");
317  self.zombie_faller_should_drop = true;
318  break;
319  }
320  else if ( self ‪zombie_faller_drop_not_occupied() )
321  {
322  self.zombie_faller_should_drop = true;
323  break;
324  }
325  else
326  {
327  //NOTE: instead of playing a looping idle, they just flail and attack over and over
328  if ( ‪math::cointoss() )
329  {
330  self AnimScripted( "fall_anim", self.origin, self.zombie_faller_location.angles, "ai_zm_dlc5_zombie_ceiling_attack_01" );
331  wait( level.faller_attack_01_time );
332  }
333  else
334  {
335  self AnimScripted( "fall_anim", self.origin, self.zombie_faller_location.angles, "ai_zm_dlc5_zombie_ceiling_attack_02" );
336  wait( level.faller_attack_02_time );
337  }
338  }
339  }
340  }
341 
342  self notify("falling");
343  //now the fall location (spot) can be used by another zombie faller again
344  spot = self.zombie_faller_location;
346 
347  self AnimScripted( "fall_anim", self.origin, spot.angles, "ai_zm_dlc5_zombie_ceiling_dropdown_01" );
348  wait( level.faller_fall_time );
349 
350  // rsh040711 - set the death func back to normal
351  self.deathFunction = &‪zm_spawner::zombie_death_animscript;
352  self.normal_death = true;
353 
354  self notify("fall_anim_finished");
355  spot notify("stop_zombie_fall_fx");
356 
357  //play fall loop
358  self StopAnimScripted();
359 
360  // Get Z distance
361  landAnimDelta = 15; //GetMoveDelta( landAnim, 0, 1 )[2];//delta in the anim doesn't seem to reflect actual distance to ground correctly
362  ground_pos = ‪zm_utility::groundpos_ignore_water_new( self.origin );
363  //draw_arrow_time( self.origin, ground_pos, (1, 1, 0), 10 );
364  physDist = self.origin[2] - ground_pos[2] + landAnimDelta;
365 
366  if ( physDist > 0 )
367  {
368  self.faller_drop = true;
369 
370  //high enough above the ground to play some of the falling loop before we can play the land
371  //self animcustom(&zombie_fall_loop );
372  //self waittill("faller_on_ground");
373 
374  //play land
375  //self animcustom(&zombie_land );
376  self waittill( "zombie_land_done" );
377  }
378 
379  self.in_the_ceiling = false;
380  self traverseMode( "gravity" );
381 
382  self.no_powerups = false;
383 }
384 
386 {
387  self endon("death");
388 
389  self SetAnimStateFromASD( "zm_faller_fall_loop" );
390 
391  while(1)
392  {
393  ground_pos = ‪zm_utility::groundpos_ignore_water_new( self.origin );
394  if( self.origin[2] - ground_pos[2] < 20)
395  {
396  self notify("faller_on_ground");
397  break;
398  }
399  wait .05;
400  }
401 }
402 
403 function ‪zombie_land()
404 {
405  self SetAnimStateFromASD( "zm_faller_land" );
406  ‪zombie_shared::DoNoteTracks( "land_anim" );
407 
408  self notify( "zombie_land_done" );
409 }
410 
411 
413 {
414  if ( ‪IS_TRUE( self.zombie_faller_location.drop_now ) )
415  {
416  return true;
417  }
418  return false;
419 }
420 
422 {
423  if ( ‪IS_TRUE(self.zombie_faller_location.drop_not_occupied) )
424  {
425  if( isdefined(self.zone_name) && isdefined(level.zones[ self.zone_name ]) )
426  {
427  return !level.zones[ self.zone_name ].is_occupied;
428  }
429  }
430  return false;
431 }
432 
433 //Watchs for players standing in the general area
435 {
436  players = GetPlayers();
437  for(i=0; i<players.size; i++)
438  {
439  self thread ‪zombie_faller_watch_player(players[i]);
440  }
441 }
442 
444 {
445  self endon("falling");
446  self endon("death");
447  player endon("disconnect");
448 
449 
450  range = 200;
451  rangeSqr = range*range;
452 
453  ‪timer = 5000; //5 seconds
454 
455  inRange = false;
456  inRangeTime = 0;
457 
458  //Used to detect player passing under zombie
459  closeRange = 60;
460  closeRangeSqr = closeRange*closeRange;
461  dirToPlayerEnter = (0,0,0);
462  inCloseRange = false;
463 
464  while(1)
465  {
466  //Watch for standing in general area
467  distSqr = distance2dsquared(self.origin, player.origin);
468  if(distSqr < rangeSqr)
469  {
470  if(inRange)
471  {
472  if(inRangeTime+‪timer < GetTime())
473  {
474  self.zombie_faller_should_drop = true;
475  break;
476  }
477  }
478  else
479  {
480  inRange = true;
481  inRangeTime = GetTime();
482  }
483  }
484  else
485  {
486  inRange = false;
487  }
488 
489  //Watch for pass under
490  if(distSqr<closeRangeSqr)
491  {
492  //Just entered range
493  if(!inCloseRange)
494  {
495  dirToPlayerEnter = player.origin - self.origin;
496  dirToPlayerEnter = (dirToPlayerEnter[0], dirToPlayerEnter[1], 0.0);
497  dirToPlayerEnter = vectornormalize(dirToPlayerEnter);
498  }
499 
500  inCloseRange = true;
501  }
502  else
503  {
504  //Just exited range
505  if(inCloseRange)
506  {
507  dirToPlayerExit = player.origin - self.origin;
508  dirToPlayerExit = (dirToPlayerExit[0], dirToPlayerExit[1], 0.0);
509  dirToPlayerExit = vectornormalize(dirToPlayerExit);
510 
511  if(vectordot(dirToPlayerEnter, dirToPlayerExit) < 0)
512  {
513  self.zombie_faller_should_drop = true;
514  break;
515  }
516  }
517 
518  inCloseRange = false;
519  }
520 
521  wait .1;
522  }
523 }
524 
526 {
527  self endon("falling");
528  self endon("death");
529 
530  if ( isdefined( self.zone_name ) )
531  {
532  if ( isdefined(level.zones) && isdefined(level.zones[ self.zone_name ] ) )
533  {
534  zone = level.zones[ self.zone_name ];
535  while ( 1 )
536  {
537  //no players in an adjacent zone? Delete me if nobody can see me
538  //NOTE: what if he's not in a zone at all?
539  if ( (!zone.is_enabled ||!zone.is_active) )
540  {
542  {
543  if ( self.health != level.zombie_health )
544  {
545  //took some damage - fall instead of delete
546  //IPrintLnBold("damaged zombie faller in inactive zone dropping down");
547  self.zombie_faller_should_drop = true;
548  break;
549  }
550  else
551  {
552  //IPrintLnBold("deleting zombie faller in inactive zone");
554  return;
555  }
556  }
557  }
558  wait( 0.5 );
559  }
560  }
561  }
562 }
563 
565 {
566  victims = ‪zombie_fall_get_vicitims(spot);
567  return victims.size > 0;
568 }
569 
571 {
572  ret = [];
573  players = GetPlayers();
574 
575  checkDist2 = 40.0;
576  checkDist2 *= checkDist2;
577  for ( i = 0; i < players.size; i++ )
578  {
579  player = players[i];
580 
582  {
583  continue;
584  }
585 
586  // if the player is in crouch or prone, fallers can't attack them
587  stance = player GetStance();
588  if ( stance == "crouch" || stance == "prone" )
589  {
590  continue;
591  }
592 
593  // make sure the player is below us first
594  zCheck = self.origin[2] - player.origin[2];
595  if ( zCheck < 0.0 || zCheck > 120.0 )
596  {
597  continue;
598  }
599 
600  dist2 = Distance2DSquared(player.origin, self.origin);
601  if ( dist2 < checkDist2 )
602  {
603  ret[ret.size] = player;
604  }
605  }
606 
607  return ret;
608 }
609 
610 function ‪get_fall_anim(spot)
611 {
612  return level._zombie_fall_anims[self.animname]["fall"];
613 }
614 
616 {
617  if ( isdefined( self.zombie_faller_location ) )
618  {
619  self.zombie_faller_location.is_enabled = true;
620  self.zombie_faller_location = undefined;
621  }
622 }
623 
624 //Wait until we die, then clear our spawn spot so it can be used again
625 function ‪zombie_faller_death_wait(endon_notify)
626 {
627  self endon( "falling" );
628  if(isDefined(endon_notify))
629  {
630  self endon(endon_notify);
631  }
632  self waittill( "death" );
633  //in case we're killed while still hanging out in our location
635 }
636 
637 function ‪zombie_fall_death_func( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime )
638 {
639  // rsh040711 - set noclip so death anim can translate through the ceiling
640  self animmode( "noclip" );
641  self.deathanim = "zm_faller_emerge_death";
642 
644 }
645 
646 /*
647 zombie_fall_death:
648 Track when the zombie should die, set the death anim, and stop the animscripted so he can die
649 */
650 function ‪zombie_fall_death(spot)
651 {
652  //self.zombie_fall_death_out = false;
653 
654  self endon("fall_anim_finished");
655 
656  while (self.health > 1) // health will only go down to 1 when playing animation with AnimScripted()
657  {
658  self waittill("damage", amount, attacker, dir, p, type);
659  }
660 
661  self StopAnimScripted(); //Need to stop anim so we don't get into delayedDeath (native var).
662  spot notify("stop_zombie_fall_fx");
663 }
664 
666 {
667  toks = strtok(type, "_");
668  if(toks.size<2)
669  {
670  return type;
671  }
672 
673  //Throw out "MOD_"
674  returnStr = toks[1];
675 
676  for(i=2;i<toks.size;i++)
677  {
678  returnStr += toks[i];
679  }
680 
681  returnStr = tolower(returnStr);
682  return returnStr;
683 }
684 
685 //-------------------------------------------------------------------
686 // Play the fx as the zombie crawls out of the ceiling and thread another function to handle the dust falling
687 // off when the zombie is out of the ceiling.
688 //-------------------------------------------------------------------
689 function ‪zombie_fall_fx(spot)
690 {
691  spot thread ‪zombie_fall_dust_fx(self);
692  spot thread ‪zombie_fall_burst_fx();
693  playsoundatposition ("zmb_zombie_spawn", spot.origin);
694  self endon("death");
695  spot endon("stop_zombie_fall_fx");
696  wait 1;
697  if (self.zombie_move_speed != "sprint")
698  {
699  // wait longer before starting billowing fx if it's not a really fast animation
700  wait 1;
701  }
702 }
703 
705 {
706  self endon("stop_zombie_fall_fx");
707  self endon("fall_anim_finished");
708 
709  playfx(level._effect["rise_burst"],self.origin + ( 0,0,randomintrange(5,10) ) );
710  wait(.25);
711  playfx(level._effect["rise_billow"],self.origin + ( randomintrange(-10,10),randomintrange(-10,10),randomintrange(5,10) ) );
712 }
713 
714 function ‪zombie_fall_dust_fx(zombie)
715 {
716  dust_tag = "J_SpineUpper";
717 
718  self endon("stop_zombie_fall_dust_fx");
719  self thread ‪stop_zombie_fall_dust_fx(zombie);
720 
721  dust_time = 4.5; // play dust fx for a max time
722  dust_interval = .3; //randomfloatrange(.1,.25); // wait this time in between playing the effect
723 
724  for (t = 0; t < dust_time; t += dust_interval)
725  {
726  PlayfxOnTag(level._effect["rise_dust"], zombie, dust_tag);
727  wait dust_interval;
728  }
729 }
730 
732 {
733  zombie waittill("death");
734  self notify("stop_zombie_fall_dust_fx");
735 }
736 
738 {
739  //self.deathFunction =&faller_death_ragdoll;
740  //self.zombie_fall_death_out = true;
741  //self notify("zombie_fall_death_out");
742  self.in_the_ceiling = false;
743 }
744 
745 function ‪handle_fall_notetracks( entity )
746 {
747  // the anim notetracks control which death anim to play
748  // default to "deathin" (still in the ground)
749 
750  //if (note == "deathout" )
751  //{
752  // self.deathFunction =&faller_death_ragdoll;
753  //self.zombie_fall_death_out = true;
754  //self notify("zombie_fall_death_out");
755  //}
756 
757  // attack all players beneath us
758  victims = ‪zombie_fall_get_vicitims( entity.zombie_faller_location );
759  for ( i = 0; i < victims.size; i++ )
760  {
761  victims[i] DoDamage( entity.meleeDamage, entity.origin, self, self, "none", "MOD_MELEE" );
762  //damaged someone!
763  entity.zombie_faller_should_drop = true;
764  }
765 }
766 
767 function ‪faller_death_ragdoll( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime )
768 {
769  self StartRagdoll();
770  self launchragdoll((0, 0, -1));
771 
773 }
774 
775 //Test if self is in player's FOV
776 function ‪in_player_fov( player )
777 {
778  playerAngles = player getplayerangles();
779  playerForwardVec = AnglesToForward( playerAngles );
780  playerUnitForwardVec = VectorNormalize( playerForwardVec );
781 
782  banzaiPos = self.origin;
783  playerPos = player GetOrigin();
784  playerToBanzaiVec = banzaiPos - playerPos;
785  playerToBanzaiUnitVec = VectorNormalize( playerToBanzaiVec );
786 
787  forwardDotBanzai = VectorDot( playerUnitForwardVec, playerToBanzaiUnitVec );
788  angleFromCenter = ACos( forwardDotBanzai );
789 
790  playerFOV = GetDvarFloat( "cg_fov" );
791  banzaiVsPlayerFOVBuffer = GetDvarFloat( "g_banzai_player_fov_buffer" );
792  if ( banzaiVsPlayerFOVBuffer <= 0 )
793  {
794  banzaiVsPlayerFOVBuffer = 0.2;
795  }
796 
797  inPlayerFov = ( angleFromCenter <= ( playerFOV * 0.5 * ( 1 - banzaiVsPlayerFOVBuffer ) ) );
798 
799  return inPlayerFov;
800 }
801 
802 //-------------------------------------------------------------------------------
803 // MCG 030711:
804 // can faller zombie potentially be seen by any players?
805 // self = zombie to check.
806 //-------------------------------------------------------------------------------
807 function ‪potentially_visible( how_close )
808 {
809  if ( !isdefined( how_close ) )
810  {
811  how_close = ‪DEFAULT_DIST_SQ_VISIBLE;
812  }
813  potentiallyVisible = false;
814 
815  players = getplayers();
816  for ( i = 0; i < players.size; i++ )
817  {
818  dist = DistanceSquared(self.origin, players[i].origin);
819  if(dist < how_close)
820  {
821  inPlayerFov = self ‪in_player_fov(players[i]);
822  if(inPlayerFov)
823  {
824  potentiallyVisible = true;
825  //no need to check rest of players
826  break;
827  }
828  }
829  }
830 
831  return potentiallyVisible;
832 }
833 
834 //similar to fallers except they emerge from the wall at player level rather than drop from the ceiling
835 function ‪do_zombie_emerge(spot)
836 {
837  self endon("death");
838 
840 
841  self.no_powerups = true;
842  self.in_the_ceiling = true;
843 
844  anim_org = spot.origin;
845  anim_ang = spot.angles;
846 
847  self thread ‪zombie_emerge_fx(spot);
848  self thread ‪zombie_faller_death_wait("risen");
849  if(isDefined(level.custom_faller_entrance_logic))
850  {
851  self thread [[level.custom_faller_entrance_logic]]();
852  }
853 
854  self ‪zombie_faller_emerge( spot );
855  self.create_eyes = 1;
856  wait(.1);
857  self notify("risen", spot.script_string );
859 }
860 
861 
862 function ‪zombie_faller_emerge( spot )
863 {
864  self endon("death");
865 
866  if (‪IS_TRUE(self.zombie_faller_location.emerge_bottom))
867  {
868  self AnimScripted( "fall_anim", self.zombie_faller_location.origin, self.zombie_faller_location.angles, "zombie_riser_elevator_from_floor");
869  }
870  else
871  {
872  self AnimScripted( "fall_anim", self.zombie_faller_location.origin, self.zombie_faller_location.angles, "zombie_riser_elevator_from_ceiling" );
873  }
874 
875  self ‪zombie_shared::DoNoteTracks( "rise_anim" );
876 
877  // rsh040711 - set the death func back to normal
878  self.deathFunction = &‪zm_spawner::zombie_death_animscript;
879 
880  self.in_the_ceiling = false;
881  self.no_powerups = false;
882 }
883 
884 
885 
886 function ‪zombie_emerge_fx(spot)
887 {
888  spot thread ‪zombie_emerge_dust_fx(self);
889  playsoundatposition ("zmb_zombie_spawn", spot.origin);
890  self endon("death");
891  spot endon("stop_zombie_fall_fx");
892  wait 1;
893 }
894 
895 
896 
897 function ‪zombie_emerge_dust_fx(zombie)
898 {
899  dust_tag = "J_SpineUpper";
900 
901  self endon("stop_zombie_fall_dust_fx");
902  self thread ‪stop_zombie_fall_dust_fx(zombie);
903 
904  dust_time = 3.5; // play dust fx for a max time
905  dust_interval = .5; //randomfloatrange(.1,.25); // wait this time in between playing the effect
906 
907  for (t = 0; t < dust_time; t += dust_interval)
908  {
909  PlayfxOnTag(level._effect["rise_dust"], zombie, dust_tag);
910  wait dust_interval;
911  }
912 }
913 
915 {
916  zombie waittill("death");
917  self notify("stop_zombie_fall_dust_fx");
918 }
‪zombie_faller_do_fall
‪function zombie_faller_do_fall()
Definition: _zm_ai_faller.gsc:269
‪zombie_fall_dust_fx
‪function zombie_fall_dust_fx(zombie)
Definition: _zm_ai_faller.gsc:714
‪groundpos_ignore_water_new
‪function groundpos_ignore_water_new(origin)
Definition: _zm_utility.gsc:4590
‪stop_zombie_fall_dust_fx
‪function stop_zombie_fall_dust_fx(zombie)
Definition: _zm_ai_faller.gsc:731
‪DEFAULT_DIST_SQ_VISIBLE
‪#define DEFAULT_DIST_SQ_VISIBLE
Definition: _zm_ai_faller.gsc:24
‪zombie_fall_burst_fx
‪function zombie_fall_burst_fx()
Definition: _zm_ai_faller.gsc:704
‪zombie_fall_should_attack
‪function zombie_fall_should_attack(spot)
Definition: _zm_ai_faller.gsc:564
‪fallerDropActionUpdate
‪function fallerDropActionUpdate(entity, asmStateName)
Definition: _zm_ai_faller.gsc:64
‪BT_REGISTER_API
‪#define BT_REGISTER_API(name, function)
Definition: behavior.gsh:1
‪isFallerInCeiling
‪function isFallerInCeiling(entity)
Definition: _zm_ai_faller.gsc:92
‪timer
‪function timer(n_time, str_endon, x, y, height)
Definition: lui_shared.gsc:163
‪zombie_land
‪function zombie_land()
Definition: _zm_ai_faller.gsc:403
‪get_fall_anim
‪function get_fall_anim(spot)
Definition: _zm_ai_faller.gsc:610
‪zombie_fall_death_func
‪function zombie_fall_death_func(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
Definition: _zm_ai_faller.gsc:637
‪zombie_fall_death
‪function zombie_fall_death(spot)
Definition: _zm_ai_faller.gsc:650
‪fallerDropActionTerminate
‪function fallerDropActionTerminate(entity, asmStateName)
Definition: _zm_ai_faller.gsc:75
‪BHTN_RUNNING
‪#define BHTN_RUNNING
Definition: behavior_tree.gsh:9
‪cointoss
‪function cointoss()
Definition: math_shared.csc:171
‪ASM_REGISTER_NOTETRACK_HANDLER
‪#define ASM_REGISTER_NOTETRACK_HANDLER(notetrackname, handlerfunction)
Definition: animation_state_machine.gsh:4
‪setup_deathfunc
‪function setup_deathfunc(func_name)
Definition: _zm_ai_faller.gsc:164
‪zombie_faller_emerge
‪function zombie_faller_emerge(spot)
Definition: _zm_ai_faller.gsc:862
‪mocompCeilingDeath
‪function private mocompCeilingDeath(entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration)
Definition: _zm_ai_faller.gsc:112
‪zombie_faller_delete
‪function zombie_faller_delete()
Definition: _zm_ai_faller.gsc:120
‪zombie_fall_wait
‪function zombie_fall_wait()
Definition: _zm_ai_faller.gsc:525
‪zombie_faller_watch_all_players
‪function zombie_faller_watch_all_players()
Definition: _zm_ai_faller.gsc:434
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪get_desired_origin
‪function get_desired_origin()
Definition: zombie_utility.gsc:1570
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪AI_ANIM_USE_BOTH_DELTAS_NOGRAVITY
‪#define AI_ANIM_USE_BOTH_DELTAS_NOGRAVITY
Definition: animation_state_machine.gsh:84
‪zombie_faller_always_drop
‪function zombie_faller_always_drop()
Definition: _zm_ai_faller.gsc:412
‪ASM_FALLER_DEATHOUT_NOTETRACK
‪#define ASM_FALLER_DEATHOUT_NOTETRACK
Definition: _zm_ai_faller.gsc:28
‪shouldFallerDrop
‪function shouldFallerDrop(entity)
Definition: _zm_ai_faller.gsc:82
‪reset_attack_spot
‪function reset_attack_spot()
Definition: zombie_utility.gsc:1671
‪InitFallerBehaviorsAndASM
‪function private InitFallerBehaviorsAndASM()
Definition: _zm_ai_faller.gsc:41
‪zombie_faller_enable_location
‪function zombie_faller_enable_location()
Definition: _zm_ai_faller.gsc:615
‪hide_pop
‪function hide_pop()
Definition: zombie_utility.gsc:1593
‪DoNoteTracks
‪function DoNoteTracks(flagName, customFunction, debugIdentifier, var1)
Definition: shared.gsc:387
‪zombie_fall_loop
‪function zombie_fall_loop()
Definition: _zm_ai_faller.gsc:385
‪ASM_REGISTER_MOCOMP
‪#define ASM_REGISTER_MOCOMP(name, initFunction, updateFunction, terminateFunction)
Definition: animation_state_machine.gsh:1
‪FALLER_DIST_SQ_VISIBLE
‪#define FALLER_DIST_SQ_VISIBLE
Definition: _zm_ai_faller.gsc:25
‪wait_network_frame
‪function wait_network_frame(n_count=1)
Definition: util_shared.gsc:64
‪zombie_fall_fx
‪function zombie_fall_fx(spot)
Definition: _zm_ai_faller.gsc:689
‪handle_fall_death_notetracks
‪function handle_fall_death_notetracks(entity)
Definition: _zm_ai_faller.gsc:737
‪AI_ANIM_USE_BOTH_DELTAS_NOCLIP
‪#define AI_ANIM_USE_BOTH_DELTAS_NOCLIP
Definition: animation_state_machine.gsh:83
‪zombie_emerge_dust_fx
‪function zombie_emerge_dust_fx(zombie)
Definition: _zm_ai_faller.gsc:897
‪zombie_emerge_fx
‪function zombie_emerge_fx(spot)
Definition: _zm_ai_faller.gsc:886
‪do_zombie_emerge
‪function do_zombie_emerge(spot)
Definition: _zm_ai_faller.gsc:835
‪_damage_mod_to_damage_type
‪function _damage_mod_to_damage_type(type)
Definition: _zm_ai_faller.gsc:665
‪stop_zombie_emerge_dust_fx
‪function stop_zombie_emerge_dust_fx(zombie)
Definition: _zm_ai_faller.gsc:914
‪zombie_faller_death_wait
‪function zombie_faller_death_wait(endon_notify)
Definition: _zm_ai_faller.gsc:625
‪fallerDropAction
‪function fallerDropAction(entity, asmStateName)
Definition: _zm_ai_faller.gsc:57
‪fallerCeilingDeath
‪function fallerCeilingDeath(entity)
Definition: _zm_ai_faller.gsc:102
‪faller_death_ragdoll
‪function faller_death_ragdoll(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
Definition: _zm_ai_faller.gsc:767
‪BHTN_SUCCESS
‪#define BHTN_SUCCESS
Definition: behavior_tree.gsh:8
‪do_zombie_fall
‪function do_zombie_fall(spot)
Definition: _zm_ai_faller.gsc:188
‪zombie_faller_watch_player
‪function zombie_faller_watch_player(player)
Definition: _zm_ai_faller.gsc:443
‪zombie_fall_get_vicitims
‪function zombie_fall_get_vicitims(spot)
Definition: _zm_ai_faller.gsc:570
‪handle_fall_notetracks
‪function handle_fall_notetracks(entity)
Definition: _zm_ai_faller.gsc:745
‪player_is_in_laststand
‪function player_is_in_laststand()
Definition: laststand_shared.gsc:18
‪potentially_visible
‪function potentially_visible(how_close)
Definition: _zm_ai_faller.gsc:807
‪ASM_FALLER_MELEE_NOTETRACK
‪#define ASM_FALLER_MELEE_NOTETRACK
Definition: _zm_ai_faller.gsc:27
‪faller_script_parameters
‪function faller_script_parameters()
Definition: _zm_ai_faller.gsc:132
‪zombie_death_animscript
‪function zombie_death_animscript(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
Definition: _zm_spawner.gsc:1739
‪RequestState
‪function RequestState(entity, stateName)
Definition: animation_state_machine_utility.gsc:8
‪init
‪function autoexec init()
Definition: _zm_ai_faller.gsc:32
‪BT_REGISTER_ACTION
‪#define BT_REGISTER_ACTION(name, initFunction, updateFunction, terminateFunction)
Definition: behavior.gsh:4
‪in_player_fov
‪function in_player_fov(player)
Definition: _zm_ai_faller.gsc:776
‪mocompFallerDrop
‪function private mocompFallerDrop(entity, mocompAnim, mocompAnimBlendOutTime, mocompAnimFlag, mocompDuration)
Definition: _zm_ai_faller.gsc:107
‪zombie_faller_drop_not_occupied
‪function zombie_faller_drop_not_occupied()
Definition: _zm_ai_faller.gsc:421