1 #using scripts\shared\clientfield_shared;
2 #using scripts\shared\system_shared;
3 #using scripts\shared\util_shared;
4 #using scripts\shared\flag_shared;
5 #using scripts\shared\math_shared;
6 #using scripts\shared\ai_shared;
7 #using scripts\shared\ai\systems\animation_state_machine_utility;
8 #using scripts\shared\ai\systems\animation_state_machine_notetracks;
9 #using scripts\shared\ai\systems\animation_state_machine_mocomp;
10 #using scripts\shared\ai\archetype_utility;
11 #using scripts\shared\ai\archetype_locomotion_utility;
12 #using scripts\shared\ai\systems\behavior_tree_utility;
13 #using scripts\shared\ai\systems\blackboard;
14 #using scripts\shared\ai\zombie;
15 #using scripts\shared\ai\zombie_utility;
17 #using scripts\zm\_zm_attackables;
18 #using scripts\zm\_zm_behavior_utility;
19 #using scripts\zm\_zm_spawner;
20 #using scripts\zm\_zm_utility;
22 #insert scripts\shared\shared.gsh;
23 #insert scripts\shared\ai\zombie.gsh;
24 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
25 #insert scripts\shared\ai\systems\behavior.gsh;
26 #insert scripts\shared\ai\systems\behavior_tree.gsh;
27 #insert scripts\shared\ai\systems\blackboard.gsh;
28 #insert scripts\shared\ai\utility.gsh;
29 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
31 #insert scripts\zm\_zm_behavior.gsh;
34 #namespace zm_behavior;
36 #define BHB_BURST "bhb_burst"
145 SetDvar(
"scr_zm_use_code_enemy_selection", 1 );
151 if ( isdefined( behaviorTreeEntity.enablePushTime ) )
153 if ( GetTime() >= behaviorTreeEntity.enablePushTime )
155 behaviorTreeEntity PushActors(
true );
156 behaviorTreeEntity.enablePushTime = undefined;
160 if( GetDvarInt(
"scr_zm_use_code_enemy_selection", 0 ) )
166 if( level.intermission )
171 if ( behaviorTreeEntity GetPathMode() ==
"dont move" )
176 behaviorTreeEntity.ignoreme =
false;
178 behaviorTreeEntity.ignore_player = [];
182 if (
IS_TRUE( behaviorTreeEntity.ignore_find_flesh ) )
187 if ( behaviorTreeEntity.team ==
"allies" )
199 behaviorTreeEntity.zombie_poi = zombie_poi;
201 players = GetPlayers();
204 if( !isdefined(behaviorTreeEntity.ignore_player) || (players.size == 1) )
206 behaviorTreeEntity.ignore_player = [];
208 else if(!isDefined(level._should_skip_ignore_player_logic) || ![[level._should_skip_ignore_player_logic]]() )
211 while (i < behaviorTreeEntity.ignore_player.size)
213 if( IsDefined( behaviorTreeEntity.ignore_player[i] ) && IsDefined( behaviorTreeEntity.ignore_player[i].ignore_counter ) && behaviorTreeEntity.ignore_player[i].ignore_counter > 3 )
215 behaviorTreeEntity.ignore_player[i].ignore_counter = 0;
216 behaviorTreeEntity.ignore_player = ArrayRemoveValue( behaviorTreeEntity.ignore_player, behaviorTreeEntity.ignore_player[i] );
217 if (!IsDefined(behaviorTreeEntity.ignore_player))
218 behaviorTreeEntity.ignore_player = [];
230 designated_target =
false;
231 if ( IsDefined( player ) &&
IS_TRUE( player.b_is_designated_target ) )
233 designated_target =
true;
236 if( !isDefined( player ) && !isDefined( zombie_poi ) && !isDefined( behaviorTreeEntity.attackable ) )
239 if( IsDefined( behaviorTreeEntity.ignore_player ) )
241 if(isDefined(level._should_skip_ignore_player_logic) && [[level._should_skip_ignore_player_logic]]() )
245 behaviorTreeEntity.ignore_player = [];
249 if(
IS_TRUE( behaviortreeentity.isPuppet ) )
255 if( isdefined( level.no_target_override ) )
257 [[ level.no_target_override ]]( behaviorTreeEntity );
261 behaviorTreeEntity SetGoal( behaviorTreeEntity.origin );
269 if ( !isDefined( level.check_for_alternate_poi ) || ![[level.check_for_alternate_poi]]() )
271 behaviorTreeEntity.enemyoverride = zombie_poi;
273 behaviorTreeEntity.favoriteenemy = player;
276 if( isdefined( behaviorTreeEntity.v_zombie_custom_goal_pos ) )
278 goalPos = behaviorTreeEntity.v_zombie_custom_goal_pos;
280 if ( isdefined( behaviorTreeEntity.n_zombie_custom_goal_radius ) )
282 behaviorTreeEntity.goalradius = behaviorTreeEntity.n_zombie_custom_goal_radius;
285 behaviorTreeEntity SetGoal( goalPos );
287 else if ( isdefined( behaviorTreeEntity.enemyoverride ) && isdefined( behaviorTreeEntity.enemyoverride[1] ) )
289 behaviorTreeEntity.has_exit_point = undefined;
291 goalPos = behaviorTreeEntity.enemyoverride[0];
295 if( !IsDefined(zombie_poi) )
297 AIProfile_BeginEntry(
"zombiefindflesh-enemyoverride" );
298 queryResult = PositionQuery_Source_Navigation( goalPos, 0, 48, 36, 4 );
299 AIProfile_EndEntry();
301 foreach( point
in queryResult.data )
303 goalPos = point.origin;
308 behaviorTreeEntity SetGoal( goalPos );
311 else if ( isdefined( behaviorTreeEntity.attackable ) && !designated_target )
313 if ( isdefined( behaviorTreeEntity.attackable_slot ) )
315 if ( isdefined( behaviorTreeEntity.attackable_goal_radius ) )
317 behaviorTreeEntity.goalradius = behaviorTreeEntity.attackable_goal_radius;
320 nav_mesh = GetClosestPointOnNavMesh( behaviorTreeEntity.attackable_slot.origin, 64 );
321 if ( isdefined( nav_mesh ) )
323 behaviorTreeEntity SetGoal( nav_mesh );
327 behaviorTreeEntity SetGoal( behaviorTreeEntity.attackable_slot.origin );
331 else if ( IsDefined( behaviorTreeEntity.favoriteenemy ) )
333 behaviorTreeEntity.has_exit_point = undefined;
335 behaviorTreeEntity.ignoreall =
false;
337 if ( IsDefined( level.enemy_location_override_func ) )
339 goalPos = [[ level.enemy_location_override_func ]]( behaviorTreeEntity, behaviorTreeEntity.favoriteenemy );
341 if ( IsDefined( goalPos ) )
343 behaviorTreeEntity SetGoal( goalPos );
350 else if(
IS_TRUE(behaviorTreeEntity.is_rat_test) )
356 else if ( IsDefined( behaviorTreeEntity.favoriteenemy.last_valid_position ) )
367 if( players.size > 1 )
369 for(i = 0; i < behaviorTreeEntity.ignore_player.size; i++)
371 if( IsDefined( behaviorTreeEntity.ignore_player[i] ) )
373 if( !IsDefined( behaviorTreeEntity.ignore_player[i].ignore_counter ) )
374 behaviorTreeEntity.ignore_player[i].ignore_counter = 0;
376 behaviorTreeEntity.ignore_player[i].ignore_counter += 1;
387 AIProfile_BeginEntry(
"zombieFindFleshCode" );
389 if( level.intermission )
391 AIProfile_EndEntry();
395 behaviorTreeEntity.ignore_player = [];
399 if ( behaviorTreeEntity.team ==
"allies" )
403 AIProfile_EndEntry();
407 if ( level.wait_and_revive )
409 AIProfile_EndEntry();
413 if ( level.zombie_poi_array.size > 0 )
422 if( !isDefined( behaviorTreeEntity.enemy ) && !isDefined( zombie_poi ) )
425 if(
IS_TRUE( behaviortreeentity.isPuppet ) )
427 AIProfile_EndEntry();
432 if( isdefined( level.no_target_override ) )
434 [[ level.no_target_override ]]( behaviorTreeEntity );
438 behaviorTreeEntity SetGoal( behaviorTreeEntity.origin );
441 AIProfile_EndEntry();
445 behaviorTreeEntity.enemyoverride = zombie_poi;
447 if ( IsDefined( behaviorTreeEntity.enemyoverride ) && IsDefined( behaviorTreeEntity.enemyoverride[1] ) )
449 behaviorTreeEntity.has_exit_point = undefined;
451 goalPos = behaviorTreeEntity.enemyoverride[0];
452 queryResult = PositionQuery_Source_Navigation( goalPos, 0, 48, 36, 4 );
453 foreach( point
in queryResult.data )
455 goalPos = point.origin;
458 behaviorTreeEntity SetGoal( goalPos );
460 else if ( IsDefined( behaviorTreeEntity.enemy ) )
462 behaviorTreeEntity.has_exit_point = undefined;
465 if (
IS_TRUE( behaviorTreeEntity.is_rat_test ) )
467 AIProfile_EndEntry();
472 if ( IsDefined( level.enemy_location_override_func ) )
474 goalPos = [[ level.enemy_location_override_func ]]( behaviorTreeEntity, behaviorTreeEntity.enemy );
476 if ( IsDefined( goalPos ) )
478 behaviorTreeEntity SetGoal( goalPos );
485 else if ( IsDefined( behaviorTreeEntity.enemy.last_valid_position ) )
495 AIProfile_EndEntry();
500 AIProfile_BeginEntry(
"zombieUpdateGoal" );
502 shouldRepath =
false;
504 if ( !shouldRepath && IsDefined(
self.favoriteenemy ) )
506 if ( !IsDefined(
self.nextGoalUpdate ) ||
self.nextGoalUpdate <= GetTime() )
511 else if ( DistanceSquared(
self.origin,
self.favoriteenemy.origin ) <=
SQR( level.zigzag_activation_distance ) )
516 else if ( IsDefined(
self.pathGoalPos ) )
519 distanceToGoalSqr = DistanceSquared(
self.origin,
self.pathGoalPos );
521 shouldRepath = distanceToGoalSqr <
SQR( 72 );
525 if (
IS_TRUE( level.validate_on_navmesh ) )
527 if ( !IsPointOnNavMesh(
self.origin,
self ) )
529 shouldRepath =
false;
535 if ( GetTime() >
self.keep_moving_time )
537 self.keep_moving =
false;
542 goalPos =
self.favoriteenemy.origin;
543 if ( IsDefined(
self.favoriteenemy.last_valid_position ) )
545 goalPos =
self.favoriteenemy.last_valid_position;
547 self SetGoal( goalPos );
549 should_zigzag =
true;
550 if ( IsDefined( level.should_zigzag ) )
552 should_zigzag =
self [[ level.should_zigzag ]]();
556 if(
IS_TRUE(level.do_randomized_zigzag_path) && should_zigzag )
558 if ( DistanceSquared(
self.origin, goalPos ) >
SQR( level.zigzag_activation_distance ) )
560 self.keep_moving =
true;
561 self.keep_moving_time = GetTime() + 250;
562 path =
self CalcApproximatePathToPosition( goalPos,
false );
565 if ( GetDvarInt(
"ai_debugZigZag" ) )
567 for ( index = 1; index < path.size; index++ )
569 RecordLine( path[index - 1], path[index],
ORANGE,
"Animscript",
self );
574 deviationDistance = RandomIntRange( level.zigzag_distance_min, level.zigzag_distance_max );
576 if( IsDefined(
self.zigzag_distance_min ) && IsDefined(
self.zigzag_distance_max ) )
578 deviationDistance = RandomIntRange(
self.zigzag_distance_min,
self.zigzag_distance_max );
584 for ( index = 1; index < path.size; index++ )
586 currentSegLength = Distance( path[index - 1], path[index] );
588 if ( ( segmentLength + currentSegLength ) > deviationDistance )
590 remainingLength = deviationDistance - segmentLength;
592 seedPosition = path[index - 1] + ( VectorNormalize( path[index] - path[index - 1] ) * remainingLength );
594 /# RecordCircle( seedPosition, 2,
ORANGE,
"Animscript",
self ); #/
596 innerZigZagRadius = level.inner_zigzag_radius;
597 outerZigZagRadius = level.outer_zigzag_radius;
600 queryResult = PositionQuery_Source_Navigation(
609 PositionQuery_Filter_InClaimedLocation( queryResult,
self );
611 if ( queryResult.data.size > 0 )
613 point = queryResult.data[ RandomInt( queryResult.data.size ) ];
616 self SetGoal( point.origin );
622 segmentLength += currentSegLength;
628 self.nextGoalUpdate = GetTime() + RandomIntRange(500, 1000);
630 AIProfile_EndEntry();
636 AIProfile_BeginEntry(
"zombieUpdateGoalCode" );
638 shouldRepath =
false;
640 if ( !shouldRepath && IsDefined(
self.enemy ) )
642 if ( !IsDefined(
self.nextGoalUpdate ) ||
self.nextGoalUpdate <= GetTime() )
647 else if ( DistanceSquared(
self.origin,
self.enemy.origin ) <=
SQR( 200 ) )
652 else if ( IsDefined(
self.pathGoalPos ) )
655 distanceToGoalSqr = DistanceSquared(
self.origin,
self.pathGoalPos );
657 shouldRepath = distanceToGoalSqr <
SQR( 72 );
663 if ( GetTime() >
self.keep_moving_time )
665 self.keep_moving =
false;
670 goalPos =
self.enemy.origin;
671 if ( IsDefined(
self.enemy.last_valid_position ) )
673 goalPos =
self.enemy.last_valid_position;
677 if(
IS_TRUE(level.do_randomized_zigzag_path) )
679 if ( DistanceSquared(
self.origin, goalPos ) >
SQR( 240 ) )
681 self.keep_moving =
true;
682 self.keep_moving_time = GetTime() + 250;
684 path =
self CalcApproximatePathToPosition( goalPos,
false );
687 if ( GetDvarInt(
"ai_debugZigZag" ) )
689 for ( index = 1; index < path.size; index++ )
691 RecordLine( path[index - 1], path[index],
ORANGE,
"Animscript",
self );
696 deviationDistance = RandomIntRange( 240, 480 );
701 for ( index = 1; index < path.size; index++ )
703 currentSegLength = Distance( path[index - 1], path[index] );
705 if ( ( segmentLength + currentSegLength ) > deviationDistance )
707 remainingLength = deviationDistance - segmentLength;
709 seedPosition = path[index - 1] + ( VectorNormalize( path[index] - path[index - 1] ) * remainingLength );
711 /# RecordCircle( seedPosition, 2,
ORANGE,
"Animscript",
self ); #/
713 innerZigZagRadius = level.inner_zigzag_radius;
714 outerZigZagRadius = level.outer_zigzag_radius;
717 queryResult = PositionQuery_Source_Navigation(
726 PositionQuery_Filter_InClaimedLocation( queryResult,
self );
728 if ( queryResult.data.size > 0 )
730 point = queryResult.data[ RandomInt( queryResult.data.size ) ];
732 if ( TracePassedOnNavMesh( seedPosition, point.origin, 16 ) )
735 goalPos = point.origin;
742 segmentLength += currentSegLength;
747 self SetGoal( goalPos );
749 self.nextGoalUpdate = GetTime() + RandomIntRange(500, 1000);
751 AIProfile_EndEntry();
756 if ( !IsDefined( level.playable_areas ) )
758 level.playable_areas = GetEntArray(
"player_volume",
"script_noteworthy" );
761 foreach(area
in level.playable_areas)
763 if(behaviorTreeEntity IsTouching(area))
775 if ( behaviorTreeEntity HasPath() )
780 if (
IS_TRUE( behaviorTreeEntity.keep_moving ) )
790 return level.wait_and_revive;
795 if (
IS_TRUE( behaviorTreeEntity.tesla_death ) )
805 behaviorTreeEntity.no_powerups =
true;
810 behaviorTreeEntity.no_powerups =
false;
815 player = util::GetHostPlayer();
816 queryResult = level.move_away_points;
820 if ( !IsDefined( queryResult ) )
825 for(i = 0; i < queryResult.data.size; i++)
832 isBehind = vectordot( player.origin - behaviorTreeEntity.origin, queryResult.data[i].origin - behaviorTreeEntity.origin );
835 behaviorTreeEntity SetGoal( queryResult.data[i].origin );
836 ArrayRemoveIndex(level.move_away_points.data, i,
false);
842 for(i = 0; i < queryResult.data.size; i++)
849 dist_zombie = DistanceSquared( queryResult.data[i].origin, behaviorTreeEntity.origin );
850 dist_player = DistanceSquared( queryResult.data[i].origin, player.origin );
852 if ( dist_zombie < dist_player )
854 behaviorTreeEntity SetGoal( queryResult.data[i].origin );
855 ArrayRemoveIndex(level.move_away_points.data, i,
false);
865 if(
IS_TRUE( behaviorTreeEntity.grapple_is_fatal ) )
874 if (
IS_TRUE( behaviorTreeEntity.knockdown ) )
884 if (
IS_TRUE( behaviorTreeEntity.pushed ) )
906 behaviorTreeEntity.knockdown =
false;
916 behaviorTreeEntity.pushed =
false;
921 if(
IS_TRUE( behaviorTreeEntity.zombie_tesla_hit ) && !
IS_TRUE( behaviorTreeEntity.tesla_death ) )
935 behaviorTreeEntity.zombie_tesla_hit =
false;
942 behaviorTreeEntity.old_powerups = behaviorTreeEntity.no_powerups;
953 behaviorTreeEntity.no_powerups = behaviorTreeEntity.old_powerups;
955 if ( !
IS_TRUE( behaviorTreeEntity.missingLegs ) )
957 behaviorTreeEntity PushActors(
false );
967 if(
IS_TRUE( behaviorTreeEntity.got_to_entrance ) )
977 if(
IS_TRUE( behaviorTreeEntity.at_entrance_tear_spot ) )
992 if( IsDefined( behaviorTreeEntity.attacking_spot_index ) && behaviorTreeEntity.attacking_spot_index >= 0 )
1002 if( IsDefined( behaviorTreeEntity.first_node ) && IsDefined( behaviorTreeEntity.first_node.barrier_chunks ) )
1015 if (
IS_TRUE( behaviorTreeEntity.missingLegs ) )
1018 if( isdefined( behaviorTreeEntity.first_node.zbarrier ) )
1020 if( !behaviorTreeEntity.first_node.zbarrier ZBarrierSupportsZombieReachThroughAttacks() )
1024 if ( isdefined( behaviorTreeEntity.first_node ) )
1029 if ( isdefined( chunks ) && chunks.size > 0 )
1036 if(GetDvarString(
"zombie_reachin_freq") ==
"")
1038 SetDvar(
"zombie_reachin_freq",
"50");
1040 freq = GetDvarInt(
"zombie_reachin_freq");
1042 players = GetPlayers();
1045 behaviorTreeEntity.player_targets = [];
1046 for(i=0;i<players.size;i++)
1048 if ( isAlive( players[i] ) && !isDefined( players[i].revivetrigger ) && distance2d( behaviorTreeEntity.origin, players[i].origin ) <= 109.8 && !
IS_TRUE( players[i].zombie_vars[
"zombie_powerup_zombie_blood_on" ] ) &&
1051 behaviorTreeEntity.player_targets[behaviorTreeEntity.player_targets.size] = players[i];
1056 if ( !attack || freq < randomint(100) )
1066 if(
IS_TRUE( behaviorTreeEntity.missingLegs) )
1069 if( !IsDefined(behaviorTreeEntity.first_node.zbarrier) )
1074 if( !behaviorTreeEntity.first_node.zbarrier ZBarrierSupportsZombieTaunts() )
1079 if(GetDvarString(
"zombie_taunt_freq") ==
"")
1081 SetDvar(
"zombie_taunt_freq",
"5");
1083 freq = GetDvarInt(
"zombie_taunt_freq");
1085 if( freq >= randomint(100) )
1094 if( IsDefined( behaviorTreeEntity.first_node ) && IsDefined( behaviorTreeEntity.first_node.barrier_chunks ) )
1098 if(
IS_TRUE( behaviorTreeEntity.at_entrance_tear_spot ) && !
IS_TRUE( behaviorTreeEntity.completed_emerging_into_playable_area ) )
1110 if( IsDefined( behaviorTreeEntity.chunk ) )
1120 if (
IS_TRUE( behaviorTreeEntity.completed_emerging_into_playable_area ) )
1141 if(
IS_TRUE( behaviorTreeEntity.is_rat_test ) )
1146 if (
IS_TRUE( behaviorTreeEntity.zombie_think_done ) )
1156 isAtScriptGoal = behaviorTreeEntity IsAtGoal();
1158 return isAtScriptGoal;
1163 isAtScriptGoal = behaviorTreeEntity IsAtGoal();
1164 isAtEntrance = IsDefined( behaviorTreeEntity.first_node ) && isAtScriptGoal;
1166 return isAtEntrance;
1173 if( IsDefined( behaviorTreeEntity.chunk ) )
1175 behaviorTreeEntity.first_node.zbarrier SetZBarrierPieceState(behaviorTreeEntity.chunk,
"targetted_by_zombie");
1182 while( 0 < behaviorTreeEntity.first_node.zbarrier.chunk_health[behaviorTreeEntity.chunk] )
1184 behaviorTreeEntity.first_node.zbarrier.chunk_health[behaviorTreeEntity.chunk]--;
1186 behaviorTreeEntity.lastchunk_destroy_time = GetTime();
1191 if (
IS_TRUE( behaviorTreeEntity.marked_for_death ) || behaviorTreeEntity.health < 0 )
1196 if( !IsDefined( behaviorTreeEntity.attacking_spot ) )
1211 if( IsDefined( behaviorTreeEntity.attacking_spot ) )
1214 behaviorTreeEntity SetGoal( behaviorTreeEntity.attacking_spot );
1216 if ( behaviorTreeEntity IsAtGoal() )
1218 behaviorTreeEntity.at_entrance_tear_spot =
true;
1231 behaviorTreeEntity.entrance_nodes = [];
1233 if( IsDefined( behaviorTreeEntity.find_flesh_struct_string ) )
1235 if ( behaviorTreeEntity.find_flesh_struct_string ==
"find_flesh" )
1240 for( i=0; i<level.exterior_goals.size; i++ )
1242 if( IsDefined(level.exterior_goals[i].script_string) && level.exterior_goals[i].script_string == behaviorTreeEntity.find_flesh_struct_string )
1244 node = level.exterior_goals[i];
1249 behaviorTreeEntity.entrance_nodes[behaviorTreeEntity.entrance_nodes.size] = node;
1251 assert( IsDefined( node ),
"Did not find an entrance node with .script_string:" + behaviorTreeEntity.find_flesh_struct_string+
"!!! [Fix this!]" );
1253 behaviorTreeEntity.first_node = node;
1256 behaviorTreeEntity SetGoal( node.origin );
1261 behaviorTreeEntity.got_to_entrance =
true;
1272 behaviorTreeEntity.attackable = undefined;
1276 if (
IS_TRUE( behaviorTreeEntity.missingLegs ) )
1278 behaviorTreeEntity.attackable = undefined;
1282 if (
IS_TRUE( behaviorTreeEntity.aat_turned ) )
1284 behaviorTreeEntity.attackable = undefined;
1288 if ( !IsDefined( behaviorTreeEntity.attackable ) )
1294 if ( !
IS_TRUE( behaviorTreeEntity.attackable.is_active ) )
1296 behaviorTreeEntity.attackable = undefined;
1303 behaviorTreeEntity.got_to_entrance =
false;
1313 behaviorTreeEntity.got_to_entrance =
true;
1321 behaviorTreeEntity.at_entrance_tear_spot =
false;
1329 behaviorTreeEntity.at_entrance_tear_spot =
true;
1337 behaviortreeentity.keepClaimedNode =
true;
1341 boardActionAST = behaviorTreeEntity ASTSearch( IString( asmStateName ) );
1357 behaviortreeentity.keepClaimedNode =
false;
1363 behaviortreeentity.keepClaimedNode =
true;
1368 boardActionAST = behaviorTreeEntity ASTSearch( IString( asmStateName ) );
1384 behaviortreeentity.keepClaimedNode =
false;
1390 behaviortreeentity.keepClaimedNode =
true;
1394 boardActionAST = behaviorTreeEntity ASTSearch( IString( asmStateName ) );
1410 behaviortreeentity.keepClaimedNode =
false;
1413 self.lastchunk_destroy_time = GetTime();
1422 behaviortreeentity.keepClaimedNode =
true;
1423 behaviortreeentity.boardAttack =
true;
1432 behaviortreeentity.keepClaimedNode =
false;
1433 behaviortreeentity.boardAttack =
false;
1443 behaviortreeentity.keepClaimedNode =
true;
1452 behaviortreeentity.keepClaimedNode =
false;
1459 behaviorTreeEntity.clamptonavmesh = 0;
1460 if( IsDefined( behaviorTreeEntity.attacking_spot_index ) )
1462 behaviorTreeEntity.saved_attacking_spot_index = behaviorTreeEntity.attacking_spot_index;
1466 behaviorTreeEntity.isInMantleAction =
true;
1478 behaviorTreeEntity.clamptonavmesh = 1;
1480 behaviorTreeEntity.isInMantleAction = undefined;
1490 origin = GetStartOrigin( entity.first_node.zbarrier.origin, entity.first_node.zbarrier.angles, mocompAnim );
1491 angles = GetStartAngles( entity.first_node.zbarrier.origin, entity.first_node.zbarrier.angles, mocompAnim );
1493 entity ForceTeleport( origin, angles,
true );
1495 entity.pushable =
false;
1496 entity.blockingPain =
true;
1499 entity OrientMode(
"face angle", angles[1] );
1505 entity.pushable =
false;
1506 entity.blockingPain =
true;
1511 origin = GetStartOrigin( entity.first_node.zbarrier.origin, entity.first_node.zbarrier.angles, mocompAnim );
1512 angles = GetStartAngles( entity.first_node.zbarrier.origin, entity.first_node.zbarrier.angles, mocompAnim );
1514 if( isdefined(entity.mocomp_barricade_offset) )
1516 origin = origin + AnglesToForward(angles) * entity.mocomp_barricade_offset;
1519 entity ForceTeleport( origin, angles,
true );
1522 entity OrientMode(
"face angle", angles[1] );
1524 entity.pushable =
false;
1525 entity.blockingPain =
true;
1526 entity PathMode(
"dont move" );
1527 entity.useGoalAnimWeight =
true;
1534 entity.pushable =
false;
1539 entity.pushable =
true;
1540 entity.blockingPain =
false;
1541 entity PathMode(
"move allowed" );
1542 entity.useGoalAnimWeight =
false;
1545 entity OrientMode(
"face motion" );
1550 zbarrier_origin = (entity.first_node.zbarrier.origin[0], entity.first_node.zbarrier.origin[1], entity.origin[2]);
1552 origin = GetStartOrigin( zbarrier_origin, entity.first_node.zbarrier.angles, mocompAnim );
1553 angles = GetStartAngles( zbarrier_origin, entity.first_node.zbarrier.angles, mocompAnim );
1555 if( isdefined(entity.mocomp_barricade_offset) )
1557 origin = origin + AnglesToForward(angles) * entity.mocomp_barricade_offset;
1560 entity ForceTeleport( origin, angles,
true );
1563 entity OrientMode(
"face angle", angles[1] );
1565 entity.pushable =
false;
1566 entity.blockingPain =
true;
1567 entity PathMode(
"dont move" );
1568 entity.useGoalAnimWeight =
true;
1574 entity.pushable =
false;
1579 entity.pushable =
true;
1580 entity.blockingPain =
false;
1581 entity PathMode(
"move allowed" );
1582 entity.useGoalAnimWeight =
false;
1585 entity OrientMode(
"face motion" );
1591 if( IsDefined( animationEntity.chunk ) )
1593 animationEntity.first_node.zbarrier SetZBarrierPieceState( animationEntity.chunk,
"opening" );
1599 assert( animationEntity.meleeWeapon != level.weaponnone,
"Actor does not have a melee weapon" );
1601 if ( IsDefined( animationEntity.first_node ) )
1605 if ( IsDefined( level.attack_player_thru_boards_range ) )
1607 meleeDistSq = level.attack_player_thru_boards_range * level.attack_player_thru_boards_range;
1612 for ( i = 0; i < animationEntity.player_targets.size; i++ )
1614 playerDistSq = Distance2DSquared( animationEntity.player_targets[i].origin, animationEntity.origin );
1615 heightDiff = abs( animationEntity.player_targets[i].origin[2] - animationEntity.origin[2] );
1616 if ( playerDistSq < meleeDistSq && (heightDiff * heightDiff) < meleeDistSq )
1618 playerTriggerDistSq = Distance2DSquared( animationEntity.player_targets[i].origin, animationEntity.first_node.trigger_location.origin );
1619 heightDiff = abs( animationEntity.player_targets[i].origin[2] - animationEntity.first_node.trigger_location.origin[2] );
1620 if ( playerTriggerDistSq < triggerDistSq && (heightDiff * heightDiff) < triggerDistSq )
1622 animationEntity.player_targets[i] DoDamage( animationEntity.meleeWeapon.meleeDamage, animationEntity.origin,
self,
self,
"none",
"MOD_MELEE" );
1630 animationentity Melee();
1636 zombies = GetAiSpeciesArray( level.zombie_team,
"all" );
1638 zombie_enemy = undefined;
1639 closest_dist = undefined;
1641 foreach( zombie
in zombies )
1646 dist = DistanceSquared(
self.origin, zombie.origin );
1647 if ( !isdefined( closest_dist ) || dist < closest_dist )
1649 closest_dist = dist;
1650 zombie_enemy = zombie;
1655 self.favoriteenemy = zombie_enemy;
1657 if ( isdefined(
self.favoriteenemy ) )
1659 self SetGoal(
self.favoriteenemy.origin );
1663 self SetGoal(
self.origin );
1669 entity.pullTime = GetTime();
1670 entity.pullOrigin = entity.origin;
1676 if( IsDefined( entity.damageOrigin ) )
1678 entity.n_zombie_custom_goal_radius = 8;
1679 entity.v_zombie_custom_goal_pos = entity.damageOrigin;
1685 #define SOUL_BURST_RANGE 2500 //50*50
1686 #define PULLED_IN_RANGE 16384 //128*128
1687 #define INNER_RANGE 1048576 //1024*1024
1688 #define OUTER_RANGE 4227136 //2056*2056
1692 dist_to_bomb = DistanceSquared( entity.origin, entity.damageOrigin );
1696 entity._black_hole_bomb_collapse_death =
true;
1710 if( !IsDefined( entity.interdimensional_gun_kill ) )
1717 if(
IS_TRUE( entity._black_hole_bomb_collapse_death ) )
1719 entity.skipAutoRagdoll =
true;
1720 entity DoDamage( entity.health + 666, entity.origin + ( 0, 0, 50 ), entity.interdimensional_gun_attacker, undefined, undefined,
"MOD_CRUSH" );
1724 if( IsDefined( entity.damageOrigin ) )
1726 entity.v_zombie_custom_goal_pos = entity.damageOrigin;
1731 distSq = Distance2DSquared( entity.origin, entity.pullOrigin );
1734 entity SetAvoidanceMask(
"avoid all" );
1735 entity.cant_move =
true;
1737 if ( IsDefined( entity.cant_move_cb ) )
1739 entity [[ entity.cant_move_cb ]]();
1744 entity SetAvoidanceMask(
"avoid none" );
1745 entity.cant_move =
false;
1748 entity.pullTime = GetTime();
1749 entity.pullOrigin = entity.origin;
1757 entity.v_zombie_custom_goal_pos = undefined;
1758 entity.n_zombie_custom_goal_radius = undefined;
1760 entity.pullTime = undefined;
1761 entity.pullOrigin = undefined;
1768 if( !
IS_TRUE(
self.missingLegs) &&
IS_TRUE( entity.interdimensional_gun_kill ) && !
IS_TRUE( entity._black_hole_bomb_collapse_death ) )
1778 if(
IS_TRUE( entity._black_hole_bomb_collapse_death ) )
1790 if( IsDefined( level.black_hole_bomb_death_start_func ) )
1792 entity thread [[level.black_hole_bomb_death_start_func]]( entity.damageOrigin, entity.interdimensional_gun_projectile );
1800 if( IsDefined( level._effect ) && IsDefined( level._effect[
"black_hole_bomb_zombie_gib" ] ) )
1802 fxOrigin = entity GetTagOrigin(
"tag_origin" );
1804 forward = AnglesToForward( entity.angles );
1806 PlayFX( level._effect[
"black_hole_bomb_zombie_gib" ], fxOrigin, forward, ( 0, 0, 1 ) );
1815 if( IsDefined( level._effect ) && IsDefined( level._effect[
"black_hole_bomb_zombie_destroy" ] ) )
1817 fxOrigin = entity GetTagOrigin(
"tag_origin" );
1818 PlayFx(level._effect[
"black_hole_bomb_zombie_destroy" ], fxOrigin );
1821 if( IsDefined( entity.interdimensional_gun_projectile ) )
1823 entity.interdimensional_gun_projectile notify(
"black_hole_bomb_kill" );