1 #using scripts\shared\ai_shared;
2 #using scripts\shared\callbacks_shared;
3 #using scripts\shared\clientfield_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 #using scripts\shared\array_shared;
11 #using scripts\shared\ai\systems\animation_state_machine_utility;
12 #using scripts\shared\ai\systems\animation_state_machine_notetracks;
13 #using scripts\shared\ai\systems\animation_state_machine_mocomp;
14 #using scripts\shared\ai\systems\animation_selector_table;
15 #using scripts\shared\ai\archetype_locomotion_utility;
16 #using scripts\shared\ai\archetype_utility;
17 #using scripts\shared\ai\systems\behavior_tree_utility;
18 #using scripts\shared\ai\systems\ai_blackboard;
19 #using scripts\shared\ai\systems\blackboard;
20 #using scripts\shared\ai\systems\debug;
21 #using scripts\shared\ai\systems\gib;
22 #using scripts\shared\ai\zombie_utility;
23 #using scripts\shared\ai\zombie_death;
24 #using scripts\shared\ai\zombie_shared;
25 #using scripts\codescripts\struct;
26 #using scripts\shared\ai\archetype_mocomps_utility;
29 #using scripts\shared\ai\zombie;
32 #using scripts\shared\ai\systems\ai_interface;
33 #using scripts\shared\ai\archetype_apothicon_fury_interface;
35 #insert scripts\shared\ai\archetype_damage_effects.gsh;
36 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
37 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
38 #insert scripts\shared\ai\systems\behavior.gsh;
39 #insert scripts\shared\ai\systems\behavior_tree.gsh;
40 #insert scripts\shared\ai\systems\blackboard.gsh;
41 #insert scripts\shared\ai\systems\gib.gsh;
42 #insert scripts\shared\ai\utility.gsh;
43 #insert scripts\shared\ai\zombie.gsh;
44 #insert scripts\shared\ai\archetype_apothicon_fury.gsh;
45 #insert scripts\shared\shared.gsh;
46 #insert scripts\shared\version.gsh;
48 #precache( "model", FURY_DEATH_MODEL_SWAP );
50 #namespace ApothiconFuryBehavior;
156 self.updateSight =
false;
159 self AllowPitchAngle(1);
160 self SetPitchOrient();
163 self PushActors(
true );
166 self.skipAutoRagdoll =
true;
177 self.isFurious =
false;
178 self.furiousLevel = 0;
179 self.nextBamfMeleeTime = GetTime();
181 self.nextJukeTime = GetTime();
182 self.nextPreemptiveJukeAds = RandomFloatRange( 0.7, 0.95 );
191 entity.__blackboard = undefined;
207 if( a_filtered_zombies.size > 0 )
209 foreach( zombie
in a_filtered_zombies )
224 entity OrientMode(
"face angle", entity.angles[1] );
225 entity SetRepairPaths(
false );
234 entity ASMSetAnimationRate( rate );
236 Assert( IsDefined( entity.traverseEndNode ) );
241 entity.blockingPain =
true;
242 entity.useGoalAnimWeight =
true;
243 entity.bgbIgnoreFearInHeadlights =
true;
248 if( !IsDefined(entity.traverseEndNode) )
253 entity ForceTeleport( entity.traverseEndNode.origin, entity.angles );
254 entity ASMSetAnimationRate( 1 );
257 entity.blockingPain =
false;
258 entity.useGoalAnimWeight =
false;
259 entity.bgbIgnoreFearInHeadlights =
false;
279 class AnimationAdjustmentInfoXY
295 entity.isJuking =
true;
297 if( IsDefined( entity.jukeInfo ) )
298 entity OrientMode(
"face angle", entity.jukeInfo.jukeStartAngles );
300 entity OrientMode(
"face angle", entity.angles[1] );
304 entity.usegoalanimweight =
true;
305 entity.blockingPain =
true;
306 entity PushActors(
false );
307 entity.pushable =
false;
309 moveDeltaVector = GetMoveDelta( mocompAnim, 0, 1, entity );
310 landPos = entity LocalToWorldCoords( moveDeltaVector );
312 velocity = entity GetVelocity();
313 predictedPos = entity.origin + ( velocity * 0.1 );
316 RecordCircle( landPos, 8,
BLUE,
"Script", entity );
317 Record3DText(
"" + Distance( predictedPos, landPos ), landPos,
BLUE,
"Script" );
331 vectorToStartTime = GetMoveDelta( mocompanim, 0,
startTime, entity );
332 startPos = entity LocalToWorldCoords( vectorToStartTime );
337 vectorToStopTime = GetMoveDelta( mocompanim, 0,
stopTime, entity );
338 stopPos = entity LocalToWorldCoords( vectorToStopTime );
341 RecordSphere( startPos, 3,
BLUE,
"Script", entity );
342 RecordSphere( stopPos, 3,
BLUE,
"Script", entity );
343 RecordLine( predictedPos, startPos,
BLUE,
"Script", entity );
344 RecordLine( startPos, stopPos,
BLUE,
"Script", entity );
345 RecordLine( stopPos, landPos,
BLUE,
"Script", entity );
348 newStopPos = stopPos + ( 0, 0, heightDiff );
351 RecordLine( startPos, newStopPos,
YELLOW,
"Script", entity );
353 RecordSphere( newStopPos, 3,
YELLOW,
"Script", entity );
356 entity.AnimationAdjustmentInfoZ = undefined;
358 entity.AnimationAdjustmentInfoZ.startTime =
startTime;
360 entity.AnimationAdjustmentInfoZ.enemy = entity.enemy;
362 animLength = GetAnimLength( mocompanim ) * 1000;
369 entity.AnimationAdjustmentInfoZ.
stepSize = ( heightDiff / adjustDuration );
388 animTime = entity GetAnimTime( mocompanim );
390 if( !entity.AnimationAdjustmentInfoZ.adjustMentStarted )
392 if( animTime >= entity.AnimationAdjustmentInfoZ.startTime )
394 entity.AnimationAdjustmentInfoZ.adjustMentStarted =
true;
398 if( entity.AnimationAdjustmentInfoZ.adjustMentStarted && animTime < entity.AnimationAdjustmentInfoZ.stopTime )
400 adjustedOrigin = entity.origin + ( 0, 0, entity.AnimationAdjustmentInfoZ.stepSize );
401 entity ForceTeleport( adjustedOrigin, entity.angles );
405 if( IsDefined( entity.enemy ) )
407 entity OrientMode(
"face direction", entity.enemy.origin - entity.origin );
411 /#RecordCircle( entity.AnimationAdjustmentInfoZ.landPosOnGround, 8,
GREEN,
"Script", entity );#/
416 entity.blockingPain =
false;
418 entity PushActors(
true );
419 entity.isJuking =
false;
420 entity.usegoalanimweight =
false;
421 entity.pushable =
true;
423 entity.jukeInfo = undefined;
425 /#RecordCircle( entity.AnimationAdjustmentInfoZ.landPosOnGround, 8,
GREEN,
"Script", entity );#/
427 if( IsDefined( entity.enemy ) )
429 entity OrientMode(
"face direction", entity.enemy.origin - entity.origin );
435 assert(
IS_TRUE( entity.AnimationAdjustmentInfoZ.adjustMentStarted ) );
437 if(
IS_TRUE( entity.AnimationAdjustmentInfoZ.reAdjustMentStarted ) )
440 reAdjustMentAnimTime = 0.45;
441 animTime = entity GetAnimTime( mocompanim );
442 const reAdjustmentDistThresholdSq = 1024;
445 if( animTime >= reAdjustMentAnimTime && entity.enemy === entity.AnimationAdjustmentInfoZ.enemy )
447 meleeStartPosition = entity.AnimationAdjustmentInfoZ.landPosOnGround;
449 if( IsDefined( entity.enemy.last_valid_position ) )
451 meleeEndPosition = entity.enemy.last_valid_position;
455 meleeEndPosition = entity.enemy.origin;
457 enemyForwardDir = AnglesToForward( entity.enemy.angles );
458 newMeleeEndPosition = meleeEndPosition + ( enemyForwardDir * RandomIntRange( 30, 50 ) );
459 newMeleeEndPosition = GetClosestPointOnNavMesh( newMeleeEndPosition, 20, 50 );
461 if( IsDefined( newMeleeEndPosition ) )
462 meleeEndPosition = newMeleeEndPosition;
465 if( DistanceSquared( meleeStartPosition, meleeEndPosition ) < reAdjustmentDistThresholdSq )
474 if( !IsPointOnNavMesh( meleeStartPosition, entity ) )
477 if( !IsPointOnNavMesh( meleeEndPosition, entity ) )
480 if( !TracePassedOnNavMesh( meleeStartPosition, meleeEndPosition, entity.entityRadius ) )
483 if( !entity FindPath( meleeStartPosition, meleeEndPosition ) )
486 landPos = entity.AnimationAdjustmentInfoZ.landPosOnGround;
489 RecordCircle( meleeEndPosition, 8,
CYAN,
"Script", entity );
490 RecordCircle( landPos, 8,
BLUE,
"Script", entity );
494 zDiff = landPos[2] - meleeEndPosition[2];
495 traceStart = undefined;
496 traceEnd = undefined;
501 traceOffsetAbove = -zDiff + (30);
502 traceStart = meleeEndPosition + ( 0, 0, traceOffsetAbove );
503 traceEnd = meleeEndPosition + ( 0, 0, -70 );
507 traceOffsetBelow = -zDiff - 30 ;
508 traceStart = meleeEndPosition + ( 0, 0, 70 );
509 traceEnd = meleeEndPosition + ( 0, 0, traceOffsetBelow );
512 trace = GroundTrace( traceStart, traceEnd,
false, entity,
true,
true );
525 assert( IsDefined( entity.AnimationAdjustmentInfoZ ) );
527 stopTime = entity.AnimationAdjustmentInfoZ.stopTime;
531 entity.AnimationAdjustmentInfoZ2.startTime = reAdjustMentAnimTime;
532 entity.AnimationAdjustmentInfoZ2.stopTime =
stopTime;
535 animLength = GetAnimLength( mocompanim ) * 1000;
543 entity.AnimationAdjustmentInfoZ2.
stepSize = ( heightDiff / adjustDuration );
547 Record3DText(
"- " + entity.AnimationAdjustmentInfoZ2.stepSize +
":" + adjustDuration,
landPosOnGround,
ORANGE,
"Script" );
549 Record3DText(
"+ " + entity.AnimationAdjustmentInfoZ2.stepSize +
":" + adjustDuration,
landPosOnGround,
ORANGE,
"Script" );
553 meleeEndPosition = ( meleeEndPosition[0], meleeEndPosition[1], landPos[2] );
554 xyDirection = VectorNormalize( meleeEndPosition - landPos );
555 xyDistance = Distance( meleeEndPosition, landPos );
557 entity.AnimationAdjustmentInfoXY =
new AnimationAdjustmentInfoXY();
558 entity.AnimationAdjustmentInfoXY.startTime =
startTime;
560 entity.AnimationAdjustmentInfoXY.stepSize = ( xyDistance / adjustDuration );
561 entity.AnimationAdjustmentInfoXY.xyDirection =
xyDirection;
562 entity.AnimationAdjustmentInfoXY.adjustMentStarted =
true;
565 Record3DText(
"" + xyDistance +
" (step:" + entity.AnimationAdjustmentInfoXY.stepSize +
")", meleeEndPosition,
BLUE,
"Script" );
569 entity.AnimationAdjustmentInfoZ.reAdjustMentStarted =
true;
575 assert( IsDefined( entity.enemy ) );
577 entity.AnimationAdjustmentInfoZ = undefined;
578 entity.AnimationAdjustmentInfoZ2 = undefined;
579 entity.AnimationAdjustmentInfoXY = undefined;
582 entity PathMode(
"dont move" );
583 entity.blockingPain =
true;
584 entity.useGoalAnimWeight =
true;
585 self PushActors(
false );
586 entity.isBamfing =
true;
587 entity.pushable =
false;
589 anglesToEnemy =
FLAT_ANGLES( VectorToAngles( entity.enemy.origin - entity.origin ) );
590 entity ForceTeleport( entity.origin, anglesToEnemy );
591 entity OrientMode(
"face angle", anglesToEnemy[1] );
594 moveDeltaVector = GetMoveDelta( mocompAnim, 0, 1, entity );
595 landPos = entity LocalToWorldCoords( moveDeltaVector );
598 RecordCircle( entity.enemy.origin, 8,
CYAN,
"Script", entity );
599 RecordLine( landPos, entity.enemy.origin,
CYAN,
"Script", entity );
601 RecordCircle( landPos, 8,
BLUE,
"Script", entity );
602 Record3DText(
"" + Distance( entity.origin, landPos ), landPos,
BLUE,
"Script" );
605 zDiff = entity.origin[2] - entity.enemy.origin[2];
606 traceStart = undefined;
607 traceEnd = undefined;
612 traceOffsetAbove = -zDiff + (30);
613 traceStart = landpos + ( 0, 0, traceOffsetAbove );
614 traceEnd = landPos + ( 0, 0, -70 );
618 traceOffsetBelow = -zDiff - 30 ;
619 traceStart = landpos + ( 0, 0, 70 );
620 traceEnd = landPos + ( 0, 0, traceOffsetBelow );
623 trace = GroundTrace( traceStart, traceEnd,
false, entity,
true,
true );
641 vectorToStartTime = GetMoveDelta( mocompanim, 0,
startTime, entity );
642 startPos = entity LocalToWorldCoords( vectorToStartTime );
647 vectorToStopTime = GetMoveDelta( mocompanim, 0,
stopTime, entity );
648 stopPos = entity LocalToWorldCoords( vectorToStopTime );
651 RecordSphere( startPos, 3,
BLUE,
"Script", entity );
652 RecordSphere( stopPos, 3,
BLUE,
"Script", entity );
653 RecordLine( entity.origin, startPos,
BLUE,
"Script", entity );
654 RecordLine( startPos, stopPos,
BLUE,
"Script", entity );
655 RecordLine( stopPos, landPos,
BLUE,
"Script", entity );
658 newStopPos = stopPos + ( 0, 0, heightDiff );
661 RecordLine( startPos, newStopPos,
GREEN,
"Script", entity );
663 RecordSphere( newStopPos, 3,
GREEN,
"Script", entity );
667 entity.AnimationAdjustmentInfoZ.startTime =
startTime;
669 entity.AnimationAdjustmentInfoZ.enemy = entity.enemy;
671 animLength = GetAnimLength( mocompanim ) * 1000;
678 entity.AnimationAdjustmentInfoZ.
stepSize = ( heightDiff / adjustDuration );
692 assert( IsDefined( entity.AnimationAdjustmentInfoZ ) );
694 if( !IsDefined( entity.enemy ) )
697 animTime = entity GetAnimTime( mocompanim );
699 if( !entity.AnimationAdjustmentInfoZ.adjustMentStarted )
701 if( animTime >= entity.AnimationAdjustmentInfoZ.startTime )
703 entity.AnimationAdjustmentInfoZ.adjustMentStarted =
true;
707 if( entity.AnimationAdjustmentInfoZ.adjustMentStarted && animTime < entity.AnimationAdjustmentInfoZ.stopTime )
710 adjustedOrigin = entity.origin + ( 0, 0, entity.AnimationAdjustmentInfoZ.stepSize );
714 if(
IS_TRUE( entity.AnimationAdjustmentInfoZ.reAdjustMentStarted ) )
717 if( IsDefined( entity.AnimationAdjustmentInfoZ2 ) )
719 adjustedOrigin = adjustedOrigin + ( 0, 0, entity.AnimationAdjustmentInfoZ2.stepSize );
723 if( IsDefined( entity.AnimationAdjustmentInfoXY ) )
725 adjustedOrigin = adjustedOrigin + ( entity.AnimationAdjustmentInfoXY.xyDirection * entity.AnimationAdjustmentInfoXY.stepSize );
729 entity ForceTeleport( adjustedOrigin, entity.angles );
733 if( IsDefined( entity.enemy ) )
735 entity OrientMode(
"face direction", entity.enemy.origin - entity.origin );
742 entity PathMode(
"move allowed" );
745 entity.blockingPain =
false;
746 entity.useGoalAnimWeight =
false;
748 entity OrientMode(
"face angle", entity.angles[1] );
750 entity.isBamfing =
false;
751 entity.pushable =
true;
752 self PushActors(
true );
754 entity.jukeInfo = undefined;
756 if( !IsPointOnNavMesh( entity.origin ) )
758 clampToNavmeshLocation = GetClosestPointOnNavMesh( entity.origin, 100, 25 );
760 if( IsDefined( clampToNavmeshLocation ) )
762 entity ForceTeleport( clampToNavmeshLocation );
775 if( IsDefined( behaviorTreeEntity.enemyoverride ) && IsDefined( behaviorTreeEntity.enemyoverride[1] ) )
780 if( !IsDefined( behaviortreeentity.enemy ) )
785 if( IsDefined( behaviorTreeEntity.marked_for_death ) )
790 if(
IS_TRUE( behaviorTreeEntity.ignoreMelee ) )
795 if( DistanceSquared( behaviorTreeEntity.origin, behaviorTreeEntity.enemy.origin ) >
FURY_MELEE_DIST_SQ )
800 yawToEnemy = AngleClamp180( behaviorTreeEntity.angles[ 1 ] -
GET_YAW( behaviorTreeEntity, behaviorTreeEntity.enemy.origin ) );
825 if( !IsDefined( entity.enemy ) )
828 if( !IsPlayer( entity.enemy ) )
839 if( GetTime() < entity.nextBamfMeleeTime )
845 foreach ( event
in jukeEvents )
847 if ( Distance2DSquared( entity.origin, event.data.origin ) <= tooCloseJukeDistanceSqr )
854 assert( IsDefined( entity.enemy ) );
855 enemyOrigin = entity.enemy.origin;
858 furiesNearPlayer = 0;
860 foreach( apothiconFury
in apothiconFurys )
862 if( DistanceSquared( enemyOrigin, apothiconFury.origin ) <= ( 80 * 80 ) )
866 if( furiesNearPlayer >= 4 )
869 distanceToEnemySq = DistanceSquared( enemyOrigin, entity.origin );
883 meleeStartPosition = entity.origin;
884 meleeEndPosition = enemyOrigin;
886 if( !IsPointOnNavMesh( meleeStartPosition, entity ) )
889 if( !IsPointOnNavMesh( meleeEndPosition, entity ) )
892 if( !TracePassedOnNavMesh( meleeStartPosition, meleeEndPosition, entity.entityRadius ) )
895 if( !entity FindPath( meleeStartPosition, meleeEndPosition ) )
906 distanceToEnemy = Distance(
self.enemy.origin,
self.origin );
908 return distanceToEnemy;
919 if( IsDefined( level.nextBamfMeleeTimeMin ) && IsDefined( level.nextBamfMeleeTimeMax ) )
921 entity.nextBamfMeleeTime = GetTime() + RandomFloatRange( level.nextBamfMeleeTimeMin, level.nextBamfMeleeTimeMax );
934 if( IsDefined( tauntevents ) && tauntevents.size )
951 if( IsDefined(
self.damage_direction ) )
953 return self.damage_direction;
963 if( IsDefined( entity.enemy ) )
965 entity OrientMode(
"face direction", entity.enemy.origin - entity.origin );
970 if( IsDefined( entity.enemy ) && IsPlayer(entity.enemy) && DistanceSquared( entity.enemy.origin, entity.origin ) <=
SQR(
FURY_BAMF_MELEE_RANGE ) )
972 entity.enemy DoDamage( 25, entity.origin, entity, entity, undefined,
"MOD_MELEE" );
980 entity.moveTime = GetTime();
981 entity.moveOrigin = entity.origin;
986 if ( IsDefined( entity.move_anim_end_time ) && ( GetTime() >= entity.move_anim_end_time ) )
988 entity.move_anim_end_time = undefined;
994 distSq = Distance2DSquared( entity.origin, entity.moveOrigin );
998 if ( IsDefined( entity.cant_move_cb ) )
1000 entity [[ entity.cant_move_cb ]]();
1005 entity.cant_move =
false;
1008 entity.moveTime = GetTime();
1009 entity.moveOrigin = entity.origin;
1022 velocity = entity GetVelocity();
1024 predicted_pos = entity.origin + ( velocity * predict_time );
1025 move_dist_sq = DistanceSquared( predicted_pos, entity.origin );
1026 speed = move_dist_sq / predict_time;
1034 if( a_filtered_zombies.size > 0 )
1036 foreach( zombie
in a_filtered_zombies )
1046 if( zombie.knockdown ===
true )
1051 if(
IS_TRUE( zombie.missingLegs ) )
1056 knockdown_dist_sq = 48*48;
1057 dist_sq = DistanceSquared( predicted_pos, zombie.origin );
1059 if( dist_sq > knockdown_dist_sq )
1064 origin = thrasher.origin;
1066 facing_vec = AnglesToForward( thrasher.angles );
1067 enemy_vec = zombie.origin - origin;
1069 enemy_yaw_vec = (enemy_vec[0], enemy_vec[1], 0);
1070 facing_yaw_vec = (facing_vec[0], facing_vec[1], 0);
1072 enemy_yaw_vec = VectorNormalize( enemy_yaw_vec );
1073 facing_yaw_vec = VectorNormalize( facing_yaw_vec );
1075 enemy_dot = VectorDot( facing_yaw_vec, enemy_yaw_vec );
1088 zombie.knockdown =
true;
1090 zombie_to_thrasher = entity.origin - zombie.origin;
1091 zombie_to_thrasher_2d = VectorNormalize( ( zombie_to_thrasher[0], zombie_to_thrasher[1], 0 ) );
1093 zombie_forward = AnglesToForward( zombie.angles );
1094 zombie_forward_2d = VectorNormalize( ( zombie_forward[0], zombie_forward[1], 0 ) );
1096 zombie_right = AnglesToRight( zombie.angles );
1097 zombie_right_2d = VectorNormalize( ( zombie_right[0], zombie_right[1], 0 ) );
1099 dot = VectorDot( zombie_to_thrasher_2d, zombie_forward_2d );
1103 zombie.knockdown_direction =
"front";
1106 else if ( dot < 0.5 && dot > -0.5 )
1108 dot = VectorDot( zombie_to_thrasher_2d, zombie_right_2d );
1111 zombie.knockdown_direction =
"right";
1124 zombie.knockdown_direction =
"left";
1130 zombie.knockdown_direction =
"back";
1148 foreach( apothiconFury
in apothiconFurys )
1150 if(
IS_TRUE( apothiconFury.isFurious ) )
1170 furiousInfo = SpawnStruct();
1171 furiousInfo.origin = entity.origin;
1172 furiousInfo.entity = entity;
1176 entity PushActors(
false);
1178 entity.isFurious =
true;
1184 entity.health = entity.health * 2;
1198 if( !
IS_TRUE( entity.isFurious ) )
1203 if ( IsDefined( entity.nextJukeTime ) && entity.nextJukeTime > GetTime() )
1208 if ( IsDefined( entity.enemy ) )
1210 if ( !IsPlayer( entity.enemy ) )
1215 if ( entity.enemy PlayerADS() < entity.nextPreemptiveJukeAds )
1223 entity.apothiconPreemptiveJuke =
true;
1229 return IS_TRUE( entity.apothiconPreemptiveJuke );
1234 entity.apothiconPreemptiveJuke =
false;
1242 if( !IsDefined( entity.enemy ) || !IsPlayer(entity.enemy) )
1250 if(
IS_TRUE( entity.apothiconPreemptiveJuke ) )
1255 if( IsDefined( entity.nextJukeTime ) && GetTime() < entity.nextJukeTime )
1263 foreach ( event
in jukeEvents )
1265 if ( Distance2DSquared( entity.origin, event.data.origin ) <= tooCloseJukeDistanceSqr )
1282 if ( IsDefined( entity.jukeMaxDistance ) && IsDefined( entity.enemy ) )
1284 maxDistSquared = entity.jukeMaxDistance * entity.jukeMaxDistance;
1286 if ( Distance2DSquared( entity.origin, entity.enemy.origin ) > maxDistSquared )
1311 entity notify(
"bhtn_action_notify",
"apothicon_fury_juke" );
1319 entity.nextPreemptiveJukeAds = RandomFloatRange( 0.6, 0.8 );
1321 if( IsDefined( level.nextjukeMeleeTimeMin ) && IsDefined( level.nextjukeMeleeTimeMax ) )
1323 entity.nextjukeMeleeTime = GetTime() + RandomFloatRange( level.nextjukeMeleeTimeMin, level.nextjukeMeleeTimeMax );
1333 velocity = entity GetVelocity();
1334 predictedPos = entity.origin + ( velocity * 0.1 );
1335 jukeLandPos = predictedPos + jukeVector;
1337 if( !IsDefined( jukeLandPos ) )
1340 traceStart = jukeLandPos + ( 0, 0, 70 );
1341 traceEnd = jukeLandPos + ( 0, 0, -70 );
1343 trace = GroundTrace( traceStart, traceEnd,
false, entity,
true,
true );
1352 /#RecordLine( entity.origin, predictedPos,
GREEN,
"Script", entity );#/
1353 /#RecordSphere( jukeLandPos, 2,
RED,
"Script", entity );#/
1354 /#RecordLine( predictedPos, jukeLandPos,
RED,
"Script", entity );#/
1372 jukeAnim = entity AnimMappingSearch( IString( jukeAnimAlias ) );
1373 localDeltaVector = GetMoveDelta( jukeAnim, 0, 1, entity );
1374 endPoint = entity LocalToWorldCoords( localDeltaVector );
1376 return ( endpoint - entity.origin );
1381 if( IsDefined( entity.jukeInfo ) )
1382 return entity.jukeInfo;
1385 directionToEnemy = VectorNormalize( entity.enemy.origin - entity.origin );
1386 forwardDir = AnglesToForward( entity.angles );
1389 jukeValidDistanceType = [];
1390 entityRadius = entity.entityRadius;
1393 jukeVector =
getJukeVector( entity,
"anim_zombie_juke_left_long" );
1407 jukeVector =
getJukeVector( entity,
"anim_zombie_juke_right_long" );
1421 jukeVector =
getJukeVector( entity,
"anim_zombie_juke_left_front_long" );
1435 jukeVector =
getJukeVector( entity,
"anim_zombie_juke_right_front_long" );
1448 if( possibleJukes.size )
1450 jukeInfo = array::random( possibleJukes );
1454 entity.lastJukeInfoUpdateTime = GetTime();
1478 if( a_filtered_zombies.size > 0 )
1480 foreach( zombie
in a_filtered_zombies )
1492 if( IsDefined( entity.traverseEndNode ) )
1494 entity ForceTeleport( entity.traverseEndNode.origin, entity.angles );
1498 entity.isTraveling =
false;
1499 entity notify(
"travel_complete" );
1501 entity SetRepairPaths(
true );
1503 entity.blockingPain =
false;
1504 entity.useGoalAnimWeight =
false;
1505 entity.bgbIgnoreFearInHeadlights =
false;
1507 entity ASMSetAnimationRate( 1 );
1508 entity FinishTraversal();
1521 if( a_filtered_zombies.size > 0 )
1523 foreach( zombie
in a_filtered_zombies )
1579 function apothiconDamageCallback( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, damageFromUnderneath, modelIndex, partName )
1582 if( !
IS_TRUE(
self.zombie_think_done ) )
1587 if( IsDefined( eAttacker ) && IsPlayer( eAttacker ) && IsDefined( sHitLoc ) )
1592 if( IsDefined( sHitLoc ) )
1615 #namespace ApothiconFuryBehaviorInterface;
1633 case "super_sprint":