1 #using scripts\shared\ai_shared;
2 #using scripts\shared\ai\systems\ai_interface;
3 #using scripts\shared\ai\systems\animation_state_machine_utility;
4 #using scripts\shared\ai\systems\behavior_state_machine;
5 #using scripts\shared\ai\systems\behavior_tree_utility;
6 #using scripts\shared\ai\systems\blackboard;
7 #using scripts\shared\ai\systems\shared;
8 #using scripts\shared\ai\archetype_utility;
9 #using scripts\shared\array_shared;
10 #using scripts\shared\util_shared;
13 #using scripts\shared\ai\archetype_aivsaimelee;
15 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
16 #insert scripts\shared\ai\systems\behavior.gsh;
17 #insert scripts\shared\ai\systems\behavior_state_machine.gsh;
18 #insert scripts\shared\ai\systems\behavior_tree.gsh;
19 #insert scripts\shared\ai\systems\blackboard.gsh;
20 #insert scripts\shared\ai\utility.gsh;
21 #insert scripts\shared\shared.gsh;
23 #define ARCHETYPE_VEHICLE_RAPS "raps"
25 #precache( "fx", "lensflares/fx_lensflare_sniper_glint" );
204 assert( IsDefined(
self._stairsStartNode ) && IsDefined(
self._stairsEndNode ) );
212 totalStepsWithoutOut = numTotalSteps - numOutSteps;
214 assert( stepsSoFar < ( totalStepsWithoutOut ) );
216 remainingSteps = totalStepsWithoutOut - stepsSoFar;
219 if( remainingSteps >= 8 )
223 else if( remainingSteps >= 6 )
228 assert( remainingSteps >= 3 );
235 if( !isDefined(
self.stealth ) || !IsDefined(
self.awarenesslevelcurrent ) )
238 return self.awarenesslevelcurrent;
244 if( !isDefined(
self.stealth ) || !IsDefined(
self.awarenesslevelprevious ) )
247 return self.awarenesslevelprevious;
250 #define NEAR_COVER_NODE_SQ SQR( 24 )
251 #define NEAR_COVER_NODE_WIDE_SQ SQR( 64 )
254 if( !IsDefined(
self.node ) )
259 distToNodeSqr = Distance2DSquared(
self GetNodeOffsetPosition(
self.node ),
self.origin );
261 if (
IS_TRUE(
self.keepClaimedNode ) )
273 angleToNode = Ceil( AngleClamp180(
self.angles[1] -
self GetNodeOffsetAngles(
self.node )[1] ) );
280 If(
self IsAtCoverNodeStrict() &&
self ShouldUseCoverNode() )
283 return highestStance;
294 if( IsDefined(
self.prevrelativedir ) )
296 direction =
self.prevrelativedir;
336 if ( IsDefined(
self.node ) && DistanceSquared(
self.origin,
self.node.origin ) <
SQR( 48 ) )
347 if( IsDefined( level._debug_damage_direction ) )
348 return level._debug_damage_direction;
350 if (
self.damageyaw > 135 ||
self.damageyaw <= -135 )
356 if ( (
self.damageyaw > 45 ) && (
self.damageyaw <= 135 ) )
362 if ( (
self.damageyaw > -45 ) && (
self.damageyaw <= 45 ) )
375 if( IsDefined( level._debug_damage_pain_location ) )
376 return level._debug_damage_pain_location;
379 sHitLoc =
self.damagelocation;
381 possibleHitLocations =
array();
385 possibleHitLocations[possibleHitLocations.size] =
HITLOC_HEAD;
390 possibleHitLocations[possibleHitLocations.size] =
HITLOC_CHEST;
395 possibleHitLocations[possibleHitLocations.size] =
HITLOC_GROIN;
400 possibleHitLocations[possibleHitLocations.size] =
HITLOC_LEGS;
415 possibleHitLocations[possibleHitLocations.size] =
HITLOC_LEGS;
419 if( IsDefined(
self.lastDamageTime ) && GetTime() >
self.lastDamageTime && GetTime() <=
self.lastDamageTime + 1 * 1000 )
421 if( IsDefined(
self.lastDamageLocation ) )
422 ArrayRemoveValue( possibleHitLocations,
self.lastDamageLocation );
425 if( possibleHitLocations.size == 0 )
430 possibleHitLocations = undefined;
431 possibleHitLocations = [];
437 assert( possibleHitLocations.size > 0, possibleHitLocations.size );
439 damageLocation = possibleHitLocations[RandomInt(possibleHitLocations.size)];
442 self.lastDamageLocation = damageLocation;
444 return damageLocation;
449 if ( IsDefined(
self.damageMod ) )
451 if ( IsInArray(
array(
"mod_rifle_bullet" ), ToLower(
self.damageMod ) ) )
454 if ( IsInArray(
array(
"mod_pistol_bullet" ), ToLower(
self.damageMod ) ) )
457 if ( IsInArray(
array(
"mod_melee",
"mod_melee_assassinate",
"mod_melee_weapon_butt" ), ToLower(
self.damageMod ) ) )
460 if ( IsInArray(
array(
"mod_grenade",
"mod_grenade_splash",
"mod_projectile",
"mod_projectile_splash",
"mod_explosive" ), ToLower(
self.damageMod ) ) )
469 if(isdefined(
self.special_weapon) &&isdefined(
self.special_weapon.name) )
471 return self.special_weapon.name;
474 if (isDefined(
self.damageWeapon) && isDefined(
self.damageWeapon.name) )
476 return self.damageWeapon.name;
484 if (isDefined(
self.damageMod))
486 return ToLower(
self.damageMod);
495 if( IsDefined( level._debug_damage_intensity ) )
496 return level._debug_damage_intensity;
499 damageTaken =
self.damageTaken;
500 maxHealth =
self.maxHealth;
503 if( IsAlive(
self ) )
513 ratio = damageTaken /
self.maxHealth;
519 self.lastDamageTime = GetTime();
524 ratio = damageTaken /
self.maxHealth;
530 return damageTakenType;
544 assert( IsEntity( entity ) );
546 assert( !IsDefined( entity.aiOverrideDamage ) || IsArray( entity.aiOverrideDamage ) );
552 damageOverrides = [];
553 damageOverrides[ damageOverrides.size ] =
callback;
555 foreach(
override in entity.aiOverrideDamage )
557 damageOverrides[ damageOverrides.size ] =
override;
560 entity.aiOverrideDamage = damageOverrides;
579 assert( IsEntity( entity ) );
581 assert( IsArray( entity.aiOverrideDamage ) );
583 currentDamageCallbacks = entity.aiOverrideDamage;
585 entity.aiOverrideDamage = [];
587 foreach (key, value
in currentDamageCallbacks)
591 entity.aiOverrideDamage[ entity.aiOverrideDamage.size ] = value;
606 entity.aiOverrideDamage = [];
620 assert( IsEntity( entity ) );
622 assert( !IsDefined( entity.aiOverrideKilled ) || IsArray( entity.aiOverrideKilled ) );
630 if( IsDefined(entity.predictedYawToEnemy) && IsDefined(entity.predictedYawToEnemyTime) && entity.predictedYawToEnemyTime == GetTime() )
631 return entity.predictedYawToEnemy;
633 selfPredictedPos = entity.origin;
634 moveAngle = entity.angles[1] + entity getMotionAngle();
635 selfPredictedPos += (cos( moveAngle ), sin( moveAngle ), 0) * 200.0 * lookAheadTime;
637 yaw = VectorToAngles( entity LastKnownPos( entity.enemy ) - selfPredictedPos)[1] - entity.angles[1];
638 yaw = AbsAngleClamp360( yaw );
641 entity.predictedYawToEnemy = yaw;
642 entity.predictedYawToEnemyTime = GetTime();
664 if ( IsDefined( entity.enemy ) )
672 #define DEFAULT_ENEMY_YAW 0
678 if( !IsDefined( enemy ) )
692 if( !IsDefined( enemy ) )
695 toEnemyYaw = VectorToAngles( enemy.origin -
self.origin )[1] -
self.angles[1];
696 toEnemyYaw = AbsAngleClamp360( toEnemyYaw );
697 /# recordEntText(
"EnemyYaw: " + toEnemyYaw,
self,
RED,
"Animscript" ); #/
706 if ( isDefined(
self.react_yaw ) )
709 self.react_yaw = undefined;
713 v_origin =
self GetEventPointOfInterest();
714 if ( isDefined( v_origin ) )
716 str_typeName =
self GetCurrentEventTypeName();
717 e_originator =
self GetCurrentEventOriginator();
719 if ( str_typeName ==
"bullet" && isDefined( e_originator ) )
722 v_origin = e_originator.origin;
725 deltaOrigin = v_origin -
self.origin;
726 deltaAngles = VectorToAngles( deltaOrigin );
737 if( IsDefined( level._debug_damage_location ) )
738 return level._debug_damage_location;
740 sHitLoc =
self.damagelocation;
742 if( IsDefined( sHitLoc ) )
764 return randomLocs[ RandomInt( randomLocs.size ) ];
769 directionYaw = VectorToAngles(direction)[1];
770 yawDiff = directionYaw -
self.angles[1];
771 yawDiff = yawDiff * (1.0 / 360.0);
772 flooredYawDiff = floor(yawDiff + 0.5);
773 turnAngle = (yawDiff - flooredYawDiff) * 360.0;
777 return AbsAngleClamp360( turnAngle );
783 if( IsDefined(
self.prevNode ) )
798 predictedLookAheadInfo =
self PredictExit();
799 status = predictedLookAheadInfo[
"path_prediction_status"];
801 if( !IsDefined(
self.pathgoalpos ) )
814 end = start + VectorScale( ( 0, predictedLookAheadInfo[
"path_prediction_travel_vector"][1], 0 ), 100 );
816 angleToExit = VectorToAngles( predictedLookAheadInfo[
"path_prediction_travel_vector"] )[1];
817 exitYaw = AbsAngleClamp360( angleToExit -
self.prevnode.angles[1] );
822 end = start + VectorScale( ( 0, predictedLookAheadInfo[
"path_prediction_travel_vector"][1], 0 ), 100 );
824 angleToExit = VectorToAngles( predictedLookAheadInfo[
"path_prediction_travel_vector"] )[1];
825 exitYaw = AbsAngleClamp360( angleToExit -
self.angles[1] );
829 if(
wasAtCoverNode() && DistanceSquared(
self.prevNode.origin,
self.origin ) < (5 * 5) )
831 end =
self.pathgoalpos;
833 angleToDestination = VectorToAngles(
end -
self.origin )[1];
834 angleDifference = AbsAngleClamp360( angleToDestination -
self.prevnode.angles[1] );
836 return angleDifference;
839 start = predictedLookAheadInfo[
"path_prediction_start_point"];
840 end = start + predictedLookAheadInfo[
"path_prediction_travel_vector"];
852 if(
wasAtCoverNode() && DistanceSquared(
self.prevNode.origin,
self.origin ) < (5 * 5) )
854 end =
self.pathgoalpos;
856 angleToDestination = VectorToAngles(
end -
self.origin )[1];
857 angleDifference = AbsAngleClamp360( angleToDestination -
self.prevnode.angles[1] );
859 return angleDifference;
863 end =
self.pathgoalpos;
870 if ( IsDefined( exitYaw ) )
872 Record3DText(
"Exit Yaw: " + Int( exitYaw ),
self.origin - ( 0, 0, 5 ),
RED,
"Animscript", undefined, 0.4 );
883 walkString = GetDvarString(
"tacticalWalkDirection" );
895 if( IsDefined(
self.relativedir ) )
897 direction =
self.relativedir;
923 predictedLookAheadInfo =
self PredictPath();
924 status = predictedLookAheadInfo[
"path_prediction_status"];
926 startPos =
self.origin;
929 furthestPointTowardsGoalClear =
true;
934 furthestPointTowardsGoalClear =
self FindPath( startPos, furthestPointAlongTowardsGoal,
false,
false ) &&
self MayMoveToPoint( furthestPointAlongTowardsGoal );
937 if( furthestPointTowardsGoalClear )
939 forwardDir = AnglesToForward(
self.angles );
940 possiblePainTypes = [];
943 if(
self MayMoveToPoint( endpos ) &&
self FindPath( startPos, endpos,
false,
false ) )
949 if(
self MayMoveToPoint( endpos ) &&
self FindPath( startPos, endpos,
false,
false ) )
955 if(
self MayMoveToPoint( endpos ) &&
self FindPath( startPos, endpos,
false,
false ) )
960 if( possiblePainTypes.size )
962 return array::random( possiblePainTypes );
972 return AbsAngleClamp360( VectorToAngles(
self.lookaheaddir )[1] -
self.angles[1] );
980 #define TRACKING_TURN_PERFECT_INFO_DIST 180
981 #define TRACKING_TURN_GIVE_UP_TIME 5000
984 PixBeginEvent(
"BB_ActorGetTrackingTurnYaw" );
986 if( IsDefined(
self.enemy ) )
988 predictedPos = undefined;
996 predictedPos =
self.enemy.origin;
999 self.newEnemyReaction =
false;
1003 predictedPos =
self LastKnownPos(
self.enemy );
1006 if( IsDefined( predictedPos ) )
1008 turnYaw = AbsAngleClamp360(
self.angles[1] -
GET_YAW(
self, predictedPos ) );
1047 behaviorTreeEntity StartRagdoll();
1059 if(isDefined(behaviorTreeEntity.enemy) && isDefined(behaviorTreeEntity.enemy.vehicletype) && isSubStr(behaviorTreeEntity.enemy.vehicletype,
"firefly") )
1083 return ( IsDefined( behaviorTreeEntity.frustrationLevel ) && behaviorTreeEntity.frustrationLevel > 0 );
1086 #define MAX_FRUSTRATION 4
1087 #define MIN_FRUSTRATION 0
1100 return frustrationLevel;
1103 #define AGGRESSIVE_BOOST_TIME 5000
1116 if( !entity IsBadGuy() )
1121 if( !IsDefined( entity.frustrationLevel ) )
1123 entity.frustrationLevel = 0;
1126 if( !IsDefined( entity.enemy ) )
1128 entity.frustrationLevel = 0;
1132 /#record3DText(
"frustrationLevel " + entity.frustrationLevel, entity.origin,
ORANGE,
"Animscript" );#/
1134 if ( IsActor( entity.enemy ) || IsPlayer( entity.enemy ) )
1137 if ( entity.aggressiveMode )
1139 if ( !IsDefined( entity.lastFrustrationBoost ) )
1141 entity.lastFrustrationBoost = GetTime();
1146 entity.frustrationLevel++;
1147 entity.lastFrustrationBoost = GetTime();
1153 isAwareOfEnemy = ( GetTime() - entity LastKnownTime( entity.enemy ) ) < 10 * 1000;
1156 if( entity.frustrationLevel == 4 )
1157 hasSeenEnemy = entity SeeRecently( entity.enemy, 2 );
1159 hasSeenEnemy = entity SeeRecently( entity.enemy, 5 );
1162 hasAttackedEnemyRecently = entity AttackedRecently( entity.enemy, 5 );
1164 if( !isAwareOfEnemy || IsActor( entity.enemy ) )
1166 if ( !hasSeenEnemy )
1168 entity.frustrationLevel++;
1170 else if ( !hasAttackedEnemyRecently )
1172 entity.frustrationLevel += 2;
1180 if ( hasAttackedEnemyRecently )
1182 entity.frustrationLevel -= 2;
1187 else if ( hasSeenEnemy )
1189 entity.frustrationLevel--;
1210 behaviorTreeEntity FlagEnemyUnattackable();
1224 if( IsDefined( behaviorTreeEntity.enemy ) )
1226 lastKnownPositionOfEnemy = behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy );
1228 if( behaviorTreeEntity IsInGoal( lastKnownPositionOfEnemy )
1229 && behaviorTreeEntity FindPath( behaviorTreeEntity.origin, lastKnownPositionOfEnemy,
true,
false )
1251 if( IsDefined( behaviorTreeEntity.enemy ) )
1253 if(
IS_TRUE( behaviorTreeEntity.aggressiveMode ) )
1255 lastKnownPositionOfEnemy = behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy );
1257 if( behaviorTreeEntity IsInGoal( lastKnownPositionOfEnemy )
1258 && behaviorTreeEntity FindPath( behaviorTreeEntity.origin, lastKnownPositionOfEnemy,
true,
false )
1261 behaviorTreeEntity UsePosition( lastKnownPositionOfEnemy, lastKnownPositionOfEnemy );
1285 if( IsDefined( behaviorTreeEntity.enemy ) )
1287 closestRandomNode = behaviorTreeEntity FindBestCoverNodes( behaviorTreeEntity.engageMaxDist, behaviorTreeEntity.enemy.origin )[0];
1289 if( IsDefined( closestRandomNode )
1290 && behaviorTreeEntity IsInGoal( closestRandomNode.origin )
1291 && behaviorTreeEntity FindPath( behaviorTreeEntity.origin, closestRandomNode.origin,
true,
false )
1316 if( IsDefined( behaviorTreeEntity.enemy ) &&
IS_TRUE( behaviorTreeEntity.aggressiveMode ) )
1318 origin = behaviorTreeEntity.enemy.origin;
1320 if( behaviorTreeEntity IsInGoal( origin )
1321 && behaviorTreeEntity FindPath( behaviorTreeEntity.origin, origin,
true,
false )
1324 behaviorTreeEntity UsePosition( origin, origin );
1349 if(
IS_TRUE( behaviorTreeEntity.newEnemyReaction ) )
1356 return stance ==
STANCE_STAND && behaviorTreeEntity.newEnemyReaction && !(behaviorTreeEntity IsAtCoverNodeStrict());
1370 return(
IS_TRUE( behaviorTreeEntity.malFunctionReaction ) );
1384 if( IsDefined( entity.grenade ) &&
1385 IsDefined( entity.grenade.weapon ) &&
1386 entity.grenade !== entity.knownGrenade &&
1387 !entity IsSafeFromGrenade() )
1389 if ( IsDefined( entity.node ) )
1391 offsetOrigin = entity GetNodeOffsetPosition( entity.node );
1394 percentRadius = Distance( entity.grenade.origin, offsetOrigin );
1396 if ( entity.grenadeAwareness >= percentRadius )
1403 percentRadius = Distance( entity.grenade.origin, entity.origin ) / entity.grenade.weapon.explosionradius;
1405 if ( entity.grenadeAwareness >= percentRadius )
1411 entity.knownGrenade = entity.grenade;
1430 return !entity IsSafeFromGrenade();
1444 const RECENTLY_SEEN_TIME = 6;
1446 if( IsDefined( behaviorTreeEntity.enemy ) && behaviorTreeEntity SeeRecently( behaviorTreeEntity.enemy, RECENTLY_SEEN_TIME ) )
1463 if(
IS_TRUE( behaviorTreeEntity.accurateFire ) )
1480 if(
IS_TRUE( behaviorTreeEntity.aggressiveMode ) )
1497 sameNode = behaviorTreeEntity.node === node;
1499 behaviorTreeEntity UseCoverNode( node );
1515 behaviorTreeEntity.nextFindBestCoverTime = behaviorTreeEntity GetNextFindBestCoverTime( behaviorTreeEntity.engageMinDist, behaviorTreeEntity.engagemaxdist, behaviorTreeEntity.coversearchinterval );
1529 if( IsDefined( behaviorTreeEntity.node )
1530 && behaviorTreeEntity IsAtCoverNodeStrict()
1531 && behaviorTreeEntity ShouldUseCoverNode() )
1533 if( !IsDefined( behaviorTreeEntity.coverNode ) )
1535 behaviorTreeEntity.coverNode = behaviorTreeEntity.node;
1542 behaviorTreeEntity.coverNode = undefined;
1548 if( !IsDefined( behaviorTreeEntity.enemy ) )
1552 if ( IsDefined( node ) )
1569 const NEAR_ARRIVAL_DIST_SQ = 64 * 64;
1577 if (
IS_TRUE( behaviorTreeEntity.avoid_cover ) )
1582 if( behaviorTreeEntity IsInAnyBadPlace() )
1587 if( IsDefined( behaviorTreeEntity.enemy ) )
1589 shouldUseCoverNodeResult =
false;
1590 shouldBeBoredAtCurrentCover =
false;
1591 aboutToArriveAtCover =
false;
1592 isWithinEffectiveRangeAlready =
false;
1593 isLookingAroundForEnemy =
false;
1596 if( behaviorTreeEntity ShouldHoldGroundAgainstEnemy() )
1600 if( behaviorTreeEntity HasPath() && IsDefined( behaviorTreeEntity.arrivalFinalPos ) && IsDefined( behaviorTreeEntity.pathGoalPos ) &&
self.pathGoalPos == behaviorTreeEntity.arrivalFinalPos )
1602 if( DistanceSquared( behaviorTreeEntity.origin, behaviorTreeEntity.arrivalFinalPos ) < NEAR_ARRIVAL_DIST_SQ )
1604 aboutToArriveAtCover =
true;
1609 shouldUseCoverNodeResult = behaviorTreeEntity ShouldUseCoverNode();
1612 if(
self IsAtGoal() )
1615 if( shouldUseCoverNodeResult && IsDefined( behaviorTreeEntity.node ) &&
self IsAtGoal() )
1617 lastKnownPos = behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy );
1619 dist = Distance2D( behaviorTreeEntity.origin, lastKnownPos );
1621 if( dist > behaviorTreeEntity.engageMinFalloffDist && dist <= behaviorTreeEntity.engageMaxFalloffDist )
1622 isWithinEffectiveRangeAlready =
true;
1626 shouldBeBoredAtCurrentCover = !isWithinEffectiveRangeAlready && behaviorTreeEntity IsAtCoverNode() && ( GetTime() >
self.nextFindBestCoverTime );
1629 if( !shouldUseCoverNodeResult )
1631 if( IsDefined( behaviorTreeEntity.frustrationLevel ) && behaviorTreeEntity.frustrationLevel > 0 && behaviorTreeEntity HasPath() )
1632 isLookingAroundForEnemy =
true;
1636 shouldLookForBetterCover = !isLookingAroundForEnemy
1637 && !aboutToArriveAtCover
1638 && !isWithinEffectiveRangeAlready
1639 && ( !shouldUseCoverNodeResult || shouldBeBoredAtCurrentCover || !
self IsAtGoal() );
1642 if( shouldLookForBetterCover )
1647 recordEntText(
"ChooseBetterCoverReason: SUC:" + shouldUseCoverNodeResult
1648 +
" LAE:" + isLookingAroundForEnemy
1649 +
" ARR:" + aboutToArriveAtCover
1650 +
" EFF:" + isWithinEffectiveRangeAlready
1651 +
" BOR:" + shouldBeBoredAtCurrentCover
1652 , behaviorTreeEntity, color,
"Animscript" );
1657 return !( behaviorTreeEntity ShouldUseCoverNode() && behaviorTreeEntity IsApproachingGoal() );
1660 return shouldLookForBetterCover;
1680 if (
IS_TRUE( behaviorTreeEntity.avoid_cover ) )
1685 if ( IsDefined( behaviorTreeEntity.knownGrenade ) )
1694 behaviorTreeEntity.nextFindBestCoverTime = 0;
1697 newNode = behaviorTreeEntity ChooseBetterCoverNode();
1699 if( IsDefined( newNode ) )
1724 if( shouldChooseBetterCoverResult && !behaviorTreeEntity.keepClaimedNode )
1726 transitionRunning = behaviorTreeEntity ASMIsTransitionRunning();
1727 subStatePending = behaviorTreeEntity ASMIsSubStatePending();
1728 transDecRunning = behaviorTreeEntity AsmIsTransDecRunning();
1729 isBehaviorTreeInRunningState = behaviorTreeEntity GetBehaviortreeStatus() ==
BHTN_RUNNING;
1731 if( !transitionRunning && !subStatePending && !transDecRunning && isBehaviorTreeInRunningState )
1734 goingToDifferentNode = IsDefined( node ) && ( !IsDefined( behaviorTreeEntity.node ) || node != behaviorTreeEntity.node );
1736 if ( goingToDifferentNode )
1761 if ( behaviorTreeEntity.weapon != level.weaponNone )
1763 behaviorTreeEntity.bulletsInClip = behaviorTreeEntity.weapon.clipSize;
1778 if( behaviorTreeEntity.bulletsInClip > 0 )
1786 if ( behaviorTreeEntity.weapon != level.weaponNone )
1788 return behaviorTreeEntity.bulletsInClip < (behaviorTreeEntity.weapon.clipSize * 0.2);
1805 if( IsDefined( behaviorTreeEntity.enemy ) )
1824 node = behaviorTreeEntity FindBestCoverNode();
1826 if ( !IsDefined(node) )
1831 if( behaviorTreeEntity NearClaimNode() )
1833 currentNode =
self.node;
1836 if ( IsDefined( currentNode ) && node == currentNode )
1843 if ( IsDefined( behaviorTreeEntity.coverNode ) && node == behaviorTreeEntity.coverNode )
1854 if( IsDefined( behaviorTreeEntity.fixedNode ) && behaviorTreeEntity.fixedNode )
1857 nodes = behaviorTreeEntity FindBestCoverNodes( behaviorTreeEntity.goalRadius, behaviorTreeEntity.origin );
1859 if ( nodes.size > 1 )
1864 if ( !IsDefined(node) )
1869 if( behaviorTreeEntity NearClaimNode() )
1871 currentNode =
self.node;
1874 if ( IsDefined( currentNode ) && node == currentNode )
1881 if ( IsDefined( behaviorTreeEntity.coverNode ) && node == behaviorTreeEntity.coverNode )
1900 if( IsDefined( node ) )
1930 if ( IsDefined( node ) )
1949 if( !IsDefined(
self.enemy ) )
1952 if( !IsDefined(
self.node ) )
1954 return self canSee(
self.enemy );
1959 enemyEye =
self.enemy GetEye();
1986 nodeOffset = (0,0,0);
1991 canSeeFromLeft =
true;
1992 canSeeFromRight =
true;
1997 canSeeFromLeft = sightTracePassed( lookFromPoint, enemyEye,
false, undefined );
2002 canSeeFromRight = sightTracePassed( lookFromPoint, enemyEye,
false, undefined );
2004 return ( canSeeFromRight || canSeeFromLeft );
2027 if( sightTracePassed( lookFromPoint, enemyEye,
false, undefined ) )
2044 right = AnglesToRight( node.angles );
2045 forward = AnglesToForward( node.angles );
2047 return node.origin + VectorScale( right, nodeOffset[0] ) + VectorScale( forward, nodeOffset[1] ) + ( 0, 0, nodeOffset[2] );
2061 assert( IsDefined( node ) );
2073 ErrorMsg( node.type +
" node at" + node.origin +
" supports no stance." );
2096 assert( IsDefined( stance ) );
2097 assert( IsDefined( node ) );
2122 if ( behaviorTreeEntity ShouldHoldGroundAgainstEnemy() )
2124 behaviorTreeEntity ClearPath();
2125 behaviorTreeEntity.keepClaimedNode =
true;
2129 behaviorTreeEntity.keepClaimedNode =
false;
2144 if ( behaviorTreeEntity ShouldHoldGroundAgainstEnemy() )
2154 self.weapon = weapon;
2155 self.weaponclass = weapon.weapClass;
2157 if( weapon != level.weaponNone )
2158 assert( IsDefined( weapon.worldModel ),
"Weaopon " + weapon.name +
" has no world model set in GDT." );
2160 self.weaponmodel = weapon.worldModel;
2165 self.primaryweapon = weapon;
2166 self.primaryweaponclass = weapon.weapClass;
2168 if( weapon != level.weaponNone )
2169 assert( IsDefined( weapon.worldModel ),
"Weaopon " + weapon.name +
" has no world model set in GDT." );
2174 self.secondaryweapon = weapon;
2175 self.secondaryweaponclass = weapon.weapClass;
2177 if( weapon != level.weaponNone )
2178 assert( IsDefined( weapon.worldModel ),
"Weaopon " + weapon.name +
" has no world model set in GDT." );
2183 behaviorTreeEntity.keepClaimedNode =
true;
2190 behaviorTreeEntity.keepClaimedNode =
false;
2200 return AngleClamp180( VectorToAngles( ( behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) ) - node.origin )[1] - node.angles[1] );
2208 return AngleClamp180( VectorToAngles( ( behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) ) - node.origin )[0] - node.angles[0] );
2234 if( !behaviorTreeEntity HasPath() )
2256 goalPos = undefined;
2258 if( IsDefined( behaviorTreeEntity.arrivalFinalPos ) )
2259 goalPos = behaviorTreeEntity.arrivalFinalPos;
2261 goalPos = behaviorTreeEntity.pathGoalPos;
2264 if( Isdefined( behaviorTreeEntity.pathStartPos ) && Isdefined( goalPos ) )
2266 pathDist = DistanceSquared( behaviorTreeEntity.pathStartPos, goalPos );
2274 if( behaviorTreeEntity ShouldFaceMotion() )
2279 if ( !behaviorTreeEntity IsSafeFromGrenade() )
2298 if ( isDefined( behaviorTreeEntity.stealth ) )
2302 if ( behaviorTreeEntity IsInScriptedState() )
2306 if ( behaviorTreeEntity HasValidInterrupt(
"react" ) )
2308 behaviorTreeEntity.stealth_react_last = now;
2311 if (
IS_TRUE( behaviorTreeEntity.stealth_reacting ) || ( isDefined( behaviorTreeEntity.stealth_react_last ) && ( now - behaviorTreeEntity.stealth_react_last ) < 250 ) )
2340 if( behaviorTreeEntity HasPath() )
2342 if ( isDefined( behaviorTreeEntity.arrivalFinalPos ) || isDefined( behaviorTreeEntity.pathGoalPos ) )
2344 hasWait = ( isDefined(
self.currentgoal ) && isDefined(
self.currentgoal.script_wait_min ) && isDefined(
self.currentgoal.script_wait_max ) );
2346 hasWait =
self.currentgoal.script_wait_min > 0 ||
self.currentgoal.script_wait_max > 0;
2348 if ( hasWait || !isDefined(
self.currentgoal ) || ( isDefined(
self.currentgoal ) && isDefined(
self.currentgoal.scriptbundlename ) ) )
2351 goalPos = undefined;
2352 if( IsDefined( behaviorTreeEntity.arrivalFinalPos ) )
2353 goalPos = behaviorTreeEntity.arrivalFinalPos;
2355 goalPos = behaviorTreeEntity.pathGoalPos;
2357 goalDistSq = DistanceSquared( behaviorTreeEntity.origin, goalPos );
2360 if ( goalDistSq <= ( 44 * 44 ) && ( goalDistSq <= behaviorTreeEntity.goalradius * behaviorTreeEntity.goalradius ) )
2385 if (
IS_TRUE( behaviorTreeEntity.stealth_resume ) )
2387 behaviorTreeEntity.stealth_resume = undefined;
2405 inScene = ( isDefined(
self._o_scene ) && isDefined(
self._o_scene._str_state ) &&
self._o_scene._str_state ==
"play" );
2407 return ( !
IS_TRUE( entity.stealth_reacting ) && entity HasValidInterrupt(
"react" ) && !inScene );
2419 behaviorTreeEntity.stealth_reacting =
true;
2431 behaviorTreeEntity.stealth_reacting = undefined;
2443 behaviortreeentity notify(
"stealthIdleTerminate");
2445 if (
IS_TRUE( behaviortreeentity.stealth_resume_after_idle ) )
2447 behaviortreeentity.stealth_resume_after_idle = undefined;
2448 behaviortreeentity.stealth_resume =
true;
2468 if( behaviorTreeEntity HasPath() &&
2504 if ( IsDefined( entity ) )
2506 entity Detach( riotshieldInfo.model, riotshieldInfo.tag );
2524 riotshield = SpawnStruct();
2525 riotshield.weapon = riotshieldWeapon;
2526 riotshield.tag = riotshieldTag;
2527 riotshield.model = riotshieldModel;
2529 entity Attach( riotshieldModel, riotshield.tag );
2531 entity.riotshield = riotshield;
2545 if ( IsDefined( behaviorTreeEntity.riotshield ) )
2547 riotshieldInfo = behaviorTreeEntity.riotshield;
2549 behaviorTreeEntity.riotshield = undefined;
2566 if( behaviorTreeEntity.damageweapon.rootweapon.name ==
"shotgun_pump_taser" )
2610 if( isDefined(
self.attacker) && isDefined(
self.attacker.archetype) &&
self.attacker.archetype ==
ARCHETYPE_VEHICLE_RAPS)
2622 if( isDefined( behaviorTreeEntity ) && isDefined( behaviorTreeEntity.enemy ))
2624 behaviorTreeEntity.melee = spawnStruct();
2625 behaviorTreeEntity.melee.enemy = behaviorTreeEntity.enemy;
2627 if( IsPlayer( behaviorTreeEntity.melee.enemy ) )
2629 if( !isDefined( behaviorTreeEntity.melee.enemy.meleeAttackers) )
2631 behaviorTreeEntity.melee.enemy.meleeAttackers = 0;
2634 behaviorTreeEntity.melee.enemy.meleeAttackers++;
2641 if( isdefined(behaviorTreeEntity.melee) )
2643 if( isdefined(behaviorTreeEntity.melee.enemy) )
2645 if( IsPlayer( behaviorTreeEntity.melee.enemy ) )
2647 if( isDefined( behaviorTreeEntity.melee.enemy.meleeAttackers) )
2649 behaviorTreeEntity.melee.enemy.meleeAttackers = behaviorTreeEntity.melee.enemy.meleeAttackers - 1;
2650 if ( behaviorTreeEntity.melee.enemy.meleeAttackers <= 0 )
2652 behaviorTreeEntity.melee.enemy.meleeAttackers = undefined;
2658 behaviorTreeEntity.melee = undefined;
2666 if ( isDefined( behaviorTreeEntity.melee ) )
2672 if ( isDefined( behaviorTreeEntity.enemy))
2674 if( !isPlayer ( behaviorTreeEntity.enemy ))
2676 if( isDefined( behaviorTreeEntity.enemy.melee ) )
2684 if ( !SessionModeIsCampaignGame() )
2689 if (!isDefined( behaviorTreeEntity.enemy.meleeAttackers))
2691 behaviorTreeEntity.enemy.meleeAttackers = 0;
2706 #define SHOULD_MELEE_CHECK_TIME 50
2709 if ( IsDefined( entity.lastShouldMeleeResult ) &&
2710 !entity.lastShouldMeleeResult &&
2717 entity.lastShouldMeleeCheckTime = GetTime();
2718 entity.lastShouldMeleeResult =
false;
2720 if ( !IsDefined( entity.enemy ) )
2723 if ( !( entity.enemy.allowDeath ) )
2726 if ( !IsAlive( entity.enemy ) )
2729 if ( !IsSentient( entity.enemy ) )
2732 if ( IsVehicle( entity.enemy ) && !
IS_TRUE( entity.enemy.good_melee_target ) )
2736 if ( IsPlayer( entity.enemy ) && entity.enemy GetStance() ==
"prone" )
2740 if( DistanceSquared( entity.origin, entity.enemy.origin ) > chargeDistSQ )
2754 entity.lastShouldMeleeResult =
true;
2769 assert( IsDefined( entity.enemy ) );
2771 if ( !entity CanSee( entity.enemy ) )
2777 distSQ = DistanceSquared( entity.origin, predicitedPosition );
2778 yawToEnemy = AngleClamp180( entity.angles[ 1 ] -
GET_YAW( entity, entity.enemy.origin ) );
2787 if( distSQ <= melee_range_sq && entity MayMoveToPoint( entity.enemy.origin ) )
2798 assert( IsDefined( entity.enemy ) );
2804 if ( IsDefined( entity.nextChargeMeleeTime ) )
2806 if ( GetTime() < entity.nextChargeMeleeTime )
2810 enemyDistSq = DistanceSquared( entity.origin, entity.enemy.origin );
2817 offset = entity.enemy.origin - ( VectorNormalize( entity.enemy.origin - entity.origin) *
MELEE_NEAR_RANGE);
2820 if ( enemyDistSq < chargeDistSQ && entity MayMoveToPoint(offset,
true,
true) )
2822 yawToEnemy = AngleClamp180( entity.angles[ 1 ] -
GET_YAW( entity, entity.enemy.origin ) );
2831 if ( IsDefined( behaviorTreeEntity.enemy ) )
2833 if ( DistanceSquared( behaviorTreeEntity.origin, behaviorTreeEntity.enemy.origin ) <
BLEND_MELEE_RANGE_SQ )
2835 yawToEnemy = AngleClamp180( behaviorTreeEntity.angles[ 1 ] -
GET_YAW(behaviorTreeEntity, behaviorTreeEntity.enemy.origin ) );
2846 if(isDefined(behaviorTreeEntity.enemy) && isDefined(behaviorTreeEntity.enemy.vehicletype) && isSubStr(behaviorTreeEntity.enemy.vehicletype,
"firefly") )
2871 behaviorTreeEntity PathMode(
"move delayed",
true, RandomFloatRange( 0.75, 1.5 ) );
2881 behaviorTreeEntity PathMode(
"move delayed",
true, RandomFloatRange( 0.5, 1 ) );
2894 if(IsDefined( behaviorTreeEntity.damageWeapon ))
2896 return behaviorTreeEntity.damageWeapon.specialpain || isdefined(behaviorTreeEntity.special_weapon);
2905 if(IsDefined( behaviorTreeEntity.damageWeapon ))
2907 return behaviorTreeEntity.damageWeapon.specialpain;
2920 self.animtranslationScale = 2.0;
2921 self ASMSetAnimationRate( 0.7 );
2938 if( !isDefined(behaviorTreeEntity.node) )
2954 if (isDefined(behaviorTreeEntity.node.script_balconydeathchance) && RandomInt(100) >
int(100.0 * behaviorTreeEntity.node.script_balconydeathchance))
2958 distSQ = DistanceSquared(behaviorTreeEntity.origin,behaviorTreeEntity.node.origin);
2959 if (distSQ >
SQR(16))
2963 if(isDefined(level.players) && level.players.size > 0)
2967 if(isDefined(closest_player))
2970 if(abs(closest_player.origin[2] - behaviorTreeEntity.origin[2]) < 100)
2972 distance2DfromPlayerSq = Distance2DSquared(closest_player.origin, behaviorTreeEntity.origin);
2975 if(distance2DfromPlayerSq <
SQR(600))
2983 self.b_balcony_death =
true;
2999 behaviorTreeEntity.clamptonavmesh = 0;
3013 entity UsePosition( entity.origin );
3027 if ( behaviorTreeEntity.weapon == level.weaponNone )
3046 entity StartRagdoll();
3053 self endon(
"death" );
3054 if( !isDefined( ai.laserstatus ))
3056 ai.laserstatus =
false;
3059 sniper_glint =
"lensflares/fx_lensflare_sniper_glint";
3063 self waittill(
"about_to_fire" );
3064 if( ai.laserstatus !==
true )
3067 ai.laserstatus =
true;
3069 if( ai.team !=
"allies" )
3071 tag = ai GetTagOrigin(
"tag_glint");
3073 if( isDefined( tag ))
3075 playfxontag( sniper_glint , ai ,
"tag_glint" );
3079 type =
STR( ai.classname );
3080 /#println(
"AI " + type +
" does not have a tag_glint to play sniper glint effects from, playing from tag_eye" );#/
3081 playfxontag( sniper_glint , ai ,
"tag_eye" );
3092 self endon(
"death" );
3096 self waittill(
"stopped_firing" );
3097 if( ai.laserstatus ===
true )
3100 ai.laserstatus =
false;
3116 switch ( phalanxStance )
3131 switch ( phalanxStance )
3144 if ( IsDefined( entity.damageweapon ) && IsDefined( entity.damagemod ) )
3146 weapon = entity.damageweapon;
3148 return entity.damagemod ==
"MOD_GRENADE_SPLASH" &&
3149 IsDefined( weapon.rootweapon ) &&
3150 ( IsSubStr( weapon.rootweapon.name,
"flash_grenade" ) ||
3151 IsSubStr( weapon.rootweapon.name,
"concussion_grenade" ) ||
3152 IsSubStr( weapon.rootweapon.name,
"proximity_grenade" ) );
3159 if ( IsDefined( entity.enemyoverride ) && IsDefined( entity.enemyoverride[1] ) )
3164 if ( IsDefined( entity.attackable ) &&
IS_TRUE( entity.attackable.is_active ) )
3166 if ( !IsDefined( entity.attackable_slot ) )
3171 if ( entity IsAtGoal() )
3173 entity.is_at_attackable =
true;
3183 if ( IsDefined( entity.enemyoverride ) && IsDefined( entity.enemyoverride[1] ) )
3188 if ( IsDefined( entity.attackable ) &&
IS_TRUE( entity.attackable.is_active ) )
3190 if (
IS_TRUE( entity.is_at_attackable ) )