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;
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;
17 #using scripts\shared\ai\systems\behavior_tree_utility;
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;
24 #using scripts\codescripts\struct;
26 #namespace zombie_utility;
30 self.zombie_move_speed =
"walk";
32 if ( !isdefined(
self.zombie_arms_position ) )
34 if(randomint( 2 ) == 0)
35 self.zombie_arms_position =
"up";
37 self.zombie_arms_position =
"down";
40 self.missingLegs =
false;
41 self setAvoidanceMask(
"avoid none" );
42 self PushActors(
true );
46 self.ignorePathEnemyFightDist =
true;
51 PixBeginEvent(
"get_closest_valid_player" );
53 valid_player_found =
false;
55 targets = GetPlayers();
57 if( isdefined( level.closest_player_targets_override ) )
59 targets = [[ level.closest_player_targets_override ]]();
62 if( IsDefined( ignore_player ) )
64 for(i = 0; i < ignore_player.size; i++ )
66 ArrayRemoveValue( targets, ignore_player[i] );
71 while ( targets.size && !done )
74 for(i = 0; i < targets.size; i++ )
79 ArrayRemoveValue( targets, target );
86 if( targets.size == 0 )
92 if( IsDefined(
self.closest_player_override ) )
94 target = [[
self.closest_player_override ]]( origin, targets );
96 else if( IsDefined( level.closest_player_override ) )
98 target = [[ level.closest_player_override ]]( origin, targets );
101 if( IsDefined( target ) )
107 sortedPotentialTargets = ArraySortClosest( targets,
self.origin );
109 while(sortedPotentialTargets.size)
111 if(
is_player_valid( sortedPotentialTargets[0],
true , ignore_laststand_players) )
114 return sortedPotentialTargets[0];
117 ArrayRemoveValue( sortedPotentialTargets, sortedPotentialTargets[0] );
126 if( !IsDefined( player ) )
131 if( !IsAlive( player ) )
136 if( !IsPlayer( player ) )
141 if( IsDefined(player.is_zombie) && player.is_zombie ==
true )
146 if( player.sessionstate ==
"spectator" )
151 if( player.sessionstate ==
"intermission" )
161 if(!
IS_TRUE(ignore_laststand_players))
169 if ( player IsNoTarget() )
175 if(
IS_TRUE(checkIgnoreMeFlag) && player.ignoreme )
181 if( IsDefined( level.is_player_valid_override ) )
183 return [[ level.is_player_valid_override ]]( player );
192 if (
self.missingLegs &&
self HasAnimStateFromASD( animstate +
"_crawl" ) )
194 return animstate +
"_crawl";
208 if ( animscript !=
"pain" && animscript !=
"death" )
210 self.a.special =
"none";
213 assert( IsDefined( animscript ),
"Animscript not specified in initAnimTree" );
214 self.a.script = animscript;
220 assert(
self.
a.movement==
"stop" ||
self.a.movement==
"walk" ||
self.a.movement==
"run",
"UpdateAnimPose "+
self.a.pose+
" "+
self.a.movement );
222 self.desired_anim_pose = undefined;
227 if ( IsDefined(
self.longDeathStarting ) )
229 if ( animscript !=
"pain" && animscript !=
"death" )
233 self DoDamage(
self.health + 100,
self.origin );
235 if ( animscript !=
"pain" )
237 self.longDeathStarting = undefined;
238 self notify(
"kill_long_death" );
241 if ( IsDefined(
self.
a.mayOnlyDie ) && animscript !=
"death" )
245 self DoDamage(
self.health + 100,
self.origin );
249 if ( IsDefined(
self.
a.postScriptFunc ) )
251 scriptFunc =
self.a.postScriptFunc;
252 self.a.postScriptFunc = undefined;
254 [[scriptFunc]]( animscript );
257 if ( animscript !=
"death" )
259 self.a.nodeath =
false;
262 self.isHoldingGrenade = undefined;
264 self.coverNode = undefined;
265 self.changingCoverPos =
false;
266 self.a.scriptStartTime = GetTime();
268 self.a.atConcealmentNode =
false;
269 if ( IsDefined(
self.node ) && (
self.node.type ==
"Conceal Crouch" ||
self.node.type ==
"Conceal Stand") )
271 self.a.atConcealmentNode =
true;
281 if (IsDefined (
self.node))
283 yaw =
self.node.angles[1] -
GetYaw(pos);
287 yaw =
self.angles[1] -
GetYaw(pos);
290 yaw = AngleClamp180( yaw );
299 pos =
self.enemy.origin;
303 if (IsDefined (
self.node))
305 forward = AnglesToForward(
self.node.angles);
309 forward = AnglesToForward(
self.angles);
312 forward = VectorScale (forward, 150);
313 pos =
self.origin + forward;
316 if (IsDefined (
self.node))
318 yaw =
self.node.angles[1] -
GetYaw(pos);
322 yaw =
self.angles[1] -
GetYaw(pos);
325 yaw = AngleClamp180( yaw );
334 pos =
self.enemy.origin;
338 forward = AnglesToForward(
self.coverNode.angles +
self.animarray[
"angle_step_out"][
self.a.cornerMode]);
339 forward = VectorScale (forward, 150);
340 pos =
self.origin + forward;
343 yaw =
self.CoverNode.angles[1] +
self.animarray[
"angle_step_out"][
self.a.cornerMode] -
GetYaw(pos);
344 yaw = AngleClamp180( yaw );
351 yaw =
self.angles[1] -
GetYaw(pos);
352 yaw = AngleClamp180( yaw );
361 pos =
self.enemy.origin;
365 forward = AnglesToForward(
self.angles);
366 forward = VectorScale (forward, 150);
367 pos =
self.origin + forward;
370 yaw =
self.angles[1] -
GetYaw(pos);
371 yaw = AngleClamp180( yaw );
377 angles = VectorToAngles(org-
self.origin);
383 angles = VectorToAngles((org[0], org[1], 0)-(
self.origin[0],
self.origin[1], 0));
392 yaw =
self.angles[1] -
GetYaw(
self.enemy.origin);
393 yaw = AngleClamp180( yaw );
408 yaw =
self.angles[1] -
GetYaw2d(
self.enemy.origin);
409 yaw = AngleClamp180( yaw );
422 yaw =
self.angles[1] -
GetYaw(org);
423 yaw = AngleClamp180( yaw );
435 yaw =
self.angles[1] - angles;
436 yaw = AngleClamp180( yaw );
448 angles = VectorToAngles(org-start);
454 yaw =
self GetTagAngles( tag )[1] -
GetYawFromOrigin(org,
self GetTagOrigin(tag));
455 yaw = AngleClamp180( yaw );
461 yaw =
self.angles[1] -
GetYaw(org);
462 yaw = AngleClamp180( yaw );
468 yaw =
self GetTagAngles(
"TAG_EYE")[1] -
GetYaw(org);
469 yaw = AngleClamp180( yaw );
475 yaw =
self.coverNode.angles[1] +
self.animarray[
"angle_step_out"][
self.a.cornerMode] -
GetYaw(org);
476 yaw = AngleClamp180( yaw );
483 if ( IsDefined(
self.coverNode ) )
488 return self IsStanceAllowed( stance );
495 if ( IsDefined(myNode) && (
self nearNode(myNode) || (IsDefined(
self.coverNode ) && myNode ==
self.coverNode)) )
506 if (IsDefined(myNode))
517 if (IsDefined(myNode))
520 return myNode.angles[1];
523 return self.desiredAngle;
529 if (IsDefined(myNode))
531 return AnglesToForward ( myNode.angles );
534 return AnglesToForward(
self.angles );
540 if (IsDefined(myNode))
542 return myNode.origin;
566 angleFrac = angle / 360.0;
567 angle = (angleFrac - floor( angleFrac )) * 360.0;
593 forwardWeight = (90 - abs(yaw)) / 90;
594 leftWeight = (90 - AbsAngleClamp180(abs(yaw-90))) / 90;
601 if ( IsDefined(
self.alwaysRunForward ) )
603 assert(
self.alwaysRunForward );
609 useLeans = GetDvarInt(
"ai_useLeanRunAnimations");
611 if (forwardWeight > 0)
613 result[
"front"] = forwardWeight;
621 result[
"right"] = -1 * leftWeight;
626 result[
"back"] = -1 * forwardWeight;
633 result[
"right"] = -1 * leftWeight;
641 backWeight = -1 * forwardWeight;
642 if ( leftWeight > backWeight )
646 else if ( leftWeight < forwardWeight )
664 if (angle<45 || angle>315)
687 for (i =
set.size - 1; i >= 0; i--)
689 if (input ==
set[i])
701 self endon(killmestring);
703 self notify (notifyString);
710 for (i=0;i<maxtime;i++)
712 Print3d (org, msg, color, 1, 1);
721 self notify (
"got known enemy2");
722 self endon (
"got known enemy2");
723 self endon (
"death");
730 if (
self.enemy.team ==
"allies")
732 color = (0.4, 0.7, 1);
736 color = (1, 0.7, 0.4);
743 if (!IsDefined (
self.lastEnemySightPos))
748 Print3d (
self.lastEnemySightPos,
string, color, 1, 2.15);
756 self notify (
"timeout");
762 self endon (
"death");
763 self notify (
"stop debug " + org);
764 self endon (
"stop debug " + org);
768 ent endon (
"timeout");
770 if (
self.enemy.team ==
"allies")
772 color = (0.4, 0.7, 1);
776 color = (1, 0.7, 0.4);
782 Print3d (org,
string, color, 1, size);
800 self endon (
"death");
808 line (fromPoint, toPoint, color);
815 self thread
showDebugProc( fromPoint, toPoint +( 0, 0, -5 ), color, printTime );
820 if ( IsDefined( node.offset ) )
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);
833 cover_stand_offset = (-3.7, -22, 63);
836 nodeOffset = (0,0,0);
838 right = AnglesToRight(node.angles);
839 forward = AnglesToForward(node.angles);
844 case "Cover Left Wide":
856 case "Cover Right Wide":
868 case "Conceal Stand":
874 case "Cover Crouch Window":
875 case "Conceal Crouch":
880 node.offset = nodeOffset;
886 return VectorScale( right, baseoffset[0] ) + VectorScale( forward, baseoffset[1] ) + (0, 0, baseoffset[2]);
893 pitch = AngleClamp180( VectorToAngles( toPoint - fromPoint )[0] );
894 if ( abs( pitch ) > 45 )
896 if ( IsDefined( atNode ) && atNode.type !=
"Cover Crouch" && atNode.type !=
"Conceal Crouch" )
901 if ( pitch > 45 || pitch < anim.coverCrouchLeanPitch - 45 )
914 line(start,
end, (1,0,0), 1);
916 line(start, end2, (0,0,1), 1);
926 idleanim = RandomInt(total_anims);
928 assert (total_anims);
931 if (total_anims == 1)
939 for (i = 0; i < total_anims; i++)
941 total_weight += animWeights[i];
944 anim_play = RandomFloat(total_weight);
947 for (i = 0; i < total_anims; i++)
949 current_weight += animWeights[i];
950 if (anim_play >= current_weight)
964 return ((
self.
a.forced_cover ==
"none") || (
self.a.forced_cover ==
"Show"));
969 return IsDefined(
self.
a.forced_cover) && (
self.a.forced_cover == msg);
976 for (i=0;i<newtime;i++)
978 Print3d (org, msg, color, alpha, scale);
991 for (i=0;i<newtime;i++)
994 Print3d (org + (0,0,up), msg, color, alpha, scale);
1002 return (vec1[0]*vec2[1] - vec1[1]*vec2[0] > 0);
1007 self.a.current_script =
"none";
1008 self notify (anim.scriptChange);
1024 return (GetTime() -
self.personalSightTime <
timer);
1029 if (!
self.grenadeAmmo)
1034 if (
self.script_forceGrenade)
1039 return (IsPlayer(
self.enemy));
1044 idleanim = RandomInt (
array.size);
1048 for (i=0;i<
array.size;i++)
1050 anim_weight +=
array[i];
1053 anim_play = RandomFloat (anim_weight);
1056 for (i=0;i<
array.size;i++)
1058 anim_weight +=
array[i];
1059 if (anim_play < anim_weight)
1072 assert(IsDefined(
name),
"Need to define the footstep surface type.");
1073 assert(IsDefined(fx),
"Need to define the mud footstep effect.");
1075 if (!IsDefined(anim.optionalStepEffects))
1077 anim.optionalStepEffects = [];
1080 anim.optionalStepEffects[anim.optionalStepEffects.size] =
name;
1081 level._effect[
"step_" +
name] = fx;
1088 self endon (
"death");
1089 level notify (
"newdebugline");
1090 level endon (
"newdebugline");
1094 line (start,
end, (0.3,1,0), 1);
1102 return (
self.spawnflags & 4) == 4;
1106 return (
self.spawnflags & 8) == 8;
1111 if ( stance ==
"stand" )
1117 Assert( stance ==
"crouch" );
1126 assert( IsDefined(
self.
a.array) );
1129 if ( !IsDefined(
self.
a.array[animname]) )
1132 assert( IsDefined(
self.
a.array[animname]),
"self.a.array[ \"" + animname +
"\" ] is undefined" );
1136 return self.a.array[animname];
1141 assert( IsDefined(
self.
a.array ) );
1144 if ( !IsDefined(
self.
a.array[animname]) )
1147 assert( IsDefined(
self.
a.array[animname]),
"self.a.array[ \"" + animname +
"\" ] is undefined" );
1151 return self.a.array[animname].size > 0;
1156 assert( IsDefined(
self.
a.array ) );
1159 if ( !IsDefined(
self.
a.array[animname]) )
1162 assert( IsDefined(
self.
a.array[animname]),
"self.a.array[ \"" + animname +
"\" ] is undefined" );
1166 assert(
self.
a.array[animname].size > 0 );
1168 if (
self.
a.array[animname].size > 1 )
1170 index = RandomInt(
self.
a.array[animname].size );
1177 return self.a.array[animname][index];
1183 println(
"self.a.array:");
1184 keys = getArrayKeys(
self.
a.array );
1186 for ( i=0; i < keys.size; i++ )
1188 if ( isarray(
self.
a.array[ keys[i] ] ) )
1190 println(
" array[ \"" + keys[i] +
"\" ] = {array of size " +
self.
a.array[ keys[i] ].size +
"}" );
1194 println(
" array[ \"" + keys[i] +
"\" ] = ",
self.
a.array[ keys[i] ] );
1202 moveDelta = getMoveDelta( theanim, 0, 1,
self );
1203 return self localToWorldCoords( moveDelta );
1208 if ( !IsDefined( enemy ) )
1217 function damageLocationIsAny(
a, b, c, d, e, f, g, h, i, j, k, ovr )
1240 if(!isDefined(
self.damageLocation))
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));
1260 self endon (
"killanimscript" );
1262 lastOrg =
self.origin;
1268 force = distance(
self.origin, lastOrg );
1269 lastOrg =
self.origin;
1271 if (
self.health == 1 )
1273 self.a.nodeath =
true;
1274 self startRagdoll();
1277 physicsExplosionSphere( lastOrg, 600, 0, force * 0.1 );
1278 self notify (
"killanimscript" );
1286 return IsDefined(
self.cqbwalking ) &&
self.cqbwalking;
1291 return value * value;
1296 self.a.idleSet = RandomInt( 2 );
1302 assert( intMax > 0 );
1304 index = intSeed % anim.randomIntTableSize;
1305 return anim.randomIntTable[ index ] % intMax;
1311 return IsDefined(
self.banzai ) &&
self.banzai;
1317 return IsDefined(
self.heavy_machine_gunner ) &&
self.heavy_machine_gunner;
1343 if ((skeleton ==
"base") && IsSubStr(
get_skeleton(),
"scaled"))
1354 if (IsDefined(
self.skeleton))
1356 return self.skeleton;
1367 if ( level.dog_debug_orient ==
self getentnum() )
1369 if ( IsDefined( val1 ) )
1370 println(
"DOG: Setting orient mode: " + mode +
" " + val1 +
" " + getTime() );
1372 println(
"DOG: Setting orient mode: " + mode +
" " + getTime() );
1376 if ( IsDefined( val1 ) )
1377 self OrientMode( mode, val1 );
1379 self OrientMode( mode );
1385 if ( IsDefined( level.dog_debug_anims ) && level.dog_debug_anims )
1386 println( text+
" " + getTime() );
1388 if ( IsDefined( level.dog_debug_anims_ent ) && level.dog_debug_anims_ent ==
self getentnum() )
1389 println( text+
" " + getTime() );
1396 if ( IsDefined( level.dog_debug_turns ) && level.dog_debug_turns ==
self getentnum() )
1399 currentYawColor = (1,1,1);
1400 lookaheadYawColor = (1,0,0);
1401 desiredYawColor = (1,1,0);
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 );
1434 function set_zombie_var( zvar, value, is_float =
false, column = 1, is_team_based =
false )
1438 if ( is_team_based )
1440 foreach( team
in level.teams )
1442 DEFAULT(level.zombie_vars[team],[]);
1443 level.zombie_vars[ team ][ zvar ] = value;
1448 level.zombie_vars[zvar] = value;
1456 if( !IsDefined( spawner ) )
1458 /# println(
"ZM >> spawn_zombie - NO SPAWNER DEFINED" ); #/
1462 while ( GetFreeActorCount() < 1 )
1467 spawner.script_moveoverride =
true;
1469 if(
IS_TRUE(spawner.script_forcespawn ))
1473 else if( IsActorSpawner( spawner ) && IsDefined( level.overrideZombieSpawn ) )
1475 guy = [[level.overrideZombieSpawn]]();
1479 guy = spawner SpawnFromSpawner( 0,
true );
1485 guy.spawn_time = GetTime();
1487 if ( isdefined( level.giveExtraZombies ) )
1489 guy [[level.giveExtraZombies]]();
1492 guy EnableAimAssist();
1494 if(IsDefined(round_number))
1496 guy._starting_round_number = round_number;
1500 guy.team = level.zombie_team;
1501 if( IsActor( guy ) )
1502 guy ClearEntityOwner();
1503 level.zombieMeleePlayerCounter = 0;
1505 if( IsActor( guy ) )
1506 guy forceteleport( spawner.origin );
1511 spawner.count = 666;
1513 if( IsDefined( target_name ) )
1515 guy.targetname = target_name;
1518 if(IsDefined(spawn_point) && IsDefined(level.move_spawn_func))
1520 guy thread [[level.move_spawn_func]](spawn_point);
1524 if( IsDefined( spawner.zm_variant_type ) )
1526 guy.variant_type = spawner.zm_variant_type;
1534 /# println(
"ZM >> spawn_zombie - FAILED TO SPAWN A ZOMBIE FROM SPAWNER AT ", spawner.origin ); #/
1540 /# println(
"ZM >> spawn_zombie - ZOMBIE SPAWNER MUST BE SET FORCESPAWN", spawner.origin ); #/
1572 if( IsDefined(
self.target ) )
1574 ent = GetEnt(
self.target,
"targetname" );
1575 if( !IsDefined( ent ) )
1580 if( !IsDefined( ent ) )
1582 ent = GetNode(
self.target,
"targetname" );
1585 assert( IsDefined( ent ),
"Cannot find the targeted ent/node/struct, \"" +
self.target +
"\" at " +
self.origin );
1595 self endon(
"death" );
1600 if ( IsDefined(
self ) )
1606 self.create_eyes =
true;
1621 if (note ==
"deathout" || note ==
"deathhigh")
1623 self.zombie_rise_death_out =
true;
1624 self notify(
"zombie_rise_death_out");
1627 spot notify(
"stop_zombie_rise_fx");
1638 zombie.zombie_rise_death_out =
false;
1640 zombie endon(
"rise_anim_finished");
1642 while ( IsDefined( zombie ) && IsDefined( zombie.health ) && zombie.health > 1)
1644 zombie waittill(
"damage", amount);
1647 if( IsDefined(spot) )
1649 spot notify(
"stop_zombie_rise_fx");
1652 if ( IsDefined( zombie ) )
1655 zombie StopAnimScripted();
1661 if (
self.zombie_rise_death_out )
1663 return "zm_rise_death_out";
1666 self.noragdoll =
true;
1667 self.nodeathragdoll =
true;
1668 return "zm_rise_death_in";
1673 if( IsDefined(
self.attacking_node ) )
1675 node =
self.attacking_node;
1676 index =
self.attacking_spot_index;
1677 node.attack_spots_taken[index] =
false;
1679 self.attacking_node = undefined;
1680 self.attacking_spot_index = undefined;
1686 self.guts_explosion=1;
1702 self endon(
"zombie_delete");
1703 self endon(
"death");
1707 while(!IsDefined(
self.create_eyes))
1722 if(!IsDefined(
self) || !IsActor(
self ))
1726 if ( !IsDefined(
self.no_eye_glow ) || !
self.no_eye_glow )
1735 if(!IsDefined(
self) || !IsActor(
self ))
1739 if ( !IsDefined(
self.no_eye_glow ) || !
self.no_eye_glow )
1755 self endon(
"death");
1760 prevorigin =
self.origin;
1763 if(
IS_TRUE(level.toggle_keyline_always) )
1775 if ( IsDefined(
self.lastchunk_destroy_time) )
1777 if ( (GetTime() -
self.lastchunk_destroy_time) < 8000 )
1782 if ( DistanceSquared(
self.origin, prevorigin ) < 576 )
1791 prevorigin =
self.origin;
1808 self endon(
"death");
1810 if(
IS_TRUE(level.debug_keyline_zombies) )
1818 prevorigin =
self.origin;
1821 if( !level.zombie_vars[
"zombie_use_failsafe"] )
1826 if (
IS_TRUE(
self.ignore_round_spawn_failsafe ) )
1831 if(!IsDefined(level.failsafe_waittime))
1833 level.failsafe_waittime = 30;
1836 wait( level.failsafe_waittime );
1838 if(
self.missingLegs )
1851 if ( IsDefined(
self.lastchunk_destroy_time) )
1853 if ( (GetTime() -
self.lastchunk_destroy_time) < 8000 )
1858 if (
self.origin[2] < level.zombie_vars[
"below_world_check"] )
1860 if(
IS_TRUE(level.put_timed_out_zombies_back_in_queue ) && !level
flag::get(
"special_round") && !
IS_TRUE(
self.isscreecher ) )
1862 level.zombie_total++;
1863 level.zombie_total_subtract++;
1866 self dodamage(
self.health + 100, (0,0,0) );
1871 if ( DistanceSquared(
self.origin, prevorigin ) < 576 )
1873 if( IsDefined( level.move_failsafe_override ) )
1875 self thread [[level.move_failsafe_override]]( prevorigin );
1880 if(
IS_TRUE(level.put_timed_out_zombies_back_in_queue ) && !level
flag::get(
"special_round"))
1883 if ( !
self.ignoreall && !
IS_TRUE(
self.nuked) && !
IS_TRUE(
self.marked_for_death) && !
IS_TRUE(
self.isscreecher ) && !
self.missingLegs )
1885 level.zombie_total++;
1886 level.zombie_total_subtract++;
1891 level.zombies_timeout_playspace++;
1894 self dodamage(
self.health + 100, (0,0,0) );
1899 prevorigin =
self.origin;
1909 level.zombie_health = level.zombie_vars[
"zombie_health_start"];
1910 for ( i=2; i <= round_number; i++ )
1915 old_health = level.zombie_health;
1916 level.zombie_health += Int( level.zombie_health * level.zombie_vars[
"zombie_health_increase_multiplier"] );
1918 if ( level.zombie_health < old_health )
1921 level.zombie_health = old_health;
1927 level.zombie_health = Int( level.zombie_health + level.zombie_vars[
"zombie_health_increase"] );
1936 count = GetDvarInt(
"zombie_default_max", -1 );
1947 max = int( max_num * 0.25 );
1949 else if( n_round < 3 )
1951 max = int( max_num * 0.3 );
1953 else if( n_round < 4 )
1955 max = int( max_num * 0.5 );
1957 else if( n_round < 5 )
1959 max = int( max_num * 0.7 );
1961 else if( n_round < 6 )
1963 max = int( max_num * 0.9 );
1971 if( level.round_number <= 3 )
1976 level endon(
"intermission" );
1977 level endon(
"end_of_round" );
1978 level endon(
"restart_round" );
1979 level endon(
"kill_round" );
1982 while ( level.zombie_total > 4 )
1989 while( a_ai_zombies.size > 0 || level.zombie_total > 0 )
1991 if( a_ai_zombies.size == 1 )
1993 ai_zombie = a_ai_zombies[0];
1995 if( IsAlive( ai_zombie ) )
1997 if ( IsDefined( level.zombie_speed_up ) )
1999 ai_zombie thread [[ level.zombie_speed_up ]]();
2004 if( !
IS_EQUAL(ai_zombie.zombie_move_speed,
"sprint") )
2007 ai_zombie.zombie_move_speed_original = ai_zombie.zombie_move_speed;
2021 return enemies.size;
2027 a_ai_valid_enemies = [];
2028 a_ai_enemies = GetAITeamArray( level.zombie_team );
2030 for( i = 0; i < a_ai_enemies.size; i++ )
2032 if (
IS_TRUE( a_ai_enemies[i].ignore_enemy_count ) )
2036 ARRAY_ADD( a_ai_valid_enemies, a_ai_enemies[i] );
2039 return a_ai_valid_enemies;
2047 enemies = GetAiSpeciesArray( level.zombie_team,
"all" );
2049 for( i = 0; i < enemies.size; i++ )
2057 return valid_enemies;
2064 self.zombie_move_speed_override = new_move_speed;
2070 str_restore_move_speed =
self.zombie_move_speed_restore;
2072 self.zombie_move_speed_override = undefined;
2079 if( isdefined(
self.zombie_move_speed_override ) )
2081 self.zombie_move_speed_restore = new_move_speed;
2085 self.zombie_move_speed_original =
self.zombie_move_speed;
2087 if ( IsDefined( new_move_speed ) )
2089 self.zombie_move_speed = new_move_speed;
2093 if( level.gamedifficulty == 0 )
2098 if( IsDefined( level.zm_variant_type_max ) )
2106 debug_variant_type = GetDvarInt(
"scr_zombie_variant_type", -1 );
2108 if( debug_variant_type != -1 )
2110 if(debug_variant_type <= level.zm_variant_type_max[
self.zombie_move_speed][
self.zombie_arms_position] )
2112 self.variant_type = debug_variant_type;
2116 self.variant_type = level.zm_variant_type_max[
self.zombie_move_speed][
self.zombie_arms_position] - 1;
2121 self.variant_type = RandomInt( level.zm_variant_type_max[
self.zombie_move_speed][
self.zombie_arms_position] );
2128 if ( isdefined(
self.zm_variant_type_max ) )
2130 self.variant_type = RandomInt(
self.zm_variant_type_max[
self.zombie_move_speed][
self.zombie_arms_position] );
2134 if ( isdefined( level.zm_variant_type_max[
self.zombie_move_speed] ) )
2136 self.variant_type = RandomInt( level.zm_variant_type_max[
self.zombie_move_speed][
self.zombie_arms_position] );
2141 ErrorMsg(
"No variants set up for move speed " +
self.zombie_move_speed );
2143 self.variant_type = 0;
2149 self.needs_run_update =
true;
2150 self notify(
"needs_run_update" );
2158 if( isdefined(level.zombie_force_run) )
2160 self.zombie_move_speed =
"run";
2161 level.zombie_force_run--;
2162 if( level.zombie_force_run <= 0 )
2164 level.zombie_force_run = undefined;
2170 rand = randomintrange( level.zombie_move_speed, level.zombie_move_speed + 35 );
2175 self.zombie_move_speed =
"walk";
2177 else if( rand <= 70 )
2179 self.zombie_move_speed =
"run";
2183 self.zombie_move_speed =
"sprint";
2189 rand = randomintrange( level.zombie_move_speed, level.zombie_move_speed + 25 );
2194 self.zombie_move_speed =
"walk";
2198 self.zombie_move_speed =
"run";
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 ) );
2210 zombie_forward = AnglesToForward(
self.angles );
2211 zombie_forward_2d = VectorNormalize( ( zombie_forward[0], zombie_forward[1], 0 ) );
2213 zombie_right = AnglesToRight(
self.angles );
2214 zombie_right_2d = VectorNormalize( ( zombie_right[0], zombie_right[1], 0 ) );
2216 dot = VectorDot( zombie_to_entity_2d, zombie_forward_2d );
2220 self.knockdown_direction =
"front";
2223 else if ( dot < 0.5 && dot > -0.5 )
2225 dot = VectorDot( zombie_to_entity_2d, zombie_right_2d );
2228 self.knockdown_direction =
"right";
2241 self.knockdown_direction =
"left";
2247 self.knockdown_direction =
"back";
2254 corpse_array = GetCorpseArray();
2256 for ( i = 0; i < corpse_array.size; i++ )
2258 if ( IsDefined( corpse_array[ i ] ) )
2260 corpse_array[ i ] Delete();
2268 actors = GetAiSpeciesArray( level.zombie_team,
"all" );
2269 if (IsDefined(actors))
2270 count += actors.size;
2277 corpse_array = GetCorpseArray();
2278 if (IsDefined(corpse_array))
2279 return corpse_array.size;
2293 self waittill(
"damage", amount, attacker, direction_vec, point, type, tagName, ModelName, Partname, weapon );
2295 if( !IsDefined(
self ) )
2305 if(
self head_should_gib( attacker, type, point ) && type !=
"MOD_BURNED" )
2311 if( !
IS_TRUE(
self.gibbed) && isDefined(
self.damageLocation) )
2314 if (
self damagelocationisany(
"head",
"helmet",
"neck" ) )
2320 self.stumble = undefined;
2323 switch(
self.damageLocation )
2334 case "right_arm_upper":
2335 case "right_arm_lower":
2342 case "left_arm_upper":
2343 case "left_arm_lower":
2350 case "right_leg_upper":
2351 case "right_leg_lower":
2353 if(
self.health <= 0 )
2358 if( randomint( 100 ) > 75 )
2361 self.missingLegs =
true;
2365 case "left_leg_upper":
2366 case "left_leg_lower":
2368 if(
self.health <= 0 )
2371 if( randomint( 100 ) > 75 )
2374 self.missingLegs =
true;
2380 if(
self.damageLocation ==
"none" )
2383 if( type ==
"MOD_GRENADE" || type ==
"MOD_GRENADE_SPLASH" || type ==
"MOD_PROJECTILE" || type ==
"MOD_PROJECTILE_SPLASH" )
2393 if( IsDefined( level.custom_derive_damage_refs ) )
2399 if(
IS_TRUE(
self.missingLegs) &&
self.health > 0 )
2402 self AllowedStances(
"crouch" );
2405 self setPhysParams( 15, 0, 24 );
2407 self AllowPitchAngle( 1 );
2408 self setPitchOrient();
2410 health =
self.health;
2411 health = health * 0.1;
2413 if ( IsDefined(
self.crawl_anim_override ) )
2415 self [[
self.crawl_anim_override ]]();
2420 if(
self.health > 0 )
2423 if ( IsDefined( level.gib_on_damage ) )
2425 self thread [[ level.gib_on_damage ]]();
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;
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] ) )
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] ) )
2459 return self [[level.zombie_gib_weapons[weapon]]]( damage_percent );
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] ) )
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] ) )
2483 return self [[level.zombie_gib_head_weapons[weapon]]]( damage_location );
2490 if( !IsDefined( type ) )
2500 if ( IsDefined(
self.no_gib ) && (
self.no_gib == 1 ) )
2505 prev_health = amount +
self.health;
2506 if( prev_health <= 0 )
2511 damage_percent = ( amount / prev_health ) * 100;
2514 if( IsDefined( attacker ) )
2516 if( IsPlayer( attacker ) ||
IS_TRUE(attacker.can_gib_zombies) )
2518 if( IsPlayer( attacker ) )
2520 weapon = attacker GetCurrentWeapon();
2524 weapon = attacker.weapon;
2541 case "MOD_TELEFRAG":
2544 case "MOD_TRIGGER_HURT":
2559 if( type ==
"MOD_PISTOL_BULLET" || type ==
"MOD_RIFLE_BULLET" )
2561 if( !IsDefined( attacker ) || !IsPlayer( attacker ) )
2566 if( weapon == level.weaponNone || (IsDefined(level.start_weapon) && weapon == level.start_weapon) || weapon.isGasWeapon )
2576 if( damage_percent < 10 /*|| damage_percent >= 100*/ )
2591 if( !isdefined( attacker ) )
2596 if( !IsPlayer( attacker ) )
2598 if( !
IS_TRUE( attacker.can_gib_zombies) )
2605 if( IsPlayer(attacker ))
2607 weapon = attacker GetCurrentWeapon();
2611 weapon = attacker.weapon;
2626 if( type !=
"MOD_RIFLE_BULLET" && type !=
"MOD_PISTOL_BULLET" )
2629 if( type ==
"MOD_GRENADE" || type ==
"MOD_GRENADE_SPLASH" )
2631 if( Distance( point,
self GetTagOrigin(
"j_head" ) ) > 55 )
2641 else if( type ==
"MOD_PROJECTILE" )
2643 if( Distance( point,
self GetTagOrigin(
"j_head" ) ) > 10 )
2653 else if( weapon.weapClass !=
"spread" )
2660 if ( !
self damagelocationisany(
"head",
"helmet",
"neck" ) )
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 )
2675 if( SessionModeIsCampaignGame() && (type ==
"MOD_PISTOL_BULLET" && weapon.weapClass !=
"smg"))
2680 low_health_percent = (
self.health /
self.maxhealth ) * 100;
2681 if( low_health_percent > 10 )
2694 self endon(
"death" );
2701 if ( !IsDefined(
self.gibSpawn5 ) || !IsDefined(
self.gibSpawnTag5 ) )
2706 self.hat_gibbed =
true;
2708 if ( IsDefined(
self.hatmodel ) )
2710 self detach(
self.hatModel,
"" );
2714 temp_array[0] = level._ZOMBIE_GIB_PIECE_INDEX_HAT;
2716 self gib(
"normal", temp_array );
2719 if ( IsDefined( level.track_gibs ) )
2721 level [[ level.track_gibs ]](
self, temp_array );
2727 self endon(
"death" );
2728 self endon(
"exploding" );
2730 if( !IsAlive(
self ) )
2735 if( !IsPlayer( attacker ) )
2740 if ( !IsDefined( means_of_death ) )
2742 means_of_death =
"MOD_UNKNOWN";
2745 dot_location =
self.damageLocation;
2746 dot_weapon =
self.damageweapon;
2750 if( IsDefined(
delay ) )
2754 if (IsDefined(
self))
2760 if(IsDefined(attacker))
2762 self DoDamage( dmg,
self GetTagOrigin(
"j_neck" ), attacker,
self, dot_location, means_of_death, 0, dot_weapon );
2766 self DoDamage( dmg,
self GetTagOrigin(
"j_neck" ));
2775 if( !IsDefined( level.gib_tags ) )
2780 closestTag = undefined;
2782 for( i = 0; i < level.gib_tags.size; i++ )
2784 if( !IsDefined( closestTag ) )
2786 closestTag = level.gib_tags[i];
2790 if( DistanceSquared( point,
self GetTagOrigin( level.gib_tags[i] ) ) < DistanceSquared( point,
self GetTagOrigin( closestTag ) ) )
2792 closestTag = level.gib_tags[i];
2798 if( closestTag ==
"J_SpineLower" || closestTag ==
"J_SpineUpper" || closestTag ==
"J_Spine4" )
2806 else if( closestTag ==
"J_Shoulder_LE" || closestTag ==
"J_Elbow_LE" || closestTag ==
"J_Wrist_LE" )
2811 else if( closestTag ==
"J_Shoulder_RI" || closestTag ==
"J_Elbow_RI" || closestTag ==
"J_Wrist_RI" )
2816 else if( closestTag ==
"J_Hip_LE" || closestTag ==
"J_Knee_LE" || closestTag ==
"J_Ankle_LE" )
2824 if( randomint(100) > 75)
2826 self.missingLegs =
true;
2828 else if( closestTag ==
"J_Hip_RI" || closestTag ==
"J_Knee_RI" || closestTag ==
"J_Ankle_RI" )
2836 if( randomint(100) > 75)
2838 self.missingLegs =
true;
2852 tags[tags.size] =
"J_SpineLower";
2853 tags[tags.size] =
"J_SpineUpper";
2854 tags[tags.size] =
"J_Spine4";
2857 tags[tags.size] =
"J_Shoulder_LE";
2858 tags[tags.size] =
"J_Elbow_LE";
2859 tags[tags.size] =
"J_Wrist_LE";
2862 tags[tags.size] =
"J_Shoulder_RI";
2863 tags[tags.size] =
"J_Elbow_RI";
2864 tags[tags.size] =
"J_Wrist_RI";
2867 tags[tags.size] =
"J_Hip_LE";
2868 tags[tags.size] =
"J_Knee_LE";
2869 tags[tags.size] =
"J_Ankle_LE";
2872 tags[tags.size] =
"J_Hip_RI";
2873 tags[tags.size] =
"J_Knee_RI";
2874 tags[tags.size] =
"J_Ankle_RI";
2876 level.gib_tags = tags;
2882 if( ( damageyaw > 135 ) ||( damageyaw <= -135 ) )
2886 else if( ( damageyaw > 45 ) &&( damageyaw <= 135 ) )
2890 else if( ( damageyaw > -45 ) &&( damageyaw <= 45 ) )
2909 if ( GetDvarString( dvar ) !=
"" )
2910 return getdvarfloat( dvar );
2913 SetDvar( dvar, def );
2926 val = randomint( 100 );
2934 else if ( val > 37 )
2939 self.missingLegs =
true;
2940 self AllowedStances(
"crouch" );
2943 self setPhysParams( 15, 0, 24 );
2945 self AllowPitchAngle( 1 );
2946 self setPitchOrient();
2948 health =
self.health;
2949 health = health * 0.1;
2954 self endon(
"death" );
2956 if (
IS_TRUE(
self.head_gibbed ) )
2966 self.head_gibbed =
true;
2971 if( !
IS_TRUE(
self.disable_head_gib ) )
2986 val = randomint( 100 );
2991 val = randomint( 100 );
2996 val = randomint( 100 );
3001 val = randomint( 100 );
3007 val = randomint( 100 );
3018 level._IGNORE_PLAYER_HANDLER = [];
3023 Assert( IsDefined( archetype ),
"IgnorePlayerHandler undefined archetype." );
3025 Assert( !IsDefined( level._IGNORE_PLAYER_HANDLER[ archetype ] ),
"IgnorePlayerHandler for " + archetype +
" is already registered." );
3027 level._IGNORE_PLAYER_HANDLER[ archetype ] = ignore_player_func;
3032 if ( IsDefined( level._IGNORE_PLAYER_HANDLER[
self.archetype ] ) )
3034 self [[ level._IGNORE_PLAYER_HANDLER[
self.archetype ] ]]();
3041 if ( IsDefined(
self ) && IsDefined(
self.hud_damagefeedback ) )
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;