‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
zombie_utility.gsc
Go to the documentation of this file.
1 #using scripts\shared\ai_shared;
2 #using scripts\shared\clientfield_shared;
3 #using scripts\shared\flag_shared;
4 #using scripts\shared\fx_shared;
5 #using scripts\shared\math_shared;
6 #using scripts\shared\scene_shared;
7 #using scripts\shared\spawner_shared;
8 #using scripts\shared\util_shared;
9 
10 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
11 #using scripts\shared\array_shared;
12 #using scripts\shared\laststand_shared;
13 #using scripts\shared\ai\zombie_shared;
14 #using scripts\shared\ai\zombie_death;
15 #using scripts\shared\ai\systems\gib;
16 
17 #using scripts\shared\ai\systems\behavior_tree_utility;
18 
19 #insert scripts\shared\shared.gsh;
20 #insert scripts\shared\ai\zombie.gsh;
21 #insert scripts\shared\ai\systems\gib.gsh;
22 #insert scripts\shared\ai\systems\blackboard.gsh;
23 
24 #using scripts\codescripts\struct;
25 
26 #namespace zombie_utility;
27 
29 {
30  self.zombie_move_speed = "walk";
31 
32  if ( !isdefined( self.zombie_arms_position ) )
33  {
34  if(randomint( 2 ) == 0)
35  self.zombie_arms_position = "up";
36  else
37  self.zombie_arms_position = "down";
38  }
39 
40  self.missingLegs = false;
41  self setAvoidanceMask( "avoid none" );
42  self PushActors( true );
43 
45 
46  self.ignorePathEnemyFightDist = true; // prevent sight tracing in Actor_ShouldFaceMotion
47 }
48 
49 function ‪get_closest_valid_player( origin, ignore_player, ignore_laststand_players = false )
50 {
51  PixBeginEvent( "get_closest_valid_player" );
52 
53  valid_player_found = false;
54 
55  targets = GetPlayers();
56 
57  if( isdefined( level.closest_player_targets_override ) )
58  {
59  targets = [[ level.closest_player_targets_override ]]();
60  }
61 
62  if( IsDefined( ignore_player ) )
63  {
64  for(i = 0; i < ignore_player.size; i++ )
65  {
66  ArrayRemoveValue( targets, ignore_player[i] );
67  }
68  }
69 
70  done = true;
71  while ( targets.size && !done )
72  {
73  done = true;
74  for(i = 0; i < targets.size; i++ )
75  {
76  target = targets[i];
77  if( !‪is_player_valid( target, true, ignore_laststand_players ) )
78  {
79  ArrayRemoveValue( targets, target );
80  done = false;
81  break;
82  }
83  }
84  }
85 
86  if( targets.size == 0 )
87  {
88  pixendevent();
89  return undefined;
90  }
91 
92  if( IsDefined( self.closest_player_override ) )
93  {
94  target = [[ self.closest_player_override ]]( origin, targets );
95  }
96  else if( IsDefined( level.closest_player_override ) )
97  {
98  target = [[ level.closest_player_override ]]( origin, targets );
99  }
100 
101  if( IsDefined( target ) )
102  {
103  pixendevent();
104  return target;
105  }
106 
107  sortedPotentialTargets = ArraySortClosest( targets, self.origin );
108 
109  while(sortedPotentialTargets.size)
110  {
111  if( ‪is_player_valid( sortedPotentialTargets[0], true , ignore_laststand_players) )
112  {
113  pixendevent();
114  return sortedPotentialTargets[0];
115  }
116 
117  ArrayRemoveValue( sortedPotentialTargets, sortedPotentialTargets[0] );
118  }
119 
120  pixendevent();
121  return undefined;
122 }
123 
124 function ‪is_player_valid( player, checkIgnoreMeFlag, ignore_laststand_players )
125 {
126  if( !IsDefined( player ) )
127  {
128  return false;
129  }
130 
131  if( !IsAlive( player ) )
132  {
133  return false;
134  }
135 
136  if( !IsPlayer( player ) )
137  {
138  return false;
139  }
140 
141  if( IsDefined(player.is_zombie) && player.is_zombie == true )
142  {
143  return false;
144  }
145 
146  if( player.sessionstate == "spectator" )
147  {
148  return false;
149  }
150 
151  if( player.sessionstate == "intermission" )
152  {
153  return false;
154  }
155 
156  if( ‪IS_TRUE(player.intermission) )
157  {
158  return false;
159  }
160 
161  if(!‪IS_TRUE(ignore_laststand_players))
162  {
164  {
165  return false;
166  }
167  }
168 
169  if ( player IsNoTarget() )
170  {
171  return false;
172  }
173 
174  //We only want to check this from the zombie attack script
175  if( ‪IS_TRUE(checkIgnoreMeFlag) && player.ignoreme )
176  {
177  return false;
178  }
179 
180  //for additional level specific checks
181  if( IsDefined( level.is_player_valid_override ) )
182  {
183  return [[ level.is_player_valid_override ]]( player );
184  }
185 
186  return true;
187 }
188 
189 
190 function ‪append_missing_legs_suffix( animstate )
191 {
192  if ( self.missingLegs && self HasAnimStateFromASD( animstate + "_crawl" ) )
193  {
194  return animstate + "_crawl";
195  }
196 
197  return animstate;
198 }
199 
200 
201 // Every script calls initAnimTree to ensure a clean, fresh, known animtree state.
202 // ClearAnim should never be called directly, and this should never occur other than
203 // at the start of an animscript
204 // This function now also does any initialization for the scripts that needs to happen
205 // at the beginning of every main script.
206 function ‪initAnimTree(animscript)
207 {
208  if ( animscript != "pain" && animscript != "death" )
209  {
210  self.a.special = "none";
211  }
212 
213  assert( IsDefined( animscript ), "Animscript not specified in initAnimTree" );
214  self.a.script = animscript;
215 }
216 
217 // UpdateAnimPose does housekeeping at the start of every script's main function.
219 {
220  assert( self.‪a.movement=="stop" || self.a.movement=="walk" || self.a.movement=="run", "UpdateAnimPose "+self.a.pose+" "+self.a.movement );
221 
222  self.desired_anim_pose = undefined;
223 }
224 
225 function ‪initialize( animscript )
226 {
227  if ( IsDefined( self.longDeathStarting ) )
228  {
229  if ( animscript != "pain" && animscript != "death" )
230  {
231  // we probably just came out of an animcustom.
232  // just die, it's not safe to do anything else
233  self DoDamage( self.health + 100, self.origin );
234  }
235  if ( animscript != "pain" )
236  {
237  self.longDeathStarting = undefined;
238  self notify( "kill_long_death" );
239  }
240  }
241  if ( IsDefined( self.‪a.mayOnlyDie ) && animscript != "death" )
242  {
243  // we probably just came out of an animcustom.
244  // just die, it's not safe to do anything else
245  self DoDamage( self.health + 100, self.origin );
246  }
247 
248  // scripts can define this to allow cleanup before moving on
249  if ( IsDefined( self.‪a.postScriptFunc ) )
250  {
251  scriptFunc = self.a.postScriptFunc;
252  self.a.postScriptFunc = undefined;
253 
254  [[scriptFunc]]( animscript );
255  }
256 
257  if ( animscript != "death" )
258  {
259  self.a.nodeath = false;
260  }
261 
262  self.isHoldingGrenade = undefined;
263 
264  self.coverNode = undefined;
265  self.changingCoverPos = false;
266  self.a.scriptStartTime = GetTime();
267 
268  self.a.atConcealmentNode = false;
269  if ( IsDefined( self.node ) && (self.node.type == "Conceal Crouch" || self.node.type == "Conceal Stand") )
270  {
271  self.a.atConcealmentNode = true;
272  }
273 
274  ‪initAnimTree( animscript );
275 
277 }
278 
280 {
281  if (IsDefined (self.node))
282  {
283  yaw = self.node.angles[1] - ‪GetYaw(pos);
284  }
285  else
286  {
287  yaw = self.angles[1] - ‪GetYaw(pos);
288  }
289 
290  yaw = AngleClamp180( yaw );
291  return yaw;
292 }
293 
295 {
296  pos = undefined;
297  if ( ‪isValidEnemy( self.enemy ) )
298  {
299  pos = self.enemy.origin;
300  }
301  else
302  {
303  if (IsDefined (self.node))
304  {
305  forward = AnglesToForward(self.node.angles);
306  }
307  else
308  {
309  forward = AnglesToForward(self.angles);
310  }
311 
312  forward = VectorScale (forward, 150);
313  pos = self.origin + forward;
314  }
315 
316  if (IsDefined (self.node))
317  {
318  yaw = self.node.angles[1] - ‪GetYaw(pos);
319  }
320  else
321  {
322  yaw = self.angles[1] - ‪GetYaw(pos);
323  }
324 
325  yaw = AngleClamp180( yaw );
326  return yaw;
327 }
328 
330 {
331  pos = undefined;
332  if ( ‪isValidEnemy( self.enemy ) )
333  {
334  pos = self.enemy.origin;
335  }
336  else
337  {
338  forward = AnglesToForward(self.coverNode.angles + self.animarray["angle_step_out"][self.a.cornerMode]);
339  forward = VectorScale (forward, 150);
340  pos = self.origin + forward;
341  }
342 
343  yaw = self.CoverNode.angles[1] + self.animarray["angle_step_out"][self.a.cornerMode] - ‪GetYaw(pos);
344  yaw = AngleClamp180( yaw );
345  return yaw;
346 }
347 
348 function ‪GetYawToSpot(spot)
349 {
350  pos = spot;
351  yaw = self.angles[1] - ‪GetYaw(pos);
352  yaw = AngleClamp180( yaw );
353  return yaw;
354 }
355 // warning! returns (my yaw - yaw to enemy) instead of (yaw to enemy - my yaw)
357 {
358  pos = undefined;
359  if ( ‪isValidEnemy( self.enemy ) )
360  {
361  pos = self.enemy.origin;
362  }
363  else
364  {
365  forward = AnglesToForward(self.angles);
366  forward = VectorScale (forward, 150);
367  pos = self.origin + forward;
368  }
369 
370  yaw = self.angles[1] - ‪GetYaw(pos);
371  yaw = AngleClamp180( yaw );
372  return yaw;
373 }
374 
375 function ‪GetYaw(org)
376 {
377  angles = VectorToAngles(org-self.origin);
378  return angles[1];
379 }
380 
381 function ‪GetYaw2d(org)
382 {
383  angles = VectorToAngles((org[0], org[1], 0)-(self.origin[0], self.origin[1], 0));
384  return angles[1];
385 }
386 
387 // 0 if I'm facing my enemy, 90 if I'm side on, 180 if I'm facing away.
389 {
390  assert( ‪isValidEnemy( self.enemy ) );
391 
392  yaw = self.angles[1] - ‪GetYaw(self.enemy.origin);
393  yaw = AngleClamp180( yaw );
394 
395  if (yaw < 0)
396  {
397  yaw = -1 * yaw;
398  }
399 
400  return yaw;
401 }
402 
403 // 0 if I'm facing my enemy, 90 if I'm side on, 180 if I'm facing away.
405 {
406  assert( ‪isValidEnemy( self.enemy ) );
407 
408  yaw = self.angles[1] - ‪GetYaw2d(self.enemy.origin);
409  yaw = AngleClamp180( yaw );
410 
411  if (yaw < 0)
412  {
413  yaw = -1 * yaw;
414  }
415 
416  return yaw;
417 }
418 
419 // 0 if I'm facing my enemy, 90 if I'm side on, 180 if I'm facing away.
420 function ‪AbsYawToOrigin(org)
421 {
422  yaw = self.angles[1] - ‪GetYaw(org);
423  yaw = AngleClamp180( yaw );
424 
425  if (yaw < 0)
426  {
427  yaw = -1 * yaw;
428  }
429 
430  return yaw;
431 }
432 
433 function ‪AbsYawToAngles(angles)
434 {
435  yaw = self.angles[1] - angles;
436  yaw = AngleClamp180( yaw );
437 
438  if (yaw < 0)
439  {
440  yaw = -1 * yaw;
441  }
442 
443  return yaw;
444 }
445 
446 function ‪GetYawFromOrigin(org, start)
447 {
448  angles = VectorToAngles(org-start);
449  return angles[1];
450 }
451 
452 function ‪GetYawToTag(tag, org)
453 {
454  yaw = self GetTagAngles( tag )[1] - ‪GetYawFromOrigin(org, self GetTagOrigin(tag));
455  yaw = AngleClamp180( yaw );
456  return yaw;
457 }
458 
459 function ‪GetYawToOrigin(org)
460 {
461  yaw = self.angles[1] - ‪GetYaw(org);
462  yaw = AngleClamp180( yaw );
463  return yaw;
464 }
465 
466 function ‪GetEyeYawToOrigin(org)
467 {
468  yaw = self GetTagAngles("TAG_EYE")[1] - ‪GetYaw(org);
469  yaw = AngleClamp180( yaw );
470  return yaw;
471 }
472 
474 {
475  yaw = self.coverNode.angles[1] + self.animarray["angle_step_out"][self.a.cornerMode] - ‪GetYaw(org);
476  yaw = AngleClamp180( yaw );
477  return yaw;
478 }
479 
480 
481 function ‪isStanceAllowedWrapper( stance )
482 {
483  if ( IsDefined( self.coverNode ) )
484  {
485  return self.coverNode ‪doesNodeAllowStance( stance );
486  }
487 
488  return self IsStanceAllowed( stance );
489 }
490 
491 
493 {
494  myNode = self.node;
495  if ( IsDefined(myNode) && (self nearNode(myNode) || (IsDefined( self.coverNode ) && myNode == self.coverNode)) )
496  {
497  return myNode;
498  }
499 
500  return undefined;
501 }
502 
503 function ‪GetNodeType()
504 {
505  myNode = ‪GetClaimedNode();
506  if (IsDefined(myNode))
507  {
508  return myNode.type;
509  }
510 
511  return "none";
512 }
513 
515 {
516  myNode = ‪GetClaimedNode();
517  if (IsDefined(myNode))
518  {
519  //thread [[anim.println]]("GetNodeDirection found node, returned: "+myNode.angles[1]);#/
520  return myNode.angles[1];
521  }
522  //thread [[anim.println]]("GetNodeDirection didn't find node, returned: "+self.desiredAngle);#/
523  return self.desiredAngle;
524 }
525 
527 {
528  myNode = ‪GetClaimedNode();
529  if (IsDefined(myNode))
530  {
531  return AnglesToForward ( myNode.angles );
532  }
533 
534  return AnglesToForward( self.angles );
535 }
536 
538 {
539  myNode = ‪GetClaimedNode();
540  if (IsDefined(myNode))
541  {
542  return myNode.origin;
543  }
544 
545  return self.origin;
546 }
547 
548 function ‪safemod(‪a,b)
549 {
550  /*
551  Here are some modulus results from in-game:
552  10 % 3 = 1
553  10 % -3 = 1
554  -10 % 3 = -1
555  -10 % -3 = -1
556  however, we never want a negative result.
557  */
558  ‪result = int(‪a) % b;
559  ‪result += b;
560  return ‪result % b;
561 }
562 
563 // Gives the result as an angle between 0 and 360
564 function ‪AngleClamp( angle )
565 {
566  angleFrac = angle / 360.0;
567  angle = (angleFrac - floor( angleFrac )) * 360.0;
568  return angle;
569 }
570 
571 // Returns an array of 4 weights (2 of which are guaranteed to be 0), which should be applied to forward,
572 // right, back and left animations to get the angle specified.
573 // front
574 // /----|----\
575 // / 180 \
576 // /\ | /\
577 // / -135 | 135 \
578 // | \ | / |
579 // left|-90----+----90-|right
580 // | / | \ |
581 // \ -45 | 45 /
582 // \/ | \/
583 // \ 0 /
584 // \----|----/
585 // back
586 
587 function ‪QuadrantAnimWeights( yaw )
588 {
589  // ALEXP 6/26/09: I don't understand why they'd want trig interpolation between angles instead of linear
590  //forwardWeight = cos( yaw );
591  //leftWeight = sin( yaw );
592 
593  forwardWeight = (90 - abs(yaw)) / 90;
594  leftWeight = (90 - AbsAngleClamp180(abs(yaw-90))) / 90;
595 
596  ‪result["front"] = 0;
597  ‪result["right"] = 0;
598  ‪result["back"] = 0;
599  ‪result["left"] = 0;
600 
601  if ( IsDefined( self.alwaysRunForward ) )
602  {
603  assert( self.alwaysRunForward ); // always set alwaysRunForward to either true or undefined.
604 
605  ‪result["front"] = 1;
606  return ‪result;
607  }
608 
609  useLeans = GetDvarInt( "ai_useLeanRunAnimations");
610 
611  if (forwardWeight > 0)
612  {
613  ‪result["front"] = forwardWeight;
614 
615  if (leftWeight > 0)
616  {
617  ‪result["left"] = leftWeight;
618  }
619  else
620  {
621  ‪result["right"] = -1 * leftWeight;
622  }
623  }
624  else if( useLeans )
625  {
626  ‪result["back"] = -1 * forwardWeight;
627  if (leftWeight > 0)
628  {
629  ‪result["left"] = leftWeight;
630  }
631  else
632  {
633  ‪result["right"] = -1 * leftWeight;
634  }
635  }
636  else //cod4 back strafe
637  {
638  // if moving backwards, don't blend.
639  // it looks horrible because the feet cycle in the opposite direction.
640  // either way, feet slide, but this looks better.
641  backWeight = -1 * forwardWeight;
642  if ( leftWeight > backWeight )
643  {
644  ‪result["left"] = 1;
645  }
646  else if ( leftWeight < forwardWeight )
647  {
648  ‪result["right"] = 1;
649  }
650  else
651  {
652  ‪result["back"] = 1;
653  }
654  }
655 
656 
657  return ‪result;
658 }
659 
660 function ‪getQuadrant(angle)
661 {
662  angle = ‪AngleClamp(angle);
663 
664  if (angle<45 || angle>315)
665  {
666  quadrant = "front";
667  }
668  else if (angle<135)
669  {
670  quadrant = "left";
671  }
672  else if (angle<225)
673  {
674  quadrant = "back";
675  }
676  else
677  {
678  quadrant = "right";
679  }
680  return quadrant;
681 }
682 
683 
684 // Checks to see if the input is equal to any of up to ten other inputs.
685 function ‪IsInSet(input, ‪set)
686 {
687  for (i = ‪set.size - 1; i >= 0; i--)
688  {
689  if (input == ‪set[i])
690  {
691  return true;
692  }
693  }
694 
695  return false;
696 }
697 
698 function ‪NotifyAfterTime(notifyString, killmestring, time)
699 {
700  self endon("death");
701  self endon(killmestring);
702  wait time;
703  self notify (notifyString);
704 }
705 
706 function ‪drawStringTime(msg, org, color, ‪timer)
707 {
708  /#
709  maxtime = ‪timer*20;
710  for (i=0;i<maxtime;i++)
711  {
712  Print3d (org, msg, color, 1, 1);
713  wait .05;
714  }
715  #/
716 }
717 
718 function ‪showLastEnemySightPos(string)
719 {
720  /#
721  self notify ("got known enemy2");
722  self endon ("got known enemy2");
723  self endon ("death");
724 
725  if ( !‪isValidEnemy( self.enemy ) )
726  {
727  return;
728  }
729 
730  if (self.enemy.team == "allies")
731  {
732  color = (0.4, 0.7, 1);
733  }
734  else
735  {
736  color = (1, 0.7, 0.4);
737  }
738 
739  while (1)
740  {
742 
743  if (!IsDefined (self.lastEnemySightPos))
744  {
745  continue;
746  }
747 
748  Print3d (self.lastEnemySightPos, string, color, 1, 2.15); // origin, text, RGB, alpha, scale
749  }
750  #/
751 }
752 
753 function ‪debugTimeout()
754 {
755  wait(5);
756  self notify ("timeout");
757 }
758 
759 function ‪debugPosInternal( org, string, size )
760 {
761  /#
762  self endon ("death");
763  self notify ("stop debug " + org);
764  self endon ("stop debug " + org);
765 
766  ent = SpawnStruct();
767  ent thread ‪debugTimeout();
768  ent endon ("timeout");
769 
770  if (self.enemy.team == "allies")
771  {
772  color = (0.4, 0.7, 1);
773  }
774  else
775  {
776  color = (1, 0.7, 0.4);
777  }
778 
779  while (1)
780  {
782  Print3d (org, string, color, 1, size); // origin, text, RGB, alpha, scale
783  }
784  #/
785 }
786 
787 function ‪debugPos( org, string )
788 {
789  thread ‪debugPosInternal( org, string, 2.15 );
790 }
791 
792 function ‪debugPosSize( org, string, size )
793 {
794  thread ‪debugPosInternal( org, string, size );
795 }
796 
797 function ‪showDebugProc(fromPoint, toPoint, color, printTime)
798 {
799  /#
800  self endon ("death");
801 // self notify ("stop debugline " + self.export);
802 // self endon ("stop debugline " + self.export);
803 
804  ‪timer = printTime*20;
805  for (i=0;i<‪timer;i+=1)
806  {
808  line (fromPoint, toPoint, color);
809  }
810  #/
811 }
812 
813 function ‪showDebugLine( fromPoint, toPoint, color, printTime )
814 {
815  self thread ‪showDebugProc( fromPoint, toPoint +( 0, 0, -5 ), color, printTime );
816 }
817 
818 function ‪getNodeOffset(node)
819 {
820  if ( IsDefined( node.offset ) )
821  {
822  return node.offset;
823  }
824 
825  //(right offset, forward offset, vertical offset)
826  // you can get an actor's current eye offset by setting scr_eyeoffset to his entnum.
827  // this should be redone whenever animations change significantly.
828  cover_left_crouch_offset = (-26, .4, 36);
829  cover_left_stand_offset = (-32, 7, 63);
830  cover_right_crouch_offset = (43.5, 11, 36);
831  cover_right_stand_offset = (36, 8.3, 63);
832  cover_crouch_offset = (3.5, -12.5, 45); // maybe we could account for the fact that in cover crouch he can stand if he needs to?
833  cover_stand_offset = (-3.7, -22, 63);
834 
835  cornernode = false;
836  nodeOffset = (0,0,0);
837 
838  right = AnglesToRight(node.angles);
839  forward = AnglesToForward(node.angles);
840 
841  switch(node.type)
842  {
843  case "Cover Left":
844  case "Cover Left Wide":
845  if ( node ‪isNodeDontStand() && !node ‪isNodeDontCrouch() )
846  {
847  nodeOffset = ‪calculateNodeOffset( right, forward, cover_left_crouch_offset );
848  }
849  else
850  {
851  nodeOffset = ‪calculateNodeOffset( right, forward, cover_left_stand_offset );
852  }
853  break;
854 
855  case "Cover Right":
856  case "Cover Right Wide":
857  if ( node ‪isNodeDontStand() && !node ‪isNodeDontCrouch() )
858  {
859  nodeOffset = ‪calculateNodeOffset( right, forward, cover_right_crouch_offset );
860  }
861  else
862  {
863  nodeOffset = ‪calculateNodeOffset( right, forward, cover_right_stand_offset );
864  }
865  break;
866 
867  case "Cover Stand":
868  case "Conceal Stand":
869  case "Turret":
870  nodeOffset = ‪calculateNodeOffset( right, forward, cover_stand_offset );
871  break;
872 
873  case "Cover Crouch":
874  case "Cover Crouch Window":
875  case "Conceal Crouch":
876  nodeOffset = ‪calculateNodeOffset( right, forward, cover_crouch_offset );
877  break;
878  }
879 
880  node.offset = nodeOffset;
881  return node.offset;
882 }
883 
884 function ‪calculateNodeOffset( right, forward, baseoffset )
885 {
886  return VectorScale( right, baseoffset[0] ) + VectorScale( forward, baseoffset[1] ) + (0, 0, baseoffset[2]);
887 }
888 
889 function ‪checkPitchVisibility( fromPoint, toPoint, atNode )
890 {
891  // check vertical angle is within our aiming abilities
892 
893  pitch = AngleClamp180( VectorToAngles( toPoint - fromPoint )[0] );
894  if ( abs( pitch ) > 45 )
895  {
896  if ( IsDefined( atNode ) && atNode.type != "Cover Crouch" && atNode.type != "Conceal Crouch" )
897  {
898  return false;
899  }
900 
901  if ( pitch > 45 || pitch < anim.coverCrouchLeanPitch - 45 )
902  {
903  return false;
904  }
905  }
906  return true;
907 }
908 
909 function ‪showLines(start, ‪end, end2)
910 {
911  /#
912  for (;;)
913  {
914  line(start, ‪end, (1,0,0), 1);
916  line(start, end2, (0,0,1), 1);
918  }
919  #/
920 }
921 
922 // Returns an animation from an array of animations with a corresponding array of weights.
923 function ‪anim_array(‪animArray, animWeights)
924 {
925  total_anims = ‪animArray.size;
926  idleanim = RandomInt(total_anims);
927 
928  assert (total_anims);
929  assert (‪animArray.size == animWeights.size);
930 
931  if (total_anims == 1)
932  {
933  return ‪animArray[0];
934  }
935 
936  weights = 0;
937  total_weight = 0;
938 
939  for (i = 0; i < total_anims; i++)
940  {
941  total_weight += animWeights[i];
942  }
943 
944  anim_play = RandomFloat(total_weight);
945  current_weight = 0;
946 
947  for (i = 0; i < total_anims; i++)
948  {
949  current_weight += animWeights[i];
950  if (anim_play >= current_weight)
951  {
952  continue;
953  }
954 
955  idleanim = i;
956  break;
957  }
958 
959  return ‪animArray[idleanim];
960 }
961 
963 {
964  return ((self.‪a.forced_cover == "none") || (self.a.forced_cover == "Show"));
965 }
966 
967 function ‪forcedCover(msg)
968 {
969  return IsDefined(self.‪a.forced_cover) && (self.a.forced_cover == msg);
970 }
971 
972 function ‪print3dtime(‪timer, org, msg, color, alpha, scale)
973 {
974  /#
975  newtime = ‪timer / 0.05;
976  for (i=0;i<newtime;i++)
977  {
978  Print3d (org, msg, color, alpha, scale);
980  }
981  #/
982 }
983 
984 function ‪print3drise (org, msg, color, alpha, scale)
985 {
986  /#
987  newtime = 5 / 0.05;
988  up = 0;
989  org = org;
990 
991  for (i=0;i<newtime;i++)
992  {
993  up+=0.5;
994  Print3d (org + (0,0,up), msg, color, alpha, scale);
996  }
997  #/
998 }
999 
1000 function ‪crossproduct (vec1, vec2)
1001 {
1002  return (vec1[0]*vec2[1] - vec1[1]*vec2[0] > 0);
1003 }
1004 
1006 {
1007  self.a.current_script = "none";
1008  self notify (anim.scriptChange);
1009 }
1010 
1012 {
1014  ‪scriptChange();
1015 }
1016 
1018 {
1019  if (!IsDefined(‪timer))
1020  {
1021  ‪timer = 500;
1022  }
1023 
1024  return (GetTime() - self.personalSightTime < ‪timer);
1025 }
1026 
1028 {
1029  if (!self.grenadeAmmo)
1030  {
1031  return false;
1032  }
1033 
1034  if (self.script_forceGrenade)
1035  {
1036  return true;
1037  }
1038 
1039  return (IsPlayer(self.enemy));
1040 }
1041 
1043 {
1044  idleanim = RandomInt (‪array.size);
1045  if (‪array.size > 1)
1046  {
1047  anim_weight = 0;
1048  for (i=0;i<‪array.size;i++)
1049  {
1050  anim_weight += ‪array[i];
1051  }
1052 
1053  anim_play = RandomFloat (anim_weight);
1054 
1055  anim_weight = 0;
1056  for (i=0;i<‪array.size;i++)
1057  {
1058  anim_weight += ‪array[i];
1059  if (anim_play < anim_weight)
1060  {
1061  idleanim = i;
1062  break;
1063  }
1064  }
1065  }
1066 
1067  return idleanim;
1068 }
1069 
1071 {
1072  assert(IsDefined(‪name), "Need to define the footstep surface type.");
1073  assert(IsDefined(fx), "Need to define the mud footstep effect.");
1074 
1075  if (!IsDefined(anim.optionalStepEffects))
1076  {
1077  anim.optionalStepEffects = [];
1078  }
1079 
1080  anim.optionalStepEffects[anim.optionalStepEffects.size] = ‪name;
1081  level._effect["step_" + ‪name] = fx;
1082  anim.optionalStepEffectFunction = &‪zombie_shared::playFootStepEffect;
1083 }
1084 
1086 {
1087  /#
1088  self endon ("death");
1089  level notify ("newdebugline");
1090  level endon ("newdebugline");
1091 
1092  for (;;)
1093  {
1094  line (start,‪end, (0.3,1,0), 1);
1096  }
1097  #/
1098 }
1099 
1101 {
1102  return (self.spawnflags & 4) == 4;
1103 }
1105 {
1106  return (self.spawnflags & 8) == 8;
1107 }
1108 
1109 function ‪doesNodeAllowStance( stance )
1110 {
1111  if ( stance == "stand" )
1112  {
1113  return !self ‪isNodeDontStand();
1114  }
1115  else
1116  {
1117  Assert( stance == "crouch" );
1118  return !self ‪isNodeDontCrouch();
1119  }
1120 }
1121 
1122 function ‪animArray( animname ) /* string */
1123 {
1124  //println( "playing anim: ", animname );
1125 
1126  assert( IsDefined(self.‪a.array) );
1127 
1128  /#
1129  if ( !IsDefined(self.‪a.array[animname]) )
1130  {
1131  ‪dumpAnimArray();
1132  assert( IsDefined(self.‪a.array[animname]), "self.a.array[ \"" + animname + "\" ] is undefined" );
1133  }
1134  #/
1135 
1136  return self.a.array[animname];
1137 }
1138 
1139 function ‪animArrayAnyExist( animname )
1140 {
1141  assert( IsDefined( self.‪a.array ) );
1142 
1143  /#
1144  if ( !IsDefined(self.‪a.array[animname]) )
1145  {
1146  ‪dumpAnimArray();
1147  assert( IsDefined(self.‪a.array[animname]), "self.a.array[ \"" + animname + "\" ] is undefined" );
1148  }
1149  #/
1150 
1151  return self.a.array[animname].size > 0;
1152 }
1153 
1154 function ‪animArrayPickRandom( animname )
1155 {
1156  assert( IsDefined( self.‪a.array ) );
1157 
1158  /#
1159  if ( !IsDefined(self.‪a.array[animname]) )
1160  {
1161  ‪dumpAnimArray();
1162  assert( IsDefined(self.‪a.array[animname]), "self.a.array[ \"" + animname + "\" ] is undefined" );
1163  }
1164  #/
1165 
1166  assert( self.‪a.array[animname].size > 0 );
1167 
1168  if ( self.‪a.array[animname].size > 1 )
1169  {
1170  index = RandomInt( self.‪a.array[animname].size );
1171  }
1172  else
1173  {
1174  index = 0;
1175  }
1176 
1177  return self.a.array[animname][index];
1178 }
1179 
1180 /#
1182 {
1183  println("self.a.array:");
1184  keys = getArrayKeys( self.‪a.array );
1185 
1186  for ( i=0; i < keys.size; i++ )
1187  {
1188  if ( isarray( self.‪a.array[ keys[i] ] ) )
1189  {
1190  println( " array[ \"" + keys[i] + "\" ] = {array of size " + self.‪a.array[ keys[i] ].size + "}" );
1191  }
1192  else
1193  {
1194  println( " array[ \"" + keys[i] + "\" ] = ", self.‪a.array[ keys[i] ] );
1195  }
1196  }
1197 }
1198 #/
1199 
1200 function ‪getAnimEndPos( theanim )
1201 {
1202  moveDelta = getMoveDelta( theanim, 0, 1, self );
1203  return self localToWorldCoords( moveDelta );
1204 }
1205 
1206 function ‪isValidEnemy( enemy )
1207 {
1208  if ( !IsDefined( enemy ) )
1209  {
1210  return false;
1211  }
1212 
1213  return true;
1214 }
1215 
1216 
1217 function ‪damageLocationIsAny( ‪a, b, c, d, e, f, g, h, i, j, k, ovr )
1218 {
1219  /* possibile self.damageLocation's:
1220  "torso_upper"
1221  "torso_lower"
1222  "helmet"
1223  "head"
1224  "neck"
1225  "left_arm_upper"
1226  "left_arm_lower"
1227  "left_hand"
1228  "right_arm_upper"
1229  "right_arm_lower"
1230  "right_hand"
1231  "gun"
1232  "none"
1233  "left_leg_upper"
1234  "left_leg_lower"
1235  "left_foot"
1236  "right_leg_upper"
1237  "right_leg_lower"
1238  "right_foot"
1239  */
1240  if(!isDefined(self.damageLocation))
1241  return false;
1242 
1243  if ( !IsDefined( ‪a ) ) return false; if ( self.damageLocation == ‪a ) return true;
1244  if ( !IsDefined( b ) ) return false; if ( self.damageLocation == b ) return true;
1245  if ( !IsDefined( c ) ) return false; if ( self.damageLocation == c ) return true;
1246  if ( !IsDefined( d ) ) return false; if ( self.damageLocation == d ) return true;
1247  if ( !IsDefined( e ) ) return false; if ( self.damageLocation == e ) return true;
1248  if ( !IsDefined( f ) ) return false; if ( self.damageLocation == f ) return true;
1249  if ( !IsDefined( g ) ) return false; if ( self.damageLocation == g ) return true;
1250  if( !IsDefined( h ) ) return false; if( self.damageLocation == h ) return true;
1251  if( !IsDefined( i ) ) return false; if( self.damageLocation == i ) return true;
1252  if( !IsDefined( j ) ) return false; if( self.damageLocation == j ) return true;
1253  if( !IsDefined( k ) ) return false; if( self.damageLocation == k ) return true;
1254  assert(!IsDefined(ovr));
1255  return false;
1256 }
1257 
1258 function ‪ragdollDeath( moveAnim )
1259 {
1260  self endon ( "killanimscript" );
1261 
1262  lastOrg = self.origin;
1263  moveVec = (0,0,0);
1264 
1265  for ( ;; )
1266  {
1268  force = distance( self.origin, lastOrg );
1269  lastOrg = self.origin;
1270 
1271  if ( self.health == 1 )
1272  {
1273  self.a.nodeath = true;
1274  self startRagdoll();
1275 
1277  physicsExplosionSphere( lastOrg, 600, 0, force * 0.1 );
1278  self notify ( "killanimscript" );
1279  return;
1280  }
1281  }
1282 }
1283 
1285 {
1286  return IsDefined( self.cqbwalking ) && self.cqbwalking;
1287 }
1288 
1289 function ‪squared( value )
1290 {
1291  return value * value;
1292 }
1293 
1295 {
1296  self.a.idleSet = RandomInt( 2 );
1297 }
1298 
1299 // meant to be used with any integer seed, for a small integer maximum (ideally one that divides anim.randomIntTableSize)
1300 function ‪getRandomIntFromSeed( intSeed, intMax )
1301 {
1302  assert( intMax > 0 );
1303 
1304  index = intSeed % anim.randomIntTableSize;
1305  return anim.randomIntTable[ index ] % intMax;
1306 }
1307 
1308 // MikeD (1/24/2008): Added Banzai Feature.
1309 function ‪is_banzai()
1310 {
1311  return IsDefined( self.banzai ) && self.banzai;
1312 }
1313 
1314 // SCRIPTER_MOD: JesseS (4/16/2008): HMG guys have their own anims
1316 {
1317  return IsDefined( self.heavy_machine_gunner ) && self.heavy_machine_gunner;
1318 }
1319 
1320 function ‪is_zombie()
1321 {
1322  if (IsDefined(self.‪is_zombie) && self.‪is_zombie)
1323  {
1324  return true;
1325  }
1326 
1327  return false;
1328 }
1329 
1330 
1331 function ‪is_civilian()
1332 {
1333  if (IsDefined(self.‪is_civilian) && self.‪is_civilian)
1334  {
1335  return true;
1336  }
1337 
1338  return false;
1339 }
1340 
1341 function ‪is_skeleton(skeleton)
1342 {
1343  if ((skeleton == "base") && IsSubStr(‪get_skeleton(), "scaled"))
1344  {
1345  // Scaled skeletons should identify as "base" as well
1346  return true;
1347  }
1348 
1349  return (‪get_skeleton() == skeleton);
1350 }
1351 
1353 {
1354  if (IsDefined(self.skeleton))
1355  {
1356  return self.skeleton;
1357  }
1358  else
1359  {
1360  return "base";
1361  }
1362 }
1363 
1364 function ‪set_orient_mode( mode, val1 )
1365 {
1366 /#
1367  if ( level.dog_debug_orient == self getentnum() )
1368  {
1369  if ( IsDefined( val1 ) )
1370  println( "DOG: Setting orient mode: " + mode + " " + val1 + " " + getTime() );
1371  else
1372  println( "DOG: Setting orient mode: " + mode + " " + getTime() );
1373  }
1374 #/
1375 
1376  if ( IsDefined( val1 ) )
1377  self OrientMode( mode, val1 );
1378  else
1379  self OrientMode( mode );
1380 }
1381 
1382 function ‪debug_anim_print( text )
1383 {
1384 /#
1385  if ( IsDefined( level.dog_debug_anims ) && level.dog_debug_anims )
1386  println( text+ " " + getTime() );
1387 
1388  if ( IsDefined( level.dog_debug_anims_ent ) && level.dog_debug_anims_ent == self getentnum() )
1389  println( text+ " " + getTime() );
1390 #/
1391 }
1392 
1393 function ‪debug_turn_print( text, line )
1394 {
1395 /#
1396  if ( IsDefined( level.dog_debug_turns ) && level.dog_debug_turns == self getentnum() )
1397  {
1398  duration = 200;
1399  currentYawColor = (1,1,1);
1400  lookaheadYawColor = (1,0,0);
1401  desiredYawColor = (1,1,0);
1402 
1403  currentYaw = AngleClamp180(self.angles[1]);
1404  desiredYaw = AngleClamp180(self.desiredangle);
1405  lookaheadDir = self.lookaheaddir;
1406  lookaheadAngles = vectortoangles(lookaheadDir);
1407  lookaheadYaw = AngleClamp180(lookaheadAngles[1]);
1408  println( text+ " " + getTime() + " cur: " + currentYaw + " look: " + lookaheadYaw + " desired: " + desiredYaw );
1409  }
1410 #/
1411 }
1412 
1414 {
1415 /#
1416  return ( ‪anim_get_dvar_int( "debug_dog_allow_combat", "1" ) );
1417 #/
1418 
1419  return true;
1420 }
1421 
1423 {
1424 /#
1425  return ( ‪anim_get_dvar_int( "debug_dog_allow_movement", "1" ) );
1426 #/
1427 
1428  return true;
1429 }
1430 
1431 //--------------------------------------------------------------------------------------------------
1432 // FUNCTIONS MOVED TO SHARED UTILITY FROM CP (_ZM_UTILITY)
1433 //--------------------------------------------------------------------------------------------------
1434 function ‪set_zombie_var( zvar, value, is_float = false, column = 1, is_team_based = false )
1435 {
1436  ‪DEFAULT(level.zombie_vars,[]);
1437 
1438  if ( is_team_based )
1439  {
1440  foreach( team in level.teams )
1441  {
1442  ‪DEFAULT(level.zombie_vars[team],[]);
1443  level.zombie_vars[ team ][ zvar ] = value;
1444  }
1445  }
1446  else
1447  {
1448  level.zombie_vars[zvar] = value;
1449  }
1450 
1451  return value;
1452 }
1453 
1454 function ‪spawn_zombie( spawner,target_name,spawn_point,round_number)
1455 {
1456  if( !IsDefined( spawner ) )
1457  {
1458  /# println( "ZM >> spawn_zombie - NO SPAWNER DEFINED" ); #/
1459  return undefined;
1460  }
1461 
1462  while ( GetFreeActorCount() < 1 )
1463  {
1465  }
1466 
1467  spawner.script_moveoverride = true;
1468 
1469  if( ‪IS_TRUE(spawner.script_forcespawn ))
1470  {
1471  if(‪IS_BONUSZM)
1472  guy = spawner ‪spawner::spawn( true );
1473  else if( IsActorSpawner( spawner ) && IsDefined( level.overrideZombieSpawn ) )
1474  {
1475  guy = [[level.overrideZombieSpawn]]();
1476  }
1477  else
1478  {
1479  guy = spawner SpawnFromSpawner( 0, true );
1480  }
1481 
1482  if( !‪zombie_spawn_failed( guy ) )
1483  {
1484 
1485  guy.spawn_time = GetTime(); // Time at spawning
1486 
1487  if ( isdefined( level.giveExtraZombies ) )
1488  {
1489  guy [[level.giveExtraZombies]]();
1490  }
1491 
1492  guy EnableAimAssist();
1493 
1494  if(IsDefined(round_number))
1495  {
1496  guy._starting_round_number = round_number;
1497  }
1498 
1499  //guy.type = "zombie";
1500  guy.team = level.zombie_team;
1501  if( IsActor( guy ) )
1502  guy ClearEntityOwner();
1503  level.zombieMeleePlayerCounter = 0;
1504 
1505  if( IsActor( guy ) )
1506  guy forceteleport( spawner.origin );
1507 
1508 
1509  guy show();
1510 
1511  spawner.count = 666;
1512 
1513  if( IsDefined( target_name ) )
1514  {
1515  guy.targetname = target_name;
1516  }
1517 
1518  if(IsDefined(spawn_point) && IsDefined(level.move_spawn_func))
1519  {
1520  guy thread [[level.move_spawn_func]](spawn_point);
1521  }
1522 
1523  /#
1524  if( IsDefined( spawner.zm_variant_type ) )
1525  {
1526  guy.variant_type = spawner.zm_variant_type;
1527  }
1528  #/
1529 
1530  return guy;
1531  }
1532  else
1533  {
1534  /# println( "ZM >> spawn_zombie - FAILED TO SPAWN A ZOMBIE FROM SPAWNER AT ", spawner.origin ); #/
1535  return undefined;
1536  }
1537  }
1538  else
1539  {
1540  /# println( "ZM >> spawn_zombie - ZOMBIE SPAWNER MUST BE SET FORCESPAWN", spawner.origin ); #/
1541  return undefined;
1542  }
1543 
1544  return undefined;
1545 }
1546 
1554 {
1555  if ( IsDefined(‪spawn) && IsAlive(‪spawn) )
1556  {
1557  if ( IsAlive(‪spawn) )
1558  {
1559  return false;
1560  }
1561  }
1562 
1563  return true;
1564 }
1565 
1566 
1567 //--------------------------------------------------------------------------------------------------
1568 // FUNCTIONS MOVED TO SHARED UTILITY FROM CP (_ZM_SPAWNER)
1569 //--------------------------------------------------------------------------------------------------
1571 {
1572  if( IsDefined( self.target ) )
1573  {
1574  ent = GetEnt( self.target, "targetname" );
1575  if( !IsDefined( ent ) )
1576  {
1577  ent = ‪struct::get( self.target, "targetname" );
1578  }
1579 
1580  if( !IsDefined( ent ) )
1581  {
1582  ent = GetNode( self.target, "targetname" );
1583  }
1584 
1585  assert( IsDefined( ent ), "Cannot find the targeted ent/node/struct, \"" + self.target + "\" at " + self.origin );
1586 
1587  return ent.origin;
1588  }
1589 
1590  return undefined;
1591 }
1592 
1593 function ‪hide_pop()
1594 {
1595  self endon( "death" );
1596 
1597  self Ghost();
1598 
1599  wait( 0.5 );
1600  if ( IsDefined( self ) )
1601  {
1602  self Show();
1604  if(IsDefined(self))
1605  {
1606  self.create_eyes = true;
1607  }
1608  }
1609 }
1610 
1611 function ‪handle_rise_notetracks(note, spot)
1612 {
1613  self thread ‪finish_rise_notetracks(note, spot);
1614 }
1615 
1616 function ‪finish_rise_notetracks(note, spot)
1617 {
1618  // the anim notetracks control which death anim to play
1619  // default to "deathin" (still in the ground)
1620 
1621  if (note == "deathout" || note == "deathhigh")
1622  {
1623  self.zombie_rise_death_out = true;
1624  self notify("zombie_rise_death_out");
1625 
1626  wait 2;
1627  spot notify("stop_zombie_rise_fx");
1628  }
1629 }
1630 
1631 /*
1632 function zombie_rise_death:
1633 function Track when the zombie should die, set the death anim, and stop the animscripted so he can die
1634 */
1635 function ‪zombie_rise_death(zombie, spot)
1636 {
1637  //self.nodeathragdoll = true;
1638  zombie.zombie_rise_death_out = false;
1639 
1640  zombie endon("rise_anim_finished");
1641 
1642  while ( IsDefined( zombie ) && IsDefined( zombie.health ) && zombie.health > 1) // health will only go down to 1 when playing animation with AnimScripted()
1643  {
1644  zombie waittill("damage", amount);
1645  }
1646 
1647  if( IsDefined(spot) )
1648  {
1649  spot notify("stop_zombie_rise_fx");
1650  }
1651 
1652  if ( IsDefined( zombie ) )
1653  {
1654  zombie.deathanim = zombie ‪get_rise_death_anim();
1655  zombie StopAnimScripted(); // stop the anim so the zombie can die. death anim is handled by the anim scripts.
1656  }
1657 }
1658 
1660 {
1661  if ( self.zombie_rise_death_out )
1662  {
1663  return "zm_rise_death_out";
1664  }
1665 
1666  self.noragdoll = true;
1667  self.nodeathragdoll = true;
1668  return "zm_rise_death_in";
1669 }
1670 
1672 {
1673  if( IsDefined( self.attacking_node ) )
1674  {
1675  node = self.attacking_node;
1676  index = self.attacking_spot_index;
1677  node.attack_spots_taken[index] = false;
1678 
1679  self.attacking_node = undefined;
1680  self.attacking_spot_index = undefined;
1681  }
1682 }
1683 
1685 {
1686  self.guts_explosion=1;
1687 
1689 }
1690 
1691 //--------------------------------------------------------------------------------------------------
1692 // ZOMBIE EYE GLOWS
1693 //--------------------------------------------------------------------------------------------------
1694 /*
1695 function delayed_zombie_eye_glow:
1696 function Fixes problem where zombies that climb out of the ground are warped to their start positions
1697 function and their eyes glowed above the ground for a split second before their animation started even
1698 function though the zombie model is hidden. and applying this delay to all the zombies doesn't really matter.
1699 */
1701 {
1702  self endon("zombie_delete");
1703  self endon("death");
1704 
1705  if ( ‪IS_TRUE( self.in_the_ground ) || ‪IS_TRUE( self.in_the_ceiling ) )
1706  {
1707  while(!IsDefined(self.create_eyes))
1708  {
1709  wait(0.1);
1710  }
1711  }
1712  else
1713  {
1714  wait .5;
1715  }
1716  self ‪zombie_eye_glow();
1717 }
1718 
1719 // When a Zombie spawns, set his eyes to glowing.
1721 {
1722  if(!IsDefined(self) || !IsActor( self ))
1723  {
1724  return;
1725  }
1726  if ( !IsDefined( self.no_eye_glow ) || !self.no_eye_glow )
1727  {
1728  self ‪clientfield::set("zombie_has_eyes", 1);
1729  }
1730 }
1731 
1732 // Called when either the Zombie dies or if his head gets blown off
1734 {
1735  if(!IsDefined(self) || !IsActor( self ))
1736  {
1737  return;
1738  }
1739  if ( !IsDefined( self.no_eye_glow ) || !self.no_eye_glow )
1740  {
1741  self ‪clientfield::set("zombie_has_eyes", 0);
1742  }
1743 }
1744 
1745 
1746 
1747 
1748 //--------------------------------------------------------------------------------------------------
1749 // ZOMBIE ROUND FUNCTIONALITY
1750 //--------------------------------------------------------------------------------------------------
1751 //put the conditions in here which should
1752 //cause the failsafe to reset
1754 {
1755  self endon("death");//guy just died
1756 
1758  //FAILSAFE "hack shit" DT#33203
1760  prevorigin = self.origin;
1761  while(1)
1762  {
1763  if( ‪IS_TRUE(level.toggle_keyline_always) )
1764  {
1765  self ‪clientfield::set("zombie_keyline_render", 1);
1766  wait( 1.0 );
1767  continue;
1768  }
1769 
1770  wait( 4.0 );
1771 
1772 
1773  //if i've torn a board down in the last 5 seconds, just
1774  //wait again.
1775  if ( IsDefined(self.lastchunk_destroy_time) )
1776  {
1777  if ( (GetTime() - self.lastchunk_destroy_time) < 8000 )
1778  continue;
1779  }
1780 
1781  //hasnt moved 24 inches in 10 seconds - draw outline
1782  if ( DistanceSquared( self.origin, prevorigin ) < 576 )
1783  {
1784  self ‪clientfield::set("zombie_keyline_render", 1);
1785  }
1786  else
1787  {
1788  self ‪clientfield::set("zombie_keyline_render", 0);
1789  }
1790 
1791  prevorigin = self.origin;
1792  }
1794  //END OF FAILSAFE "hack"
1796 }
1797 
1798 
1799 
1800 
1801 //--------------------------------------------------------------------------------------------------
1802 // ZOMBIE ROUND FUNCTIONALITY
1803 //--------------------------------------------------------------------------------------------------
1804 //put the conditions in here which should
1805 //cause the failsafe to reset
1807 {
1808  self endon("death");//guy just died
1809 
1810  if( ‪IS_TRUE(level.debug_keyline_zombies) )
1811  {
1812  self thread ‪round_spawn_failsafe_debug_draw();
1813  }
1814 
1816  //FAILSAFE "hack shit" DT#33203
1818  prevorigin = self.origin;
1819  while(1)
1820  {
1821  if( !level.zombie_vars["zombie_use_failsafe"] )
1822  {
1823  return;
1824  }
1825 
1826  if ( ‪IS_TRUE( self.ignore_round_spawn_failsafe ) )
1827  {
1828  return;
1829  }
1830 
1831  if(!IsDefined(level.failsafe_waittime))
1832  {
1833  level.failsafe_waittime = 30;
1834  }
1835 
1836  wait( level.failsafe_waittime );
1837 
1838  if( self.missingLegs )
1839  {
1840  wait( 10.0 );
1841  }
1842 
1843  //inert zombies can ignore this
1844  if ( ‪IS_TRUE( self.is_inert ) )
1845  {
1846  continue;
1847  }
1848 
1849  //if i've torn a board down in the last 5 seconds, just
1850  //wait 30 again.
1851  if ( IsDefined(self.lastchunk_destroy_time) )
1852  {
1853  if ( (GetTime() - self.lastchunk_destroy_time) < 8000 )
1854  continue;
1855  }
1856 
1857  //fell out of world
1858  if ( self.origin[2] < level.zombie_vars["below_world_check"] )
1859  {
1860  if(‪IS_TRUE(level.put_timed_out_zombies_back_in_queue ) && !level ‪flag::get("special_round") && !‪IS_TRUE( self.isscreecher ) )
1861  {
1862  level.zombie_total++;
1863  level.zombie_total_subtract++;
1864  }
1865 
1866  self dodamage( self.health + 100, (0,0,0) );
1867  break;
1868  }
1869 
1870  //hasnt moved 24 inches in 30 seconds?
1871  if ( DistanceSquared( self.origin, prevorigin ) < 576 )
1872  {
1873  if( IsDefined( level.move_failsafe_override ) )
1874  {
1875  self thread [[level.move_failsafe_override]]( prevorigin );
1876  }
1877  else
1878  {
1879  //add this zombie back into the spawner queue to be re-spawned
1880  if(‪IS_TRUE(level.put_timed_out_zombies_back_in_queue ) && !level ‪flag::get("special_round"))
1881  {
1882  //only if they have crawled thru a window and then timed out
1883  if ( !self.ignoreall && !‪IS_TRUE(self.nuked) && !‪IS_TRUE(self.marked_for_death) && !‪IS_TRUE( self.isscreecher ) && !self.missingLegs )
1884  {
1885  level.zombie_total++;
1886  level.zombie_total_subtract++;
1887  }
1888  }
1889 
1890  //add this to the stats even tho he really didn't 'die'
1891  level.zombies_timeout_playspace++;
1892 
1893  // DEBUG HACK
1894  self dodamage( self.health + 100, (0,0,0) );
1895  }
1896  break;
1897  }
1898 
1899  prevorigin = self.origin;
1900  }
1902  //END OF FAILSAFE "hack"
1904 }
1905 
1906 
1907 function ‪ai_calculate_health( round_number )
1908 {
1909  level.zombie_health = level.zombie_vars["zombie_health_start"];
1910  for ( i=2; i <= round_number; i++ )
1911  {
1912  // After round 10, get exponentially harder
1913  if ( i >= 10 )
1914  {
1915  old_health = level.zombie_health;
1916  level.zombie_health += Int( level.zombie_health * level.zombie_vars["zombie_health_increase_multiplier"] );
1917 
1918  if ( level.zombie_health < old_health )
1919  {
1920  // we must have overflowed the signed integer space, just use the last good health, it'll give some headroom to the capped value to account for extra damage applications
1921  level.zombie_health = old_health;
1922  return;
1923  }
1924  }
1925  else
1926  {
1927  level.zombie_health = Int( level.zombie_health + level.zombie_vars["zombie_health_increase"] );
1928  }
1929  }
1930 }
1931 
1932 
1933 function ‪default_max_zombie_func( max_num, n_round )
1934 {
1935  /#
1936  count = GetDvarInt( "zombie_default_max", -1 );
1937  if ( count > -1 )
1938  {
1939  return count;
1940  }
1941  #/
1942 
1943  max = max_num;
1944 
1945  if( n_round < 2 )
1946  {
1947  max = int( max_num * 0.25 );
1948  }
1949  else if( n_round < 3 )
1950  {
1951  max = int( max_num * 0.3 );
1952  }
1953  else if( n_round < 4 )
1954  {
1955  max = int( max_num * 0.5 );
1956  }
1957  else if( n_round < 5 )
1958  {
1959  max = int( max_num * 0.7 );
1960  }
1961  else if( n_round < 6 )
1962  {
1963  max = int( max_num * 0.9 );
1964  }
1965 
1966  return max;
1967 }
1968 
1970 {
1971  if( level.round_number <= 3 )
1972  {
1973  return;
1974  }
1975 
1976  level endon( "intermission" );
1977  level endon( "end_of_round" );
1978  level endon( "restart_round" );
1979  level endon( "kill_round" );
1980 
1981  // Wait until we've finished spawning
1982  while ( level.zombie_total > 4 )
1983  {
1984  wait( 3.0 );
1985  }
1986 
1987  // Keep checking as long as there's a zombie left.
1988  a_ai_zombies = ‪get_round_enemy_array();
1989  while( a_ai_zombies.size > 0 || level.zombie_total > 0 )
1990  {
1991  if( a_ai_zombies.size == 1 )
1992  {
1993  ai_zombie = a_ai_zombies[0];
1994 
1995  if( IsAlive( ai_zombie ) )
1996  {
1997  if ( IsDefined( level.zombie_speed_up ) )
1998  {
1999  ai_zombie thread [[ level.zombie_speed_up ]]();
2000  }
2001  else
2002  {
2003  //set_zombie_run_cycle to sprint
2004  if( !‪IS_EQUAL(ai_zombie.zombie_move_speed, "sprint") )
2005  {
2006  ai_zombie ‪zombie_utility::set_zombie_run_cycle( "sprint" );
2007  ai_zombie.zombie_move_speed_original = ai_zombie.zombie_move_speed;
2008  }
2009  }
2010  }
2011  }
2012  wait(0.5);
2013 
2014  a_ai_zombies = ‪get_round_enemy_array();
2015  }
2016 }
2017 
2019 {
2020  enemies = ‪get_round_enemy_array();
2021  return enemies.size;
2022 }
2023 
2025 {
2026  a_ai_enemies = [];
2027  a_ai_valid_enemies = [];
2028  a_ai_enemies = GetAITeamArray( level.zombie_team );
2029 
2030  for( i = 0; i < a_ai_enemies.size; i++ )
2031  {
2032  if ( ‪IS_TRUE( a_ai_enemies[i].ignore_enemy_count ) )
2033  {
2034  continue;
2035  }
2036  ‪ARRAY_ADD( a_ai_valid_enemies, a_ai_enemies[i] );
2037  }
2038 
2039  return a_ai_valid_enemies;
2040 }
2041 
2042 // Returns an array of all zombies
2044 {
2045  enemies = [];
2046  valid_enemies = [];
2047  enemies = GetAiSpeciesArray( level.zombie_team, "all" );
2048 
2049  for( i = 0; i < enemies.size; i++ )
2050  {
2051  if ( enemies[i].archetype == ‪ARCHETYPE_ZOMBIE )
2052  {
2053  ‪ARRAY_ADD( valid_enemies, enemies[i] );
2054  }
2055  }
2056 
2057  return valid_enemies;
2058 }
2059 
2060 // self = zombie
2061 function ‪set_zombie_run_cycle_override_value( new_move_speed )
2062 {
2063  ‪set_zombie_run_cycle( new_move_speed );
2064  self.zombie_move_speed_override = new_move_speed;
2065 }
2066 
2067 // self = zombie
2069 {
2070  str_restore_move_speed = self.zombie_move_speed_restore;
2071 
2072  self.zombie_move_speed_override = undefined; // turn off the override, so set_zombie_run_cycle will accept our change
2073  ‪set_zombie_run_cycle( str_restore_move_speed );
2074 }
2075 
2076 function ‪set_zombie_run_cycle( new_move_speed )
2077 {
2078  // if we're currently overriding the zombie speed, store off any attempted changes and we can restore them later
2079  if( isdefined( self.zombie_move_speed_override ) )
2080  {
2081  self.zombie_move_speed_restore = new_move_speed;
2082  return;
2083  }
2084 
2085  self.zombie_move_speed_original = self.zombie_move_speed;
2086 
2087  if ( IsDefined( new_move_speed ) )
2088  {
2089  self.zombie_move_speed = new_move_speed;
2090  }
2091  else
2092  {
2093  if( level.gamedifficulty == 0 ) //no sprinters on easy
2094  self ‪set_run_speed_easy();
2095  else
2096  self ‪set_run_speed();
2097  }
2098  if( IsDefined( level.zm_variant_type_max ) )
2099  {
2100  /#
2101  // sjakatdar TU3 (11/12/2015)
2102  // Removed the debugging here to make sure that we have same behavior as ship as this lead to some ship only problems
2103  // If you need to test variations, just change the script locally
2104  if(0)
2105  {
2106  debug_variant_type = GetDvarInt( "scr_zombie_variant_type", -1 );
2107 
2108  if( debug_variant_type != -1 )
2109  {
2110  if(debug_variant_type <= level.zm_variant_type_max[self.zombie_move_speed][self.zombie_arms_position] )
2111  {
2112  self.variant_type = debug_variant_type;
2113  }
2114  else
2115  {
2116  self.variant_type = level.zm_variant_type_max[self.zombie_move_speed][self.zombie_arms_position] - 1;
2117  }
2118  }
2119  else
2120  {
2121  self.variant_type = RandomInt( level.zm_variant_type_max[self.zombie_move_speed][self.zombie_arms_position] );
2122  }
2123  }
2124  #/
2125 
2126  if( self.archetype === ‪ARCHETYPE_ZOMBIE )
2127  {
2128  if ( isdefined( self.zm_variant_type_max ) )
2129  {
2130  self.variant_type = RandomInt( self.zm_variant_type_max[self.zombie_move_speed][self.zombie_arms_position] );
2131  }
2132  else
2133  {
2134  if ( isdefined( level.zm_variant_type_max[self.zombie_move_speed] ) )
2135  {
2136  self.variant_type = RandomInt( level.zm_variant_type_max[self.zombie_move_speed][self.zombie_arms_position] );
2137  }
2138  else
2139  {
2140  /#
2141  ErrorMsg( "No variants set up for move speed " + self.zombie_move_speed );
2142  #/
2143  self.variant_type = 0;
2144  }
2145  }
2146  }
2147  }
2148 
2149  self.needs_run_update = true;
2150  self notify( "needs_run_update" );
2151 
2152  self.deathanim = self ‪zombie_utility::append_missing_legs_suffix( "zm_death" );
2153 }
2154 
2156 {
2157  // We may want to force running zombies at the start of a round, to get zombies in to the arena quickly
2158  if( isdefined(level.zombie_force_run) )
2159  {
2160  self.zombie_move_speed = "run";
2161  level.zombie_force_run--;
2162  if( level.zombie_force_run <= 0 )
2163  {
2164  level.zombie_force_run = undefined;
2165  }
2166 
2167  return;
2168  }
2169 
2170  rand = randomintrange( level.zombie_move_speed, level.zombie_move_speed + 35 );
2171 
2172 // self thread print_run_speed( rand );
2173  if( rand <= 35 )
2174  {
2175  self.zombie_move_speed = "walk";
2176  }
2177  else if( rand <= 70 )
2178  {
2179  self.zombie_move_speed = "run";
2180  }
2181  else
2182  {
2183  self.zombie_move_speed = "sprint";
2184  }
2185 }
2186 
2188 {
2189  rand = randomintrange( level.zombie_move_speed, level.zombie_move_speed + 25 );
2190 
2191 // self thread print_run_speed( rand );
2192  if( rand <= 35 )
2193  {
2194  self.zombie_move_speed = "walk";
2195  }
2196  else
2197  {
2198  self.zombie_move_speed = "run";
2199  }
2200 }
2201 
2202 //self = zombie being knocked down
2203 //entity = entity knocking zombie down
2204 function ‪setup_zombie_knockdown( entity )
2205 {
2206  self.knockdown = true;
2207  zombie_to_entity = entity.origin - self.origin;
2208  zombie_to_entity_2d = VectorNormalize( ( zombie_to_entity[0], zombie_to_entity[1], 0 ) );
2209 
2210  zombie_forward = AnglesToForward( self.angles );
2211  zombie_forward_2d = VectorNormalize( ( zombie_forward[0], zombie_forward[1], 0 ) );
2212 
2213  zombie_right = AnglesToRight( self.angles );
2214  zombie_right_2d = VectorNormalize( ( zombie_right[0], zombie_right[1], 0 ) );
2215 
2216  dot = VectorDot( zombie_to_entity_2d, zombie_forward_2d );
2217 
2218  if( dot >= 0.5 )
2219  {
2220  self.knockdown_direction = "front";
2221  self.getup_direction = ‪GETUP_BACK;
2222  }
2223  else if ( dot < 0.5 && dot > -0.5 )
2224  {
2225  dot = VectorDot( zombie_to_entity_2d, zombie_right_2d );
2226  if( dot > 0 )
2227  {
2228  self.knockdown_direction = "right";
2229 
2230  if ( ‪math::cointoss() )
2231  {
2232  self.getup_direction = ‪GETUP_BACK;
2233  }
2234  else
2235  {
2236  self.getup_direction = ‪GETUP_BELLY;
2237  }
2238  }
2239  else
2240  {
2241  self.knockdown_direction = "left";
2242  self.getup_direction = ‪GETUP_BELLY;
2243  }
2244  }
2245  else
2246  {
2247  self.knockdown_direction = "back";
2248  self.getup_direction = ‪GETUP_BELLY;
2249  }
2250 }
2251 
2253 {
2254  corpse_array = GetCorpseArray();
2255 
2256  for ( i = 0; i < corpse_array.size; i++ )
2257  {
2258  if ( IsDefined( corpse_array[ i ] ) )
2259  {
2260  corpse_array[ i ] Delete();
2261  }
2262  }
2263 }
2264 
2266 {
2267  count = 0;
2268  actors = GetAiSpeciesArray( level.zombie_team, "all" );
2269  if (IsDefined(actors))
2270  count += actors.size;
2271  count += ‪get_current_corpse_count();
2272  return count;
2273 }
2274 
2276 {
2277  corpse_array = GetCorpseArray();
2278  if (IsDefined(corpse_array))
2279  return corpse_array.size;
2280  return 0;
2281 }
2282 
2283 //--------------------------------------------------------------------------------------------------
2284 // ZOMBIE GIBBING
2285 //--------------------------------------------------------------------------------------------------
2286 // gib limbs if enough firepower occurs
2288 {
2289 // self endon( "death" );
2290 
2291  while( 1 )
2292  {
2293  self waittill( "damage", amount, attacker, direction_vec, point, type, tagName, ModelName, Partname, weapon );
2294 
2295  if( !IsDefined( self ) )
2296  {
2297  return;
2298  }
2299 
2300  if( !self ‪zombie_should_gib( amount, attacker, type ) )
2301  {
2302  continue;
2303  }
2304 
2305  if( self ‪head_should_gib( attacker, type, point ) && type != "MOD_BURNED" )
2306  {
2307  self ‪zombie_head_gib( attacker, type );
2308  continue;
2309  }
2310 
2311  if( !‪IS_TRUE(self.gibbed) && isDefined(self.damageLocation) )
2312  {
2313  // The head_should_gib() above checks for this, so we should not randomly gib if shot in the head
2314  if ( self damagelocationisany( "head", "helmet", "neck" ) )
2315  {
2316  continue;
2317  }
2318 
2319  //Zombie is about to stumble, so don't gib.
2320  self.stumble = undefined;
2321 
2322 
2323  switch( self.damageLocation )
2324  {
2325  case "torso_upper":
2326  case "torso_lower":
2327  // HACK the torso that gets swapped for guts also removes the left arm
2328  // so we need to sometimes do another ref
2329 
2332  break;
2333 
2334  case "right_arm_upper":
2335  case "right_arm_lower":
2336  case "right_hand":
2337 
2340  break;
2341 
2342  case "left_arm_upper":
2343  case "left_arm_lower":
2344  case "left_hand":
2345 
2348  break;
2349 
2350  case "right_leg_upper":
2351  case "right_leg_lower":
2352  case "right_foot":
2353  if( self.health <= 0 )
2354  {
2355 
2357 
2358  if( randomint( 100 ) > 75 )
2360 
2361  self.missingLegs = true;
2362  }
2363  break;
2364 
2365  case "left_leg_upper":
2366  case "left_leg_lower":
2367  case "left_foot":
2368  if( self.health <= 0 )
2369  {
2371  if( randomint( 100 ) > 75 )
2373 
2374  self.missingLegs = true;
2375 
2376  }
2377  break;
2378  default:
2379 
2380  if( self.damageLocation == "none" )
2381  {
2382  // SRS 9/7/2008: might be a nade or a projectile
2383  if( type == "MOD_GRENADE" || type == "MOD_GRENADE_SPLASH" || type == "MOD_PROJECTILE" || type == "MOD_PROJECTILE_SPLASH" )
2384  {
2385  // ... in which case we have to derive the ref ourselves
2386  self ‪derive_damage_refs( point );
2387  break;
2388  }
2389  }
2390 
2391  }
2392 
2393  if( IsDefined( level.custom_derive_damage_refs ) )
2394  {
2395  //refs = self [[ level.custom_derive_damage_refs ]](refs, point, weapon);
2396  }
2397 
2398  // Don't stand if a leg is gone
2399  if( ‪IS_TRUE(self.missingLegs) && self.health > 0 )//( self.a.gib_ref == "no_legs" || self.a.gib_ref == "right_leg" || self.a.gib_ref == "left_leg" ) && self.health > 0 ) //( GibServerUtils::IsGibbed(self, GIB_LEGS_LEFT_LEG_FLAG) || GibServerUtils::IsGibbed(self, GIB_LEGS_RIGHT_LEG_FLAG) ) && self.health > 0)
2400  {
2401 
2402  self AllowedStances( "crouch" );
2403 
2404  // reduce collbox so player can jump over
2405  self setPhysParams( 15, 0, 24 );
2406 
2407  self AllowPitchAngle( 1 );
2408  self setPitchOrient();
2409 
2410  health = self.health;
2411  health = health * 0.1;
2412 
2413  if ( IsDefined( self.crawl_anim_override ) )
2414  {
2415  self [[ self.crawl_anim_override ]]();
2416  }
2417  }
2418 
2419 
2420  if( self.health > 0 )
2421  {
2422 
2423  if ( IsDefined( level.gib_on_damage ) )
2424  {
2425  self thread [[ level.gib_on_damage ]]();
2426  }
2427  }
2428  }
2429  }
2430 }
2431 
2432 function ‪add_zombie_gib_weapon_callback( weapon_name, gib_callback, gib_head_callback )
2433 {
2434  ‪DEFAULT(level.zombie_gib_weapons,[]);
2435  ‪DEFAULT(level.zombie_gib_head_weapons,[]);
2436  level.zombie_gib_weapons[weapon_name] = gib_callback;
2437  level.zombie_gib_head_weapons[weapon_name] = gib_head_callback;
2438 }
2439 
2441 {
2442  ‪DEFAULT(level.zombie_gib_weapons,[]);
2443  ‪DEFAULT(level.zombie_gib_head_weapons,[]);
2444  if ( IsWeapon( weapon ) )
2445  weapon = weapon.name;
2446  if ( IsDefined(level.zombie_gib_weapons[weapon] ) )
2447  return true;
2448  return false;
2449 }
2450 
2451 function ‪get_zombie_weapon_gib_callback( weapon, damage_percent )
2452 {
2453  ‪DEFAULT(level.zombie_gib_weapons,[]);
2454  ‪DEFAULT(level.zombie_gib_head_weapons,[]);
2455  if ( IsWeapon( weapon ) )
2456  weapon = weapon.name;
2457  if ( IsDefined(level.zombie_gib_weapons[weapon] ) )
2458  {
2459  return self [[level.zombie_gib_weapons[weapon]]]( damage_percent );
2460  }
2461  return false;
2462 }
2463 
2465 {
2466  ‪DEFAULT(level.zombie_gib_weapons,[]);
2467  ‪DEFAULT(level.zombie_gib_head_weapons,[]);
2468  if ( IsWeapon( weapon ) )
2469  weapon = weapon.name;
2470  if ( IsDefined(level.zombie_gib_head_weapons[weapon] ) )
2471  return true;
2472  return false;
2473 }
2474 
2475 function ‪get_zombie_weapon_gib_head_callback( weapon, damage_location )
2476 {
2477  ‪DEFAULT(level.zombie_gib_weapons,[]);
2478  ‪DEFAULT(level.zombie_gib_head_weapons,[]);
2479  if ( IsWeapon( weapon ) )
2480  weapon = weapon.name;
2481  if ( IsDefined(level.zombie_gib_head_weapons[weapon] ) )
2482  {
2483  return self [[level.zombie_gib_head_weapons[weapon]]]( damage_location );
2484  }
2485  return false;
2486 }
2487 
2488 function ‪zombie_should_gib( amount, attacker, type )
2489 {
2490  if( !IsDefined( type ) )
2491  {
2492  return false;
2493  }
2494 
2495  if ( ‪IS_TRUE( self.is_on_fire ) )
2496  {
2497  return false;
2498  }
2499 
2500  if ( IsDefined( self.no_gib ) && ( self.no_gib == 1 ) )
2501  {
2502  return false;
2503  }
2504 
2505  prev_health = amount + self.health;
2506  if( prev_health <= 0 )
2507  {
2508  prev_health = 1;
2509  }
2510 
2511  damage_percent = ( amount / prev_health ) * 100;
2512 
2513  weapon = undefined;
2514  if( IsDefined( attacker ) )
2515  {
2516  if( IsPlayer( attacker ) || ‪IS_TRUE(attacker.can_gib_zombies) )
2517  {
2518  if( IsPlayer( attacker ) )
2519  {
2520  weapon = attacker GetCurrentWeapon();
2521  }
2522  else
2523  {
2524  weapon = attacker.weapon;
2525  }
2526 
2527  if ( ‪have_zombie_weapon_gib_callback( weapon ) )
2528  {
2529  if ( self ‪get_zombie_weapon_gib_callback( weapon, damage_percent ) )
2530  {
2531  return true;
2532  }
2533  return false;
2534  }
2535  }
2536  }
2537 
2538  switch( type )
2539  {
2540  case "MOD_UNKNOWN":
2541  case "MOD_TELEFRAG":
2542  case "MOD_FALLING":
2543  case "MOD_SUICIDE":
2544  case "MOD_TRIGGER_HURT":
2545  case "MOD_BURNED":
2546  return false;
2547  case "MOD_MELEE":
2548 //Z2 HasPerk( "specialty_altmelee" ) is returning undefined
2549 // if( isPlayer( attacker ) && randomFloat( 1 ) > 0.25 && attacker HasPerk( "specialty_altmelee" ) )
2550 // {
2551 // return true;
2552 // }
2553 // else
2554  {
2555  return false;
2556  }
2557  }
2558 
2559  if( type == "MOD_PISTOL_BULLET" || type == "MOD_RIFLE_BULLET" )
2560  {
2561  if( !IsDefined( attacker ) || !IsPlayer( attacker ) )
2562  {
2563  return false;
2564  }
2565 
2566  if( weapon == level.weaponNone || (IsDefined(level.start_weapon) && weapon == level.start_weapon) || weapon.isGasWeapon )
2567  {
2568  return false;
2569  }
2570  }
2571 
2572 // println( "**DEBUG amount = ", amount );
2573 // println( "**DEBUG self.head_gibbed = ", self.head_gibbed );
2574 // println( "**DEBUG self.health = ", self.health );
2575 
2576  if( damage_percent < 10 /*|| damage_percent >= 100*/ )
2577  {
2578  return false;
2579  }
2580 
2581  return true;
2582 }
2583 
2584 function ‪head_should_gib( attacker, type, point )
2585 {
2586  if( ‪IS_TRUE(self.head_gibbed) )
2587  {
2588  return false;
2589  }
2590 
2591  if( !isdefined( attacker ) )
2592  {
2593  return false;
2594  }
2595 
2596  if( !IsPlayer( attacker ) )
2597  {
2598  if( !‪IS_TRUE( attacker.can_gib_zombies) )//allow non player types to gib (robot)
2599  {
2600  return false;
2601  }
2602  }
2603 
2604  // check if the attacker was a player
2605  if( IsPlayer(attacker ))
2606  {
2607  weapon = attacker GetCurrentWeapon();
2608  }
2609  else
2610  {
2611  weapon = attacker.weapon;
2612  }
2613 
2615  {
2616  if ( self ‪get_zombie_weapon_gib_head_callback( weapon, self.damagelocation ) )
2617  {
2618  return true;
2619  }
2620  return false;
2621  }
2622 
2623  // SRS 9/2/2008: check for damage type
2624  // - most SMGs use pistol bullets
2625  // - projectiles = rockets, raygun
2626  if( type != "MOD_RIFLE_BULLET" && type != "MOD_PISTOL_BULLET" )
2627  {
2628  // maybe it's ok, let's see if it's a grenade
2629  if( type == "MOD_GRENADE" || type == "MOD_GRENADE_SPLASH" )
2630  {
2631  if( Distance( point, self GetTagOrigin( "j_head" ) ) > 55 )
2632  {
2633  return false;
2634  }
2635  else
2636  {
2637  // the grenade airburst close to the head so return true
2638  return true;
2639  }
2640  }
2641  else if( type == "MOD_PROJECTILE" )
2642  {
2643  if( Distance( point, self GetTagOrigin( "j_head" ) ) > 10 )
2644  {
2645  return false;
2646  }
2647  else
2648  {
2649  return true;
2650  }
2651  }
2652  // shottys don't give a testable damage type but should still gib heads
2653  else if( weapon.weapClass != "spread" )
2654  {
2655  return false;
2656  }
2657  }
2658 
2659  // check location now that we've checked for grenade damage (which reports "none" as a location)
2660  if ( !self damagelocationisany( "head", "helmet", "neck" ) )
2661  {
2662  return false;
2663  }
2664 
2665  // check weapon - don't want "none", base pistol, or flamethrower
2666  if( ( type == "MOD_PISTOL_BULLET" && weapon.weapClass != "smg" && weapon.weapClass != "spread" ) ||
2667  weapon == level.weaponNone ||
2668  (IsDefined(level.start_weapon) && weapon == level.start_weapon) ||
2669  weapon.isGasWeapon )
2670  {
2671  return false;
2672  }
2673 
2674  //DCS: temporarily added for cp zombie gibbing until can check a weapon gdt "do gibbing" availability.
2675  if( SessionModeIsCampaignGame() && (type == "MOD_PISTOL_BULLET" && weapon.weapClass != "smg"))
2676  {
2677  return false;
2678  }
2679  // check the enemy's health
2680  low_health_percent = ( self.health / self.maxhealth ) * 100;
2681  if( low_health_percent > 10 )
2682  {
2683  // TOOD(David Young 9-15-14): Commenting out because gibbing anything
2684  // should not happen here. Will remove completely once hat gibbing is supported.
2685  // self zombie_hat_gib( attacker, type );
2686  return false;
2687  }
2688 
2689  return true;
2690 }
2691 
2692 function ‪zombie_hat_gib( attacker, means_of_death )
2693 {
2694  self endon( "death" );
2695 
2696  if ( ‪IS_TRUE( self.hat_gibbed ) )
2697  {
2698  return;
2699  }
2700 
2701  if ( !IsDefined( self.gibSpawn5 ) || !IsDefined( self.gibSpawnTag5 ) )
2702  {
2703  return;
2704  }
2705 
2706  self.hat_gibbed = true;
2707 
2708  if ( IsDefined( self.hatmodel ) )
2709  {
2710  self detach( self.hatModel, "" );
2711  }
2712 
2713  temp_array = [];
2714  temp_array[0] = level._ZOMBIE_GIB_PIECE_INDEX_HAT;
2715 
2716  self ‪gib( "normal", temp_array );
2717 
2718  //stat tracking
2719  if ( IsDefined( level.track_gibs ) )
2720  {
2721  level [[ level.track_gibs ]]( self, temp_array );
2722  }
2723 }
2724 
2725 function ‪head_gib_damage_over_time( dmg, ‪delay, attacker, means_of_death )
2726 {
2727  self endon( "death" );
2728  self endon( "exploding" );
2729 
2730  if( !IsAlive( self ) )
2731  {
2732  return;
2733  }
2734 
2735  if( !IsPlayer( attacker ) )
2736  {
2737  attacker = self;
2738  }
2739 
2740  if ( !IsDefined( means_of_death ) )
2741  {
2742  means_of_death = "MOD_UNKNOWN";
2743  }
2744 
2745  dot_location = self.damageLocation;
2746  dot_weapon = self.damageweapon;
2747 
2748  while( 1 )
2749  {
2750  if( IsDefined( ‪delay ) )
2751  {
2752  wait( ‪delay );
2753  }
2754  if (IsDefined(self))
2755  {
2756  if( ‪IS_TRUE( self.no_gib ) )
2757  {
2758  return;
2759  }
2760  if(IsDefined(attacker))
2761  {
2762  self DoDamage( dmg, self GetTagOrigin( "j_neck" ), attacker, self, dot_location, means_of_death, 0, dot_weapon );//player can drop out
2763  }
2764  else
2765  {
2766  self DoDamage( dmg, self GetTagOrigin( "j_neck" ));
2767  }
2768  }
2769  }
2770 }
2771 
2772 // SRS 9/7/2008: need to derive damage location for types that return location of "none"
2773 function ‪derive_damage_refs( point )
2774 {
2775  if( !IsDefined( level.gib_tags ) )
2776  {
2777  ‪init_gib_tags();
2778  }
2779 
2780  closestTag = undefined;
2781 
2782  for( i = 0; i < level.gib_tags.size; i++ )
2783  {
2784  if( !IsDefined( closestTag ) )
2785  {
2786  closestTag = level.gib_tags[i];
2787  }
2788  else
2789  {
2790  if( DistanceSquared( point, self GetTagOrigin( level.gib_tags[i] ) ) < DistanceSquared( point, self GetTagOrigin( closestTag ) ) )
2791  {
2792  closestTag = level.gib_tags[i];
2793  }
2794  }
2795  }
2796 
2797  // figure out the refs based on the tag returned
2798  if( closestTag == "J_SpineLower" || closestTag == "J_SpineUpper" || closestTag == "J_Spine4" )
2799  {
2800  // HACK the torso that gets swapped for guts also removes the left arm
2801  // so we need to sometimes do another ref
2802  //GibServerUtils::GibEntity( self, GIB_TORSO_GUTS_FLAG );
2804 
2805  }
2806  else if( closestTag == "J_Shoulder_LE" || closestTag == "J_Elbow_LE" || closestTag == "J_Wrist_LE" )
2807  {
2810  }
2811  else if( closestTag == "J_Shoulder_RI" || closestTag == "J_Elbow_RI" || closestTag == "J_Wrist_RI" )
2812  {
2815  }
2816  else if( closestTag == "J_Hip_LE" || closestTag == "J_Knee_LE" || closestTag == "J_Ankle_LE" )
2817  {
2818  if ( ‪IS_TRUE( self.noCrawler ) )
2819  {
2820  return;
2821  }
2822 
2824  if( randomint(100) > 75)
2826  self.missingLegs = true;
2827  }
2828  else if( closestTag == "J_Hip_RI" || closestTag == "J_Knee_RI" || closestTag == "J_Ankle_RI" )
2829  {
2830  if ( ‪IS_TRUE( self.noCrawler ) )
2831  {
2832  return;
2833  }
2834 
2836  if( randomint(100) > 75)
2838  self.missingLegs = true;
2839  }
2840 
2841 
2842  //return refs;
2843 }
2844 
2846 {
2847  tags = [];
2848 
2849  // "guts", "right_arm", "left_arm", "right_leg", "left_leg", "no_legs"
2850 
2851  // "guts"
2852  tags[tags.size] = "J_SpineLower";
2853  tags[tags.size] = "J_SpineUpper";
2854  tags[tags.size] = "J_Spine4";
2855 
2856  // "left_arm"
2857  tags[tags.size] = "J_Shoulder_LE";
2858  tags[tags.size] = "J_Elbow_LE";
2859  tags[tags.size] = "J_Wrist_LE";
2860 
2861  // "right_arm"
2862  tags[tags.size] = "J_Shoulder_RI";
2863  tags[tags.size] = "J_Elbow_RI";
2864  tags[tags.size] = "J_Wrist_RI";
2865 
2866  // "left_leg"/"no_legs"
2867  tags[tags.size] = "J_Hip_LE";
2868  tags[tags.size] = "J_Knee_LE";
2869  tags[tags.size] = "J_Ankle_LE";
2870 
2871  // "right_leg"/"no_legs"
2872  tags[tags.size] = "J_Hip_RI";
2873  tags[tags.size] = "J_Knee_RI";
2874  tags[tags.size] = "J_Ankle_RI";
2875 
2876  level.gib_tags = tags;
2877 }
2878 
2879 //--------------------------------------------------------------------------------------------------
2880 function ‪getAnimDirection( damageyaw )
2881 {
2882  if( ( damageyaw > 135 ) ||( damageyaw <= -135 ) ) // Front quadrant
2883  {
2884  return "front";
2885  }
2886  else if( ( damageyaw > 45 ) &&( damageyaw <= 135 ) ) // Right quadrant
2887  {
2888  return "right";
2889  }
2890  else if( ( damageyaw > -45 ) &&( damageyaw <= 45 ) ) // Back quadrant
2891  {
2892  return "back";
2893  }
2894  else
2895  { // Left quadrant
2896  return "left";
2897  }
2898  return "front";
2899 }
2900 
2901 function ‪anim_get_dvar_int( dvar, def )
2902 {
2903  return int( ‪anim_get_dvar( dvar, def ) );
2904 }
2905 
2906 // dvar set/fetch/check
2907 function ‪anim_get_dvar( dvar, def )
2908 {
2909  if ( GetDvarString( dvar ) != "" )
2910  return getdvarfloat( dvar );
2911  else
2912  {
2913  SetDvar( dvar, def );
2914  return def;
2915  }
2916 }
2917 
2918 function ‪makeZombieCrawler( b_both_legs )
2919 {
2920  if( ‪IS_TRUE( b_both_legs ) )
2921  {
2922  val = 100;
2923  }
2924  else
2925  {
2926  val = randomint( 100 );
2927  }
2928 
2929  if( val > 75 )
2930  {
2933  }
2934  else if ( val > 37 )
2936  else
2938 
2939  self.missingLegs = true;
2940  self AllowedStances( "crouch" );
2941 
2942  // reduce collbox so player can jump over
2943  self setPhysParams( 15, 0, 24 );
2944 
2945  self AllowPitchAngle( 1 );
2946  self setPitchOrient();
2947 
2948  health = self.health;
2949  health = health * 0.1;
2950 }
2951 
2952 function ‪zombie_head_gib( attacker, means_of_death )
2953 {
2954  self endon( "death" );
2955 
2956  if ( ‪IS_TRUE( self.head_gibbed ) )
2957  {
2958  return;
2959  }
2960 
2961  if( ‪IS_TRUE( self.no_gib ) )
2962  {
2963  return;
2964  }
2965 
2966  self.head_gibbed = true;
2967 
2968  self ‪zombie_eye_glow_stop();
2969 
2970 
2971  if( !‪IS_TRUE( self.disable_head_gib ) )
2972  {
2974  }
2975 
2976  self thread ‪head_gib_damage_over_time( ceil( self.health * 0.2 ), 1, attacker, means_of_death );
2977 }
2978 
2980 {
2981  if( ‪IS_TRUE( self.no_gib ) )
2982  {
2983  return;
2984  }
2985 
2986  val = randomint( 100 );
2987  if( val > 50 )
2988  {
2990  }
2991  val = randomint( 100 );
2992  if( val > 50 )
2993  {
2995  }
2996  val = randomint( 100 );
2997  if( val > 50 )
2998  {
3000  }
3001  val = randomint( 100 );
3002  if( val > 50 )
3003  {
3006  }
3007  val = randomint( 100 );
3008  if( val > 50 )
3009  {
3012  }
3013 }
3014 
3015 // ------------- ignore player utility ----------- //
3017 {
3018  level._IGNORE_PLAYER_HANDLER = [];
3019 }
3020 
3021 function ‪register_ignore_player_handler( archetype, ignore_player_func )
3022 {
3023  Assert( IsDefined( archetype ), "IgnorePlayerHandler undefined archetype." );
3024 
3025  Assert( !IsDefined( level._IGNORE_PLAYER_HANDLER[ archetype ] ), "IgnorePlayerHandler for " + archetype + " is already registered." );
3026 
3027  level._IGNORE_PLAYER_HANDLER[ archetype ] = ignore_player_func;
3028 }
3029 
3031 {
3032  if ( IsDefined( level._IGNORE_PLAYER_HANDLER[ self.archetype ] ) )
3033  {
3034  self [[ level._IGNORE_PLAYER_HANDLER[ self.archetype ] ]]();
3035  }
3036 }
3037 
3038 // hit marker on player, call this in the damage callback for AI on the player attacker to show crosshair
3039 function ‪show_hit_marker() // self = player
3040 {
3041  if ( IsDefined( self ) && IsDefined( self.hud_damagefeedback ) )
3042  {
3043  self.hud_damagefeedback SetShader( "damage_feedback", 24, 48 );
3044  self.hud_damagefeedback.alpha = 1;
3045  self.hud_damagefeedback FadeOverTime(1);
3046  self.hud_damagefeedback.alpha = 0;
3047  }
3048 }
‪run_ignore_player_handler
‪function run_ignore_player_handler()
Definition: zombie_utility.gsc:3030
‪safemod
‪function safemod(a, b)
Definition: zombie_utility.gsc:548
‪is_zombie
‪function is_zombie()
Definition: zombie_utility.gsc:1320
‪set_zombie_run_cycle_override_value
‪function set_zombie_run_cycle_override_value(new_move_speed)
Definition: zombie_utility.gsc:2061
‪IsInSet
‪function IsInSet(input, set)
Definition: zombie_utility.gsc:685
‪GetNodeYawToOrigin
‪function GetNodeYawToOrigin(pos)
Definition: zombie_utility.gsc:279
‪clear_all_corpses
‪function clear_all_corpses()
Definition: zombie_utility.gsc:2252
‪get_zombie_weapon_gib_callback
‪function get_zombie_weapon_gib_callback(weapon, damage_percent)
Definition: zombie_utility.gsc:2451
‪getRandomIntFromSeed
‪function getRandomIntFromSeed(intSeed, intMax)
Definition: zombie_utility.gsc:1300
‪anim_get_dvar_int
‪function anim_get_dvar_int(dvar, def)
Definition: zombie_utility.gsc:2901
‪debugPosSize
‪function debugPosSize(org, string, size)
Definition: zombie_utility.gsc:792
‪GetClaimedNode
‪function GetClaimedNode()
Definition: zombie_utility.gsc:492
‪timer
‪function timer(n_time, str_endon, x, y, height)
Definition: lui_shared.gsc:163
‪debugTimeout
‪function debugTimeout()
Definition: zombie_utility.gsc:753
‪GetCoverNodeYawToOrigin
‪function GetCoverNodeYawToOrigin(org)
Definition: zombie_utility.gsc:473
‪GIB_TORSO_RIGHT_ARM_FLAG
‪#define GIB_TORSO_RIGHT_ARM_FLAG
Definition: gib.gsh:25
‪animArray
‪function animArray(animname)
Definition: zombie_utility.gsc:1122
‪GibLeftArm
‪function GibLeftArm(entity)
Definition: gib.gsc:450
‪GetYaw2d
‪function GetYaw2d(org)
Definition: zombie_utility.gsc:381
‪get_zombie_weapon_gib_head_callback
‪function get_zombie_weapon_gib_head_callback(weapon, damage_location)
Definition: zombie_utility.gsc:2475
‪delayed_zombie_eye_glow
‪function delayed_zombie_eye_glow()
Definition: zombie_utility.gsc:1700
‪set_zombie_run_cycle_restore_from_override
‪function set_zombie_run_cycle_restore_from_override()
Definition: zombie_utility.gsc:2068
‪debug_allow_movement
‪function debug_allow_movement()
Definition: zombie_utility.gsc:1422
‪zombie_head_gib
‪function zombie_head_gib(attacker, means_of_death)
Definition: zombie_utility.gsc:2952
‪persistentDebugLine
‪function persistentDebugLine(start, end)
Definition: zombie_utility.gsc:1085
‪anim_get_dvar
‪function anim_get_dvar(dvar, def)
Definition: zombie_utility.gsc:2907
‪have_zombie_weapon_gib_head_callback
‪function have_zombie_weapon_gib_head_callback(weapon)
Definition: zombie_utility.gsc:2464
‪GetYawToOrigin
‪function GetYawToOrigin(org)
Definition: zombie_utility.gsc:459
‪get_current_actor_count
‪function get_current_actor_count()
Definition: zombie_utility.gsc:2265
‪print3drise
‪function print3drise(org, msg, color, alpha, scale)
Definition: zombie_utility.gsc:984
‪GetYawToEnemy
‪function GetYawToEnemy()
Definition: zombie_utility.gsc:356
‪cointoss
‪function cointoss()
Definition: math_shared.csc:171
‪set_zombie_var
‪function set_zombie_var(zvar, value, is_float=false, column=1, is_team_based=false)
Definition: zombie_utility.gsc:1434
‪delayedScriptChange
‪function delayedScriptChange()
Definition: zombie_utility.gsc:1011
‪checkPitchVisibility
‪function checkPitchVisibility(fromPoint, toPoint, atNode)
Definition: zombie_utility.gsc:889
‪ZOMBIE_CLIENTFIELD
‪#define ZOMBIE_CLIENTFIELD
Definition: zombie.gsh:61
‪print3dtime
‪function print3dtime(timer, org, msg, color, alpha, scale)
Definition: zombie_utility.gsc:972
‪canThrowGrenade
‪function canThrowGrenade()
Definition: zombie_utility.gsc:1027
‪round_spawn_failsafe_debug_draw
‪function round_spawn_failsafe_debug_draw()
Definition: zombie_utility.gsc:1753
‪set_run_speed_easy
‪function set_run_speed_easy()
Definition: zombie_utility.gsc:2187
‪anim_array
‪function anim_array(animArray, animWeights)
Definition: zombie_utility.gsc:923
‪UpdateAnimPose
‪function UpdateAnimPose()
Definition: zombie_utility.gsc:218
‪forcedCover
‪function forcedCover(msg)
Definition: zombie_utility.gsc:967
‪squared
‪function squared(value)
Definition: zombie_utility.gsc:1289
‪drawStringTime
‪function drawStringTime(msg, org, color, timer)
Definition: zombie_utility.gsc:706
‪debugPos
‪function debugPos(org, string)
Definition: zombie_utility.gsc:787
‪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
‪get_round_enemy_array
‪function get_round_enemy_array()
Definition: zombie_utility.gsc:2024
‪get
‪function get(kvp_value, kvp_key="targetname")
Definition: struct.csc:13
‪a
‪function add_remove_list a
Definition: util_shared.csc:906
‪AbsYawToAngles
‪function AbsYawToAngles(angles)
Definition: zombie_utility.gsc:433
‪is_civilian
‪function is_civilian()
Definition: zombie_utility.gsc:1331
‪delay
‪function delay(time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6)
Definition: util_shared.csc:784
‪initAnimTree
‪function initAnimTree(animscript)
Definition: zombie_utility.gsc:206
‪Annihilate
‪function Annihilate(entity)
Definition: gib.gsc:393
‪gib
‪function gib(attacker)
Definition: _amws.gsc:1072
‪GetNodeYawToEnemy
‪function GetNodeYawToEnemy()
Definition: zombie_utility.gsc:294
‪zombie_should_gib
‪function zombie_should_gib(amount, attacker, type)
Definition: zombie_utility.gsc:2488
‪add_zombie_gib_weapon_callback
‪function add_zombie_gib_weapon_callback(weapon_name, gib_callback, gib_head_callback)
Definition: zombie_utility.gsc:2432
‪damageLocationIsAny
‪function damageLocationIsAny(a, b, c, d, e, f, g, h, i, j, k, ovr)
Definition: zombie_utility.gsc:1217
‪GetYawToTag
‪function GetYawToTag(tag, org)
Definition: zombie_utility.gsc:452
‪randomizeIdleSet
‪function randomizeIdleSet()
Definition: zombie_utility.gsc:1294
‪have_zombie_weapon_gib_callback
‪function have_zombie_weapon_gib_callback(weapon)
Definition: zombie_utility.gsc:2440
‪GibRightLeg
‪function GibRightLeg(entity)
Definition: gib.gsc:496
‪reset_attack_spot
‪function reset_attack_spot()
Definition: zombie_utility.gsc:1671
‪GetYaw
‪function GetYaw(org)
Definition: zombie_utility.gsc:375
‪calculateNodeOffset
‪function calculateNodeOffset(right, forward, baseoffset)
Definition: zombie_utility.gsc:884
‪GetYawToSpot
‪function GetYawToSpot(spot)
Definition: zombie_utility.gsc:348
‪GibLeftLeg
‪function GibLeftLeg(entity)
Definition: gib.gsc:485
‪isNodeDontStand
‪function isNodeDontStand()
Definition: zombie_utility.gsc:1100
‪round_spawn_failsafe
‪function round_spawn_failsafe()
Definition: zombie_utility.gsc:1806
‪GetNodeDirection
‪function GetNodeDirection()
Definition: zombie_utility.gsc:514
‪hide_pop
‪function hide_pop()
Definition: zombie_utility.gsc:1593
‪DEFAULT
‪#define DEFAULT(__var, __default)
Definition: shared.gsh:270
‪show_hit_marker
‪function show_hit_marker()
Definition: zombie_utility.gsc:3039
‪AbsYawToOrigin
‪function AbsYawToOrigin(org)
Definition: zombie_utility.gsc:420
‪GetEyeYawToOrigin
‪function GetEyeYawToOrigin(org)
Definition: zombie_utility.gsc:466
‪isNodeDontCrouch
‪function isNodeDontCrouch()
Definition: zombie_utility.gsc:1104
‪getQuadrant
‪function getQuadrant(angle)
Definition: zombie_utility.gsc:660
‪is_player_valid
‪function is_player_valid(player, checkIgnoreMeFlag, ignore_laststand_players)
Definition: zombie_utility.gsc:124
‪zombie_rise_death
‪function zombie_rise_death(zombie, spot)
Definition: zombie_utility.gsc:1635
‪get_current_corpse_count
‪function get_current_corpse_count()
Definition: zombie_utility.gsc:2275
‪isValidEnemy
‪function isValidEnemy(enemy)
Definition: zombie_utility.gsc:1206
‪zombie_gib_on_damage
‪function zombie_gib_on_damage()
Definition: zombie_utility.gsc:2287
‪wait_network_frame
‪function wait_network_frame(n_count=1)
Definition: util_shared.gsc:64
‪GetYawFromOrigin
‪function GetYawFromOrigin(org, start)
Definition: zombie_utility.gsc:446
‪get_skeleton
‪function get_skeleton()
Definition: zombie_utility.gsc:1352
‪end
‪function end(final)
Definition: _killcam.gsc:511
‪append_missing_legs_suffix
‪function append_missing_legs_suffix(animstate)
Definition: zombie_utility.gsc:190
‪QuadrantAnimWeights
‪function QuadrantAnimWeights(yaw)
Definition: zombie_utility.gsc:587
‪ARRAY_ADD
‪#define ARRAY_ADD(__array, __item)
Definition: shared.gsh:304
‪crossproduct
‪function crossproduct(vec1, vec2)
Definition: zombie_utility.gsc:1000
‪ai_calculate_health
‪function ai_calculate_health(round_number)
Definition: zombie_utility.gsc:1907
‪zombie_eye_glow_stop
‪function zombie_eye_glow_stop()
Definition: zombie_utility.gsc:1733
‪showDebugLine
‪function showDebugLine(fromPoint, toPoint, color, printTime)
Definition: zombie_utility.gsc:813
‪animArrayPickRandom
‪function animArrayPickRandom(animname)
Definition: zombie_utility.gsc:1154
‪isStanceAllowedWrapper
‪function isStanceAllowedWrapper(stance)
Definition: zombie_utility.gsc:481
‪getAnimEndPos
‪function getAnimEndPos(theanim)
Definition: zombie_utility.gsc:1200
‪GetNodeOrigin
‪function GetNodeOrigin()
Definition: zombie_utility.gsc:537
‪playFootStepEffect
‪function playFootStepEffect(foot, groundType)
Definition: zombie_shared.gsc:485
‪IsGibbed
‪function IsGibbed(localClientNum, entity, gibFlag)
Definition: gib.csc:734
‪init_gib_tags
‪function init_gib_tags()
Definition: zombie_utility.gsc:2845
‪array
‪function filter array
Definition: array_shared.csc:16
‪random_weight
‪function random_weight(array)
Definition: zombie_utility.gsc:1042
‪spawn_zombie
‪function spawn_zombie(spawner, target_name, spawn_point, round_number)
Definition: zombie_utility.gsc:1454
‪isCQBWalking
‪function isCQBWalking()
Definition: zombie_utility.gsc:1284
‪set_run_speed
‪function set_run_speed()
Definition: zombie_utility.gsc:2155
‪showLastEnemySightPos
‪function showLastEnemySightPos(string)
Definition: zombie_utility.gsc:718
‪derive_damage_refs
‪function derive_damage_refs(point)
Definition: zombie_utility.gsc:2773
‪set_zombie_run_cycle
‪function set_zombie_run_cycle(new_move_speed)
Definition: zombie_utility.gsc:2076
‪ARCHETYPE_ZOMBIE
‪#define ARCHETYPE_ZOMBIE
Definition: archetype_shared.gsh:10
‪GETUP_BELLY
‪#define GETUP_BELLY
Definition: blackboard.gsh:206
‪AbsYawToEnemy
‪function AbsYawToEnemy()
Definition: zombie_utility.gsc:388
‪zombie_gut_explosion
‪function zombie_gut_explosion()
Definition: zombie_utility.gsc:1684
‪debug_anim_print
‪function debug_anim_print(text)
Definition: zombie_utility.gsc:1382
‪setFootstepEffect
‪function setFootstepEffect(name, fx)
Definition: zombie_utility.gsc:1070
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪IS_EQUAL
‪#define IS_EQUAL(__a, __b)
Definition: shared.gsh:250
‪head_should_gib
‪function head_should_gib(attacker, type, point)
Definition: zombie_utility.gsc:2584
‪GIB_TORSO_LEFT_ARM_FLAG
‪#define GIB_TORSO_LEFT_ARM_FLAG
Definition: gib.gsh:26
‪notForcedCover
‪function notForcedCover()
Definition: zombie_utility.gsc:962
‪gib_random_parts
‪function gib_random_parts()
Definition: zombie_utility.gsc:2979
‪GetNodeType
‪function GetNodeType()
Definition: zombie_utility.gsc:503
‪zombie_hat_gib
‪function zombie_hat_gib(attacker, means_of_death)
Definition: zombie_utility.gsc:2692
‪showDebugProc
‪function showDebugProc(fromPoint, toPoint, color, printTime)
Definition: zombie_utility.gsc:797
‪animArrayAnyExist
‪function animArrayAnyExist(animname)
Definition: zombie_utility.gsc:1139
‪player_is_in_laststand
‪function player_is_in_laststand()
Definition: laststand_shared.gsc:18
‪is_heavy_machine_gun
‪function is_heavy_machine_gun()
Definition: zombie_utility.gsc:1315
‪is_skeleton
‪function is_skeleton(skeleton)
Definition: zombie_utility.gsc:1341
‪get_closest_valid_player
‪function get_closest_valid_player(origin, ignore_player, ignore_laststand_players=false)
Definition: zombie_utility.gsc:49
‪get_rise_death_anim
‪function get_rise_death_anim()
Definition: zombie_utility.gsc:1659
‪handle_rise_notetracks
‪function handle_rise_notetracks(note, spot)
Definition: zombie_utility.gsc:1611
‪init_ignore_player_handler
‪function autoexec init_ignore_player_handler()
Definition: zombie_utility.gsc:3016
‪doesNodeAllowStance
‪function doesNodeAllowStance(stance)
Definition: zombie_utility.gsc:1109
‪is_banzai
‪function is_banzai()
Definition: zombie_utility.gsc:1309
‪get_zombie_array
‪function get_zombie_array()
Definition: zombie_utility.gsc:2043
‪debug_turn_print
‪function debug_turn_print(text, line)
Definition: zombie_utility.gsc:1393
‪NotifyAfterTime
‪function NotifyAfterTime(notifyString, killmestring, time)
Definition: zombie_utility.gsc:698
‪get_current_zombie_count
‪function get_current_zombie_count()
Definition: zombie_utility.gsc:2018
‪ragdollDeath
‪function ragdollDeath(moveAnim)
Definition: zombie_utility.gsc:1258
‪register_ignore_player_handler
‪function register_ignore_player_handler(archetype, ignore_player_func)
Definition: zombie_utility.gsc:3021
‪zombie_speed_up
‪function zombie_speed_up()
Definition: zombie_utility.gsc:1969
‪zombie_eye_glow
‪function zombie_eye_glow()
Definition: zombie_utility.gsc:1720
‪AbsYawToEnemy2d
‪function AbsYawToEnemy2d()
Definition: zombie_utility.gsc:404
‪sawEnemyMove
‪function sawEnemyMove(timer)
Definition: zombie_utility.gsc:1017
‪scriptChange
‪function scriptChange()
Definition: zombie_utility.gsc:1005
‪getAnimDirection
‪function getAnimDirection(damageyaw)
Definition: zombie_utility.gsc:2880
‪finish_rise_notetracks
‪function finish_rise_notetracks(note, spot)
Definition: zombie_utility.gsc:1616
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪zombie_spawn_failed
‪function zombie_spawn_failed(spawn)
Definition: zombie_utility.gsc:1553
‪set_orient_mode
‪function set_orient_mode(mode, val1)
Definition: zombie_utility.gsc:1364
‪GetCoverNodeYawToEnemy
‪function GetCoverNodeYawToEnemy()
Definition: zombie_utility.gsc:329
‪IS_BONUSZM
‪#define IS_BONUSZM
Definition: shared.gsh:532
‪GibRightArm
‪function GibRightArm(entity)
Definition: gib.gsc:467
‪GibHead
‪function GibHead(entity)
Definition: gib.gsc:443
‪head_gib_damage_over_time
‪function head_gib_damage_over_time(dmg, delay, attacker, means_of_death)
Definition: zombie_utility.gsc:2725
‪getNodeOffset
‪function getNodeOffset(node)
Definition: zombie_utility.gsc:818
‪name
‪class GroundFx name
‪showLines
‪function showLines(start, end, end2)
Definition: zombie_utility.gsc:909
‪initialize
‪function initialize(animscript)
Definition: zombie_utility.gsc:225
‪debugPosInternal
‪function debugPosInternal(org, string, size)
Definition: zombie_utility.gsc:759
‪zombieSpawnSetup
‪function zombieSpawnSetup()
Definition: zombie_utility.gsc:28
‪debug_allow_combat
‪function debug_allow_combat()
Definition: zombie_utility.gsc:1413
‪setup_zombie_knockdown
‪function setup_zombie_knockdown(entity)
Definition: zombie_utility.gsc:2204
‪default_max_zombie_func
‪function default_max_zombie_func(max_num, n_round)
Definition: zombie_utility.gsc:1933
‪GetNodeForward
‪function GetNodeForward()
Definition: zombie_utility.gsc:526
‪dumpAnimArray
‪function dumpAnimArray()
Definition: zombie_utility.gsc:1181
‪AngleClamp
‪function AngleClamp(angle)
Definition: zombie_utility.gsc:564
‪makeZombieCrawler
‪function makeZombieCrawler(b_both_legs)
Definition: zombie_utility.gsc:2918
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265
‪GETUP_BACK
‪#define GETUP_BACK
Definition: blackboard.gsh:205